././@PaxHeader0000000000000000000000000000003200000000000010210 xustar0026 mtime=1614542835.18547 quodlibet-4.4.0/0000755000175000017500000000000000000000000012476 5ustar00lazkalazka././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540322.5227451 quodlibet-4.4.0/COPYING0000644000175000017500000004325400000000000013541 0ustar00lazkalazka 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. ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540385.9231853 quodlibet-4.4.0/MANIFEST.in0000644000175000017500000000145200000000000014236 0ustar00lazkalazkainclude COPYING include HACKING include NEWS.rst include README.rst include po/*.po 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 setup.cfg include pyproject.toml include poetry.lock recursive-include docs *.py Makefile *.rst *.png *.ico *.svg *.css prune docs/_build_guide prune docs/_build_all prune docs/_rtd_theme* ././@PaxHeader0000000000000000000000000000003200000000000010210 xustar0026 mtime=1614542365.44656 quodlibet-4.4.0/NEWS.rst0000644000175000017500000035572500000000000014025 0ustar00lazkalazka.. _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 (#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 (#1122) (#3242) (:user:`Nick Boultbee ` * Renamed "Search Library" to "Track List" browser (:user:`Joschua Gandert `) * Support moving library folders (scandirs) (#3506) (:user:`Nick Boultbee `) * Support JACK via Gstreamer (#3511) (:user:`Nick Boultbee `) * Make ID3 Replaygain ALL_CAPS (#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 (#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) (#3496) (:user:`Nick Boultbee `) * Playlists: don't clear on deletion (#3491) (:user:`Nick Boultbee `) * IRadio - do station updates in background (#3310) (:user:`Nick Boultbee `) * Improve plugin window style (#3481) (:user:`Nick Boultbee `) * Query: allow validation from extensions :up: (:user:`Nick Boultbee `) * Plugins: improve query plugins (#3485) (:user:`Nick Boultbee `) * Saved list editor: improve style (:user:`Nick Boultbee `) * Tag Editor: Add smart replacer for colon delimiters (#3456) (:user:`Nick Boultbee `) * Improve local cover art detection (#3454) (#3459) (:user:`Nick Boultbee `) * Add support for TKEY 'Initial Key' column (#3420) (:user:`Cole Robinson`) * add ability to sort by date added to Album List Browser (#3410) (:user:`Uriel Zajaczkovski`) * Add originalartistsort (:user:`Nick Boultbee `) * add check to Missing.py, fix #3336 (#3382) (:user:`Ironbalden`) * Add support for ~elapsed and ~#elapsed (#3379) (:user:`Nick Boultbee `) * Format date panes (#3346) (#3349) (:user:`Nick Boultbee `) * Update song order in song list when modified (#2509) (:user:`Thomas Leberbauer`) * Restyle the search query :pr:`3517` (:user:`Nick Boultbee `) * Fix non-splitter EditTags plugins (#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 (#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. (#3528) (:user:`Ian Campbell`) * First version of Musicbrainz Sync plugin that sends ratings (#3180) (:user:`LoveIsGrief`) * add plugin 'synchronize to device' (#2636) (: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 (#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 (#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 (#3483) (:user:`Nick Boultbee `) Documentation: * Update plugin development page (:user:`Nick Boultbee `) * Update plugins.rst to include locations on MacOS. (#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 (#3489) (:user:`Nick Boultbee `) * Add .editorconfig that agrees with PEP-008 and our Flake8 config (:user:`Nick Boultbee `) * Refactor ID3 tag writing for readability (#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�00000000032�00000000000�010210� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������26 mtime=1614542835.18547 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/PKG-INFO����������������������������������������������������������������������������0000644�0001750�0001750�00000000464�00000000000�013577� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Metadata-Version: 1.0 Name: quodlibet Version: 4.4.0 Summary: a music library, tagger, and player Home-page: https://quodlibet.readthedocs.org Author: Steven Robertson and Christoph Reiter Author-email: quod-libet-development@googlegroups.com License: GPL-2.0-or-later Description: UNKNOWN Platform: UNKNOWN ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9231853 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/README.rst��������������������������������������������������������������������������0000644�0001750�0001750�00000001505�00000000000�014166� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Ex Falso / Quod Libet - A Music Library / Editor / Player ========================================================= 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. Ex Falso is a tag editor with the same tag editing interface as Quod Libet. https://quodlibet.readthedocs.io .. image:: https://github.com/quodlibet/quodlibet/raw/master/docs/images/paned.png :align: center :width: 670 :height: 594 For information on how to build/install/test Quod Libet check out https://quodlibet.readthedocs.org/en/latest/development/overview.html .. image:: https://badges.gitter.im/Join%20Chat.svg :target: https://gitter.im/quodlibet/Lobby �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614542835.1094697 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/data/�������������������������������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�013407� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9231853 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/data/README.rst���������������������������������������������������������������������0000644�0001750�0001750�00000001167�00000000000�015103� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9231853 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/data/exfalso.1����������������������������������������������������������������������0000644�0001750�0001750�00000005111�00000000000�015130� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" 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�00000000032�00000000000�010210� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������26 mtime=1614542365.44656 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/data/io.github.quodlibet.ExFalso.appdata.xml.in�������������������������������������0000644�0001750�0001750�00000004411�00000000000�023366� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?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.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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9271855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/data/io.github.quodlibet.ExFalso.desktop.in�����������������������������������������0000644�0001750�0001750�00000000440�00000000000�022624� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������[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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9271855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/data/io.github.quodlibet.QuodLibet-search-provider.ini������������������������������0000644�0001750�0001750�00000000300�00000000000�024742� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������[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�00000000032�00000000000�010210� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������26 mtime=1614542365.44656 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/data/io.github.quodlibet.QuodLibet.appdata.xml.in�����������������������������������0000644�0001750�0001750�00000005201�00000000000�023713� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?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.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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9271855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/data/io.github.quodlibet.QuodLibet.desktop.in���������������������������������������0000644�0001750�0001750�00000001562�00000000000�023161� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������[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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9271855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/data/net.sacredchao.QuodLibet.service.in��������������������������������������������0000644�0001750�0001750�00000000112�00000000000�022140� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������[D-BUS Service] Name=net.sacredchao.QuodLibet Exec=@PREFIX@/bin/quodlibet ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9271855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/data/operon.1�����������������������������������������������������������������������0000644�0001750�0001750�00000020710�00000000000�014773� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9271855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/data/org.mpris.MediaPlayer2.quodlibet.service.in������������������������������������0000644�0001750�0001750�00000000122�00000000000�023555� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������[D-BUS Service] Name=org.mpris.MediaPlayer2.quodlibet Exec=@PREFIX@/bin/quodlibet ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9271855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/data/org.mpris.quodlibet.service.in�������������������������������������������������0000644�0001750�0001750�00000000105�00000000000�021301� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������[D-BUS Service] Name=org.mpris.quodlibet Exec=@PREFIX@/bin/quodlibet �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9271855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/data/quodlibet.1��������������������������������������������������������������������0000644�0001750�0001750�00000020430�00000000000�015460� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" 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 .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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9271855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/data/quodlibet.bash�����������������������������������������������������������������0000644�0001750�0001750�00000036706�00000000000�016252� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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) # 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 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9271855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/data/quodlibet.zsh������������������������������������������������������������������0000644�0001750�0001750�00000005067�00000000000�016135� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#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]' �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614542835.1094697 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/�������������������������������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�013426� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9311855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/Makefile�����������������������������������������������������������������������0000644�0001750�0001750�00000000441�00000000000�015065� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������all: python3 -m sphinx -b html -n . _build_all guide: python3 -m sphinx -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 -b linkcheck -n . _build_all �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9311855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/README.rst���������������������������������������������������������������������0000644�0001750�0001750�00000000564�00000000000�015122� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Quod Libet / Ex Falso Documentation =================================== Dependencies: * sphinx (http://sphinx-doc.org/) 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9311855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/bugs_repo.rst������������������������������������������������������������������0000644�0001750�0001750�00000001774�00000000000�016156� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������====================== 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9311855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/changelog.rst������������������������������������������������������������������0000644�0001750�0001750�00000000056�00000000000�016110� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Changelog ========= .. include:: ../NEWS.rst ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9311855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/conf.py������������������������������������������������������������������������0000644�0001750�0001750�00000003532�00000000000�014730� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the 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' master_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', '#'), 'pr': ('https://github.com/quodlibet/quodlibet/pull/%s', '#'), 'user': ('https://github.com/%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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9311855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/contact.rst��������������������������������������������������������������������0000644�0001750�0001750�00000001740�00000000000�015615� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _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 want to address the wider Quod Libet community consider sending a mail to our `quod-libet-devel Google group <http://groups.google.com/group/quod-libet-development>`_. Quod Libet has an IRC channel on `OFTC <https://www.oftc.net/>`_ , *#quodlibet*. It is a good place to ask for help with installation and configuration, or discuss development (assuming people there are paying attention). There is also now a `Quod Libet Gitter chatroom <https://gitter.im/quodlibet/Lobby>`_ too, for people that prefer that. ��������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614542835.1134696 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/development/�������������������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�015750� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9311855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/development/contributing.rst���������������������������������������������������0000644�0001750�0001750�00000012134�00000000000�021212� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9311855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/development/devenv.rst���������������������������������������������������������0000644�0001750�0001750�00000004523�00000000000�017775� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. 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 ``master``: `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 If you want to build a bundle yourself or change/add dependencies, see the `osx_bundle directory <https://github.com/quodlibet/quodlibet/tree/master/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/master/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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9311855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/development/faq.rst������������������������������������������������������������0000644�0001750�0001750�00000003566�00000000000�017263� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9311855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/development/flatpak.rst��������������������������������������������������������0000644�0001750�0001750�00000000500�00000000000�020117� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9311855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/development/formats.rst��������������������������������������������������������0000644�0001750�0001750�00000014274�00000000000�020165� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9311855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/development/guidelines.rst�����������������������������������������������������0000644�0001750�0001750�00000006021�00000000000�020631� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9311855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/development/index.rst����������������������������������������������������������0000644�0001750�0001750�00000000310�00000000000�017603� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Development Guide ================= .. toctree:: :titlesonly: overview devenv testing contributing guidelines plugins tools faq maint formats flatpak ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9311855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/development/maint.rst����������������������������������������������������������0000644�0001750�0001750�00000004351�00000000000�017615� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������===================== 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 master 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 | | <--- "master" branch 3.4.-1 | /|\ Release Checklist ----------------- New Stable branch: * git checkout -b quodlibet-x.y * git commit -m "new stable branch * git push * git checkout master * Update version to (X, Y + 1, -1) * git commit -m "version bump" New Stable release: * git checkout quodlibet-x.y * Cherry pick stuff from master * Update NEWS * 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 master * 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 * Write release mail ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9311855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/development/overview.rst�������������������������������������������������������0000644�0001750�0001750�00000001530�00000000000�020347� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������======== 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9311855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/development/plugins.rst��������������������������������������������������������0000644�0001750�0001750�00000006125�00000000000�020167� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _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/master/quodlibet/plugins>`_ . * The easiest way to get started creating a new plugin is to look for `existing plugins <https://github.com/quodlibet/quodlibet/tree/master/quodlibet/ext>`_ that do something similar to what you want. �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9311855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/development/testing.rst��������������������������������������������������������0000644�0001750�0001750�00000002716�00000000000�020165� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9311855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/development/tools.rst����������������������������������������������������������0000644�0001750�0001750�00000010235�00000000000�017643� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9311855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/downloads.rst������������������������������������������������������������������0000644�0001750�0001750�00000007272�00000000000�016162� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _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 -------------------- Stable Repo (14.04+): :: $ sudo add-apt-repository ppa:lazka/ppa Unstable PPA (16.04+): :: $ sudo add-apt-repository ppa:lazka/dumpingplace .. _debian: |debian-logo| Debian -------------------- Stable Repo: * 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 Unstable Repo: * Debian Testing:: # deb http://lazka.github.io/ql-debian/testing/ quodlibet-unstable/ 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>`__ * `Fedora Unstable Repo <https://software.opensuse.org/download.html?project=home%3Alazka0%3Aql-unstable&package=quodlibet>`__ For stable releases 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>`__ * `openSUSE Unstable Repo <https://software.opensuse.org/download.html?project=home%3Alazka0%3Aql-unstable&package=quodlibet>`__ .. _arch: |arch-logo| Arch Linux ---------------------- Stable: :: $ pacman -S quodlibet Unstable: See `quodlibet-git <https://aur.archlinux.org/packages/quodlibet-git/>`__ in the `AUR <https://wiki.archlinux.org/index.php/AUR>`__. .. _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=1614542835.1134696 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/ext/���������������������������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�014226� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9311855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/ext/contributors.py������������������������������������������������������������0000644�0001750�0001750�00000001422�00000000000�017334� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9311855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/extra.css����������������������������������������������������������������������0000644�0001750�0001750�00000000703�00000000000�015263� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.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=1614542835.1134696 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/favicon/�����������������������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�015053� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9311855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/favicon/Makefile���������������������������������������������������������������0000644�0001750�0001750�00000001436�00000000000�016517� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������SOURCE=favicon.svg DEST=favicon.ico all: $(DEST) favicon-16.png: $(SOURCE) inkscape $(SOURCE) --export-png $@ -w 16 -h 16 favicon-24.png: $(SOURCE) inkscape $(SOURCE) --export-png $@ -w 24 -h 24 favicon-32.png: $(SOURCE) inkscape $(SOURCE) --export-png $@ -w 32 -h 32 favicon-48.png: $(SOURCE) inkscape $(SOURCE) --export-png $@ -w 48 -h 48 favicon-64.png: $(SOURCE) inkscape $(SOURCE) --export-png $@ -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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9311855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/favicon/README.rst�������������������������������������������������������������0000644�0001750�0001750�00000000126�00000000000�016541� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������The svg is based on ``quodlibet/images/hicolor/scalable/apps/quodlibet-symbolic.svg`` ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9311855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/favicon/favicon.ico������������������������������������������������������������0000644�0001750�0001750�00000103276�00000000000�017205� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� �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))*̣dÚֵ)))))M5��������M5))*ǡ9)))))M5��������C.)))2ĔK*))))))B.���������C.M5M5M5M5M5M5M5M5M5M5B.�����������������������������������������������������������������������������������������������������(������0���� ������ ��v��v���������������������������������������������������������������������������������������������������������������������"���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))))ճ3)ҳέ))))))))oM���f�����������foM))))׶ΦjÚŖ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���#������������������������������������������������������������������������������������������������������������������������������������������������������(��� ���@���� ��������H��H������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� ��������������������������������������������������������������������������������� ������������������� 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!))))))ѫṛֹeͥg)))))))))))f!����������������������ݔf!))))),پ)),)))))))))))f!����������������������ݔf!))))).ؾ6ŕLֹΦ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ϮӮwӮwͤe)))))))))))))))))%������������������������������%))))))))))ͪƘQ)))ÒGͤe)))))))))))))))))%������������������������������%)))))))))0ִ))))ҭuǙS)))))))))))))))))%������������������������������%)))))))))6Щo)))Χjؾ))))))))))))))))))%������������������������������%))))))))))έ̩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ͫ8))))ҳ)))))))))))))))))))))))oM��������������������������������������������oM)))))))))))))Ϯ))))))™)))))))))))))))))))))))oM��������������������������������������������oM))))))))))))5>)))))/ǡ)))))))))))))))))))))))oM��������������������������������������������oM))))))))))))<.))))1չ?)))))))))))))))))))))))oM��������������������������������������������oM)))))))))))),ҳÒG/ÒH׷Щ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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9311855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/favicon/favicon.svg������������������������������������������������������������0000644�0001750�0001750�00000025336�00000000000�017232� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!-- Created with Inkscape (http://www.inkscape.org/) --> <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="0.91 r13725" 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="1.4" inkscape:cx="-45.20774" inkscape:cy="34.393848" 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="26" inkscape:window-maximized="0" showborder="true" fit-margin-top="9" fit-margin-left="9" fit-margin-right="9" fit-margin-bottom="9" /> <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 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;direction:ltr;block-progression:tb;writing-mode:lr-tb;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 a 1.9917783,1.9917783 0 0 0 1.49058,1.92934 c 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 a 1.9917783,1.9917783 0 0 0 0.0965,-0.32675 c 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 a 1.9917783,1.9917783 0 0 0 0.028,0.0591 c 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 l 0,-45.23063 a 1.9917783,1.9917783 0 0 0 -0.14937,-0.75929 c -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 1.63683,5.93272 c 2.67259,-0.12031 5.84877,0.89692 8.0939,2.61083 2.19347,1.6745 3.39486,3.79871 3.17097,6.22369 -0.6258,1.93583 -2.13019,2.77326 -4.41881,2.98427 -2.3584,0.21743 -5.24815,-0.54727 -6.94252,-1.67729 a 1.9917783,1.9917783 0 0 0 -0.27696,-0.1556 c -1.77529,-0.81224 -3.58592,-2.92202 -4.16054,-4.85758 -0.2873,-0.96777 -0.28982,-1.83791 -0.0467,-2.53615 0.24275,-0.69706 0.69841,-1.31175 1.77064,-1.87644 0.002,-8e-4 7.9e-4,-0.002 0.003,-0.003 0.79854,-0.41468 1.77991,-0.65145 2.80688,-0.71261 z m -2.30899,13.4556 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9311855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/features.rst�������������������������������������������������������������������0000644�0001750�0001750�00000007751�00000000000�016010� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _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 * 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=1614542835.1134696 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/�������������������������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�014523� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614542835.1134696 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/browse/������������������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�016024� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9311855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/browse/album.rst���������������������������������������������������������0000644�0001750�0001750�00000006166�00000000000�017667� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9311855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/browse/audiofeeds.rst����������������������������������������������������0000644�0001750�0001750�00000001010�00000000000�020656� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Audio Feeds Browser ------------------- The *Audio Feeds* browser allows you to subscribe to syndicated feeds with attached audio files; these are often called "podcasts" or "blogcasts." 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*, to download it to your hard drive. Currently this has no effect on the feed itself (so changes to the local song will not be reflected in the feed list). ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9311855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/browse/filesystem.rst����������������������������������������������������0000644�0001750�0001750�00000001077�00000000000�020747� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9311855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/browse/index.rst���������������������������������������������������������0000644�0001750�0001750�00000000313�00000000000�017662� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _Browse: Browsing Your Library ===================== .. toctree:: :titlesonly: overview playlists search album paned filesystem iradio audiofeeds soundcloud ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9311855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/browse/iradio.rst��������������������������������������������������������0000644�0001750�0001750�00000001356�00000000000�020032� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9311855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/browse/overview.rst������������������������������������������������������0000644�0001750�0001750�00000004042�00000000000�020424� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9311855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/browse/paned.rst���������������������������������������������������������0000644�0001750�0001750�00000011647�00000000000�017656� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9311855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/browse/playlists.rst�����������������������������������������������������0000644�0001750�0001750�00000012671�00000000000�020611� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _Playlists: Playlists ========= The Playlist Browser -------------------- .. image:: ../images/PlaylistBrowser.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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9311855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/browse/search.rst��������������������������������������������������������0000644�0001750�0001750�00000001235�00000000000�020024� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9311855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/browse/soundcloud.rst����������������������������������������������������0000644�0001750�0001750�00000007027�00000000000�020743� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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=1614542835.1134696 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/commands/����������������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�016324� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9311855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/commands/Makefile��������������������������������������������������������0000644�0001750�0001750�00000000176�00000000000�017770� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������MANDIR=../../../data all: $(MANDIR)/exfalso.1 $(MANDIR)/quodlibet.1 $(MANDIR)/operon.1 $(MANDIR)/%.1:%.rst rst2man $< > $@ ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9311855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/commands/exfalso.rst�����������������������������������������������������0000644�0001750�0001750�00000003536�00000000000�020526� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������========= 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 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9311855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/commands/index.rst�������������������������������������������������������0000644�0001750�0001750�00000000145�00000000000�020165� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Command Manuals =============== .. toctree:: :titlesonly: quodlibet exfalso operon ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9311855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/commands/operon.rst������������������������������������������������������0000644�0001750�0001750�00000015165�00000000000�020370� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������======== 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9311855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/commands/quodlibet.rst���������������������������������������������������0000644�0001750�0001750�00000016305�00000000000�021053� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������=========== 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 audio feeds. 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 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 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9311855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/config_files.rst���������������������������������������������������������0000644�0001750�0001750�00000004166�00000000000�017713� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9311855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/editing_tags.rst���������������������������������������������������������0000644�0001750�0001750�00000012463�00000000000�017724� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _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 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. 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9351854 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/faq.rst������������������������������������������������������������������0000644�0001750�0001750�00000023201�00000000000�016022� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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 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 ``QUODLIBET_USERDIR`` environment variable is set, this will be used * else, ``$XDG_CONFIG_HOME/config`` will be used, if it exists * 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 master 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 master 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 master 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614542835.1174695 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/images/������������������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�015770� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9351854 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/images/PlaylistBrowser.png�����������������������������������������������0000644�0001750�0001750�00000335273�00000000000�021660� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9351854 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/images/browser_window.png������������������������������������������������0000644�0001750�0001750�00000111372�00000000000�021555� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9351854 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/images/main_overview.png�������������������������������������������������0000644�0001750�0001750�00000130766�00000000000�021365� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9351854 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/images/plugins.png�������������������������������������������������������0000644�0001750�0001750�00000115306�00000000000�020165� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9351854 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/images/queue.png���������������������������������������������������������0000644�0001750�0001750�00000027425�00000000000�017634� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9351854 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/index.rst����������������������������������������������������������������0000644�0001750�0001750�00000000421�00000000000�016361� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9351854 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/interacting.rst����������������������������������������������������������0000644�0001750�0001750�00000007403�00000000000�017570� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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/master/quodlibet/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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9351854 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/overview.rst�������������������������������������������������������������0000644�0001750�0001750�00000013246�00000000000�017131� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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: 400px :figwidth: 400px 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. 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 left off. 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: 450px 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614542835.1174695 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/playback/����������������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�016311� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9351854 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/playback/backends.rst����������������������������������������������������0000644�0001750�0001750�00000006224�00000000000�020621� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614542835.1174695 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/playback/images/���������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�017556� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9351854 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/playback/images/replaygain_force.png�������������������������������������0000644�0001750�0001750�00000027423�00000000000�023605� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9351854 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/playback/images/replaygain_plugin.png������������������������������������0000644�0001750�0001750�00000043130�00000000000�023776� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9351854 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/playback/images/replaygain_pref.png��������������������������������������0000644�0001750�0001750�00000011172�00000000000�023435� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9351854 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/playback/index.rst�������������������������������������������������������0000644�0001750�0001750�00000000116�00000000000�020150� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Playback ======== .. toctree:: :titlesonly: backends replaygain ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9351854 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/playback/replaygain.rst��������������������������������������������������0000644�0001750�0001750�00000007137�00000000000�021206� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9351854 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/queue.rst����������������������������������������������������������������0000644�0001750�0001750�00000004103�00000000000�016377� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _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. Ignore and Keep Songs --------------------- With :ref:`release 4.2.0 <release-4.2.0>`, the queue was updated with two new checkboxes: *Ignore* and *Keep Songs*. When the *Keep Songs* checkbox is checked, songs won't be consumed from the queue anymore when played. In this way, the queue can function as a kind of temporary playlist. With the *Ignore* checkbox checked, the queue won't have priority anymore. This means that if a song is played from the song list, then songs from the song list will continue playing even if the queue is not empty. If both *Keep Songs* and *Ignore* are enabled, songs will be kept in the queue while one at the same time is free to switch between playing songs from the queue and the song list. If a song in the queue is selected, songs will keep playing from the queue, while if a song in the song list is selected, then songs from the song list will be played instead. Disable and Mode Selection -------------------------- 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 cannot be played from - but you can still add songs to it. The queue also has two different modes, that can be changed in the queue preferences. In the *Ephemeral* mode, the queue consumes songs as described in the :ref:`Overview <Queue_Overview>`. This is the default behavior. 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9351854 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/renaming_files.rst�������������������������������������������������������0000644�0001750�0001750�00000012102�00000000000�020233� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _RenamingFiles: Renaming files ============== Basic Syntax ------------ 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. 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9351854 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/searching.rst������������������������������������������������������������0000644�0001750�0001750�00000020206�00000000000�017220� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9351854 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/shortcuts.rst������������������������������������������������������������0000644�0001750�0001750�00000003626�00000000000�017322� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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 ����������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9351854 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/stats_rating.rst���������������������������������������������������������0000644�0001750�0001750�00000002344�00000000000�017762� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _Stats: Library Statistics ================== Play Count ---------- The internal ``~#playcount`` tag gets incremented after a song ends or is forced to end by the user and the time it was played was more than half of the song's duration. 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. 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614542835.1174695 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/tags/��������������������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�015461� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9351854 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/tags/index.rst�����������������������������������������������������������0000644�0001750�0001750�00000000141�00000000000�017316� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Tags ==== .. toctree:: :titlesonly: tags internal_tags tied_tags patterns �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9351854 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/tags/internal_tags.rst���������������������������������������������������0000644�0001750�0001750�00000013144�00000000000�021050� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _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*) The ``~people`` Internal Tag ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The internal ``~people`` tag combines the following tags to one: ``albumartist``, ``artist``, ``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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9351854 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/tags/patterns.rst��������������������������������������������������������0000644�0001750�0001750�00000006742�00000000000�020064� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9351854 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/tags/tags.rst������������������������������������������������������������0000644�0001750�0001750�00000006175�00000000000�017162� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9351854 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/guide/tags/tied_tags.rst�������������������������������������������������������0000644�0001750�0001750�00000002362�00000000000�020161� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9351854 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/icons.rst����������������������������������������������������������������������0000644�0001750�0001750�00000001346�00000000000�015277� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. |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=1614542835.1174695 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/images/������������������������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�014673� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9391856 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/images/album-list-2017-08.png��������������������������������������������������0000644�0001750�0001750�00001032205�00000000000�020271� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9391856 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/images/album.png���������������������������������������������������������������0000644�0001750�0001750�00000312512�00000000000�016505� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9391856 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/images/covergrid-plus-waveform-2017-08.png�������������������������������������0000644�0001750�0001750�00001667335�00000000000�023033� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9391856 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/images/exfalso.png�������������������������������������������������������������0000644�0001750�0001750�00000160760�00000000000�017054� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9391856 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/images/paned.png���������������������������������������������������������������0000644�0001750�0001750�00000174275�00000000000�016510� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9391856 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/images/plugins.png�������������������������������������������������������������0000644�0001750�0001750�00000113513�00000000000�017066� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9431856 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/images/queue_2browsers.png�����������������������������������������������������0000644�0001750�0001750�00000337054�00000000000�020551� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9431856 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/images/soundcloud-browser-2017-08.png������������������������������������������0000644�0001750�0001750�00000740233�00000000000�022066� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9431856 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/images/tagedit.png�������������������������������������������������������������0000644�0001750�0001750�00000141700�00000000000�017025� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9431856 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/images/tagrename.png�����������������������������������������������������������0000644�0001750�0001750�00000200644�00000000000�017352� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9431856 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/index.rst����������������������������������������������������������������������0000644�0001750�0001750�00000002647�00000000000�015300� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9431856 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/license.rst��������������������������������������������������������������������0000644�0001750�0001750�00000001031�00000000000�015575� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9431856 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/packaging.rst������������������������������������������������������������������0000644�0001750�0001750�00000006751�00000000000�016115� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _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.7) * **PyGObject** including **cairo support** (>= 3.18) * **pycairo** (>= 1.8) * **mutagen** (>= 1.34) * **GTK+** (>= 3.18) * **libsoup** (>= 2.52) * 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 **python-dbus**: * "Browse Folders" * Screensaver plugins * uPnP server * Gnome search provider * gajim status updater * MPRIS * ... **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). **paho-mqtt** * For the MQTT plugin **pyinotify**: * For the auto library update plugin **musicbrainzngs** (>= 0.6): * For the Musicbrainz plugin Build Dependencies ------------------ * **Python** >= 3.7 (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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9431856 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/screenshots.rst����������������������������������������������������������������0000644�0001750�0001750�00000002131�00000000000�016515� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _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=1614542835.1174695 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/tables/������������������������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�014700� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9431856 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/tables/default.rst�������������������������������������������������������������0000644�0001750�0001750�00000002373�00000000000�017063� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. list-table:: :header-rows: 1 * - Release - File - SHA256 - PGP * - 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>`__ * - Quod Libet 4.2.1 - `quodlibet-4.2.1.tar.gz <https://github.com/quodlibet/quodlibet/releases/download/release-4.2.1/quodlibet-4.2.1.tar.gz>`__ - `SHA256 <https://github.com/quodlibet/quodlibet/releases/download/release-4.2.1/quodlibet-4.2.1.tar.gz.sha256>`__ - `SIG <https://github.com/quodlibet/quodlibet/releases/download/release-4.2.1/quodlibet-4.2.1.tar.gz.sig>`__ * - Quod Libet 4.1.0 - `quodlibet-4.1.0.tar.gz <https://github.com/quodlibet/quodlibet/releases/download/release-4.1.0/quodlibet-4.1.0.tar.gz>`__ - `SHA256 <https://github.com/quodlibet/quodlibet/releases/download/release-4.1.0/quodlibet-4.1.0.tar.gz.sha256>`__ - `SIG <https://github.com/quodlibet/quodlibet/releases/download/release-4.1.0/quodlibet-4.1.0.tar.gz.sig>`__ ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9431856 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/tables/osx_exfalso.rst���������������������������������������������������������0000644�0001750�0001750�00000002271�00000000000�017766� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. list-table:: :header-rows: 1 * - Release - File - SHA256 - PGP * - 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>`__ * - Ex Falso 4.1.0 - `ExFalso-4.1.0.dmg <https://github.com/quodlibet/quodlibet/releases/download/release-4.1.0/ExFalso-4.1.0.dmg>`__ - `SHA256 <https://github.com/quodlibet/quodlibet/releases/download/release-4.1.0/ExFalso-4.1.0.dmg.sha256>`__ - `SIG <https://github.com/quodlibet/quodlibet/releases/download/release-4.1.0/ExFalso-4.1.0.dmg.sig>`__ ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9431856 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/tables/osx_quodlibet.rst�������������������������������������������������������0000644�0001750�0001750�00000002327�00000000000�020317� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. list-table:: :header-rows: 1 * - Release - File - SHA256 - PGP * - 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>`__ * - Quod Libet 4.1.0 - `QuodLibet-4.1.0.dmg <https://github.com/quodlibet/quodlibet/releases/download/release-4.1.0/QuodLibet-4.1.0.dmg>`__ - `SHA256 <https://github.com/quodlibet/quodlibet/releases/download/release-4.1.0/QuodLibet-4.1.0.dmg.sha256>`__ - `SIG <https://github.com/quodlibet/quodlibet/releases/download/release-4.1.0/QuodLibet-4.1.0.dmg.sig>`__ ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9431856 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/tables/windows.rst�������������������������������������������������������������0000644�0001750�0001750�00000002517�00000000000�017131� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. list-table:: :header-rows: 1 * - Release - File - SHA256 - PGP * - 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>`__ * - Quod Libet 4.2.1 - `quodlibet-4.2.1-installer.exe <https://github.com/quodlibet/quodlibet/releases/download/release-4.2.1/quodlibet-4.2.1-installer.exe>`__ - `SHA256 <https://github.com/quodlibet/quodlibet/releases/download/release-4.2.1/quodlibet-4.2.1-installer.exe.sha256>`__ - `SIG <https://github.com/quodlibet/quodlibet/releases/download/release-4.2.1/quodlibet-4.2.1-installer.exe.sig>`__ * - Quod Libet 4.1.0 - `quodlibet-4.1.0-installer.exe <https://github.com/quodlibet/quodlibet/releases/download/release-4.1.0/quodlibet-4.1.0-installer.exe>`__ - `SHA256 <https://github.com/quodlibet/quodlibet/releases/download/release-4.1.0/quodlibet-4.1.0-installer.exe.sha256>`__ - `SIG <https://github.com/quodlibet/quodlibet/releases/download/release-4.1.0/quodlibet-4.1.0-installer.exe.sig>`__ ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9431856 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/tables/windows_portable.rst����������������������������������������������������0000644�0001750�0001750�00000002544�00000000000�021021� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. list-table:: :header-rows: 1 * - Release - File - SHA256 - PGP * - 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>`__ * - Quod Libet 4.2.1 (portable) - `quodlibet-4.2.1-portable.exe <https://github.com/quodlibet/quodlibet/releases/download/release-4.2.1/quodlibet-4.2.1-portable.exe>`__ - `SHA256 <https://github.com/quodlibet/quodlibet/releases/download/release-4.2.1/quodlibet-4.2.1-portable.exe.sha256>`__ - `SIG <https://github.com/quodlibet/quodlibet/releases/download/release-4.2.1/quodlibet-4.2.1-portable.exe.sig>`__ * - Quod Libet 4.1.0 (portable) - `quodlibet-4.1.0-portable.exe <https://github.com/quodlibet/quodlibet/releases/download/release-4.1.0/quodlibet-4.1.0-portable.exe>`__ - `SHA256 <https://github.com/quodlibet/quodlibet/releases/download/release-4.1.0/quodlibet-4.1.0-portable.exe.sha256>`__ - `SIG <https://github.com/quodlibet/quodlibet/releases/download/release-4.1.0/quodlibet-4.1.0-portable.exe.sig>`__ ������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614542835.1174695 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/translation/�������������������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�015764� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9431856 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/translation/faq.rst������������������������������������������������������������0000644�0001750�0001750�00000010564�00000000000�017273� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9431856 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/translation/howto.rst����������������������������������������������������������0000644�0001750�0001750�00000005114�00000000000�017657� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _Translating: How-to ====== 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. Many of the translations files are missing a lot of strings, so please try the trunk version in your language. Of course, there might be mistakes in the English, too! Please let us know if you find them. 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 To translate the last release, update to the stable branch:: $ git branch -a # to get the list of branches $ git checkout quodlibet-X.X # for example: quodlibet-3.3 To translate current trunk, update to the default branch:: $ git checkout master 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:: $ LANG=<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 send us the .po file you made: * Create a pull request. * Or create a `new issue <https://github.com/quodlibet/quodlibet/issues/new>`__ linking to your updated .po file. If you don't have a place for making the file accessible create a `gist <https://gist.github.com/>`__ with the content of the .po file and include the gist URL in the issue description. ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9431856 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/docs/translation/index.rst����������������������������������������������������������0000644�0001750�0001750�00000000126�00000000000�017624� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Translation Guide ================= .. toctree:: :titlesonly: howto faq ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9431856 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/exfalso.py��������������������������������������������������������������������������0000755�0001750�0001750�00000000625�00000000000�014517� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/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=1614542835.1214697 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/gdist/������������������������������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�013610� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9431856 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/gdist/__init__.py�������������������������������������������������������������������0000644�0001750�0001750�00000017222�00000000000�015725� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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, 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("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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9431856 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/gdist/appdata.py��������������������������������������������������������������������0000644�0001750�0001750�00000007670�00000000000�015606� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9431856 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/gdist/bash_completions.py�����������������������������������������������������������0000644�0001750�0001750�00000004055�00000000000�017517� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9431856 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/gdist/clean.py����������������������������������������������������������������������0000644�0001750�0001750�00000006503�00000000000�015250� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9431856 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/gdist/coverage.py�������������������������������������������������������������������0000644�0001750�0001750�00000005764�00000000000�015771� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9431856 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/gdist/dbus_services.py��������������������������������������������������������������0000644�0001750�0001750�00000007764�00000000000�017040� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9431856 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/gdist/docs.py�����������������������������������������������������������������������0000644�0001750�0001750�00000003626�00000000000�015121� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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", "-b", "html", "-c", DOCS_ROOT, "-n", "-E", srcdir, TARGET]) ����������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9431856 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/gdist/gettextutil.py����������������������������������������������������������������0000644�0001750�0001750�00000030174�00000000000�016551� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2015-2017 Christoph Reiter # 2019 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 glob import subprocess import contextlib import fnmatch import tempfile import shutil import functools import warnings # pattern -> (language, [keywords]) XGETTEXT_CONFIG = { "*.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"]), } class GettextError(Exception): pass class GettextWarning(Warning): pass def _read_potfiles(src_root, potfiles): """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(os.path.normpath(os.path.join(src_root, line))) return paths def _write_potfiles(src_root, potfiles, paths): with open(potfiles, "w", encoding="utf-8") as h: for path in paths: path = os.path.relpath(path, src_root) h.write(path + "\n") def _src_root(po_dir): return os.path.normpath(os.path.join(po_dir, "..")) def get_pot_dependencies(po_dir): """Returns a list of paths that are used as input for the .pot file""" src_root = _src_root(po_dir) potfiles_path = os.path.join(po_dir, "POTFILES.in") return _read_potfiles(src_root, potfiles_path) def _get_pattern(path): for pattern in XGETTEXT_CONFIG: match_part = os.path.basename(path) 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, src_root): 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("Unknown filetype: " + path) 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") 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() try: os.close(fd) _write_potfiles(src_root, potfiles_in, paths) args = ["xgettext", "--from-code=utf-8", "--add-comments", "--files-from=" + potfiles_in, "--directory=" + src_root, "--output=" + 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: raise GettextError(stderr or ("Got error: %d" % p.returncode)) if stderr: warnings.warn(stderr, GettextWarning) finally: os.unlink(potfiles_in) except Exception: os.unlink(out_path) raise return out_path @contextlib.contextmanager def create_pot(po_dir): """Temporarily creates a .pot file in a temp directory.""" src_root = _src_root(po_dir) potfiles_path = os.path.join(po_dir, "POTFILES.in") pot_path = _create_pot(potfiles_path, src_root) try: yield pot_path finally: os.unlink(pot_path) def update_linguas(po_dir): """Create a LINGUAS file in po_dir""" linguas = os.path.join(po_dir, "LINGUAS") with open(linguas, "w", encoding="utf-8") as h: for l in list_languages(po_dir): h.write(l + "\n") def list_languages(po_dir): """Returns a list of available language codes""" po_files = glob.glob(os.path.join(po_dir, "*.po")) return sorted([os.path.basename(po[:-3]) for po in po_files]) def compile_po(po_path, target_file): """Creates an .mo from a .po""" try: subprocess.check_output( ["msgfmt", "-o", target_file, po_path], universal_newlines=True, stderr=subprocess.STDOUT) except subprocess.CalledProcessError as e: raise GettextError(e.output) def po_stats(po_path): """Returns a string containing translation statistics""" try: return subprocess.check_output( ["msgfmt", "--statistics", 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_dir, lang_code): """The default path to the .po file for a given language code""" return os.path.join(po_dir, lang_code + ".po") def update_po(pot_path, po_path, out_path=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. Returns the path written to. Raises GettextError on error. """ if out_path is None: out_path = po_path try: subprocess.check_output( ["msgmerge", "-o", out_path, po_path, pot_path], universal_newlines=True, stderr=subprocess.STDOUT) except subprocess.CalledProcessError as e: raise GettextError(e.output) def check_po(po_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", 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): """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") os.close(fd) os.unlink(po_path) create_po(pot_path, po_path) try: check_po(po_path, ignore_header=True) finally: os.remove(po_path) def create_po(pot_path, po_path): """Create a new <po_path> file based on <pot_path> Returns the path to the new po file or raise GettextError in case something went wrong or the file already exists. """ if os.path.exists(po_path): raise GettextError("%r already exists" % po_path) if not os.path.exists(pot_path): raise GettextError("%r missing" % pot_path) try: subprocess.check_output( ["msginit", "--no-translator", "-i", pot_path, "-o", po_path], universal_newlines=True, stderr=subprocess.STDOUT) except subprocess.CalledProcessError as e: raise GettextError(e.output) if not os.path.exists(po_path): raise GettextError( "something went wrong; %r didn't get created" % po_path) update_po(pot_path, po_path) def get_missing(po_dir): """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 = os.path.join(po_dir, "POTFILES.in") skip_path = os.path.join(po_dir, "POTFILES.skip") # Generate a set of paths of files which are not marked translatable # and not skipped pot_files = {os.path.relpath(p, src_root) for p in _read_potfiles(src_root, potfiles_path)} skip_files = {os.path.relpath(p, src_root) for p in _read_potfiles(src_root, skip_path)} not_translatable = set() for root, dirs, files in os.walk(src_root): for dirname in dirs: dirpath = os.path.relpath(os.path.join(root, dirname), src_root) if dirpath in skip_files or dirpath.startswith("."): dirs.remove(dirname) for name in files: path = os.path.relpath(os.path.join(root, name), 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] # Filter out any files not containing translations fd, temp_path = tempfile.mkstemp("POTFILES.in") 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: os.unlink(pot_path) finally: os.unlink(temp_path) def _get_xgettext_version(): """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(): """Raises GettextError in case the required gettext programs are missing Tries to include a helpful error message.. """ 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9431856 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/gdist/icons.py����������������������������������������������������������������������0000644�0001750�0001750�00000005516�00000000000�015304� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9471855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/gdist/man.py������������������������������������������������������������������������0000644�0001750�0001750�00000005206�00000000000�014740� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9471855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/gdist/po.py�������������������������������������������������������������������������0000644�0001750�0001750�00000021140�00000000000�014576� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2007 Joe Wreschnig # 2009-2010,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. """translation support This module contains commands to support building and installing gettext message catalogs. """ import os from tempfile import mkstemp from distutils.errors import DistutilsOptionError from distutils.dep_util import newer_group, newer 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 = 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") 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: os.remove(temp_path) 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 = self.distribution.po_directory langs = gettextutil.list_languages(po_directory) if self.lang is not None: if self.lang not in langs: raise SystemExit("Error: %r not found" % self.lang) 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 = 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("Created %r" % os.path.abspath(po_path)) 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 = None self.po_build_dir = None def finalize_options(self): self.set_undefined_options('build', ('build_base', 'build_base')) self.po_build_dir = os.path.join(self.build_base, '_po_build') def run(self): po_directory = 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(pot_deps + [po_path], out_path): to_build.append((po_path, out_path)) if not to_build: return self.mkpath(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 = None self.lang = None self.po_build_dir = 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 langs = gettextutil.list_languages(self.po_build_dir) 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 = os.path.join(self.build_base, 'share', 'locale') for language in langs: fullpath = os.path.join(basepath, language, "LC_MESSAGES") destpath = os.path.join(fullpath, po_package + ".mo") self.mkpath(fullpath) po_path = gettextutil.get_po_path(self.po_build_dir, language) if newer(po_path, 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9471855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/gdist/scripts.py��������������������������������������������������������������������0000644�0001750�0001750�00000003241�00000000000�015651� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9471855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/gdist/search_provider.py������������������������������������������������������������0000644�0001750�0001750�00000003560�00000000000�017345� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9471855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/gdist/shortcuts.py������������������������������������������������������������������0000644�0001750�0001750�00000007656�00000000000�016236� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000032�00000000000�010210� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������26 mtime=1614542365.44656 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/gdist/tests.py����������������������������������������������������������������������0000644�0001750�0001750�00000013023�00000000000�015323� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9471855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/gdist/util.py�����������������������������������������������������������������������0000644�0001750�0001750�00000002510�00000000000�015135� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9471855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/gdist/zsh_completions.py������������������������������������������������������������0000644�0001750�0001750�00000003631�00000000000�017405� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9471855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/operon.py���������������������������������������������������������������������������0000755�0001750�0001750�00000000631�00000000000�014355� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614542835.1214697 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/po/���������������������������������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�013114� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9471855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/po/POTFILES.in����������������������������������������������������������������������0000644�0001750�0001750�00000016443�00000000000�014701� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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/audiofeeds.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/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/tracks.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_library_update.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/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/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/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/weblyrics.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/_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/importexport.py quodlibet/ext/songsmenu/k3b.py quodlibet/ext/songsmenu/lastfmsync.py quodlibet/ext/songsmenu/makesorttags.py quodlibet/ext/songsmenu/migratemetadata.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/libraries.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/plugins/listenbrainz/__init__.py quodlibet/plugins/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/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/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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9471855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/po/POTFILES.skip��������������������������������������������������������������������0000644�0001750�0001750�00000000142�00000000000�015226� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������tests/test_qltk_notif.py tests/test_util.py tests/test_util_i18n.py build dist quodlibet/packages ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9471855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/po/bg.po����������������������������������������������������������������������������0000644�0001750�0001750�00000570125�00000000000�014056� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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: 2017-05-17 18:58+0200\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" #: ../data/exfalso.appdata.xml.in.h:1 ../data/exfalso.desktop.in.h:2 msgid "Edit tags in your audio files" msgstr "Редактиране на етикетите в аудио файловете Ви" #: ../data/exfalso.appdata.xml.in.h:2 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/exfalso.appdata.xml.in.h:3 ../data/quodlibet.appdata.xml.in.h:3 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/exfalso.desktop.in.h:1 msgid "Audio tag editor" msgstr "Редактор на музикални етикети" #: ../data/quodlibet.appdata.xml.in.h:1 ../data/quodlibet.desktop.in.h:2 msgid "Listen to, browse, or edit your audio collection" msgstr "За слушане, разглеждане или редактиране на Вашата аудио колекция" #: ../data/quodlibet.appdata.xml.in.h:2 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 "" #: ../data/quodlibet.desktop.in.h:1 msgid "Music Player" msgstr "Слушане на музика" #: ../quodlibet/browsers/albums/main.py:168 #: ../quodlibet/browsers/covergrid/main.py:54 #, fuzzy msgid "_Title" msgstr "Заглавие" #: ../quodlibet/browsers/albums/main.py:169 #: ../quodlibet/browsers/covergrid/main.py:55 ../quodlibet/qltk/prefs.py:49 msgid "_Artist" msgstr "_Изпълнител" #: ../quodlibet/browsers/albums/main.py:170 #: ../quodlibet/browsers/covergrid/main.py:56 ../quodlibet/qltk/prefs.py:54 msgid "_Date" msgstr "_Дата" #: ../quodlibet/browsers/albums/main.py:171 #: ../quodlibet/browsers/covergrid/main.py:57 ../quodlibet/qltk/prefs.py:53 #, fuzzy msgid "_Genre" msgstr "_Жанр" #: ../quodlibet/browsers/albums/main.py:172 #: ../quodlibet/browsers/covergrid/main.py:58 ../quodlibet/qltk/prefs.py:58 #: ../quodlibet/qltk/ratingsmenu.py:39 msgid "_Rating" msgstr "_Оценка" #: ../quodlibet/browsers/albums/main.py:178 #: ../quodlibet/browsers/covergrid/main.py:64 #, fuzzy msgid "Sort _by…" msgstr "Сортиране по дата" #: ../quodlibet/browsers/albums/main.py:199 #: ../quodlibet/browsers/covergrid/main.py:85 #: ../quodlibet/browsers/paned/prefs.py:166 #: ../quodlibet/browsers/playlists/main.py:629 #: ../quodlibet/qltk/exfalsowindow.py:109 ../quodlibet/qltk/pluginwin.py:341 #: ../quodlibet/qltk/quodlibetwindow.py:1016 #, fuzzy msgid "_Preferences" msgstr "Настройки" #: ../quodlibet/browsers/albums/main.py:361 #, fuzzy msgid "Album List" msgstr "Списък с албуми" #: ../quodlibet/browsers/albums/main.py:362 msgid "_Album List" msgstr "Спис_ък с албуми" #: ../quodlibet/browsers/albums/main.py:472 #: ../quodlibet/browsers/covergrid/main.py:279 #: ../quodlibet/browsers/covergrid/main.py:488 msgid "All Albums" msgstr "Всички албуми" #: ../quodlibet/browsers/albums/main.py:473 #: ../quodlibet/browsers/covergrid/main.py:280 #: ../quodlibet/browsers/covergrid/main.py:489 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d албум" msgstr[1] "%d албума" #: ../quodlibet/browsers/albums/main.py:650 #: ../quodlibet/browsers/covergrid/main.py:467 #, 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:381 ../quodlibet/util/collection.py:245 #, 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:379 ../quodlibet/util/collection.py:249 #, 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:120 #, fuzzy msgid "Options" msgstr "[Опции]" #: ../quodlibet/browsers/albums/prefs.py:74 #: ../quodlibet/browsers/covergrid/prefs.py:123 msgid "Album Display" msgstr "Показване на албум" #: ../quodlibet/browsers/albums/prefs.py:78 #: ../quodlibet/browsers/covergrid/prefs.py:127 #: ../quodlibet/browsers/media.py:39 #: ../quodlibet/browsers/playlists/prefs.py:56 #: ../quodlibet/ext/songsmenu/albumart.py:326 #: ../quodlibet/ext/songsmenu/duplicates.py:350 #: ../quodlibet/ext/songsmenu/filterall.py:48 #: ../quodlibet/qltk/bookmarks.py:101 ../quodlibet/qltk/cbes.py:93 #: ../quodlibet/qltk/data_editors.py:99 ../quodlibet/qltk/data_editors.py:324 #: ../quodlibet/qltk/exfalsowindow.py:297 ../quodlibet/qltk/pluginwin.py:79 #: ../quodlibet/qltk/pluginwin.py:427 ../quodlibet/qltk/prefs.py:707 #: ../quodlibet/qltk/textedit.py:164 ../quodlibet/update.py:148 msgid "_Close" msgstr "_Затваряне" #: ../quodlibet/browsers/audiofeeds.py:55 #: ../quodlibet/browsers/audiofeeds.py:67 #: ../quodlibet/browsers/audiofeeds.py:69 #: ../quodlibet/browsers/audiofeeds.py:159 #: ../quodlibet/browsers/paned/models.py:86 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:46 #: ../quodlibet/formats/_audio.py:495 ../quodlibet/order/__init__.py:27 #: ../quodlibet/qltk/information.py:240 ../quodlibet/qltk/information.py:247 #: ../quodlibet/qltk/information.py:273 ../quodlibet/qltk/wlw.py:70 msgid "Unknown" msgstr "Неизвестен" #: ../quodlibet/browsers/audiofeeds.py:246 msgid "New Feed" msgstr "Нова емисия" #: ../quodlibet/browsers/audiofeeds.py:247 msgid "Enter the location of an audio feed:" msgstr "Въведете местоположението на аудио емисия:" #: ../quodlibet/browsers/audiofeeds.py:248 #: ../quodlibet/browsers/collection/prefs.py:90 #: ../quodlibet/browsers/iradio.py:341 ../quodlibet/browsers/paned/prefs.py:78 #: ../quodlibet/browsers/playlists/menu.py:96 #: ../quodlibet/browsers/playlists/util.py:52 ../quodlibet/qltk/bookmarks.py:62 #: ../quodlibet/qltk/cbes.py:55 ../quodlibet/qltk/data_editors.py:311 #: ../quodlibet/qltk/edittags.py:288 ../quodlibet/qltk/edittags.py:488 #: ../quodlibet/qltk/quodlibetwindow.py:1354 ../quodlibet/qltk/scanbox.py:61 msgid "_Add" msgstr "Добавяне" #: ../quodlibet/browsers/audiofeeds.py:265 #, fuzzy msgid "Audio Feeds" msgstr "_Аудио емисии" #: ../quodlibet/browsers/audiofeeds.py:266 msgid "_Audio Feeds" msgstr "_Аудио емисии" #: ../quodlibet/browsers/audiofeeds.py:345 #: ../quodlibet/browsers/audiofeeds.py:350 #, fuzzy msgid "_Download…" msgstr "_Изтегляне…" #: ../quodlibet/browsers/audiofeeds.py:359 msgid "Download Files" msgstr "Изтегляне на файлове" #. Save button #: ../quodlibet/browsers/audiofeeds.py:359 #: ../quodlibet/browsers/audiofeeds.py:371 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:81 #: ../quodlibet/ext/songsmenu/albumart.py:322 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:355 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:278 #: ../quodlibet/ext/songsmenu/html.py:76 #: ../quodlibet/ext/songsmenu/lastfmsync.py:216 #: ../quodlibet/ext/songsmenu/playlist.py:51 #: ../quodlibet/ext/songsmenu/replaygain.py:365 #: ../quodlibet/ext/songsmenu/tapbpm.py:182 ../quodlibet/qltk/_editutils.py:39 #: ../quodlibet/qltk/lyrics.py:38 ../quodlibet/qltk/msg.py:52 #: ../quodlibet/qltk/renamefiles.py:168 ../quodlibet/qltk/tracknumbers.py:113 msgid "_Save" msgstr "_Запазване" #: ../quodlibet/browsers/audiofeeds.py:371 msgid "Download File" msgstr "Изтегляне на файл" #: ../quodlibet/browsers/audiofeeds.py:394 #: ../quodlibet/browsers/playlists/main.py:213 #: ../quodlibet/qltk/data_editors.py:96 msgid "_New" msgstr "_Нов" #: ../quodlibet/browsers/audiofeeds.py:454 #: ../quodlibet/browsers/audiofeeds.py:513 msgid "Unable to add feed" msgstr "Неуспех при добавяне на емисията" #: ../quodlibet/browsers/audiofeeds.py:455 #: ../quodlibet/browsers/audiofeeds.py:514 #, fuzzy, python-format msgid "" "%s could not be added. The server may be down, or the location may not be an " "audio feed." msgstr "" "<b>%s</b> не може да бъде добавена. Сървърът може да не е на линия или " "местоположението да не е аудио емисия." #. refresh button #: ../quodlibet/browsers/audiofeeds.py:462 ../quodlibet/browsers/media.py:217 #: ../quodlibet/browsers/media.py:386 ../quodlibet/qltk/filesel.py:259 #: ../quodlibet/qltk/pluginwin.py:413 #, fuzzy msgid "_Refresh" msgstr "_Опресняване" #: ../quodlibet/browsers/audiofeeds.py:463 #: ../quodlibet/browsers/playlists/main.py:457 #: ../quodlibet/browsers/playlists/util.py:43 ../quodlibet/qltk/delete.py:143 #: ../quodlibet/qltk/filesel.py:256 ../quodlibet/qltk/lyrics.py:39 #: ../quodlibet/qltk/maskedbox.py:28 ../quodlibet/qltk/songsmenu.py:392 #, fuzzy msgid "_Delete" msgstr "Из_триване" #: ../quodlibet/browsers/audiofeeds.py:530 msgid "" "The current audio backend does not support URLs, Audio Feeds browser " "disabled." msgstr "" #: ../quodlibet/browsers/_base.py:147 ../quodlibet/browsers/_base.py:150 msgid "Library Browser" msgstr "Разглеждане на фонотеката" #: ../quodlibet/browsers/_base.py:274 ../quodlibet/ext/songsmenu/refresh.py:30 #: ../quodlibet/qltk/exfalsowindow.py:241 ../quodlibet/qltk/information.py:542 #: ../quodlibet/qltk/maskedbox.py:68 ../quodlibet/util/collection.py:527 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d песен" msgstr[1] "%d песни" #: ../quodlibet/browsers/_base.py:402 ../quodlibet/browsers/_base.py:407 #: ../quodlibet/qltk/tagsfrompath.py:194 ../quodlibet/qltk/textedit.py:141 #: ../quodlibet/util/__init__.py:622 msgid "Invalid pattern" msgstr "Невалиден шаблон" #: ../quodlibet/browsers/collection/main.py:78 msgid "Album Collection" msgstr "" #: ../quodlibet/browsers/collection/main.py:79 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:66 #: ../quodlibet/browsers/paned/prefs.py:51 msgid "_Custom" msgstr "_Потребителски" #. Remove button #: ../quodlibet/browsers/collection/prefs.py:94 #: ../quodlibet/browsers/paned/prefs.py:82 #: ../quodlibet/browsers/playlists/menu.py:97 #: ../quodlibet/ext/playlist/remove_duplicates.py:60 #: ../quodlibet/qltk/bookmarks.py:97 ../quodlibet/qltk/bookmarks.py:127 #: ../quodlibet/qltk/cbes.py:82 ../quodlibet/qltk/cbes.py:89 #: ../quodlibet/qltk/data_editors.py:81 ../quodlibet/qltk/data_editors.py:94 #: ../quodlibet/qltk/data_editors.py:301 ../quodlibet/qltk/data_editors.py:314 #: ../quodlibet/qltk/data_editors.py:322 ../quodlibet/qltk/edittags.py:494 #: ../quodlibet/qltk/edittags.py:634 ../quodlibet/qltk/maskedbox.py:48 #: ../quodlibet/qltk/maskedbox.py:88 ../quodlibet/qltk/queue.py:350 #: ../quodlibet/qltk/scanbox.py:36 ../quodlibet/qltk/scanbox.py:63 #, fuzzy msgid "_Remove" msgstr "_Премахване" #: ../quodlibet/browsers/collection/prefs.py:122 #: ../quodlibet/ext/songsmenu/filterall.py:34 #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:92 #: ../quodlibet/qltk/edittags.py:431 msgid "Tag" msgstr "Етикет" #: ../quodlibet/browsers/collection/prefs.py:128 msgid "Merge" msgstr "Сливане" #: ../quodlibet/browsers/collection/prefs.py:188 #, fuzzy msgid "Album Collection Preferences" msgstr "Настройки на списъка с албуми" #: ../quodlibet/browsers/collection/prefs.py:195 #: ../quodlibet/browsers/paned/prefs.py:209 #: ../quodlibet/ext/songsmenu/editplaycount.py:45 #: ../quodlibet/ext/songsmenu/exact_rating.py:38 #: ../quodlibet/player/gstbe/prefs.py:40 ../quodlibet/qltk/prefs.py:127 #: ../quodlibet/qltk/textedit.py:65 msgid "_Apply" msgstr "_Прилагане" #: ../quodlibet/browsers/collection/prefs.py:198 #: ../quodlibet/browsers/paned/prefs.py:213 #: ../quodlibet/browsers/playlists/menu.py:95 #: ../quodlibet/browsers/playlists/util.py:42 #: ../quodlibet/errorreport/ui.py:108 #: ../quodlibet/ext/playlist/export_to_folder.py:37 #: ../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:44 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:281 #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:88 #: ../quodlibet/ext/songsmenu/importexport.py:35 #: ../quodlibet/ext/songsmenu/lastfmsync.py:215 #: ../quodlibet/ext/songsmenu/playlist.py:50 #: ../quodlibet/ext/songsmenu/replaygain.py:364 #: ../quodlibet/ext/songsmenu/tapbpm.py:181 ../quodlibet/plugins/playlist.py:39 #: ../quodlibet/qltk/chooser.py:184 ../quodlibet/qltk/chooser.py:205 #: ../quodlibet/qltk/chooser.py:229 ../quodlibet/qltk/chooser.py:253 #: ../quodlibet/qltk/delete.py:90 ../quodlibet/qltk/delete.py:133 #: ../quodlibet/qltk/edittags.py:287 ../quodlibet/qltk/_editutils.py:38 #: ../quodlibet/qltk/getstring.py:28 ../quodlibet/qltk/maskedbox.py:27 #: ../quodlibet/qltk/msg.py:54 ../quodlibet/qltk/msg.py:93 #: ../quodlibet/qltk/ratingsmenu.py:33 ../quodlibet/qltk/songsmenu.py:45 #: ../quodlibet/qltk/songsmenu.py:73 ../quodlibet/update.py:94 msgid "_Cancel" msgstr "_Отказ" #: ../quodlibet/browsers/covergrid/main.py:125 #, fuzzy msgid "Cover Grid" msgstr "Общ размер:" #: ../quodlibet/browsers/covergrid/main.py:126 #, 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:71 #, fuzzy msgid "Show \"All Albums\" Item" msgstr "Всички албуми" #: ../quodlibet/browsers/covergrid/prefs.py:78 msgid "Vertical Split" msgstr "" #: ../quodlibet/browsers/covergrid/prefs.py:110 #: ../quodlibet/browsers/covergrid/prefs.py:111 #, fuzzy msgid "Cover Magnification" msgstr "Няма нови станции" #: ../quodlibet/browsers/filesystem.py:40 #, fuzzy msgid "File System" msgstr "Ф_айлова система" #: ../quodlibet/browsers/filesystem.py:41 msgid "_File System" msgstr "Ф_айлова система" #: ../quodlibet/browsers/filesystem.py:113 ../quodlibet/browsers/media.py:491 #: ../quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "Неуспех при копиране на песните" #: ../quodlibet/browsers/filesystem.py:114 ../quodlibet/qltk/songlist.py:268 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "" "Избраните файлове не могат да бъдат копирани към други списъци с песни или " "към опашката." #: ../quodlibet/browsers/filesystem.py:189 msgid "_Add to Library" msgstr "Пре_зареждане на фонотеката" #: ../quodlibet/browsers/iradio.py:178 msgid "Unsupported file type" msgstr "Неподдържан вид файл" #: ../quodlibet/browsers/iradio.py:179 #, 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:219 ../quodlibet/browsers/iradio.py:232 #: ../quodlibet/browsers/iradio.py:810 msgid "Unable to add station" msgstr "Неуспех при добавяне на станцията" #: ../quodlibet/browsers/iradio.py:243 ../quodlibet/browsers/iradio.py:471 #, fuzzy msgid "Internet Radio" msgstr "_Радио по Интернет" #: ../quodlibet/browsers/iradio.py:243 #, fuzzy msgid "Downloading station list" msgstr "Изтегляне на файлове" #: ../quodlibet/browsers/iradio.py:339 msgid "New Station" msgstr "Нова станция" #: ../quodlibet/browsers/iradio.py:340 msgid "Enter the location of an Internet radio station:" msgstr "Въведете местоположението на радиостанция в Интернет:" #: ../quodlibet/browsers/iradio.py:358 msgid "Electronic" msgstr "" #: ../quodlibet/browsers/iradio.py:361 msgid "Hip Hop / Rap" msgstr "" #: ../quodlibet/browsers/iradio.py:362 msgid "Oldies" msgstr "" #: ../quodlibet/browsers/iradio.py:363 msgid "R&B" msgstr "" #: ../quodlibet/browsers/iradio.py:364 msgid "Japanese" msgstr "" #: ../quodlibet/browsers/iradio.py:365 msgid "Indian" msgstr "" #: ../quodlibet/browsers/iradio.py:367 msgid "Religious" msgstr "" #: ../quodlibet/browsers/iradio.py:369 msgid "Charts" msgstr "" #: ../quodlibet/browsers/iradio.py:370 msgid "Turkish" msgstr "" #: ../quodlibet/browsers/iradio.py:371 msgid "Reggae / Dancehall" msgstr "" #: ../quodlibet/browsers/iradio.py:372 #, fuzzy msgid "Latin" msgstr "оценка" #: ../quodlibet/browsers/iradio.py:373 msgid "College Radio" msgstr "" #: ../quodlibet/browsers/iradio.py:374 msgid "Talk / News" msgstr "" #: ../quodlibet/browsers/iradio.py:375 msgid "Ambient" msgstr "" #: ../quodlibet/browsers/iradio.py:376 msgid "Jazz" msgstr "" #: ../quodlibet/browsers/iradio.py:377 ../quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "" #: ../quodlibet/browsers/iradio.py:378 ../quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "" #: ../quodlibet/browsers/iradio.py:379 msgid "Alternative" msgstr "" #: ../quodlibet/browsers/iradio.py:380 msgid "Metal" msgstr "" #: ../quodlibet/browsers/iradio.py:381 msgid "Country" msgstr "" #: ../quodlibet/browsers/iradio.py:382 msgid "News" msgstr "" #: ../quodlibet/browsers/iradio.py:383 msgid "Schlager" msgstr "" #: ../quodlibet/browsers/iradio.py:384 msgid "Funk" msgstr "" #: ../quodlibet/browsers/iradio.py:385 msgid "Indie" msgstr "" #: ../quodlibet/browsers/iradio.py:386 msgid "Blues" msgstr "" #: ../quodlibet/browsers/iradio.py:387 msgid "Soul" msgstr "" #: ../quodlibet/browsers/iradio.py:388 msgid "Lounge" msgstr "" #: ../quodlibet/browsers/iradio.py:389 msgid "Punk" msgstr "" #: ../quodlibet/browsers/iradio.py:390 msgid "Reggaeton" msgstr "" #: ../quodlibet/browsers/iradio.py:392 msgid "Slavic" msgstr "" #: ../quodlibet/browsers/iradio.py:394 msgid "Greek" msgstr "" #: ../quodlibet/browsers/iradio.py:395 msgid "Gothic" msgstr "" #: ../quodlibet/browsers/iradio.py:396 ../quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "" #: ../quodlibet/browsers/iradio.py:449 msgid "Would you like to load a list of popular radio stations?" msgstr "" #: ../quodlibet/browsers/iradio.py:455 #, fuzzy msgid "_Load Stations" msgstr "_Нова станция" #: ../quodlibet/browsers/iradio.py:472 msgid "_Internet Radio" msgstr "_Радио по Интернет" #: ../quodlibet/browsers/iradio.py:538 #, fuzzy msgid "_New Station…" msgstr "Нова станция" #: ../quodlibet/browsers/iradio.py:541 #, fuzzy msgid "_Update Stations" msgstr "_Нова станция" #: ../quodlibet/browsers/iradio.py:568 #, fuzzy msgid "All Stations" msgstr "Нова станция" #. TODO: support for ~#rating=!None etc (#1940) #: ../quodlibet/browsers/iradio.py:572 #: ../quodlibet/browsers/soundcloud/main.py:64 msgid "Favorites" msgstr "" #: ../quodlibet/browsers/iradio.py:580 msgid "No Category" msgstr "" #: ../quodlibet/browsers/iradio.py:802 msgid "No stations found" msgstr "Няма открити станции." #: ../quodlibet/browsers/iradio.py:803 #, python-format msgid "No Internet radio stations were found at %s." msgstr "Няма открити Интернет радиостанции на %s." #: ../quodlibet/browsers/iradio.py:811 msgid "All stations listed are already in your library." msgstr "Всички изписани станции са вече във фонотеката Ви." #: ../quodlibet/browsers/iradio.py:828 #, fuzzy msgid "Add to Favorites" msgstr "_Добавяне към списък" #: ../quodlibet/browsers/iradio.py:832 #, fuzzy msgid "Remove from Favorites" msgstr "Премахване от фонотеката" #: ../quodlibet/browsers/iradio.py:932 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "%(count)d станция" msgstr[1] "%(count)d станции" #: ../quodlibet/browsers/media.py:36 #, fuzzy msgid "Device Properties" msgstr "Информация" #: ../quodlibet/browsers/media.py:52 msgid "Device:" msgstr "" #: ../quodlibet/browsers/media.py:54 msgid "Not mounted" msgstr "" #: ../quodlibet/browsers/media.py:55 #, fuzzy msgid "Mount point:" msgstr "точка на монтиране" #: ../quodlibet/browsers/media.py:61 ../quodlibet/qltk/cbes.py:40 msgid "_Name:" msgstr "_Име:" #: ../quodlibet/browsers/media.py:135 #, fuzzy msgid "Media Devices" msgstr "Аудио устройство: %s" #: ../quodlibet/browsers/media.py:136 #, fuzzy msgid "_Media Devices" msgstr "Аудио устройство: %s" #. eject button #: ../quodlibet/browsers/media.py:224 ../quodlibet/browsers/media.py:378 #, fuzzy msgid "_Eject" msgstr "_Избор" #: ../quodlibet/browsers/media.py:360 #, fuzzy msgid "_Properties" msgstr "Информация" #: ../quodlibet/browsers/media.py:365 #: ../quodlibet/browsers/playlists/main.py:464 msgid "_Rename" msgstr "_Преименуване" #: ../quodlibet/browsers/media.py:461 #, python-format msgid "%(used-size)s used, %(free-size)s available" msgstr "" #: ../quodlibet/browsers/media.py:479 #, fuzzy, python-format msgid "%s is not connected." msgstr "<b>%s</b> не е валидно местоположение." #: ../quodlibet/browsers/media.py:499 #, fuzzy, python-format msgid "Copying %(song)s" msgstr "Пропадна изтриването на <b>%s</b>." #: ../quodlibet/browsers/media.py:513 ../quodlibet/browsers/media.py:529 #, fuzzy msgid "Unable to copy song" msgstr "Неуспех при копиране на песните" #: ../quodlibet/browsers/media.py:514 msgid "There is not enough free space for this song." msgstr "" #: ../quodlibet/browsers/media.py:526 #, fuzzy, python-format msgid "%s could not be copied." msgstr "<b>%s</b> не е валидно местоположение." #: ../quodlibet/browsers/media.py:545 #, fuzzy msgid "Unable to delete songs" msgstr "Неуспех при добавяне на песните" #: ../quodlibet/browsers/media.py:557 #, fuzzy, python-format msgid "Deleting %(song)s" msgstr "Пропадна изтриването на <b>%s</b>." #: ../quodlibet/browsers/media.py:575 #, fuzzy, python-format msgid "%s could not be deleted." msgstr "<b>%s</b> не е валидно местоположение." #: ../quodlibet/browsers/media.py:579 #, fuzzy msgid "Unable to delete song" msgstr "Неуспех при редактиране на песента" #: ../quodlibet/browsers/media.py:594 #, fuzzy, python-format msgid "Ejecting %s failed." msgstr "Пропадна изтриването на <b>%s</b>." #: ../quodlibet/browsers/media.py:597 #, fuzzy msgid "Unable to eject device" msgstr "Неуспех при изтриването на файл" #: ../quodlibet/browsers/media.py:603 msgid "No device backend, Media Devices browser disabled." msgstr "" #: ../quodlibet/browsers/paned/main.py:40 ../quodlibet/qltk/shortcuts.py:44 #, fuzzy msgid "Paned Browser" msgstr "_Изглед на панели" #: ../quodlibet/browsers/paned/main.py:41 msgid "_Paned Browser" msgstr "_Изглед на панели" #: ../quodlibet/browsers/paned/main.py:90 msgid "Select _All" msgstr "_Избор на всички" #: ../quodlibet/browsers/paned/models.py:104 ../quodlibet/qltk/pluginwin.py:122 #: ../quodlibet/qltk/pluginwin.py:164 msgid "All" msgstr "Всички" #: ../quodlibet/browsers/paned/prefs.py:67 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "<tt>%s</tt>" msgstr "" #: ../quodlibet/browsers/paned/prefs.py:162 msgid "_Wide Mode" msgstr "" #: ../quodlibet/browsers/paned/prefs.py:197 msgid "Paned Browser Preferences" msgstr "Настройки на панели" #: ../quodlibet/browsers/paned/prefs.py:204 msgid "Equal pane width" msgstr "" #: ../quodlibet/browsers/playlists/main.py:48 #: ../quodlibet/browsers/playlists/main.py:575 #: ../quodlibet/qltk/pluginwin.py:168 #, fuzzy msgid "Playlists" msgstr "Сп_исъци с песни" #: ../quodlibet/browsers/playlists/main.py:49 msgid "_Playlists" msgstr "Сп_исъци с песни" #: ../quodlibet/browsers/playlists/main.py:152 msgid "_Remove from Playlist" msgstr "Премахване от фонотеката" #: ../quodlibet/browsers/playlists/main.py:215 #: ../quodlibet/browsers/playlists/main.py:576 msgid "_Import" msgstr "_Внасяне" #: ../quodlibet/browsers/playlists/main.py:391 #: ../quodlibet/browsers/playlists/util.py:50 #: ../quodlibet/util/collection.py:570 msgid "New Playlist" msgstr "Нов списък с песни" #: ../quodlibet/browsers/playlists/main.py:413 msgid "Unable to import playlist" msgstr "Неуспех при внасяне на списъка" #: ../quodlibet/browsers/playlists/main.py:414 msgid "Quod Libet can only import playlists in the M3U and PLS formats." msgstr "Quod Libet може да внася само списъци с песни с формат M3U или PLS." #: ../quodlibet/browsers/playlists/main.py:565 msgid "Unable to rename playlist" msgstr "Неуспех при преименуване на списъка." #: ../quodlibet/browsers/playlists/main.py:576 msgid "Import Playlist" msgstr "Внасяне на списък с песни" #: ../quodlibet/browsers/playlists/menu.py:25 #, fuzzy msgid "_New Playlist…" msgstr "_Нов списък с песни" #: ../quodlibet/browsers/playlists/menu.py:86 #, 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:90 #, 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:33 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "" #: ../quodlibet/browsers/playlists/util.py:35 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" #: ../quodlibet/browsers/playlists/util.py:51 #, fuzzy msgid "Enter a name for the new playlist:" msgstr "Въведете име за новата папка:" #: ../quodlibet/browsers/playlists/util.py:102 #, fuzzy, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" "Внасяне на списък с песни.\n" "\n" "Добавени са %d/%d песни." #: ../quodlibet/browsers/search.py:33 msgid "_Limit Results" msgstr "_Ограничаване на резултатите" #: ../quodlibet/browsers/search.py:48 msgid "Search Library" msgstr "Търсене във фонотеката" #: ../quodlibet/browsers/search.py:49 msgid "_Search Library" msgstr "Т_ърсене във фонотеката" #: ../quodlibet/browsers/soundcloud/main.py:38 #, fuzzy msgid "Soundcloud Browser" msgstr "_Изглед на панели" #: ../quodlibet/browsers/soundcloud/main.py:39 msgid "Sound_cloud" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:59 #: ../quodlibet/qltk/searchbar.py:73 msgid "Search" msgstr "Търсене" #: ../quodlibet/browsers/soundcloud/main.py:136 #, python-format msgid "Go to %s" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:380 #, fuzzy msgid "Connected" msgstr "местонахождение" #: ../quodlibet/browsers/soundcloud/main.py:381 #, python-format msgid "Quod Libet is now connected, <b>%s</b>!" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:393 #, python-format msgid "Log out of %s" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:395 msgid "Enter code…" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:396 #, python-format msgid "Log in to %s" msgstr "" #: ../quodlibet/browsers/soundcloud/util.py:86 msgid "Soundcloud authorisation" msgstr "" #: ../quodlibet/browsers/soundcloud/util.py:87 msgid "Enter Soundcloud auth code:" msgstr "" #: ../quodlibet/cli.py:50 #, fuzzy msgid "Quod Libet is not running (add '--run' to start it)" msgstr "Quod Libet не е стартиран." #: ../quodlibet/cli.py:85 msgid "a music library and player" msgstr "фонотека и програма за слушане на музика" #: ../quodlibet/cli.py:86 #, fuzzy msgid "[option]" msgstr "[опции]" #: ../quodlibet/cli.py:88 msgid "Print the playing song and exit" msgstr "Показване на изпълняващата се песен и излизане" #: ../quodlibet/cli.py:89 msgid "Begin playing immediately" msgstr "Започване на изпълнението незабавно" #: ../quodlibet/cli.py:90 msgid "Don't show any windows on start" msgstr "" #: ../quodlibet/cli.py:93 msgid "Jump to next song" msgstr "Отиване на следващата песен" #: ../quodlibet/cli.py:95 msgid "Jump to previous song or restart if near the beginning" msgstr "" #: ../quodlibet/cli.py:96 msgid "Jump to previous song" msgstr "Отиване на предишната песен" #: ../quodlibet/cli.py:97 msgid "Start playback" msgstr "Започване на изпълнението" #: ../quodlibet/cli.py:98 msgid "Pause playback" msgstr "Паузиране на изпълнението" #: ../quodlibet/cli.py:99 msgid "Toggle play/pause mode" msgstr "Сменяне между Слушане и Пауза" #: ../quodlibet/cli.py:100 #, fuzzy msgid "Stop playback" msgstr "Започване на изпълнението" #: ../quodlibet/cli.py:101 msgid "Turn up volume" msgstr "Увеличаване силата на звука" #: ../quodlibet/cli.py:102 msgid "Turn down volume" msgstr "Намаляване силата на звука" #: ../quodlibet/cli.py:103 msgid "Print player status" msgstr "Показване статуса на изпълнението" #: ../quodlibet/cli.py:104 msgid "Hide main window" msgstr "Скриване на главния прозорец" #: ../quodlibet/cli.py:105 msgid "Show main window" msgstr "Показване на главния прозорец" #: ../quodlibet/cli.py:106 msgid "Toggle main window visibility" msgstr "Превключване видимостта на главния прозорец" #: ../quodlibet/cli.py:107 msgid "Focus the running player" msgstr "Фокусиране на програмата" #: ../quodlibet/cli.py:108 msgid "Remove active browser filters" msgstr "" #: ../quodlibet/cli.py:109 #, fuzzy msgid "Refresh and rescan library" msgstr "Опресн_яване на фонотеката" #: ../quodlibet/cli.py:110 #, fuzzy msgid "List available browsers" msgstr "_Изключване на разглеждането" #: ../quodlibet/cli.py:111 msgid "Print the current playlist" msgstr "Печат на текущия списък с песни" #: ../quodlibet/cli.py:112 msgid "Print the contents of the queue" msgstr "Показване съдържанието на опашката" #: ../quodlibet/cli.py:113 #, fuzzy msgid "Print the active text query" msgstr "Показване съдържанието на опашката" #: ../quodlibet/cli.py:114 msgid "Start without plugins" msgstr "" #: ../quodlibet/cli.py:115 #, fuzzy msgid "Start Quod Libet if it isn't running" msgstr "Quod Libet не е стартиран." #: ../quodlibet/cli.py:116 msgid "Exit Quod Libet" msgstr "Затваряне на Quod Libet" #: ../quodlibet/cli.py:121 msgid "Seek within the playing song" msgstr "Прескачане в слушаната в момента песен" #: ../quodlibet/cli.py:121 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: ../quodlibet/cli.py:122 #, fuzzy msgid "Set or toggle shuffle mode" msgstr "Сменяне между Слушане и Пауза" #: ../quodlibet/cli.py:123 msgid "Turn repeat off, on, or toggle it" msgstr "Включване на повтарянето, изключване или превключването му." #: ../quodlibet/cli.py:124 msgid "Set the volume" msgstr "Настройване силата на звука" #: ../quodlibet/cli.py:125 msgid "Search your audio library" msgstr "Търсене из фонотеката" #: ../quodlibet/cli.py:125 ../quodlibet/cli.py:137 ../quodlibet/cli.py:141 #: ../quodlibet/cli.py:143 msgid "query" msgstr "запитване" #: ../quodlibet/cli.py:126 msgid "Play a file" msgstr "Слушане на файл" #: ../quodlibet/cli.py:126 ../quodlibet/cli.py:137 ../quodlibet/cli.py:143 #, fuzzy msgctxt "command" msgid "filename" msgstr "файлово име" #: ../quodlibet/cli.py:127 msgid "Rate the playing song" msgstr "Оценка на текущата песен" #: ../quodlibet/cli.py:128 msgid "Set the current browser" msgstr "" #: ../quodlibet/cli.py:129 #, fuzzy msgid "Stop after the playing song" msgstr "Оценка на текущата песен" #: ../quodlibet/cli.py:130 msgid "Open a new browser" msgstr "Отваряне на нов браузър" #: ../quodlibet/cli.py:131 msgid "Show or hide the queue" msgstr "Показване или скриване на опашката" #: ../quodlibet/cli.py:133 #, fuzzy msgid "Show or hide the main song list (deprecated)" msgstr "Показване или скриване на главния изглед с песни" #: ../quodlibet/cli.py:134 msgid "Filter on a random value" msgstr "Филтриране по произволна стойност" #: ../quodlibet/cli.py:134 #, fuzzy msgctxt "command" msgid "tag" msgstr "етикет" #: ../quodlibet/cli.py:135 msgid "Filter on a tag value" msgstr "Филтриране по стойност на етикета" #: ../quodlibet/cli.py:135 msgid "tag=value" msgstr "етикет=стойност" #: ../quodlibet/cli.py:136 msgid "Enqueue a file or query" msgstr "Поставяне на файл или запитване на опашката" #: ../quodlibet/cli.py:138 msgid "Enqueue comma-separated files" msgstr "" #: ../quodlibet/cli.py:139 ../quodlibet/util/tags.py:147 msgid "filename" msgstr "файлово име" #: ../quodlibet/cli.py:140 msgid "Print filenames of results of query to stdout" msgstr "" #: ../quodlibet/cli.py:142 #, fuzzy msgid "Unqueue a file or query" msgstr "Поставяне на файл или запитване на опашката" #: ../quodlibet/cli.py:203 #, fuzzy, python-format msgid "Invalid argument for '%s'." msgstr "E: Невалиден аргумент за \"%s\"." #: ../quodlibet/cli.py:204 ../quodlibet/util/__init__.py:190 #, fuzzy, python-format msgid "Try %s --help." msgstr "E: Опитайте %s --help." #: ../quodlibet/devices/_base.py:65 #, fuzzy msgid "Unknown Device" msgstr "непознат" #: ../quodlibet/devices/__init__.py:32 #, python-format msgid "Could not import %s, which is needed for device support." msgstr "" #: ../quodlibet/devices/__init__.py:153 #, fuzzy, python-format msgid "%r is not a supported device." msgstr "E: \"%s\" не е уникална представка." #: ../quodlibet/devices/__init__.py:245 ../quodlibet/devices/__init__.py:251 #, python-format msgid "Could not find '%s'." msgstr "" #: ../quodlibet/devices/__init__.py:450 #, fuzzy msgid "Initializing device backend." msgstr "Невалидна стойност" #: ../quodlibet/devices/__init__.py:451 #, python-format msgid "Trying '%s'" msgstr "" #: ../quodlibet/devices/__init__.py:461 msgid "Couldn't connect to a device backend." msgstr "" #: ../quodlibet/devices/__init__.py:463 msgid "Device backend initialized." msgstr "" #: ../quodlibet/devices/storage.py:57 #, fuzzy msgid "_Filename pattern:" msgstr "_Файлово име" #: ../quodlibet/devices/storage.py:61 #, fuzzy msgid "Copy _album covers" msgstr "Показване на _обложките" #: ../quodlibet/devices/storage.py:65 msgid "_Remove unused covers and directories" msgstr "" #: ../quodlibet/errorreport/ui.py:60 msgid "An Error Occurred" msgstr "" #: ../quodlibet/errorreport/ui.py:62 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:72 msgid "File Bug Report" msgstr "" #: ../quodlibet/errorreport/ui.py:74 ../quodlibet/errorreport/ui.py:90 msgid "Submit Error Report" msgstr "" #: ../quodlibet/errorreport/ui.py:75 msgid "Quit Program" msgstr "" #: ../quodlibet/errorreport/ui.py:76 #, fuzzy msgid "Ignore Error" msgstr "Показване на _грешки" #: ../quodlibet/errorreport/ui.py:80 msgid "Error details:" msgstr "" #: ../quodlibet/errorreport/ui.py:92 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:100 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "" #: ../quodlibet/errorreport/ui.py:109 msgid "_Send" msgstr "" #: ../quodlibet/errorreport/ui.py:115 #, fuzzy msgid "Short description…" msgstr "описание" #: ../quodlibet/errorreport/ui.py:118 msgid "Data to be sent:" msgstr "" #: ../quodlibet/exfalso.py:34 msgid "an audio tag editor" msgstr "редактор на музикални етикети" #: ../quodlibet/exfalso.py:34 ../quodlibet/util/tags.py:148 msgid "directory" msgstr "папка" #: ../quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "" #: ../quodlibet/ext/covers/artwork_url.py:20 msgid "" "Downloads covers linked to by the artwork_url tag.This works with the " "Soundcloud browser." msgstr "" #: ../quodlibet/ext/covers/discogs.py:25 #, fuzzy msgid "Discogs Cover Source" msgstr "ID в MusicBrainz на песента" #: ../quodlibet/ext/covers/discogs.py:26 msgid "Downloads covers from Discogs." msgstr "" #: ../quodlibet/ext/covers/lastfm.py:22 msgid "Last.fm Cover Source" msgstr "" #: ../quodlibet/ext/covers/lastfm.py:23 msgid "Downloads covers from Last.fm's cover art archive." msgstr "" #: ../quodlibet/ext/covers/musicbrainz.py:19 #, fuzzy msgid "MusicBrainz Cover Source" msgstr "ID в MusicBrainz на песента" #: ../quodlibet/ext/covers/musicbrainz.py:20 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:25 msgid "Kana/Kanji Simple Inverter" msgstr "" #: ../quodlibet/ext/editing/kakasi.py:26 msgid "Converts kana/kanji to romaji before renaming." msgstr "" #: ../quodlibet/ext/editing/kakasi.py:35 msgid "Romanize _Japanese text" msgstr "" #: ../quodlibet/ext/editing/kakasi.py:63 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:19 msgid "" "Allows arbitrary regex substitutions (s///) 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:69 #, fuzzy msgid "Advanced Preferences" msgstr "Настройки на панели" #: ../quodlibet/ext/events/advanced_preferences.py:70 msgid "Allow editing of advanced config settings." msgstr "" #: ../quodlibet/ext/events/advanced_preferences.py:162 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:153 msgid "Top of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:154 msgid "Middle of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:155 msgid "Bottom of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:158 msgid "_Position:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:171 #, fuzzy msgid "_Cover size:" msgstr "Общ размер:" #: ../quodlibet/ext/events/animosd/prefs.py:177 #: ../quodlibet/ext/events/lyricswindow.py:334 ../quodlibet/qltk/prefs.py:266 #, fuzzy msgid "Display" msgstr "Редактиране на показваното" #: ../quodlibet/ext/events/animosd/prefs.py:190 msgid "_Font:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:195 msgid "Left" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:196 msgid "Center" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:197 #, fuzzy msgid "Right" msgstr "_Тежест" #: ../quodlibet/ext/events/animosd/prefs.py:200 msgid "_Align text:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:206 msgid "Text" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:217 msgid "_Text:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:227 msgid "_Fill:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:232 #: ../quodlibet/ext/events/synchronizedlyrics.py:63 msgid "Colors" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:240 msgid "_Shadows" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:241 msgid "_Outline" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:242 msgid "Rou_nded Corners" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:258 msgid "_Delay:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:264 #: ../quodlibet/qltk/pluginwin.py:172 msgid "Effects" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:270 #, fuzzy msgid "Ed_it Display Pattern…" msgstr "Редактиране на показваното" #: ../quodlibet/ext/events/animosd/prefs.py:274 #: ../quodlibet/ext/events/trayicon/prefs.py:78 #, fuzzy msgid "Preview" msgstr "Пре_глед" #: ../quodlibet/ext/events/auto_library_update.py:136 msgid "Automatic Library Update" msgstr "" #: ../quodlibet/ext/events/auto_library_update.py:137 #, python-format msgid "Keeps your library up to date with inotify. Requires %s." 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 by Brian Nelson." 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/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:97 msgid "Equalizer" msgstr "" #: ../quodlibet/ext/events/equalizer.py:98 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:132 msgid "The current backend does not support equalization." msgstr "" #: ../quodlibet/ext/events/equalizer.py:138 #, python-format msgid "%.1f kHz" msgstr "" #: ../quodlibet/ext/events/equalizer.py:139 #: ../quodlibet/ext/gstreamer/crossfeed.py:93 #: ../quodlibet/ext/gstreamer/karaoke.py:95 #, python-format msgid "%d Hz" msgstr "" #: ../quodlibet/ext/events/equalizer.py:173 #: ../quodlibet/ext/gstreamer/crossfeed.py:112 #, fuzzy, python-format msgid "%.1f dB" msgstr "%d секунда" #: ../quodlibet/ext/events/equalizer.py:192 #: ../quodlibet/ext/gstreamer/crossfeed.py:31 #, fuzzy msgid "Custom" msgstr "_Лично" #: ../quodlibet/ext/events/equalizer.py:199 #, fuzzy msgid "_Clear" msgstr "Грешки на приставките" #. Translators: statuses relating to Instant Messenger apps #: ../quodlibet/ext/events/gajim_status.py:27 msgid "online" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:28 msgid "offline" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:29 msgid "chat" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:30 msgid "away" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:31 msgid "xa" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:32 msgid "invisible" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:37 msgid "Gajim Status Message" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:38 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:45 #: ../quodlibet/ext/events/telepathy_status.py:69 msgid "paused" 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:160 msgid "Add '[paused]'" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:163 msgid "If checked, '[paused]' will be added to status message on pause." msgstr "" #: ../quodlibet/ext/events/gajim_status.py:187 msgid "Statuses for which message will be changed" msgstr "" #: ../quodlibet/ext/events/headphonemon.py:156 msgid "Pause on Headphone Unplug" msgstr "" #: ../quodlibet/ext/events/headphonemon.py:157 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" #: ../quodlibet/ext/events/inhibit.py:41 msgid "Inhibit Screensaver" msgstr "" #: ../quodlibet/ext/events/inhibit.py:42 msgid "Prevents the GNOME screensaver from activating while a song is playing." msgstr "" #: ../quodlibet/ext/events/inhibit.py:51 #, fuzzy msgid "Music is playing" msgstr "Слушане на музика" #: ../quodlibet/ext/events/iradiolog.py:16 #, fuzzy msgid "Internet Radio Log" msgstr "_Радио по Интернет" #: ../quodlibet/ext/events/iradiolog.py:17 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" #: ../quodlibet/ext/events/jep118.py:29 msgid "JEP-118" msgstr "" #: ../quodlibet/ext/events/jep118.py:30 msgid "Outputs a Jabber User Tunes file to ~/.quodlibet/jabber." 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 msgid "A restart is required for any changes to take effect" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:199 #, fuzzy msgid "No active song" msgstr "Не може да се запази песента" #: ../quodlibet/ext/events/lyricswindow.py:215 #, fuzzy msgid "No lyrics found" msgstr "Няма открити приставки." #: ../quodlibet/ext/events/lyricswindow.py:227 #, fuzzy msgid "Lyrics:" msgstr "Текст на песен" #: ../quodlibet/ext/events/lyricswindow.py:284 msgid "_Zoom level:" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:302 msgid "URL:" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:307 msgid "Revert to default" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:322 msgid "Search via above URL if the lyrics couldn't be found in LyricsWikia." msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:339 #, fuzzy msgid "Alternate search" msgstr "Изчистване на търсенето" #: ../quodlibet/ext/events/lyricswindow.py:347 #, fuzzy msgid "Lyrics Window" msgstr "Текст на песен" #: ../quodlibet/ext/events/lyricswindow.py:348 #, fuzzy msgid "Shows a window containing lyrics of the playing song." msgstr "Преглед и редакция на етикетите на вървящата песен" #: ../quodlibet/ext/events/mediaserver.py:38 msgid "UPnP AV Media Server" msgstr "" #: ../quodlibet/ext/events/mediaserver.py:39 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." 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:39 msgid "" "Allows control of Quod Libet using the MPRIS 1.0/2.0 D-Bus Interface " "Specification." msgstr "" #: ../quodlibet/ext/events/mpris/__init__.py:45 #: ../quodlibet/ext/events/trayicon/prefs.py:30 #, fuzzy msgid "Hide main window on close" msgstr "Скриване на главния прозорец" #: ../quodlibet/ext/events/mpris/__init__.py:48 #: ../quodlibet/ext/events/themeswitcher.py:84 #: ../quodlibet/ext/gstreamer/compressor.py:99 #: ../quodlibet/ext/gstreamer/crossfeed.py:136 #: ../quodlibet/ext/gstreamer/karaoke.py:99 #: ../quodlibet/ext/gstreamer/pitch.py:83 ../quodlibet/qltk/prefs.py:688 #, fuzzy msgid "Preferences" msgstr "Настройки" #: ../quodlibet/ext/events/mqtt.py:50 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/mqtt.py:56 msgid "MQTT Publisher" msgstr "" #: ../quodlibet/ext/events/mqtt.py:57 msgid "Publishes status messages to an MQTT topic." msgstr "" #: ../quodlibet/ext/events/mqtt.py:122 msgid "Broker hostname" msgstr "" #: ../quodlibet/ext/events/mqtt.py:122 msgid "broker hostname / IP" msgstr "" #: ../quodlibet/ext/events/mqtt.py:124 msgid "Broker port" msgstr "" #: ../quodlibet/ext/events/mqtt.py:124 msgid "broker port" msgstr "" #: ../quodlibet/ext/events/mqtt.py:126 msgid "Topic" msgstr "" #: ../quodlibet/ext/events/mqtt.py:128 #, fuzzy msgid "Playing Pattern" msgstr "шаблон" #: ../quodlibet/ext/events/mqtt.py:130 msgid "Status text when a song is started." msgstr "" #: ../quodlibet/ext/events/mqtt.py:132 #, fuzzy msgid "Paused Pattern" msgstr "шаблон" #: ../quodlibet/ext/events/mqtt.py:134 msgid "Text when a song is paused." msgstr "" #: ../quodlibet/ext/events/mqtt.py:136 #, fuzzy msgid "No-song Text" msgstr "%d песен" #: ../quodlibet/ext/events/mqtt.py:138 msgid "Plain text for when there is no current song" msgstr "" #: ../quodlibet/ext/events/mqtt.py:149 #, fuzzy msgid "MQTT Configuration" msgstr "Информация" #: ../quodlibet/ext/events/mqtt.py:153 #, fuzzy msgid "Status Text" msgstr "шаблон" #: ../quodlibet/ext/events/mqtt.py:185 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "" #: ../quodlibet/ext/events/mqtt.py:189 #, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s" msgstr "" #: ../quodlibet/ext/events/mqtt.py:192 #, fuzzy msgid "Connection error" msgstr "местонахождение" #: ../quodlibet/ext/events/notify.py:80 msgid "Notification text" msgstr "" #: ../quodlibet/ext/events/notify.py:88 #, fuzzy msgid "_Title:" msgstr "Заглавие" #: ../quodlibet/ext/events/notify.py:99 ../quodlibet/ext/events/notify.py:128 msgid "Revert to default pattern" msgstr "" #: ../quodlibet/ext/events/notify.py:118 msgid "_Body:" msgstr "" #: ../quodlibet/ext/events/notify.py:138 msgid "_Show notification" msgstr "" #: ../quodlibet/ext/events/notify.py:156 #, fuzzy msgid "Show notifications" msgstr "Няма нови станции" #: ../quodlibet/ext/events/notify.py:162 msgid "Only on <i>_manual</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:170 msgid "Only on <i>_automatic</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:178 msgid "On <i>a_ll</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:196 msgid "Only when the main window is not _focused" msgstr "" #: ../quodlibet/ext/events/notify.py:204 msgid "Show \"_Next\" button" msgstr "" #: ../quodlibet/ext/events/notify.py:236 msgid "Connection Error" msgstr "" #: ../quodlibet/ext/events/notify.py:237 ../quodlibet/ext/events/notify.py:391 #: ../quodlibet/ext/events/notify.py:433 msgid "Couldn't connect to notification daemon." msgstr "" #: ../quodlibet/ext/events/notify.py:251 #, fuzzy msgid "Song Notifications" msgstr "Няма нови станции" #: ../quodlibet/ext/events/notify.py:252 msgid "Displays a notification when the song changes." msgstr "" #: ../quodlibet/ext/events/notify.py:415 ../quodlibet/qltk/unity.py:65 msgid "Next" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:178 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:254 #, python-format msgid "Could not contact service '%s'." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:260 msgid "Authentication failed: invalid URL." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:277 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:282 msgid "Client is banned. Contact the author." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:286 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:351 msgid "AudioScrobbler Submission" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:352 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:450 msgid "Authentication successful." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:462 msgid "_Service:" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:462 msgid "_URL:" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:462 #, fuzzy msgid "User_name:" msgstr "_Име:" #: ../quodlibet/ext/events/qlscrobbler.py:463 msgid "_Password:" msgstr "" #. Translators: Other service #: ../quodlibet/ext/events/qlscrobbler.py:479 #, fuzzy msgid "Other…" msgstr "_Други:" #. verify data #: ../quodlibet/ext/events/qlscrobbler.py:517 msgid "_Verify account data" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:522 #: ../quodlibet/ext/songsmenu/lastfmsync.py:304 msgid "Account" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:530 #, fuzzy msgid "_Artist pattern:" msgstr "_Артист" #: ../quodlibet/ext/events/qlscrobbler.py:530 #, fuzzy msgid "_Title pattern:" msgstr "_Файлово име" #: ../quodlibet/ext/events/qlscrobbler.py:531 msgid "Exclude _filter:" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:549 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:559 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:568 msgid "Songs matching this filter will not be submitted." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:576 msgid "_Offline mode (don't submit anything)" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:580 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:27 #, fuzzy msgid "Random Album Playback" msgstr "Произволен _албум" #: ../quodlibet/ext/events/randomalbum.py:28 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:38 msgid "Rated higher" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:39 msgid "Played more often" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:40 msgid "Skipped more often" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:41 msgid "Played more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:42 msgid "Started more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:43 msgid "Added more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:44 #, fuzzy msgid "Longer albums" msgstr "албуми" #: ../quodlibet/ext/events/randomalbum.py:83 msgid "seconds before starting next album" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:87 #, fuzzy msgid "Weights" msgstr "_Тежест" #: ../quodlibet/ext/events/randomalbum.py:89 msgid "Play some albums more than others" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:103 msgid "avoid" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:114 msgid "prefer" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:201 #, fuzzy msgid "Random Album" msgstr "Произволен _албум" #: ../quodlibet/ext/events/randomalbum.py:202 #, python-format msgid "Waiting to start %s" msgstr "" #: ../quodlibet/ext/events/rbimport.py:114 #, fuzzy msgid "Import Failed" msgstr "Внасяне на списък с песни" #: ../quodlibet/ext/events/rbimport.py:119 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "" #: ../quodlibet/ext/events/rbimport.py:127 msgid "Rhythmbox Import" msgstr "" #: ../quodlibet/ext/events/rbimport.py:128 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "" #: ../quodlibet/ext/events/rbimport.py:132 #, fuzzy msgid "Start Import" msgstr "_Внасяне" #: ../quodlibet/ext/events/screensaver.py:25 msgid "Screensaver Pause" msgstr "" #: ../quodlibet/ext/events/screensaver.py:26 msgid "Pauses playback while the GNOME screensaver is active." msgstr "" #: ../quodlibet/ext/events/searchprovider.py:73 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "" #: ../quodlibet/ext/events/searchprovider.py:79 msgid "GNOME Search Provider" msgstr "" #: ../quodlibet/ext/events/searchprovider.py:80 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/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:29 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:57 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:58 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:34 #, fuzzy msgid "Synchronized Lyrics" msgstr "Текст на песен" #: ../quodlibet/ext/events/synchronizedlyrics.py:35 msgid "Shows synchronized lyrics from .lrc file with same name as the track." msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:66 msgid "Text:" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:76 msgid "Background:" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:87 msgid "Font" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:90 msgid "Size (px):" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:62 msgid "Telepathy Status Messages" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:63 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:122 #, fuzzy msgid "Playing:" msgstr "Не се изпълнява нищо" #: ../quodlibet/ext/events/telepathy_status.py:123 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:139 msgid "Paused:" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:140 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:156 msgid "Plain text for status when there is no current song" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:157 #, fuzzy msgid "No song:" msgstr "%d песен" #. Frame #: ../quodlibet/ext/events/telepathy_status.py:164 #, 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/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:77 #: ../quodlibet/ext/events/trayicon/prefs.py:98 #: ../quodlibet/ext/events/trayicon/systemtray.py:177 #: ../quodlibet/qltk/info.py:47 msgid "Not playing" msgstr "Не се изпълнява нищо" #: ../quodlibet/ext/events/trayicon/__init__.py:53 #, fuzzy msgid "Tray Icon" msgstr "Настройки на иконата за статус" #: ../quodlibet/ext/events/trayicon/__init__.py:54 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:183 #: ../quodlibet/qltk/quodlibetwindow.py:1046 #: ../quodlibet/qltk/quodlibetwindow.py:1238 #, fuzzy msgid "_Play" msgstr "Сп_исъци с песни" #: ../quodlibet/ext/events/trayicon/menu.py:63 #: ../quodlibet/qltk/quodlibetwindow.py:185 #: ../quodlibet/qltk/quodlibetwindow.py:1240 ../quodlibet/qltk/wlw.py:51 #, fuzzy msgid "P_ause" msgstr "Преслушване" #: ../quodlibet/ext/events/trayicon/menu.py:68 #: ../quodlibet/qltk/quodlibetwindow.py:190 #: ../quodlibet/qltk/quodlibetwindow.py:1041 #, fuzzy msgid "Pre_vious" msgstr "Пре_глед" #: ../quodlibet/ext/events/trayicon/menu.py:71 #: ../quodlibet/qltk/quodlibetwindow.py:194 #: ../quodlibet/qltk/quodlibetwindow.py:1051 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:1012 #, fuzzy msgid "Open _Browser" msgstr "Отваряне на нов браузър" #: ../quodlibet/ext/events/trayicon/menu.py:103 #: ../quodlibet/qltk/quodlibetwindow.py:1031 ../quodlibet/qltk/songsmenu.py:411 msgid "Edit _Tags" msgstr "Редактиране на _етикети" #: ../quodlibet/ext/events/trayicon/menu.py:112 #: ../quodlibet/qltk/quodlibetwindow.py:975 ../quodlibet/qltk/songsmenu.py:424 msgid "_Information" msgstr "_Информация" #: ../quodlibet/ext/events/trayicon/menu.py:114 #: ../quodlibet/qltk/songsmenu.py:340 #, fuzzy msgid "Play_lists" msgstr "Сп_исъци с песни" #: ../quodlibet/ext/events/trayicon/menu.py:132 #: ../quodlibet/qltk/quodlibetwindow.py:1026 msgid "_Quit" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:32 ../quodlibet/qltk/prefs.py:69 msgid "Behavior" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:42 #, fuzzy msgid "Scroll wheel adjusts volume" msgstr "" "Колелото на мишката наглася силата на звука;\n" "Shift и колелото на мишката променят песента." #: ../quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel changes song" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll _Wheel" msgstr "Колелото на ми_шката" #: ../quodlibet/ext/events/trayicon/prefs.py:84 msgid "Tooltip Display" msgstr "Показване на подсказка" #: ../quodlibet/ext/events/viewlyrics.py:23 #, fuzzy msgid "View Lyrics" msgstr "Текст на песен" #: ../quodlibet/ext/events/viewlyrics.py:24 msgid "Automatically displays lyrics beneath the song list in the main window." msgstr "" #: ../quodlibet/ext/events/viewlyrics.py:29 #, fuzzy msgid "_Lyrics" 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:406 msgid "Waveform Seek Bar" msgstr "" #: ../quodlibet/ext/events/waveformseekbar.py:410 msgid "A seekbar in the shape of the waveform of the current song." msgstr "" #: ../quodlibet/ext/events/waveformseekbar.py:443 msgid "Override foreground color:" msgstr "" #: ../quodlibet/ext/events/write_cover.py:32 msgid "Picture Saver" msgstr "" #: ../quodlibet/ext/events/write_cover.py:33 msgid "Saves the cover image of the current song to a file." msgstr "" #: ../quodlibet/ext/events/write_cover.py:66 #, fuzzy msgid "File:" msgstr "Файлове" #: ../quodlibet/ext/gstreamer/compressor.py:20 msgid "_Threshold:" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:21 msgid "Threshold until the filter is activated" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:22 msgid "R_atio:" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:22 msgid "Compression ratio" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:74 #: ../quodlibet/ext/gstreamer/karaoke.py:91 #, python-format msgid "%d %%" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:105 msgid "Audio Compressor" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:106 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:19 #, fuzzy msgid "_Preset:" msgstr "Пре_глед" #: ../quodlibet/ext/gstreamer/crossfeed.py:19 #, fuzzy msgid "Filter preset" msgstr "Само този _артист" #: ../quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Frequency cut:" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Low-pass filter cut frequency" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed _level:" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed level" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:25 msgid "Default" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Chu Moy" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Jan Meier" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:31 #, fuzzy msgid "Custom settings" msgstr "_Лично" #: ../quodlibet/ext/gstreamer/crossfeed.py:152 msgid "Crossfeed" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:153 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:20 #, fuzzy msgid "Filter _band:" msgstr "Само този _жанр" #: ../quodlibet/ext/gstreamer/karaoke.py:21 msgid "The Frequency band of the filter" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:22 #, fuzzy msgid "Filter _width:" msgstr "Само този _артист" #: ../quodlibet/ext/gstreamer/karaoke.py:23 msgid "The Frequency width of the filter" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:24 msgid "_Level:" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:24 msgid "Level of the effect" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:105 msgid "Karaoke" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:106 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:20 msgid "R_ate:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:21 msgid "_Tempo:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:22 msgid "_Pitch:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:89 #, fuzzy msgid "Audio Pitch / Speed" msgstr "_Аудио емисии" #: ../quodlibet/ext/gstreamer/pitch.py:90 #, fuzzy msgid "Controls the pitch of an audio stream." msgstr "Въведете местоположението на аудио емисия:" #: ../quodlibet/ext/playlist/export_to_folder.py:29 #: ../quodlibet/ext/playlist/export_to_folder.py:97 #: ../quodlibet/ext/playlist/export_to_folder.py:138 #, fuzzy msgid "Export Playlist to Folder" msgstr "Внасяне на списък с песни" #: ../quodlibet/ext/playlist/export_to_folder.py:38 #, fuzzy msgid "_Export" msgstr "_Внасяне" #: ../quodlibet/ext/playlist/export_to_folder.py:43 #, fuzzy msgid "Destination folder:" msgstr "Няма открити станции." #: ../quodlibet/ext/playlist/export_to_folder.py:58 #, 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:156 #, fuzzy msgid "Default filename pattern:" msgstr "_Файлово име" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:23 msgid "Export to Squeezebox" msgstr "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:25 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 "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Export playlist to Squeezebox" msgstr "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:80 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 "" "Playback follows your selection, or the next song in the list once exhausted." msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:22 msgid "Playcount Equalizer" msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:23 msgid "Shuffle, preferring songs with fewer total plays." msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:25 #, fuzzy msgid "Prefer less played" msgstr "последно слушана" #: ../quodlibet/ext/playorder/queue.py:19 #, fuzzy msgid "Queue Only" msgstr "_Опашка" #: ../quodlibet/ext/playorder/queue.py:21 msgid "" "Limits playing of songs to the queue. Select this play order in the main " "window, then double-clicking any song will enqueue it instead of playing." msgstr "" #: ../quodlibet/ext/playorder/reverse.py:14 #, fuzzy msgid "Reverse" msgstr "Никога" #: ../quodlibet/ext/playorder/reverse.py:16 msgid "Reverses the play order of songs." msgstr "" #: ../quodlibet/ext/playorder/skip_songs.py:25 #, fuzzy msgid "Skip Songs" msgstr "Няма песни" #: ../quodlibet/ext/playorder/skip_songs.py:27 msgid "" "Playback skips over songs with a rating equal or below a given threshold." msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:30 msgid "Repeat Each Track" msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:32 msgid "Shuffle songs, but repeat every track a set number of times." msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:51 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. Syntax is '@(if: " "condition, then, else)'." msgstr "" #: ../quodlibet/ext/query/pythonexpression.py:14 msgid "Python Query" msgstr "" #: ../quodlibet/ext/query/pythonexpression.py:15 msgid "" "Use Python expressions in queries. Syntax is '@(python: expression)'. The " "variable 's' is the song being matched." msgstr "" #: ../quodlibet/ext/query/savedsearch.py:19 #, fuzzy msgid "Include Saved Search" msgstr "Запазени стойности" #: ../quodlibet/ext/query/savedsearch.py:20 msgid "" "Include the results of a saved search as part of another query. Syntax is " "'@(saved: search name)'." 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:116 msgid "Port:" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:121 #, fuzzy msgid "Username:" msgstr "_Преименуване" #: ../quodlibet/ext/_shared/squeezebox/base.py:126 msgid "Password:" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:130 msgid "Library directory the server connects to." msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:132 #, fuzzy msgid "Library path:" msgstr "Фонотека" #. Add verify button #: ../quodlibet/ext/_shared/squeezebox/base.py:141 msgid "_Verify settings" msgstr "" #. Server settings Frame #: ../quodlibet/ext/_shared/squeezebox/base.py:147 msgid "Squeezebox Server" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:150 msgid "Debug" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:26 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:28 msgid "unidentified Squeezebox server" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:37 #, 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:20 #: ../quodlibet/ext/songsmenu/importexport.py:34 #: ../quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:329 #, fuzzy msgid "Fit image to _window" msgstr "Скриване на главния прозорец" #. Both labels #: ../quodlibet/ext/songsmenu/albumart.py:338 msgid "_Program:" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:343 msgid "_Edit image after saving" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:345 #, fuzzy msgid "File_name:" msgstr "Файлово име" #: ../quodlibet/ext/songsmenu/albumart.py:457 msgid "Saving failed" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:458 #, fuzzy, python-format msgid "Unable to save \"%s\"." msgstr "Не може да се запази песента" #: ../quodlibet/ext/songsmenu/albumart.py:556 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:613 #, fuzzy msgid "Album Art Downloader" msgstr "Спис_ък с албуми" #: ../quodlibet/ext/songsmenu/albumart.py:666 #, python-format msgid "from %(source)s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:669 #, python-format msgid "Resolution: %s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:672 #, fuzzy, python-format msgid "Size: %s" msgstr "Размер" #: ../quodlibet/ext/songsmenu/albumart.py:690 #, fuzzy msgid "_Search" msgstr "_Търсене:" #: ../quodlibet/ext/songsmenu/albumart.py:741 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:451 #, fuzzy msgid "Searching…" msgstr "Търсене" #: ../quodlibet/ext/songsmenu/albumart.py:804 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:922 #, fuzzy msgid "Download Album Art" msgstr "Спис_ък с албуми" #: ../quodlibet/ext/songsmenu/albumart.py:923 msgid "Downloads album covers from various websites." msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:936 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 #: ../quodlibet/qltk/downloader.py:52 msgid "Filename" msgstr "Файлово име" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:130 #, fuzzy msgid "Disc" msgstr "Д_иск" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:131 #: ../quodlibet/ext/songsmenu/replaygain.py:404 #: ../quodlibet/qltk/tracknumbers.py:92 msgid "Track" msgstr "Песен" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:132 #, 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:447 msgid "Please enter a query." msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:465 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:496 msgid "Error encountered. Please retry." msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:472 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:488 msgid "Loading result…" msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:475 #, fuzzy msgid "No results found." msgstr "Няма открити приставки." #: ../quodlibet/ext/songsmenu/browsefolders.py:159 #, fuzzy msgid "Browse Folders" msgstr "Разглеждане" #: ../quodlibet/ext/songsmenu/browsefolders.py:160 msgid "Opens the songs' folders in a file manager." msgstr "" #: ../quodlibet/ext/songsmenu/browsefolders.py:172 #, fuzzy msgid "Unable to open folders" msgstr "Неуспех при създаването на папка" #: ../quodlibet/ext/songsmenu/browsefolders.py:173 msgid "No program available to open folders." msgstr "" #: ../quodlibet/ext/songsmenu/console.py:40 msgid "Python Console" msgstr "" #: ../quodlibet/ext/songsmenu/console.py:41 msgid "Interactive Python console." msgstr "" #: ../quodlibet/ext/songsmenu/console.py:72 msgid "You can access the following objects by default:" msgstr "" #: ../quodlibet/ext/songsmenu/console.py:82 msgid "Your current working directory is:" 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:55 #, fuzzy msgid "pattern" 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:91 #, fuzzy msgid "Input value" msgstr "Невалидна стойност" #: ../quodlibet/ext/songsmenu/custom_commands.py:92 #, python-format msgid "Value for %s?" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:136 #, fuzzy msgid "Custom Commands" msgstr "_Лично" #: ../quodlibet/ext/songsmenu/custom_commands.py:137 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:188 #: ../quodlibet/ext/songsmenu/custom_commands.py:198 #: ../quodlibet/ext/songsmenu/custom_commands.py:252 msgid "Edit Custom Commands" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:199 msgid "" "Supports QL patterns\n" "eg <tt><~artist~title></tt>" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:283 #, fuzzy, python-format msgid "Unable to run custom command %s" msgstr "Неуспех при копиране на песните" #: ../quodlibet/ext/songsmenu/duplicates.py:290 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "" msgstr[1] "" #: ../quodlibet/ext/songsmenu/duplicates.py:343 msgid "Collapse / Expand all" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:347 #, python-format msgid "Duplicate key expression is '%s'" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:363 #, fuzzy msgid "Duplicates Browser" msgstr "_Изключване на разглеждането" #: ../quodlibet/ext/songsmenu/duplicates.py:364 msgid "Finds and displays similarly tagged versions of songs." msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:407 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:409 msgid "_Group duplicates by:" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:414 msgid "Duplicate Key" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:419 #, fuzzy msgid "Remove _Whitespace" msgstr "_Премахване на станция" #: ../quodlibet/ext/songsmenu/duplicates.py:420 #, fuzzy msgid "Remove _Diacritics" msgstr "_Премахване на станция" #: ../quodlibet/ext/songsmenu/duplicates.py:421 #, fuzzy msgid "Remove _Punctuation" msgstr "_Премахване на станция" #: ../quodlibet/ext/songsmenu/duplicates.py:422 msgid "Case _Insensitive" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:430 msgid "Matching options" msgstr "" #. Create a dialog. #: ../quodlibet/ext/songsmenu/editplaycount.py:19 #: ../quodlibet/ext/songsmenu/editplaycount.py:41 #, fuzzy msgid "Edit Playcount" msgstr "Редактиране на показваното" #: ../quodlibet/ext/songsmenu/editplaycount.py:20 msgid "" "Edit a song's ~#playcount and ~#skipcount.\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's ~#playcount to 0, the ~#lastplayed and ~#laststarted " "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:68 msgid "Play Count" msgstr "" #: ../quodlibet/ext/songsmenu/editplaycount.py:69 msgid "Skip Count" msgstr "" #: ../quodlibet/ext/songsmenu/embedded.py:24 #, fuzzy msgid "Edit Embedded Images" msgstr "_Премахване на станция" #: ../quodlibet/ext/songsmenu/embedded.py:25 #, fuzzy msgid "Removes or replaces embedded images." msgstr "_Премахване на станция" #: ../quodlibet/ext/songsmenu/embedded.py:78 #, fuzzy msgid "_Remove all Images" msgstr "_Премахване на станция" #: ../quodlibet/ext/songsmenu/embedded.py:82 #, fuzzy msgid "_Embed Current 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:41 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 #: ../quodlibet/qltk/downloader.py:67 #, 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 "Запис" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" 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:49 msgid "Generating fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:63 msgid "_Details" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:85 msgid "_Submit" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:115 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:118 msgid "Fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Songs with MBIDs:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with sufficient tags:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs to submit:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:162 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:178 msgid "Submitting fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:186 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/id3tlen.py:21 msgid "Fix MP3 Duration" msgstr "" #: ../quodlibet/ext/songsmenu/id3tlen.py:22 msgid "" "Removes TLEN frames from ID3 tags which can be the cause for invalid song " "durations." msgstr "" #: ../quodlibet/ext/songsmenu/ifp.py:20 msgid "Send to iFP" msgstr "" #: ../quodlibet/ext/songsmenu/ifp.py:21 msgid "Uploads songs to an iRiver iFP device." msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:51 msgid "Export Metadata" msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:52 msgid "Exports metadata of selected songs as a .tags file." msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:92 #, fuzzy msgid "Import Metadata" msgstr "Внасяне на списък с песни" #: ../quodlibet/ext/songsmenu/importexport.py:93 msgid "Imports metadata for selected songs from a .tags file." msgstr "" #: ../quodlibet/ext/songsmenu/k3b.py:23 msgid "Burn CD" msgstr "" #: ../quodlibet/ext/songsmenu/k3b.py:24 msgid "Burns CDs with K3b, Brasero or xfburn." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:96 msgid "Updating chart list." msgstr "" #. No charts to fetch, no update scheduled. #: ../quodlibet/ext/songsmenu/lastfmsync.py:114 msgid "Already up-to-date." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:121 #, python-format msgid "Fetching chart for week of %s." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:143 msgid "Sync complete." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:149 msgid "Error during sync" msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:214 #: ../quodlibet/ext/songsmenu/lastfmsync.py:244 msgid "Last.fm Sync" msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:245 msgid "Updates your library's statistics from your Last.fm profile." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:293 #, 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 "" #. Create a dialog. #: ../quodlibet/ext/songsmenu/migratemetadata.py:29 #: ../quodlibet/ext/songsmenu/migratemetadata.py:38 #, fuzzy msgid "Migrate Metadata" msgstr "Внасяне на списък с песни" #: ../quodlibet/ext/songsmenu/migratemetadata.py:32 msgid "Copies the quodlibet-specific metadata between songs." msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:45 msgid "_Copy" msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:47 msgid "_Paste" msgstr "" #. Create the tag table. #: ../quodlibet/ext/songsmenu/migratemetadata.py:57 #, fuzzy msgid "Information to copy/paste" msgstr "Информация" #. Create the indexing box. #: ../quodlibet/ext/songsmenu/migratemetadata.py:79 msgid "Map tracks by disc and track number" msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:80 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 "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:96 #, python-format msgid "There is %d stored track." msgid_plural "There are %d stored tracks." msgstr[0] "" msgstr[1] "" #: ../quodlibet/ext/songsmenu/playlist.py:31 #, fuzzy msgid "Export as Playlist" msgstr "Внасяне на списък с песни" #: ../quodlibet/ext/songsmenu/playlist.py:32 msgid "Exports songs to an M3U or PLS playlist." msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:77 msgid "Use relative paths" msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:77 msgid "Use absolute paths" msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:132 #, fuzzy msgid "Unable to export playlist" msgstr "Неуспех при внасяне на списъка" #: ../quodlibet/ext/songsmenu/playlist.py:133 #, fuzzy, python-format msgid "Writing to <b>%s</b> 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:362 msgid "ReplayGain Analyzer" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:418 msgid "Progress" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:433 msgid "Gain" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:448 msgid "Peak" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:463 #, python-format msgid "There is <b>%(to-process)s</b> album to update (of %(all)s)" msgid_plural "There are <b>%(to-process)s</b> albums to update (of %(all)s)" msgstr[0] "" msgstr[1] "" #: ../quodlibet/ext/songsmenu/replaygain.py:578 msgid "Replay Gain" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:579 msgid "" "Analyzes and updates ReplayGain information, using GStreamer. Results are " "grouped by album." msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:617 msgid "always" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:618 msgid "if <b>any</b> RG tags are missing" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:620 msgid "if <b>album</b> RG tags are missing" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:637 msgid "_Process albums:" msgstr "" #. Server settings Frame #: ../quodlibet/ext/songsmenu/replaygain.py:649 #, 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 "" #. TRANSLATORS: BPM mean "beats per minute" #: ../quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "" #: ../quodlibet/ext/songsmenu/tapbpm.py:32 #: ../quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" 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:172 #: ../quodlibet/ext/songsmenu/tapbpm.py:179 msgid "Tap BPM" msgstr "" #: ../quodlibet/ext/songsmenu/tapbpm.py:173 #, fuzzy msgid "Tap BPM for the selected song." msgstr "Неуспех при добавяне на песните" #: ../quodlibet/ext/songsmenu/website_search.py:35 #, fuzzy msgid "Website Search" msgstr "Търсене" #: ../quodlibet/ext/songsmenu/website_search.py:36 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern-example)s." msgstr "" #: ../quodlibet/ext/songsmenu/website_search.py:78 #, fuzzy msgid "Search URL patterns" msgstr "шаблон" #: ../quodlibet/ext/songsmenu/website_search.py:88 #, fuzzy msgid "Edit search URLs" msgstr "Запазване на редактираните стойности..." #. Add link to editor #: ../quodlibet/ext/songsmenu/website_search.py:114 #, fuzzy msgid "Configure Searches…" msgstr "Оцветяване на _търсените фрази" #: ../quodlibet/ext/songsmenu/wikipedia.py:46 #, python-format msgid "Search at %(website)s" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:63 msgid "Search Artist in Wikipedia" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:64 msgid "" "Opens a browser window with Wikipedia article on the playing song artist." msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:71 msgid "Search Album in Wikipedia" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:72 msgid "" "Opens a browser window with Wikipedia article on the playing song album." msgstr "" #. then (try to) load all new files #: ../quodlibet/library/libraries.py:650 ../quodlibet/library/libraries.py:660 #: ../quodlibet/library/libraries.py:726 ../quodlibet/library/libraries.py:745 #: ../quodlibet/qltk/information.py:268 ../quodlibet/qltk/prefs.py:639 #: ../quodlibet/util/library.py:124 msgid "Library" msgstr "Фонотека" #: ../quodlibet/library/libraries.py:650 #, fuzzy msgid "Checking mount points" msgstr "точка на монтиране" #: ../quodlibet/library/libraries.py:660 #, fuzzy msgid "Scanning library" msgstr "Запазване на фонотеката" #: ../quodlibet/library/libraries.py:725 #, fuzzy, python-format msgid "Scanning %s" msgstr "Проверяване на %s" #: ../quodlibet/library/libraries.py:745 msgid "Loading files" msgstr "" #: ../quodlibet/operon/base.py:70 #, python-format msgid "Failed to load file: %r" msgstr "" #: ../quodlibet/operon/commands.py:37 msgid "List tags" msgstr "" #: ../quodlibet/operon/commands.py:42 ../quodlibet/operon/commands.py:81 #: ../quodlibet/operon/commands.py:461 msgid "Print terse output" msgstr "" #: ../quodlibet/operon/commands.py:44 ../quodlibet/operon/commands.py:83 #: ../quodlibet/operon/commands.py:463 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "" #: ../quodlibet/operon/commands.py:47 ../quodlibet/operon/commands.py:86 #, fuzzy msgid "Also list programmatic tags" msgstr "Показване на про_граматични етикети" #: ../quodlibet/operon/commands.py:51 ../quodlibet/operon/commands.py:129 #: ../quodlibet/operon/commands.py:220 ../quodlibet/operon/commands.py:293 #: ../quodlibet/operon/commands.py:336 ../quodlibet/operon/commands.py:340 #: ../quodlibet/operon/commands.py:391 ../quodlibet/operon/commands.py:394 #: ../quodlibet/operon/commands.py:433 ../quodlibet/operon/commands.py:468 #: ../quodlibet/operon/commands.py:508 ../quodlibet/operon/commands.py:543 #: ../quodlibet/operon/commands.py:585 msgid "Not enough arguments" msgstr "" #: ../quodlibet/operon/commands.py:53 ../quodlibet/operon/commands.py:90 #: ../quodlibet/operon/commands.py:131 ../quodlibet/operon/commands.py:222 #: ../quodlibet/operon/commands.py:470 msgid "Too many arguments" msgstr "" #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:92 #: ../quodlibet/operon/commands.py:475 ../quodlibet/qltk/data_editors.py:363 #, fuzzy msgid "Description" msgstr "описание" #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:475 #: ../quodlibet/qltk/edittags.py:454 msgid "Value" msgstr "Стойност" #: ../quodlibet/operon/commands.py:76 msgid "List all common tags" msgstr "" #: ../quodlibet/operon/commands.py:118 msgid "Copy tags from one file to another" msgstr "" #: ../quodlibet/operon/commands.py:123 ../quodlibet/operon/commands.py:164 #: ../quodlibet/operon/commands.py:289 ../quodlibet/operon/commands.py:324 #: ../quodlibet/operon/commands.py:384 msgid "Show changes, don't apply them" msgstr "" #: ../quodlibet/operon/commands.py:125 msgid "Skip tags that can't be written" msgstr "" #: ../quodlibet/operon/commands.py:145 #, python-format msgid "Can't copy tag %r to file: %r" 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:304 ../quodlibet/operon/commands.py:444 #: ../quodlibet/operon/commands.py:676 #, python-format msgid "Can not set %r" msgstr "" #: ../quodlibet/operon/commands.py:319 #, fuzzy msgid "Remove tags" msgstr "_Премахване на станция" #: ../quodlibet/operon/commands.py:326 ../quodlibet/operon/commands.py:386 msgid "Value is a regular expression" msgstr "" #: ../quodlibet/operon/commands.py:328 #, fuzzy msgid "Remove all tags" msgstr "_Премахване на станция" #: ../quodlibet/operon/commands.py:332 msgid "Can't combine '--all' with '--regexp'" msgstr "" #: ../quodlibet/operon/commands.py:366 #, python-format msgid "Can't remove %r from %r" msgstr "" #: ../quodlibet/operon/commands.py:379 #, fuzzy msgid "Remove a tag value" msgstr "Филтриране по стойност на етикета" #: ../quodlibet/operon/commands.py:428 #, fuzzy msgid "Add a tag value" msgstr "Филтриране по стойност на етикета" #: ../quodlibet/operon/commands.py:456 #, fuzzy msgid "List file information" msgstr "Няма информация за времетраенето" #: ../quodlibet/operon/commands.py:502 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" #: ../quodlibet/operon/commands.py:515 #, fuzzy, python-format msgid "Failed to load image file: %r" msgstr "Неуспех при преименуване на файл." #: ../quodlibet/operon/commands.py:522 ../quodlibet/operon/commands.py:551 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" #: ../quodlibet/operon/commands.py:538 #, fuzzy msgid "Remove all embedded images" msgstr "_Премахване на станция" #: ../quodlibet/operon/commands.py:568 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "" #: ../quodlibet/operon/commands.py:580 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" #: ../quodlibet/operon/commands.py:639 msgid "Rename files based on tags" msgstr "" #: ../quodlibet/operon/commands.py:654 msgid "Fill tags based on the file path" msgstr "" #: ../quodlibet/operon/commands.py:704 ../quodlibet/qltk/information.py:305 #: ../quodlibet/qltk/properties.py:84 ../quodlibet/qltk/renamefiles.py:176 #: ../quodlibet/qltk/tagsfrompath.py:229 ../quodlibet/qltk/tracknumbers.py:79 msgid "File" msgstr "Файл" #: ../quodlibet/operon/commands.py:712 msgid "Fill tracknumbers for all files" msgstr "" #: ../quodlibet/operon/commands.py:731 msgid "Print tags based on the given pattern" msgstr "" #: ../quodlibet/operon/commands.py:768 #, fuzzy msgid "Display help information" msgstr "Показване на кратка информация за употреба" #: ../quodlibet/operon/util.py:40 #, 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:30 #, fuzzy msgid "_Unknown" msgstr "непознат" #: ../quodlibet/order/__init__.py:142 msgid "In Order" msgstr "Подред" #: ../quodlibet/order/__init__.py:143 msgid "_In Order" msgstr "П_одред" #: ../quodlibet/order/reorder.py:23 #, fuzzy msgid "Random" msgstr "Произв_олен" #: ../quodlibet/order/reorder.py:24 ../quodlibet/qltk/queue.py:119 msgid "_Random" msgstr "Произв_олен" #: ../quodlibet/order/reorder.py:39 ../quodlibet/order/reorder.py:40 msgid "Prefer higher rated" msgstr "" #: ../quodlibet/order/repeat.py:43 ../quodlibet/order/repeat.py:44 msgid "Repeat this track" msgstr "" #: ../quodlibet/order/repeat.py:57 ../quodlibet/order/repeat.py:58 #, fuzzy msgid "Repeat all" msgstr "П_овтаряне" #: ../quodlibet/order/repeat.py:73 ../quodlibet/order/repeat.py:74 msgid "One Song" msgstr "Една песен" #: ../quodlibet/player/gstbe/player.py:98 msgid "Stream" msgstr "" #: ../quodlibet/player/gstbe/player.py:98 msgid "Buffering" msgstr "" #: ../quodlibet/player/gstbe/player.py:319 msgid "Could not create GStreamer pipeline" msgstr "" #: ../quodlibet/player/gstbe/player.py:560 msgid "No GStreamer element found to handle media format" msgstr "" #: ../quodlibet/player/gstbe/player.py:561 #, 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:25 msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. In case the pipeline contains a sink, it will be used instead of " "the default one." msgstr "" #: ../quodlibet/player/gstbe/prefs.py:36 msgid "_Output pipeline:" msgstr "" #: ../quodlibet/player/gstbe/prefs.py:43 #, fuzzy, python-format msgid "%.1f seconds" msgstr "%d секунда" #: ../quodlibet/player/gstbe/prefs.py:57 msgid "_Buffer duration:" msgstr "" #: ../quodlibet/player/gstbe/prefs.py:66 msgid "Disable _gapless playback" msgstr "" #: ../quodlibet/player/gstbe/prefs.py:70 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions." msgstr "" #: ../quodlibet/player/gstbe/util.py:93 #, fuzzy msgid "No GStreamer audio sink found" msgstr "Няма открити станции." #: ../quodlibet/player/gstbe/util.py:112 msgid "Invalid GStreamer output pipeline" msgstr "" #: ../quodlibet/player/xinebe/player.py:90 #, fuzzy msgid "Unable to create audio output" msgstr "Неуспех при създаването на папка" #: ../quodlibet/player/xinebe/player.py:91 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "" #: ../quodlibet/plugins/__init__.py:62 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" #: ../quodlibet/plugins/__init__.py:71 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "" #: ../quodlibet/plugins/playlist.py:30 #, 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:41 ../quodlibet/qltk/songsmenu.py:46 #: ../quodlibet/qltk/songsmenu.py:74 #, fuzzy msgid "_Run Plugin" msgstr "П_риставки" #: ../quodlibet/qltk/about.py:40 #, python-format msgid "Supported formats: %s" msgstr "Поддържани формати: %s" #: ../quodlibet/qltk/about.py:43 #, python-format msgid "Audio device: %s" msgstr "Аудио устройство: %s" #. 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:207 ../quodlibet/qltk/information.py:131 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:48 ../quodlibet/qltk/edittags.py:311 msgid "_Value:" msgstr "С_тойност:" #: ../quodlibet/qltk/cbes.py:262 msgid "Saved Values" msgstr "Запазени стойности" #: ../quodlibet/qltk/cbes.py:263 #, fuzzy msgid "Edit saved values…" msgstr "Запазване на редактираните стойности..." #: ../quodlibet/qltk/controls.py:111 msgid "Auto_matic" msgstr "" #: ../quodlibet/qltk/controls.py:112 #, fuzzy msgid "_Track Mode" msgstr "Номера на песните" #: ../quodlibet/qltk/controls.py:113 #, fuzzy msgid "_Album Mode" msgstr "Спис_ък с албуми" #. Translators: player state, no action #: ../quodlibet/qltk/controls.py:122 msgid "_Mute" msgstr "" #: ../quodlibet/qltk/controls.py:128 #, fuzzy msgid "_Replay Gain Mode" msgstr "Без нагласяне на силата на звука" #. Translators: New Command/Entry/Item/... #: ../quodlibet/qltk/data_editors.py:119 #, python-format msgid "New %s" msgstr "" #: ../quodlibet/qltk/data_editors.py:218 #, fuzzy msgid "(unknown)" msgstr "непознат" #: ../quodlibet/qltk/data_editors.py:355 msgid "Tag expression" msgstr "" #: ../quodlibet/qltk/data_editors.py:382 msgid "Tag expression e.g. people:real or ~album~year." msgstr "" #: ../quodlibet/qltk/data_editors.py:383 #, fuzzy msgid "Enter new tag" 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/downloader.py:38 msgid "Downloads" msgstr "Изтегляния" #: ../quodlibet/qltk/downloader.py:62 msgid "Size" msgstr "Размер" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: ../quodlibet/qltk/downloader.py:94 ../quodlibet/qltk/renamefiles.py:265 #: ../quodlibet/qltk/wlw.py:50 msgid "_Stop" msgstr "" #: ../quodlibet/qltk/edittags.py:63 ../quodlibet/qltk/edittags.py:74 #, python-format msgid "missing from %d song" msgid_plural "missing from %d songs" msgstr[0] "липсва от %d песен" msgstr[1] "липсва от %d песни" #: ../quodlibet/qltk/edittags.py:67 ../quodlibet/qltk/edittags.py:71 #, python-format msgid "different across %d song" msgid_plural "different across %d songs" msgstr[0] "различно при %d песен" msgstr[1] "различно при %d песни" #: ../quodlibet/qltk/edittags.py:193 msgid "Split into _Multiple Values" msgstr "Разделяне на _множество стойности" #: ../quodlibet/qltk/edittags.py:211 msgid "Split Disc out of _Album" msgstr "Номерът на диска извън етикета за _албум" #: ../quodlibet/qltk/edittags.py:228 msgid "Split _Version out of Title" msgstr "_Версията извън етикета за заглавието" #: ../quodlibet/qltk/edittags.py:259 msgid "Split Arranger out of Ar_tist" msgstr "_Аранжиментът извън етикета за артист" #: ../quodlibet/qltk/edittags.py:264 msgid "Split _Performer out of Artist" msgstr "Из_пълнителят извън етикета за артист" #: ../quodlibet/qltk/edittags.py:270 #, fuzzy msgid "Split _Performer out of Title" msgstr "Из_пълнителят извън етикета за артист" #: ../quodlibet/qltk/edittags.py:276 #, fuzzy msgid "Split _Originalartist out of Title" msgstr "_Версията извън етикета за заглавието" #: ../quodlibet/qltk/edittags.py:283 msgid "Add a Tag" msgstr "Добавяне на етикет" #: ../quodlibet/qltk/edittags.py:302 msgid "_Tag:" msgstr "_Етикет:" #: ../quodlibet/qltk/edittags.py:404 msgid "Edit Tags" msgstr "Редактиране на етикетите" #: ../quodlibet/qltk/edittags.py:477 msgid "Show _programmatic tags" msgstr "Показване на про_граматични етикети" #: ../quodlibet/qltk/edittags.py:478 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" #. Translators: Revert button in the tag editor #: ../quodlibet/qltk/edittags.py:508 #, fuzzy msgctxt "edittags" msgid "_Revert" msgstr "Никога" #. Translators: Save button in the tag editor #: ../quodlibet/qltk/edittags.py:513 msgctxt "edittags" msgid "_Save" msgstr "" #: ../quodlibet/qltk/edittags.py:659 msgid "Unable to add tag" msgstr "Неуспех при добавяне на етикет" #: ../quodlibet/qltk/edittags.py:660 #, fuzzy, python-format msgid "Unable to add <b>%s</b>" msgstr "Неуспех при добавяне на песента" #: ../quodlibet/qltk/edittags.py:662 #, fuzzy, python-format msgid "" "The files currently selected do not support multiple values for <b>%s</b>." msgstr "" "Неуспех при добавяне на <b>%s</b>\n" "\n" "Текущо избраните файлове не поддържат множествени стойности." #. Can't add the new tag. #: ../quodlibet/qltk/edittags.py:689 ../quodlibet/qltk/edittags.py:856 #: ../quodlibet/qltk/tagsfrompath.py:212 ../quodlibet/util/__init__.py:554 #: ../quodlibet/util/tags.py:231 msgid "Invalid tag" msgstr "Невалиден етикет" #: ../quodlibet/qltk/edittags.py:690 ../quodlibet/qltk/edittags.py:857 #: ../quodlibet/qltk/tagsfrompath.py:213 #, python-format msgid "" "Invalid tag <b>%s</b>\n" "\n" "The files currently selected do not support editing this tag." msgstr "" "Невалиден етикет <b>%s</b>\n" "\n" "Избраните в момента файлове не поддържат редакцията на този етикет." #: ../quodlibet/qltk/edittags.py:828 ../quodlibet/qltk/edittags.py:868 msgid "Invalid value" msgstr "Невалидна стойност" #: ../quodlibet/qltk/edittags.py:829 ../quodlibet/qltk/edittags.py:869 #, python-format msgid "" "Invalid value: <b>%(value)s</b>\n" "\n" "%(error)s" msgstr "" "Невалидна стойност: <b>%(value)s</b>\n" "\n" "%(error)s" #: ../quodlibet/qltk/_editutils.py:28 msgid "Tag may not be accurate" msgstr "Етикетът може да не е точен" #: ../quodlibet/qltk/_editutils.py:31 #, 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:47 msgid "Unable to save song" msgstr "Не може да се запази песента" #: ../quodlibet/qltk/_editutils.py:50 #, 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:142 #, 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:95 #: ../quodlibet/qltk/quodlibetwindow.py:1066 msgid "_About" msgstr "" #: ../quodlibet/qltk/exfalsowindow.py:99 #: ../quodlibet/qltk/quodlibetwindow.py:1088 msgid "_Check for Updates…" msgstr "" #: ../quodlibet/qltk/exfalsowindow.py:105 #: ../quodlibet/qltk/quodlibetwindow.py:1021 ../quodlibet/qltk/songsmenu.py:304 msgid "_Plugins" msgstr "П_риставки" #: ../quodlibet/qltk/exfalsowindow.py:267 #, 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:279 msgid "Ex Falso Preferences" msgstr "Настройки на Ex Falso" #: ../quodlibet/qltk/exfalsowindow.py:289 ../quodlibet/qltk/prefs.py:598 msgid "Split _on:" msgstr "Раз_деляне на:" #: ../quodlibet/qltk/exfalsowindow.py:295 ../quodlibet/qltk/prefs.py:613 msgid "Tag Editing" msgstr "Редактиране на етикети" #: ../quodlibet/qltk/filesel.py:210 msgid "Folders" msgstr "Папки" #: ../quodlibet/qltk/filesel.py:253 #, fuzzy msgid "_New Folder…" msgstr "Нова папка" #: ../quodlibet/qltk/filesel.py:262 #, fuzzy msgid "_Select all Sub-Folders" msgstr "_Избор на всички" #: ../quodlibet/qltk/filesel.py:374 msgid "New Folder" msgstr "Нова папка" #: ../quodlibet/qltk/filesel.py:374 msgid "Enter a name for the new folder:" msgstr "Въведете име за новата папка:" #: ../quodlibet/qltk/filesel.py:387 msgid "Unable to create folder" msgstr "Неуспех при създаването на папка" #: ../quodlibet/qltk/filesel.py:404 msgid "Unable to delete folder" msgstr "Неуспех при изтриването на папка" #: ../quodlibet/qltk/filesel.py:519 ../quodlibet/qltk/pluginwin.py:167 msgid "Songs" msgstr "Песни" #. Translators: As in "by Artist Name" #: ../quodlibet/qltk/info.py:42 #, python-format msgid "by %s" msgstr "" #: ../quodlibet/qltk/info.py:43 ../quodlibet/qltk/information.py:167 #: ../quodlibet/qltk/information.py:448 #, python-format msgid "Disc %s" msgstr "Диск %s" #: ../quodlibet/qltk/info.py:44 ../quodlibet/qltk/information.py:172 #, python-format msgid "Track %s" msgstr "Песен номер %s" #: ../quodlibet/qltk/info.py:108 #, fuzzy msgid "_Edit Display…" msgstr "Редактиране на показваното" #: ../quodlibet/qltk/information.py:105 msgid "No songs are selected." msgstr "Няма избрани песни." #: ../quodlibet/qltk/information.py:106 msgid "No Songs" msgstr "Няма песни" #: ../quodlibet/qltk/information.py:121 ../quodlibet/qltk/information.py:338 #: ../quodlibet/qltk/information.py:471 ../quodlibet/qltk/information.py:531 msgid "Information" msgstr "Информация" #: ../quodlibet/qltk/information.py:126 msgid "Lyrics" msgstr "Текст на песен" #: ../quodlibet/qltk/information.py:184 ../quodlibet/qltk/information.py:396 #, python-format msgid "Produced by %s" msgstr "Продуцирано от %s" #: ../quodlibet/qltk/information.py:199 ../quodlibet/util/tags.py:76 msgid "artist" msgstr "артист" #: ../quodlibet/qltk/information.py:200 ../quodlibet/qltk/information.py:561 #: ../quodlibet/util/tags.py:76 msgid "artists" msgstr "артисти" #. for backwards compat #: ../quodlibet/qltk/information.py:221 ../quodlibet/util/tags.py:86 #: ../quodlibet/util/tags.py:114 msgid "performers" msgstr "изпълнители" #: ../quodlibet/qltk/information.py:235 ../quodlibet/qltk/information.py:248 #: ../quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "Никога" #: ../quodlibet/qltk/information.py:236 #, fuzzy, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "%d път" msgstr[1] "%d пъти" #: ../quodlibet/qltk/information.py:254 ../quodlibet/util/tags.py:139 msgid "added" msgstr "добавенa" #: ../quodlibet/qltk/information.py:255 ../quodlibet/util/tags.py:140 msgid "last played" msgstr "последно слушана" #: ../quodlibet/qltk/information.py:256 ../quodlibet/util/tags.py:150 msgid "plays" msgstr "Прослушвания" #: ../quodlibet/qltk/information.py:257 ../quodlibet/util/tags.py:151 msgid "skips" msgstr "пропускания" #: ../quodlibet/qltk/information.py:258 ../quodlibet/util/tags.py:156 msgid "rating" msgstr "оценка" #: ../quodlibet/qltk/information.py:287 msgid "path" msgstr "" #: ../quodlibet/qltk/information.py:288 ../quodlibet/util/tags.py:154 msgid "length" msgstr "времетраене" #: ../quodlibet/qltk/information.py:289 #, fuzzy msgid "format" msgstr "Информация" #: ../quodlibet/qltk/information.py:290 ../quodlibet/util/tags.py:163 msgid "codec" msgstr "" #: ../quodlibet/qltk/information.py:291 ../quodlibet/util/tags.py:164 #, fuzzy msgid "encoding" msgstr "[невалидна кодировка]" #: ../quodlibet/qltk/information.py:292 ../quodlibet/util/tags.py:160 msgid "bitrate" msgstr "" #: ../quodlibet/qltk/information.py:293 ../quodlibet/util/tags.py:161 msgid "file size" msgstr "размер на файла" #: ../quodlibet/qltk/information.py:294 ../quodlibet/util/tags.py:149 msgid "modified" msgstr "променян" #: ../quodlibet/qltk/information.py:331 msgid "Additional" msgstr "" #: ../quodlibet/qltk/information.py:383 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d избрана" msgstr[1] "%d избрани" #: ../quodlibet/qltk/information.py:458 msgid "Track unavailable" msgstr "Песента е неналична" #: ../quodlibet/qltk/information.py:464 msgid "Track List" msgstr "Списък с песни" #: ../quodlibet/qltk/information.py:505 ../quodlibet/qltk/information.py:578 #, 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:508 msgid "Selected Discography" msgstr "Избор на дискография" #: ../quodlibet/qltk/information.py:558 #, 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:586 ../quodlibet/util/tags.py:74 msgid "albums" msgstr "албуми" #: ../quodlibet/qltk/information.py:599 msgid "Total length:" msgstr "Общо времетраене:" #: ../quodlibet/qltk/information.py:603 msgid "Total size:" msgstr "Общ размер:" #: ../quodlibet/qltk/information.py:606 msgid "Files" msgstr "Файлове" #: ../quodlibet/qltk/lyrics.py:37 msgid "_Download" msgstr "Из_тегляне" #: ../quodlibet/qltk/lyrics.py:40 #, fuzzy msgid "_Edit" msgstr "_Редактиране на показваното" #. buffer.set_text(_("No lyrics found.\n\nYou can click the " #. "Download button to have Quod Libet search " #. "for lyrics online. You can also enter them " #. "yourself and click save.")) #: ../quodlibet/qltk/lyrics.py:73 ../quodlibet/qltk/lyrics.py:109 msgid "No lyrics found for this song." msgstr "Няма открит текст за тази песен." #: ../quodlibet/qltk/lyrics.py:82 #, fuzzy msgid "Searching for lyrics…" 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/msg.py:41 msgid "Discard tag changes?" msgstr "Отказване от промените?" #: ../quodlibet/qltk/msg.py:42 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "" "Етикетите бяха променени, но не бяха запазени. Ще запазите промените или ще " "се откажете от тях?" #: ../quodlibet/qltk/msg.py:55 ../quodlibet/qltk/prefs.py:595 #: ../quodlibet/qltk/textedit.py:64 ../quodlibet/qltk/tracknumbers.py:117 #, fuzzy msgid "_Revert" msgstr "Никога" #: ../quodlibet/qltk/msg.py:86 #, fuzzy msgid "File exists" msgstr "Ф_айлова система" #: ../quodlibet/qltk/msg.py:88 #, python-format msgid "Replace %(file-name)s?" msgstr "" #: ../quodlibet/qltk/msg.py:94 #, fuzzy msgid "_Replace File" msgstr "Преименуване на файлове" #: ../quodlibet/qltk/notif.py:182 msgid "Active tasks" msgstr "" #: ../quodlibet/qltk/notif.py:188 #, fuzzy, python-format msgid "%d tasks running" msgstr "Quod Libet е стартиран" #: ../quodlibet/qltk/playorder.py:254 #, fuzzy msgid "Toggle shuffle mode" msgstr "Сменяне между Слушане и Пауза" #: ../quodlibet/qltk/playorder.py:270 #, fuzzy msgid "Toggle repeat mode" msgstr "Сменяне между Слушане и Пауза" #: ../quodlibet/qltk/pluginwin.py:44 msgid "Plugin Errors" msgstr "Грешки на приставките" #: ../quodlibet/qltk/pluginwin.py:124 msgid "Enabled" msgstr "" #: ../quodlibet/qltk/pluginwin.py:125 #, fuzzy msgid "Disabled" msgstr "_Изключване на разглеждането" #: ../quodlibet/qltk/pluginwin.py:131 msgid "No category" msgstr "" #: ../quodlibet/qltk/pluginwin.py:169 msgid "Events" msgstr "" #: ../quodlibet/qltk/pluginwin.py:170 #, fuzzy msgid "Play Order" msgstr "Р_ед на прослушване" #: ../quodlibet/qltk/pluginwin.py:171 #, fuzzy msgid "Editing" msgstr "Редактиране на етикети" #: ../quodlibet/qltk/pluginwin.py:173 #, fuzzy msgid "Covers" msgstr "Общ размер:" #: ../quodlibet/qltk/pluginwin.py:309 msgid "No plugins found." msgstr "Няма открити приставки." #: ../quodlibet/qltk/pluginwin.py:358 #, fuzzy msgid "Plugins" msgstr "П_риставки" #: ../quodlibet/qltk/pluginwin.py:402 msgid "Show _Errors" msgstr "Показване на _грешки" #: ../quodlibet/qltk/prefs.py:45 msgid "_Disc" msgstr "Д_иск" #: ../quodlibet/qltk/prefs.py:46 msgid "_Track" msgstr "Песен н_омер" #: ../quodlibet/qltk/prefs.py:47 #, fuzzy msgid "Grou_ping" msgstr "групиране" #: ../quodlibet/qltk/prefs.py:50 msgid "Al_bum" msgstr "Алб_ум" #: ../quodlibet/qltk/prefs.py:55 msgid "_Filename" msgstr "_Файлово име" #: ../quodlibet/qltk/prefs.py:57 msgid "_Length" msgstr "_Времетраене" #: ../quodlibet/qltk/prefs.py:64 msgid "_Jump to playing song automatically" msgstr "_Автоматично прескачане до текущата песен" #: ../quodlibet/qltk/prefs.py:66 msgid "When the playing song changes, scroll to it in the song list" msgstr "" "Когато слушана песен се смени, автоматично да се селектира нея в списъка с " "песни" #: ../quodlibet/qltk/prefs.py:82 msgid "_Others:" msgstr "_Други:" #: ../quodlibet/qltk/prefs.py:88 #, fuzzy msgid "_Edit…" msgstr "_Редактиране на показваното" #: ../quodlibet/qltk/prefs.py:91 msgid "Add or remove additional column headers" msgstr "" #: ../quodlibet/qltk/prefs.py:101 msgid "Visible Columns" msgstr "Видими колони" #: ../quodlibet/qltk/prefs.py:104 msgid "Title includes _version" msgstr "Заглавието включва _версията" #: ../quodlibet/qltk/prefs.py:106 #, fuzzy msgid "Artist includes all _people" msgstr "Заглавието включва _версията" #: ../quodlibet/qltk/prefs.py:108 msgid "Album includes _disc subtitle" msgstr "" #: ../quodlibet/qltk/prefs.py:110 msgid "Filename includes _folder" msgstr "Името на файла вклю_чва папката" #: ../quodlibet/qltk/prefs.py:123 #, fuzzy msgid "Column Preferences" msgstr "Настройки" #: ../quodlibet/qltk/prefs.py:129 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "" #: ../quodlibet/qltk/prefs.py:142 ../quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Списък на песните" #: ../quodlibet/qltk/prefs.py:222 #, fuzzy msgid "Edit Columns" msgstr "Видими колони" #: ../quodlibet/qltk/prefs.py:259 msgid "Duration totals" msgstr "" #: ../quodlibet/qltk/prefs.py:271 msgid "_Global filter:" msgstr "_Глобален филтър:" #: ../quodlibet/qltk/prefs.py:277 msgid "Apply this query in addition to all others" msgstr "" #. Translators: The heading of the preference group, no action #: ../quodlibet/qltk/prefs.py:283 #, fuzzy msgctxt "heading" msgid "Search" msgstr "Търсене" #: ../quodlibet/qltk/prefs.py:287 ../quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Разглеждане" #: ../quodlibet/qltk/prefs.py:293 msgid "Confirm _multiple ratings" msgstr "" #: ../quodlibet/qltk/prefs.py:295 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "" #: ../quodlibet/qltk/prefs.py:298 msgid "Enable _one-click ratings" msgstr "" #: ../quodlibet/qltk/prefs.py:300 #, fuzzy msgid "Enable rating by clicking on the rating column in the song list" msgstr "" "Когато слушана песен се смени, автоматично да се селектира нея в списъка с " "песни" #: ../quodlibet/qltk/prefs.py:306 ../quodlibet/qltk/prefs.py:616 #, fuzzy msgid "Ratings" msgstr "_Оценка" #. Filename choice algorithm config #: ../quodlibet/qltk/prefs.py:312 msgid "Prefer _embedded art" msgstr "" #: ../quodlibet/qltk/prefs.py:314 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" #: ../quodlibet/qltk/prefs.py:319 msgid "_Fixed image filename:" msgstr "" #: ../quodlibet/qltk/prefs.py:321 msgid "The single image filename to use if selected" msgstr "" #: ../quodlibet/qltk/prefs.py:327 msgid "The album art image file to use when forced" msgstr "" #: ../quodlibet/qltk/prefs.py:336 #, fuzzy msgid "Album Art" msgstr "Спис_ък с албуми" #: ../quodlibet/qltk/prefs.py:357 #, fuzzy msgid "Playback" msgstr "Паузиране на изпълнението" #: ../quodlibet/qltk/prefs.py:362 msgid "Output Configuration" msgstr "" #: ../quodlibet/qltk/prefs.py:373 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" #: ../quodlibet/qltk/prefs.py:376 msgid "_Fall-back gain (dB):" msgstr "" #: ../quodlibet/qltk/prefs.py:387 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "" #: ../quodlibet/qltk/prefs.py:390 msgid "_Pre-amp gain (dB):" msgstr "" #: ../quodlibet/qltk/prefs.py:395 #, fuzzy msgid "_Enable Replay Gain volume adjustment" msgstr "Без нагласяне на силата на звука" #: ../quodlibet/qltk/prefs.py:420 #, fuzzy msgid "Replay Gain Volume Adjustment" msgstr "Без нагласяне на силата на звука" #: ../quodlibet/qltk/prefs.py:450 msgid "_Default rating:" msgstr "" #: ../quodlibet/qltk/prefs.py:493 #, fuzzy msgid "Rating _scale:" msgstr "_Оценка" #: ../quodlibet/qltk/prefs.py:542 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:547 msgid "_Bayesian averaging amount:" msgstr "" #: ../quodlibet/qltk/prefs.py:556 #, fuzzy msgid "Save ratings and play _counts" msgstr "Запазване на оценките и броя на слушания" #: ../quodlibet/qltk/prefs.py:560 msgid "_Email:" msgstr "_Е-поща:" #: ../quodlibet/qltk/prefs.py:562 msgid "Ratings and play counts will be set for this email address" msgstr "Оценките и броя на слушанията ще бъдат настроени за тази е-поща" #: ../quodlibet/qltk/prefs.py:577 #, fuzzy msgid "Auto-save tag changes" msgstr "Отказване от промените?" #: ../quodlibet/qltk/prefs.py:579 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "" #: ../quodlibet/qltk/prefs.py:587 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:610 #, fuzzy msgid "Tags" msgstr "Редактиране на етикетите" #: ../quodlibet/qltk/prefs.py:631 #, fuzzy msgid "Updating for new ratings" msgstr "_Нова станция" #: ../quodlibet/qltk/prefs.py:641 #, fuzzy msgid "Scan library _on start" msgstr "Опресн_яване на фонотеката" #: ../quodlibet/qltk/prefs.py:651 ../quodlibet/qltk/quodlibetwindow.py:1100 #, fuzzy msgid "_Scan Library" msgstr "Т_ърсене във фонотеката" #: ../quodlibet/qltk/prefs.py:653 ../quodlibet/qltk/quodlibetwindow.py:1162 msgid "Check for changes in your library" msgstr "Проверка за промени във фонотеката Ви" #: ../quodlibet/qltk/prefs.py:658 #, fuzzy msgid "Re_build Library" msgstr "Пре_зареждане на фонотеката" #: ../quodlibet/qltk/prefs.py:661 #, fuzzy msgid "Reload all songs in your library. This can take a long time." msgstr "" "Презареждане на всички песни от фонотеката ви (това може да отнеме много " "време)" #: ../quodlibet/qltk/prefs.py:671 #, fuzzy msgid "Scan Directories" msgstr "Сканиране на пап_ки" #: ../quodlibet/qltk/prefs.py:677 #, fuzzy msgid "Hidden Songs" msgstr "Няма песни" #: ../quodlibet/qltk/properties.py:158 ../quodlibet/util/collection.py:398 #, 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:162 ../quodlibet/qltk/properties.py:164 msgid "Properties" msgstr "Информация" #: ../quodlibet/qltk/queue.py:101 msgid "_Queue" msgstr "_Опашка" #: ../quodlibet/qltk/queue.py:126 msgid "Stop Once Empty" msgstr "" #: ../quodlibet/qltk/queue.py:130 #, fuzzy msgid "_Clear Queue" msgstr "Грешки на приставките" #: ../quodlibet/qltk/queue.py:242 #, python-format msgid "%(count)d song (%(time)s)" msgid_plural "%(count)d songs (%(time)s)" msgstr[0] "" msgstr[1] "" #: ../quodlibet/qltk/quodlibetwindow.py:198 msgid "_Browse Library" msgstr "Р_азглеждане на фонотеката" #: ../quodlibet/qltk/quodlibetwindow.py:395 #, fuzzy msgid "Toggle queue visibility" msgstr "Превключване видимостта на главния прозорец" #: ../quodlibet/qltk/quodlibetwindow.py:516 #, fuzzy msgid "Playback Error" msgstr "Паузиране на изпълнението" #: ../quodlibet/qltk/quodlibetwindow.py:524 #, fuzzy msgid "Set up library directories?" msgstr "Избор на папки" #: ../quodlibet/qltk/quodlibetwindow.py:525 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:531 msgid "_Not Now" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:532 msgid "_Set Up" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:956 msgid "Unable to add songs" msgstr "Неуспех при добавяне на песните" #: ../quodlibet/qltk/quodlibetwindow.py:957 #: ../quodlibet/qltk/quodlibetwindow.py:1364 #, fuzzy, python-format msgid "%s uses an unsupported protocol." msgstr "<b>%s</b> използва неподдържан протокол." #: ../quodlibet/qltk/quodlibetwindow.py:980 msgid "_Jump to Playing Song" msgstr "П_рескачане към текущата песен" #: ../quodlibet/qltk/quodlibetwindow.py:986 #, fuzzy msgid "_File" msgstr "Файл" #: ../quodlibet/qltk/quodlibetwindow.py:987 #, fuzzy msgid "_Song" msgstr "Песни" #: ../quodlibet/qltk/quodlibetwindow.py:988 msgid "_View" msgstr "_Преглед" #: ../quodlibet/qltk/quodlibetwindow.py:989 #, fuzzy msgid "_Browse" msgstr "Разглеждане" #: ../quodlibet/qltk/quodlibetwindow.py:990 msgid "_Control" msgstr "_Управление" #: ../quodlibet/qltk/quodlibetwindow.py:991 msgid "_Help" msgstr "Помощ" #: ../quodlibet/qltk/quodlibetwindow.py:997 #, fuzzy msgid "_Add a Folder…" msgstr "_Добавяне на папка..." #: ../quodlibet/qltk/quodlibetwindow.py:1002 #, fuzzy msgid "_Add a File…" msgstr "_Добавяне на файл..." #: ../quodlibet/qltk/quodlibetwindow.py:1007 #, fuzzy msgid "_Add a Location…" msgstr "Добавяне на местоположение" #: ../quodlibet/qltk/quodlibetwindow.py:1036 #, fuzzy msgid "Edit Bookmarks…" msgstr "_Редактиране на отметки..." #: ../quodlibet/qltk/quodlibetwindow.py:1056 #, fuzzy msgid "Stop After This Song" msgstr "Спиране след тази песен" #: ../quodlibet/qltk/quodlibetwindow.py:1062 msgid "_Keyboard Shortcuts" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:1071 msgid "Online Help" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:1080 #, fuzzy msgid "Search Help" msgstr "Търсене" #: ../quodlibet/qltk/quodlibetwindow.py:1352 msgid "Add a Location" msgstr "Добавяне на местоположение" #: ../quodlibet/qltk/quodlibetwindow.py:1353 msgid "Enter the location of an audio file:" msgstr "Въведете местоположението на аудио файл:" #: ../quodlibet/qltk/quodlibetwindow.py:1358 #: ../quodlibet/qltk/quodlibetwindow.py:1363 msgid "Unable to add location" msgstr "Неуспех при добавяне на местоположението" #: ../quodlibet/qltk/quodlibetwindow.py:1359 #, fuzzy, python-format msgid "%s is not a valid location." msgstr "<b>%s</b> не е валидно местоположение." #: ../quodlibet/qltk/quodlibetwindow.py:1372 #: ../quodlibet/qltk/quodlibetwindow.py:1381 msgid "Add Music" msgstr "Добавяне на музика" #: ../quodlibet/qltk/quodlibetwindow.py:1372 ../quodlibet/qltk/scanbox.py:99 #, fuzzy msgid "_Add Folders" msgstr "_Добавяне на папка..." #: ../quodlibet/qltk/quodlibetwindow.py:1379 #, fuzzy msgid "Music Files" msgstr "Слушане на музика" #: ../quodlibet/qltk/quodlibetwindow.py:1381 #, fuzzy msgid "_Add Files" msgstr "_Добавяне на файл..." #: ../quodlibet/qltk/ratingsmenu.py:24 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "" #: ../quodlibet/qltk/ratingsmenu.py:26 msgid "The saved ratings will be removed" msgstr "" #: ../quodlibet/qltk/ratingsmenu.py:27 #, python-format msgid "The rating of all selected songs will be changed to '%s'" msgstr "" #: ../quodlibet/qltk/ratingsmenu.py:57 ../quodlibet/qltk/ratingsmenu.py:111 #, fuzzy msgid "_Remove Rating" msgstr "_Премахване на станция" #: ../quodlibet/qltk/ratingsmenu.py:98 #, fuzzy msgid "Change _Rating" msgstr "_Оценка" #: ../quodlibet/qltk/renamefiles.py:46 msgid "Replace spaces with _underscores" msgstr "Заменяне на интервалите с долни черти" #: ../quodlibet/qltk/renamefiles.py:56 msgid "Strip _Windows-incompatible characters" msgstr "Премахване на _несъвместимите с Windows символи" #: ../quodlibet/qltk/renamefiles.py:74 msgid "Strip _diacritical marks" msgstr "Премахване на _диакритичните знаци" #: ../quodlibet/qltk/renamefiles.py:85 msgid "Strip non-_ASCII characters" msgstr "Премахване на н_e-ASCII символите" #: ../quodlibet/qltk/renamefiles.py:95 msgid "Use only _lowercase characters" msgstr "" #: ../quodlibet/qltk/renamefiles.py:123 msgid "Rename Files" msgstr "Преименуване на файлове" #: ../quodlibet/qltk/renamefiles.py:139 ../quodlibet/qltk/tagsfrompath.py:116 #, fuzzy msgid "Path Patterns" msgstr "шаблон" #: ../quodlibet/qltk/renamefiles.py:140 ../quodlibet/qltk/tagsfrompath.py:117 #, fuzzy msgid "Edit saved patterns…" msgstr "Запазване на редактираните стойности..." #: ../quodlibet/qltk/renamefiles.py:143 ../quodlibet/qltk/tagsfrompath.py:120 #: ../quodlibet/qltk/tracknumbers.py:58 msgid "_Preview" msgstr "Пре_глед" #: ../quodlibet/qltk/renamefiles.py:190 msgid "New Name" msgstr "Ново име" #: ../quodlibet/qltk/renamefiles.py:255 msgid "Unable to rename file" msgstr "Неуспех при преименуване на файл." #: ../quodlibet/qltk/renamefiles.py:256 #, fuzzy, python-format msgid "" "Renaming <b>%(old-name)s</b> to <b>%(new-name)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." msgstr "" "Пропадна преименуването на <b>%s</b> на <b>%s</b>. Възможно е да има вече " "файл с такова име или да нямате привилегиите да създадете нов файл или да " "премахвате стария." #: ../quodlibet/qltk/renamefiles.py:264 #, fuzzy msgid "Ignore _All Errors" msgstr "Показване на _грешки" #: ../quodlibet/qltk/renamefiles.py:267 msgid "_Continue" msgstr "_Продължаване" #: ../quodlibet/qltk/renamefiles.py:296 msgid "Path is not absolute" msgstr "Местоположението не е абсолютно" #: ../quodlibet/qltk/renamefiles.py:297 #, python-format msgid "" "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 ~/." msgstr "" "Шаблона\n" "\t<b>%s</b>\n" "съдържа /, но не започва от главната папка (root folder). За да се избегнат " "зле именувани папки, направете шаблона да започва с / или ~/." #: ../quodlibet/qltk/scanbox.py:47 #, fuzzy msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "Песните поставени в тези папки ще бъдат добавяни към фонотеката" #: ../quodlibet/qltk/scanbox.py:99 msgid "Select Directories" msgstr "Избор на папки" #: ../quodlibet/qltk/searchbar.py:52 #, fuzzy msgid "Saved Searches" msgstr "Запазени стойности" #: ../quodlibet/qltk/searchbar.py:53 #, fuzzy msgid "Edit saved searches…" msgstr "Запазване на редактираните стойности..." #: ../quodlibet/qltk/searchbar.py:74 msgid "Search your library, using free text or QL queries" msgstr "" #: ../quodlibet/qltk/searchbar.py:129 #, fuzzy msgid "Search after _typing" msgstr "Спиране след тази песен" #: ../quodlibet/qltk/searchbar.py:132 msgid "Show search results after the user stops typing." msgstr "" #: ../quodlibet/qltk/searchbar.py:187 msgid "_Limit:" msgstr "_Ограничаване:" #: ../quodlibet/qltk/searchbar.py:200 msgid "_Weight" 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 ../quodlibet/qltk/shortcuts.py:41 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: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:377 #, python-format msgid "_Filter on %s" msgstr "_Само този %s" #: ../quodlibet/qltk/songlist.py:1094 #, fuzzy msgid "All _Headers" msgstr "Спис_ък с албуми" #: ../quodlibet/qltk/songlist.py:1095 #, fuzzy msgid "_Track Headers" msgstr "Номера на песните" #: ../quodlibet/qltk/songlist.py:1096 #, fuzzy msgid "_Album Headers" msgstr "Спис_ък с албуми" #: ../quodlibet/qltk/songlist.py:1097 msgid "_People Headers" msgstr "" #: ../quodlibet/qltk/songlist.py:1098 msgid "_Date Headers" msgstr "" #: ../quodlibet/qltk/songlist.py:1099 #, fuzzy msgid "_File Headers" msgstr "_Филтри" #: ../quodlibet/qltk/songlist.py:1100 msgid "_Production Headers" msgstr "" #: ../quodlibet/qltk/songlist.py:1115 #, fuzzy msgid "_Customize Headers…" msgstr "_Филтри" #: ../quodlibet/qltk/songlist.py:1120 msgid "_Expand Column" msgstr "" #: ../quodlibet/qltk/songsmenu.py:36 #, 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:64 #, 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:149 #, fuzzy msgid "Configure Plugins…" msgstr "Оцветяване на _търсените фрази" #: ../quodlibet/qltk/songsmenu.py:345 msgid "Add to _Queue" msgstr "Добавяне към _опашката" #: ../quodlibet/qltk/songsmenu.py:368 msgid "_Copy to Device" msgstr "" #: ../quodlibet/qltk/songsmenu.py:379 #, fuzzy msgid "_Remove from Library" 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:101 msgid "Tags From Path" msgstr "Етикети от местоположението" #: ../quodlibet/qltk/tagsfrompath.py:138 msgid "Tags replace existing ones" msgstr "Етикетите заменят съществуващите" #: ../quodlibet/qltk/tagsfrompath.py:139 msgid "Tags are added to existing ones" msgstr "Етикетите се добавят към съществуващите" #. Save button #: ../quodlibet/qltk/tagsfrompath.py:153 msgid "Save" msgstr "" #: ../quodlibet/qltk/tagsfrompath.py:195 #, python-format msgid "" "The pattern\n" "\t<b>%s</b>\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" "Шаблонът\n" "\t<b>%s</b>\n" "е невалиден. Възможно е да съдържа същия етикет два пъти или има " "небалансирани скоби (< / >)." #: ../quodlibet/qltk/tagsfrompath.py:216 msgid "Invalid tags" msgstr "Невалидни етикети" #: ../quodlibet/qltk/tagsfrompath.py:217 #, 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" "Избраните в момента файлове не поддържат редактиране на тези етикети." #: ../quodlibet/qltk/textedit.py:142 #, 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:158 msgid "Edit Display" msgstr "Редактиране на показваното" #: ../quodlibet/qltk/tracknumbers.py:39 msgid "Track Numbers" msgstr "Номера на песните" #: ../quodlibet/qltk/tracknumbers.py:42 msgid "Start fro_m:" msgstr "Запо_чване от:" #: ../quodlibet/qltk/tracknumbers.py:51 msgid "_Total tracks:" msgstr "_Общо песни:" #: ../quodlibet/qltk/unity.py:52 #, fuzzy msgid "Play/Pause" msgstr "Преслушване" #: ../quodlibet/qltk/unity.py:75 #, fuzzy msgid "Previous" msgstr "Пре_глед" #: ../quodlibet/qltk/views.py:923 #, 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:89 #, fuzzy msgid "Checking for Updates" msgstr "точка на монтиране" #: ../quodlibet/update.py:124 #, fuzzy msgid "Connection failed" msgstr "местонахождение" #: ../quodlibet/update.py:133 #, python-format msgid "You are already using the newest version %(version)s" msgstr "" #: ../quodlibet/update.py:136 #, 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:420 msgid "Playlists must have a name" msgstr "" #: ../quodlibet/util/collection.py:603 #, python-format msgid "A playlist named %s already exists." msgstr "Списък с песни с името %s, вече съществува." #: ../quodlibet/util/cover/built_in.py:26 #, fuzzy msgid "Embedded album covers" msgstr "Показване на _обложките" #: ../quodlibet/util/cover/built_in.py:27 msgid "Uses covers embedded into audio files." msgstr "" #: ../quodlibet/util/cover/built_in.py:49 #, fuzzy msgid "Filesystem cover" msgstr "Ф_айлова система" #: ../quodlibet/util/cover/built_in.py:50 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "" #: ../quodlibet/util/__init__.py:93 msgid "Display brief usage information" msgstr "Показване на кратка информация за употреба" #: ../quodlibet/util/__init__.py:95 msgid "Display version and copyright" msgstr "Показване на версията на запазените права" #: ../quodlibet/util/__init__.py:135 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "" #: ../quodlibet/util/__init__.py:137 msgid "[options]" msgstr "[опции]" #: ../quodlibet/util/__init__.py:182 #, fuzzy, python-format msgid "Option %r not recognized." msgstr "E: Опцията \"%s\" не е разпозната." #: ../quodlibet/util/__init__.py:185 #, fuzzy, python-format msgid "Option %r requires an argument." msgstr "E: Опцията \"%s\" изисква аргумент." #: ../quodlibet/util/__init__.py:188 #, fuzzy, python-format msgid "%r is not a unique prefix." msgstr "E: \"%s\" не е уникална представка." #: ../quodlibet/util/__init__.py:364 #, python-format msgid "%d kbps" msgstr "%d kbps" #: ../quodlibet/util/__init__.py:419 #, fuzzy, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%d секунда" msgstr[1] "%d секунди" #: ../quodlibet/util/__init__.py:432 msgid "No time information" msgstr "Няма информация за времетраенето" #: ../quodlibet/util/__init__.py:435 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d секунда" msgstr[1] "%d секунди" #: ../quodlibet/util/__init__.py:436 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d минута" msgstr[1] "%d минути" #: ../quodlibet/util/__init__.py:437 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d час" msgstr[1] "%d часа" #: ../quodlibet/util/__init__.py:438 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d ден" msgstr[1] "%d дни" #: ../quodlibet/util/__init__.py:439 #, 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:563 #, 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 msgid "Unable to edit song" msgstr "Неуспех при редактиране на песента" #: ../quodlibet/util/songwrapper.py:113 #, python-format msgid "" "Saving <b>%s</b> 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:34 #: ../quodlibet/util/string/__init__.py:44 msgid "[Invalid Encoding]" msgstr "[невалидна кодировка]" #: ../quodlibet/util/tags.py:74 msgid "album" msgstr "албум" #: ../quodlibet/util/tags.py:75 msgid "arranger" msgstr "аранжимент" #: ../quodlibet/util/tags.py:75 msgid "arrangers" msgstr "аранжименти" #: ../quodlibet/util/tags.py:75 #, fuzzy msgid "arrangement" msgstr "аранжимент" #: ../quodlibet/util/tags.py:77 msgid "author" msgstr "автор" #: ../quodlibet/util/tags.py:77 msgid "authors" msgstr "автори" #: ../quodlibet/util/tags.py:78 msgid "composer" msgstr "композитор" #: ../quodlibet/util/tags.py:78 msgid "composers" msgstr "композитори" #: ../quodlibet/util/tags.py:78 #, fuzzy msgid "composition" msgstr "композитор" #. Translators: conducting as in conducting a musical performance #: ../quodlibet/util/tags.py:80 msgid "conductor" msgstr "диригент" #: ../quodlibet/util/tags.py:80 msgid "conductors" msgstr "диригенти" #: ../quodlibet/util/tags.py:80 #, fuzzy msgid "conducting" msgstr "диригент" #: ../quodlibet/util/tags.py:81 msgid "contact" msgstr "за контакт" #: ../quodlibet/util/tags.py:82 msgid "copyright" msgstr "авторски права" #: ../quodlibet/util/tags.py:83 msgid "date" msgstr "дата" #: ../quodlibet/util/tags.py:84 msgid "description" msgstr "описание" #: ../quodlibet/util/tags.py:85 msgid "genre" msgstr "жанр" #: ../quodlibet/util/tags.py:85 #, fuzzy msgid "genres" msgstr "жанр" #: ../quodlibet/util/tags.py:86 msgid "performer" msgstr "изпълнител" #: ../quodlibet/util/tags.py:87 msgid "grouping" msgstr "групиране" #: ../quodlibet/util/tags.py:88 msgid "language" msgstr "език" #: ../quodlibet/util/tags.py:89 msgid "license" msgstr "лиценз" #: ../quodlibet/util/tags.py:90 msgid "location" msgstr "местонахождение" #: ../quodlibet/util/tags.py:91 msgid "lyricist" msgstr "текстописец" #: ../quodlibet/util/tags.py:91 msgid "lyricists" msgstr "текстописци" #: ../quodlibet/util/tags.py:91 #, fuzzy msgid "lyrics" msgstr "текстописец" #. Translators: Also e.g. "record label", "publisher" #: ../quodlibet/util/tags.py:93 msgid "organization" msgstr "организация" #: ../quodlibet/util/tags.py:94 msgid "title" msgstr "заглавие" #: ../quodlibet/util/tags.py:95 msgid "version" msgstr "версия" #: ../quodlibet/util/tags.py:96 msgid "website" msgstr "интернет сайт" #: ../quodlibet/util/tags.py:98 msgid "album artist" msgstr "Артист на албума" #: ../quodlibet/util/tags.py:99 msgid "BPM" msgstr "BPM" #. Translators: This used to be called "part". #: ../quodlibet/util/tags.py:102 ../quodlibet/util/tags.py:103 msgid "disc subtitle" msgstr "" #: ../quodlibet/util/tags.py:104 ../quodlibet/util/tags.py:141 msgid "disc" msgstr "диск" #: ../quodlibet/util/tags.py:105 ../quodlibet/util/tags.py:143 msgid "track" msgstr "номер" #: ../quodlibet/util/tags.py:106 msgid "label ID" msgstr "каталожен номер" #: ../quodlibet/util/tags.py:107 msgid "original release date" msgstr "оригинална дата на издаване" #: ../quodlibet/util/tags.py:108 msgid "original album" msgstr "оригинален албум" #: ../quodlibet/util/tags.py:109 msgid "original artist" msgstr "оригинален артист" #: ../quodlibet/util/tags.py:110 msgid "recording date" msgstr "дата на запис" #: ../quodlibet/util/tags.py:111 msgid "release country" 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:120 #, fuzzy msgid "MusicBrainz recording ID" msgstr "ID в MusicBrainz на песента" #: ../quodlibet/util/tags.py:121 #, fuzzy msgid "MusicBrainz release track ID" msgstr "ID в MusicBrainz на песента" #: ../quodlibet/util/tags.py:122 #, fuzzy msgid "MusicBrainz release ID" msgstr "ID в MusicBrainz на песента" #: ../quodlibet/util/tags.py:123 #, fuzzy msgid "MusicBrainz artist ID" msgstr "ID в MusicBrainz на артиста" #: ../quodlibet/util/tags.py:124 #, fuzzy msgid "MusicBrainz release artist ID" msgstr "ID в MusicBrainz на песента" #: ../quodlibet/util/tags.py:125 msgid "MusicBrainz TRM ID" msgstr "" #: ../quodlibet/util/tags.py:126 msgid "MusicIP PUID" msgstr "" #: ../quodlibet/util/tags.py:127 #, fuzzy msgid "MusicBrainz album status" msgstr "ID в MusicBrainz за артиста на албума" #: ../quodlibet/util/tags.py:128 #, fuzzy msgid "MusicBrainz album type" msgstr "ID в MusicBrainz на албума" #: ../quodlibet/util/tags.py:129 #, fuzzy msgid "MusicBrainz release group ID" msgstr "ID в MusicBrainz на песента" #. Translators: "gain" means a volume adjustment, not "to acquire". #: ../quodlibet/util/tags.py:132 #, fuzzy msgid "track gain" msgstr "номер" #: ../quodlibet/util/tags.py:133 #, fuzzy msgid "track peak" msgstr "номер" #. Translators: "gain" means a volume adjustment, not "to acquire". #: ../quodlibet/util/tags.py:135 #, fuzzy msgid "album gain" msgstr "албум" #: ../quodlibet/util/tags.py:136 #, fuzzy msgid "album peak" msgstr "албум" #: ../quodlibet/util/tags.py:137 #, fuzzy msgid "reference loudness" msgstr "Настройки" #: ../quodlibet/util/tags.py:142 msgid "discs" msgstr "дискове" #: ../quodlibet/util/tags.py:144 msgid "tracks" msgstr "песни" #: ../quodlibet/util/tags.py:145 #, fuzzy msgid "last started" msgstr "последно слушана" #: ../quodlibet/util/tags.py:146 msgid "full name" msgstr "пълно име" #: ../quodlibet/util/tags.py:153 msgid "mount point" msgstr "точка на монтиране" #: ../quodlibet/util/tags.py:155 msgid "people" msgstr "човека" #: ../quodlibet/util/tags.py:157 msgid "year" msgstr "година" #: ../quodlibet/util/tags.py:158 #, fuzzy msgid "original release year" msgstr "оригинална дата на издаване" #: ../quodlibet/util/tags.py:159 #, fuzzy msgid "bookmark" msgstr "Отметки" #: ../quodlibet/util/tags.py:162 #, fuzzy msgid "file format" msgstr "формат" #: ../quodlibet/util/tags.py:165 #, fuzzy msgid "playlists" msgstr "Сп_исъци с песни" #: ../quodlibet/util/tags.py:166 msgid "channel count" msgstr "" #. Translators: e.g. "artist (sort)" #: ../quodlibet/util/tags.py:256 msgid "sort" msgstr "" #. Translators: e.g. "performer (roles)" #: ../quodlibet/util/tags.py:264 msgid "roles" msgstr "" #, fuzzy #~ msgid "browsers" #~ msgstr "Разглеждане" #~ msgid "Unable to download lyrics." #~ msgstr "Неуспех при изтегляне на текстовете" #~ msgid "Remove all songs from the queue" #~ msgstr "Премахване на всички песни от опашката" #~ msgid "Watch this folder for new songs" #~ 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 "Unable to open input files" #~ 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 "_Select" #~ 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 "Choose New Stations" #~ msgstr "Избор на нови станции" #~ msgid "Add" #~ msgstr "Добавяне" #~ msgid "_Stations..." #~ msgstr "_Станции..." #, fuzzy #~ msgid "Quod Libet" #~ msgstr "Затваряне на Quod Libet" #~ 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9471855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/po/cs.po����������������������������������������������������������������������������0000644�0001750�0001750�00000617417�00000000000�014101� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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: 2018-01-04 19:29+0100\n" "PO-Revision-Date: 2018-01-04 13:47+0100\n" "Last-Translator: Honza Hejzl <honza.hejzl@gmail.com>\n" "Language-Team: Czech (Czech Republic)\n" "Language: cs_CZ\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: Poedit 1.8.8\n" #: ../data/exfalso.appdata.xml.in.h:1 ../data/exfalso.desktop.in.h:2 msgid "Edit tags in your audio files" msgstr "Editovat tagy skladeb" #: ../data/exfalso.appdata.xml.in.h:2 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/exfalso.appdata.xml.in.h:3 ../data/quodlibet.appdata.xml.in.h:3 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/exfalso.desktop.in.h:1 msgid "Audio tag editor" msgstr "Editor tagů" #: ../data/quodlibet.appdata.xml.in.h:1 ../data/quodlibet.desktop.in.h:2 msgid "Listen to, browse, or edit your audio collection" msgstr "Poslouchejte, procházejte nebo upravujte svou hudební sbírku" #: ../data/quodlibet.appdata.xml.in.h:2 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í." #: ../data/quodlibet.desktop.in.h:1 msgid "Music Player" msgstr "Přehrávač hudby" #: ../quodlibet/browsers/albums/main.py:169 #: ../quodlibet/browsers/covergrid/main.py:55 msgid "_Title" msgstr "_Název" #: ../quodlibet/browsers/albums/main.py:170 #: ../quodlibet/browsers/covergrid/main.py:56 ../quodlibet/qltk/prefs.py:50 msgid "_Artist" msgstr "_Umělec" #: ../quodlibet/browsers/albums/main.py:171 #: ../quodlibet/browsers/covergrid/main.py:57 ../quodlibet/qltk/prefs.py:55 msgid "_Date" msgstr "_Datum" #: ../quodlibet/browsers/albums/main.py:172 #: ../quodlibet/browsers/covergrid/main.py:58 ../quodlibet/qltk/prefs.py:54 msgid "_Genre" msgstr "_Žánr" #: ../quodlibet/browsers/albums/main.py:173 #: ../quodlibet/browsers/covergrid/main.py:59 ../quodlibet/qltk/prefs.py:59 #: ../quodlibet/qltk/ratingsmenu.py:40 msgid "_Rating" msgstr "_Hodnocení" #: ../quodlibet/browsers/albums/main.py:179 #: ../quodlibet/browsers/covergrid/main.py:65 msgid "Sort _by…" msgstr "Řadit _podle…" #: ../quodlibet/browsers/albums/main.py:200 #: ../quodlibet/browsers/covergrid/main.py:86 #: ../quodlibet/browsers/paned/prefs.py:167 #: ../quodlibet/browsers/playlists/main.py:638 #: ../quodlibet/qltk/exfalsowindow.py:110 ../quodlibet/qltk/pluginwin.py:342 #: ../quodlibet/qltk/quodlibetwindow.py:1053 msgid "_Preferences" msgstr "_Nastavení" #: ../quodlibet/browsers/albums/main.py:363 msgid "Album List" msgstr "Seznam alb" #: ../quodlibet/browsers/albums/main.py:364 msgid "_Album List" msgstr "_Seznam alb" #: ../quodlibet/browsers/albums/main.py:474 #: ../quodlibet/browsers/covergrid/main.py:281 #: ../quodlibet/browsers/covergrid/main.py:492 msgid "All Albums" msgstr "Všechna alba" #: ../quodlibet/browsers/albums/main.py:475 #: ../quodlibet/browsers/covergrid/main.py:282 #: ../quodlibet/browsers/covergrid/main.py:493 #, 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:654 #: ../quodlibet/browsers/covergrid/main.py:471 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:29 #: ../quodlibet/browsers/collection/models.py:18 #: ../quodlibet/browsers/covergrid/prefs.py:31 msgid "Songs not in an album" msgstr "Skladby neobsažené v albu" #: ../quodlibet/browsers/albums/prefs.py:42 #: ../quodlibet/browsers/covergrid/prefs.py:44 #: ../quodlibet/browsers/playlists/prefs.py:36 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:100 #: ../quodlibet/qltk/information.py:386 ../quodlibet/util/collection.py:246 #, 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:43 #: ../quodlibet/browsers/covergrid/prefs.py:45 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:99 #: ../quodlibet/qltk/information.py:384 ../quodlibet/util/collection.py:250 #, 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:45 #: ../quodlibet/browsers/covergrid/prefs.py:47 msgid "An Example Album" msgstr "Příklad alba" #: ../quodlibet/browsers/albums/prefs.py:53 msgid "Album List Preferences" msgstr "Nastavení seznamu skladeb" #: ../quodlibet/browsers/albums/prefs.py:62 msgid "Show album _covers" msgstr "Zobrazovat _přebaly alb" #: ../quodlibet/browsers/albums/prefs.py:68 msgid "Inline _search includes people" msgstr "_Hledání obsahuje osoby" #: ../quodlibet/browsers/albums/prefs.py:72 #: ../quodlibet/browsers/covergrid/prefs.py:121 msgid "Options" msgstr "Možnosti" #: ../quodlibet/browsers/albums/prefs.py:75 #: ../quodlibet/browsers/covergrid/prefs.py:124 msgid "Album Display" msgstr "Zobrazení alba" #: ../quodlibet/browsers/albums/prefs.py:79 #: ../quodlibet/browsers/covergrid/prefs.py:128 #: ../quodlibet/browsers/playlists/prefs.py:57 #: ../quodlibet/ext/songsmenu/albumart.py:328 #: ../quodlibet/ext/songsmenu/duplicates.py:349 #: ../quodlibet/ext/songsmenu/filterall.py:49 #: ../quodlibet/qltk/bookmarks.py:102 ../quodlibet/qltk/cbes.py:94 #: ../quodlibet/qltk/data_editors.py:98 ../quodlibet/qltk/data_editors.py:323 #: ../quodlibet/qltk/exfalsowindow.py:298 ../quodlibet/qltk/pluginwin.py:80 #: ../quodlibet/qltk/pluginwin.py:429 ../quodlibet/qltk/prefs.py:708 #: ../quodlibet/qltk/textedit.py:165 ../quodlibet/update.py:149 msgid "_Close" msgstr "_Zavřít" #: ../quodlibet/browsers/audiofeeds.py:53 #: ../quodlibet/browsers/audiofeeds.py:65 #: ../quodlibet/browsers/audiofeeds.py:67 #: ../quodlibet/browsers/audiofeeds.py:157 #: ../quodlibet/browsers/paned/models.py:87 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:47 #: ../quodlibet/formats/_audio.py:498 ../quodlibet/order/__init__.py:28 #: ../quodlibet/qltk/information.py:245 ../quodlibet/qltk/information.py:252 #: ../quodlibet/qltk/information.py:278 ../quodlibet/qltk/wlw.py:71 msgid "Unknown" msgstr "Neznámé" #: ../quodlibet/browsers/audiofeeds.py:248 msgid "New Feed" msgstr "Nový zdroj" #: ../quodlibet/browsers/audiofeeds.py:249 msgid "Enter the location of an audio feed:" msgstr "Zadejte umístění audio zdroje:" #: ../quodlibet/browsers/audiofeeds.py:250 #: ../quodlibet/browsers/collection/prefs.py:91 #: ../quodlibet/browsers/iradio.py:347 ../quodlibet/browsers/paned/prefs.py:79 #: ../quodlibet/browsers/playlists/menu.py:97 #: ../quodlibet/browsers/playlists/util.py:54 ../quodlibet/qltk/bookmarks.py:63 #: ../quodlibet/qltk/cbes.py:56 ../quodlibet/qltk/data_editors.py:310 #: ../quodlibet/qltk/edittags.py:289 ../quodlibet/qltk/edittags.py:489 #: ../quodlibet/qltk/quodlibetwindow.py:1388 ../quodlibet/qltk/scanbox.py:62 msgid "_Add" msgstr "_Přidat" #: ../quodlibet/browsers/audiofeeds.py:304 msgid "Audio Feeds" msgstr "Audio zdroje" #: ../quodlibet/browsers/audiofeeds.py:305 msgid "_Audio Feeds" msgstr "_Audio zdroje" #: ../quodlibet/browsers/audiofeeds.py:408 #: ../quodlibet/browsers/playlists/main.py:216 #: ../quodlibet/qltk/data_editors.py:95 msgid "_New" msgstr "_Nový" #: ../quodlibet/browsers/audiofeeds.py:468 #: ../quodlibet/browsers/audiofeeds.py:527 msgid "Unable to add feed" msgstr "Nelze přidat zdroj" #: ../quodlibet/browsers/audiofeeds.py:469 #: ../quodlibet/browsers/audiofeeds.py:528 #, python-format msgid "" "%s could not be added. The server may be down, or the location may not be an " "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/audiofeeds.py:476 ../quodlibet/qltk/filesel.py:272 #: ../quodlibet/qltk/pluginwin.py:415 msgid "_Refresh" msgstr "_Obnovit" #: ../quodlibet/browsers/audiofeeds.py:477 #: ../quodlibet/browsers/playlists/main.py:459 #: ../quodlibet/browsers/playlists/util.py:45 ../quodlibet/qltk/delete.py:144 #: ../quodlibet/qltk/filesel.py:269 ../quodlibet/qltk/lyrics.py:36 #: ../quodlibet/qltk/maskedbox.py:29 ../quodlibet/qltk/songsmenu.py:363 msgid "_Delete" msgstr "_Smazat" #: ../quodlibet/browsers/audiofeeds.py:544 msgid "" "The current audio backend does not support URLs, Audio Feeds browser " "disabled." msgstr "" "Současná obslužná aplikace nepodporuje URL, prohlížeč audio zdrojů je " "zakázán." #: ../quodlibet/browsers/_base.py:148 ../quodlibet/browsers/_base.py:151 msgid "Library Browser" msgstr "Prohlížeč sbírky" #: ../quodlibet/browsers/_base.py:275 ../quodlibet/ext/songsmenu/console.py:47 #: ../quodlibet/ext/songsmenu/refresh.py:31 #: ../quodlibet/qltk/exfalsowindow.py:242 ../quodlibet/qltk/information.py:547 #: ../quodlibet/qltk/maskedbox.py:69 ../quodlibet/util/collection.py:532 #, 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:403 ../quodlibet/browsers/_base.py:408 #: ../quodlibet/qltk/tagsfrompath.py:195 ../quodlibet/qltk/textedit.py:142 #: ../quodlibet/util/__init__.py:574 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:25 #, python-format msgid "Unknown %s" msgstr "Neznámé %s" #: ../quodlibet/browsers/collection/models.py:26 #, python-format msgid "Multiple %s Values" msgstr "Více %s hodnot" #: ../quodlibet/browsers/collection/prefs.py:67 #: ../quodlibet/browsers/paned/prefs.py:52 msgid "_Custom" msgstr "_Vlastní" #. Remove button #: ../quodlibet/browsers/collection/prefs.py:95 #: ../quodlibet/browsers/paned/prefs.py:83 #: ../quodlibet/browsers/playlists/menu.py:98 #: ../quodlibet/ext/playlist/remove_duplicates.py:61 #: ../quodlibet/qltk/bookmarks.py:98 ../quodlibet/qltk/bookmarks.py:128 #: ../quodlibet/qltk/cbes.py:83 ../quodlibet/qltk/cbes.py:90 #: ../quodlibet/qltk/data_editors.py:80 ../quodlibet/qltk/data_editors.py:93 #: ../quodlibet/qltk/data_editors.py:300 ../quodlibet/qltk/data_editors.py:313 #: ../quodlibet/qltk/data_editors.py:321 ../quodlibet/qltk/edittags.py:495 #: ../quodlibet/qltk/edittags.py:635 ../quodlibet/qltk/maskedbox.py:49 #: ../quodlibet/qltk/maskedbox.py:89 ../quodlibet/qltk/queue.py:371 #: ../quodlibet/qltk/scanbox.py:37 ../quodlibet/qltk/scanbox.py:64 msgid "_Remove" msgstr "Odstranit" #: ../quodlibet/browsers/collection/prefs.py:123 #: ../quodlibet/ext/songsmenu/filterall.py:35 #: ../quodlibet/operon/commands.py:57 ../quodlibet/operon/commands.py:93 #: ../quodlibet/qltk/edittags.py:432 msgid "Tag" msgstr "Tag" #: ../quodlibet/browsers/collection/prefs.py:129 msgid "Merge" msgstr "Sloučit" #: ../quodlibet/browsers/collection/prefs.py:189 msgid "Album Collection Preferences" msgstr "Nastavení sbírky alb" #: ../quodlibet/browsers/collection/prefs.py:196 #: ../quodlibet/browsers/paned/prefs.py:210 #: ../quodlibet/ext/songsmenu/editplaycount.py:46 #: ../quodlibet/ext/songsmenu/exact_rating.py:39 #: ../quodlibet/player/gstbe/prefs.py:41 ../quodlibet/qltk/prefs.py:128 #: ../quodlibet/qltk/textedit.py:66 msgid "_Apply" msgstr "_Použít" #: ../quodlibet/browsers/collection/prefs.py:199 #: ../quodlibet/browsers/paned/prefs.py:214 #: ../quodlibet/browsers/playlists/menu.py:96 #: ../quodlibet/browsers/playlists/util.py:44 #: ../quodlibet/errorreport/ui.py:104 #: ../quodlibet/ext/playlist/export_to_folder.py:38 #: ../quodlibet/ext/playlist/remove_duplicates.py:60 #: ../quodlibet/ext/_shared/squeezebox/util.py:20 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:356 #: ../quodlibet/ext/songsmenu/editplaycount.py:45 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:282 #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:92 #: ../quodlibet/ext/songsmenu/importexport.py:40 #: ../quodlibet/ext/songsmenu/lastfmsync.py:219 #: ../quodlibet/ext/songsmenu/playlist.py:51 #: ../quodlibet/ext/songsmenu/replaygain.py:364 #: ../quodlibet/ext/songsmenu/tapbpm.py:182 ../quodlibet/qltk/chooser.py:189 #: ../quodlibet/qltk/chooser.py:210 ../quodlibet/qltk/chooser.py:234 #: ../quodlibet/qltk/chooser.py:258 ../quodlibet/qltk/delete.py:91 #: ../quodlibet/qltk/delete.py:134 ../quodlibet/qltk/edittags.py:288 #: ../quodlibet/qltk/_editutils.py:40 ../quodlibet/qltk/getstring.py:29 #: ../quodlibet/qltk/maskedbox.py:28 ../quodlibet/qltk/msg.py:55 #: ../quodlibet/qltk/msg.py:94 ../quodlibet/qltk/msg.py:112 #: ../quodlibet/qltk/ratingsmenu.py:34 ../quodlibet/update.py:95 msgid "_Cancel" msgstr "_Zrušit" #: ../quodlibet/browsers/covergrid/main.py:127 msgid "Cover Grid" msgstr "Mřížka přebalů alb" #: ../quodlibet/browsers/covergrid/main.py:128 msgid "_Cover Grid" msgstr "_Mřížka přebalů alb" #: ../quodlibet/browsers/covergrid/prefs.py:55 msgid "Cover Grid Preferences" msgstr "Nastavení mřížky přebalů alb" #: ../quodlibet/browsers/covergrid/prefs.py:65 msgid "Show album _text" msgstr "Zobrazovat _texty alba" #: ../quodlibet/browsers/covergrid/prefs.py:72 msgid "Show \"All Albums\" Item" msgstr "Zobrazit položku „Všechna alba“" #: ../quodlibet/browsers/covergrid/prefs.py:79 #, fuzzy msgid "Wide Mode" msgstr "Ši_roký mód" #: ../quodlibet/browsers/covergrid/prefs.py:111 #: ../quodlibet/browsers/covergrid/prefs.py:112 msgid "Cover Magnification" msgstr "Zvětšení přebalu alba" #: ../quodlibet/browsers/filesystem.py:41 msgid "File System" msgstr "Systém souborů" #: ../quodlibet/browsers/filesystem.py:42 msgid "_File System" msgstr "_Systém souborů" #: ../quodlibet/browsers/filesystem.py:126 ../quodlibet/qltk/songlist.py:256 msgid "Unable to copy songs" msgstr "Nelze kopírovat skladby" #: ../quodlibet/browsers/filesystem.py:127 ../quodlibet/qltk/songlist.py:257 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:199 msgid "_Add to Library" msgstr "_Přidat do sbírky" #: ../quodlibet/browsers/iradio.py:179 msgid "Unsupported file type" msgstr "Nepodporovaný formát souboru" #: ../quodlibet/browsers/iradio.py:180 #, 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:220 ../quodlibet/browsers/iradio.py:233 #: ../quodlibet/browsers/iradio.py:817 msgid "Unable to add station" msgstr "Nelze přidat stanici" #: ../quodlibet/browsers/iradio.py:244 ../quodlibet/browsers/iradio.py:477 msgid "Internet Radio" msgstr "Internetová rádia" #: ../quodlibet/browsers/iradio.py:244 msgid "Downloading station list" msgstr "Stahování seznamu stanic" #: ../quodlibet/browsers/iradio.py:345 msgid "New Station" msgstr "Nová stanice" #: ../quodlibet/browsers/iradio.py:346 msgid "Enter the location of an Internet radio station:" msgstr "Zadejte umístění stanice internetového rádia:" #: ../quodlibet/browsers/iradio.py:364 msgid "Electronic" msgstr "Elektronika" #: ../quodlibet/browsers/iradio.py:367 msgid "Hip Hop / Rap" msgstr "Hip Hop / Rap" #: ../quodlibet/browsers/iradio.py:368 msgid "Oldies" msgstr "Oldies" #: ../quodlibet/browsers/iradio.py:369 msgid "R&B" msgstr "R&B" #: ../quodlibet/browsers/iradio.py:370 msgid "Japanese" msgstr "Japonská" #: ../quodlibet/browsers/iradio.py:371 msgid "Indian" msgstr "Indická" #: ../quodlibet/browsers/iradio.py:373 msgid "Religious" msgstr "Náboženská" #: ../quodlibet/browsers/iradio.py:375 msgid "Charts" msgstr "Sborová" #: ../quodlibet/browsers/iradio.py:376 msgid "Turkish" msgstr "Turecká" #: ../quodlibet/browsers/iradio.py:377 msgid "Reggae / Dancehall" msgstr "Reggae / Taneční" #: ../quodlibet/browsers/iradio.py:378 msgid "Latin" msgstr "Latinskoamerické" #: ../quodlibet/browsers/iradio.py:379 msgid "College Radio" msgstr "College rádio" #: ../quodlibet/browsers/iradio.py:380 msgid "Talk / News" msgstr "Rozhovory / Zprávy" #: ../quodlibet/browsers/iradio.py:381 msgid "Ambient" msgstr "Ambient" #: ../quodlibet/browsers/iradio.py:382 msgid "Jazz" msgstr "Jazz" #: ../quodlibet/browsers/iradio.py:383 ../quodlibet/ext/events/equalizer.py:46 msgid "Classical" msgstr "Klasická" #: ../quodlibet/browsers/iradio.py:384 ../quodlibet/ext/events/equalizer.py:61 msgid "Pop" msgstr "Pop" #: ../quodlibet/browsers/iradio.py:385 msgid "Alternative" msgstr "Alternativní" #: ../quodlibet/browsers/iradio.py:386 msgid "Metal" msgstr "Metal" #: ../quodlibet/browsers/iradio.py:387 msgid "Country" msgstr "Country" #: ../quodlibet/browsers/iradio.py:388 msgid "News" msgstr "Zprávy" #: ../quodlibet/browsers/iradio.py:389 msgid "Schlager" msgstr "Šlágry" #: ../quodlibet/browsers/iradio.py:390 msgid "Funk" msgstr "Funky" #: ../quodlibet/browsers/iradio.py:391 msgid "Indie" msgstr "Indie" #: ../quodlibet/browsers/iradio.py:392 msgid "Blues" msgstr "Blues" #: ../quodlibet/browsers/iradio.py:393 msgid "Soul" msgstr "Soul" #: ../quodlibet/browsers/iradio.py:394 msgid "Lounge" msgstr "Lounge" #: ../quodlibet/browsers/iradio.py:395 msgid "Punk" msgstr "Punk" #: ../quodlibet/browsers/iradio.py:396 msgid "Reggaeton" msgstr "Reggaeton" #: ../quodlibet/browsers/iradio.py:398 msgid "Slavic" msgstr "Slovanská" #: ../quodlibet/browsers/iradio.py:400 msgid "Greek" msgstr "Řecká" #: ../quodlibet/browsers/iradio.py:401 msgid "Gothic" msgstr "Gotická" #: ../quodlibet/browsers/iradio.py:402 ../quodlibet/ext/events/equalizer.py:39 msgid "Rock" msgstr "Rock" #: ../quodlibet/browsers/iradio.py:455 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:461 msgid "_Load Stations" msgstr "_Načíst stanice" #: ../quodlibet/browsers/iradio.py:478 msgid "_Internet Radio" msgstr "_Internetová rádia" #: ../quodlibet/browsers/iradio.py:545 msgid "_New Station…" msgstr "_Nová stanice…" #: ../quodlibet/browsers/iradio.py:548 msgid "_Update Stations" msgstr "_Aktualizace stanic" #: ../quodlibet/browsers/iradio.py:575 msgid "All Stations" msgstr "Všechny stanice" #. TODO: support for ~#rating=!None etc (#1940) #: ../quodlibet/browsers/iradio.py:579 #: ../quodlibet/browsers/soundcloud/main.py:65 msgid "Favorites" msgstr "Oblíbené" #: ../quodlibet/browsers/iradio.py:587 msgid "No Category" msgstr "Žádná kategorie" #: ../quodlibet/browsers/iradio.py:809 msgid "No stations found" msgstr "Nenalezeny žádné stanice" #: ../quodlibet/browsers/iradio.py:810 #, python-format msgid "No Internet radio stations were found at %s." msgstr "Na %s nebyly nalezeny žádné stanice." #: ../quodlibet/browsers/iradio.py:818 msgid "All stations listed are already in your library." msgstr "Všechny stanice na seznamu jsou už ve sbírce." #: ../quodlibet/browsers/iradio.py:835 msgid "Add to Favorites" msgstr "Přidat do oblíbených" #: ../quodlibet/browsers/iradio.py:839 msgid "Remove from Favorites" msgstr "Odstranit z oblíbených" #: ../quodlibet/browsers/iradio.py:939 #, 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:45 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:91 msgid "Select _All" msgstr "Vybrat _vše" #: ../quodlibet/browsers/paned/models.py:105 ../quodlibet/qltk/pluginwin.py:123 #: ../quodlibet/qltk/pluginwin.py:165 msgid "All" msgstr "Vše" #: ../quodlibet/browsers/paned/prefs.py:68 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "<tt>%s</tt>" msgstr "" "Vzor tagu s volitelným značením, např. <tt>composer</tt> nebo\n" "<tt>%s</tt>" #: ../quodlibet/browsers/paned/prefs.py:163 msgid "_Wide Mode" msgstr "Ši_roký mód" #: ../quodlibet/browsers/paned/prefs.py:198 msgid "Paned Browser Preferences" msgstr "Nastavení prohlížeče s panely" #: ../quodlibet/browsers/paned/prefs.py:205 msgid "Equal pane width" msgstr "Stejná šířka panelů" #: ../quodlibet/browsers/playlists/main.py:48 #: ../quodlibet/browsers/playlists/main.py:574 #: ../quodlibet/qltk/pluginwin.py:169 msgid "Playlists" msgstr "Seznamy skladeb" #: ../quodlibet/browsers/playlists/main.py:49 msgid "_Playlists" msgstr "_Seznamy skladeb" #: ../quodlibet/browsers/playlists/main.py:152 msgid "_Remove from Playlist" msgstr "_Odstranit ze seznamu" #: ../quodlibet/browsers/playlists/main.py:218 #: ../quodlibet/browsers/playlists/main.py:575 msgid "_Import" msgstr "_Importovat" #: ../quodlibet/browsers/playlists/main.py:415 msgid "Unable to import playlist" msgstr "Seznam skladeb nelze importovat" #: ../quodlibet/browsers/playlists/main.py:416 msgid "Quod Libet can only import playlists in the M3U and PLS formats." msgstr "Quod Libet umí importovat jen seznamy ve formátu M3U a PLS." #: ../quodlibet/browsers/playlists/main.py:466 msgid "_Rename" msgstr "_Přejmenovat" #: ../quodlibet/browsers/playlists/main.py:564 msgid "Unable to rename playlist" msgstr "Seznam skladeb nelze přejmenovat" #: ../quodlibet/browsers/playlists/main.py:575 msgid "Import Playlist" msgstr "Importovat seznam skladeb" #: ../quodlibet/browsers/playlists/menu.py:26 msgid "_New Playlist…" msgstr "_Nový seznam skladeb…" #: ../quodlibet/browsers/playlists/menu.py:87 #, 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:91 #, python-format msgid "Confirm action for playlist \"%s\"" msgstr "Potvrdit akci pro seznam skladeb ‚%s‘" #: ../quodlibet/browsers/playlists/prefs.py:22 msgid "empty" msgstr "prázdný" #: ../quodlibet/browsers/playlists/prefs.py:40 msgid "Example Playlist" msgstr "Příklad seznamu skladeb" #: ../quodlibet/browsers/playlists/prefs.py:48 msgid "Playlist Browser Preferences" msgstr "Nastavení prohlížeče seznamu skladeb" #: ../quodlibet/browsers/playlists/prefs.py:53 msgid "Playlist display" msgstr "Zobrazení seznamu skladeb" #: ../quodlibet/browsers/playlists/util.py:35 #, 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:37 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:52 #: ../quodlibet/browsers/playlists/util.py:127 #: ../quodlibet/util/collection.py:575 msgid "New Playlist" msgstr "Nový seznam skladeb" #: ../quodlibet/browsers/playlists/util.py:53 msgid "Enter a name for the new playlist:" msgstr "Zadejte jméno nového seznamu:" #: ../quodlibet/browsers/playlists/util.py:91 #, 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/search.py:31 msgid "_Limit Results" msgstr "_Omezit výsledky" #: ../quodlibet/browsers/search.py:46 msgid "Search Library" msgstr "Prohledávat sbírku" #: ../quodlibet/browsers/search.py:47 msgid "_Search Library" msgstr "_Hledat ve sbírce" #: ../quodlibet/browsers/soundcloud/main.py:39 msgid "Soundcloud Browser" msgstr "Prohlížeč Soundcloudu" #: ../quodlibet/browsers/soundcloud/main.py:40 msgid "Sound_cloud" msgstr "Sound_cloud" #: ../quodlibet/browsers/soundcloud/main.py:60 #: ../quodlibet/qltk/searchbar.py:76 msgid "Search" msgstr "Hledání" #: ../quodlibet/browsers/soundcloud/main.py:69 #, fuzzy msgid "My tracks" msgstr "skladby" #: ../quodlibet/browsers/soundcloud/main.py:141 #, python-format msgid "Go to %s" msgstr "Přejít na %s" #: ../quodlibet/browsers/soundcloud/main.py:393 msgid "Connected" msgstr "Připojeno" #: ../quodlibet/browsers/soundcloud/main.py:394 #, python-format msgid "Quod Libet is now connected, <b>%s</b>!" msgstr "Quod Libet je nyní připojen, <b>%s</b>!" #: ../quodlibet/browsers/soundcloud/main.py:406 #, python-format msgid "Log out of %s" msgstr "Odhlásit se z %s" #: ../quodlibet/browsers/soundcloud/main.py:408 msgid "Enter code…" msgstr "Vložit kód…" #: ../quodlibet/browsers/soundcloud/main.py:409 #, python-format msgid "Log in to %s" msgstr "Přihlásit do %s" #: ../quodlibet/browsers/soundcloud/util.py:87 msgid "Soundcloud authorisation" msgstr "Autorizace Soundcloudu" #: ../quodlibet/browsers/soundcloud/util.py:88 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:86 msgid "a music library and player" msgstr "hudební sbírka a přehrávač" #: ../quodlibet/cli.py:87 msgid "[option]" msgstr "[volba]" #: ../quodlibet/cli.py:89 msgid "Print the playing song and exit" msgstr "Vypsat přehrávanou skladbu a skončit." #: ../quodlibet/cli.py:90 msgid "Begin playing immediately" msgstr "Ihned začít přehrávat" #: ../quodlibet/cli.py:91 msgid "Don't show any windows on start" msgstr "Při startu nezobrazovat žádná okna" #: ../quodlibet/cli.py:94 msgid "Jump to next song" msgstr "Další skladba" #: ../quodlibet/cli.py:96 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:97 msgid "Jump to previous song" msgstr "Předchozí skladba" #: ../quodlibet/cli.py:98 msgid "Start playback" msgstr "Přehrávat" #: ../quodlibet/cli.py:99 msgid "Pause playback" msgstr "Pauza" #: ../quodlibet/cli.py:100 msgid "Toggle play/pause mode" msgstr "Prohodit režim přehrávání/pauza" #: ../quodlibet/cli.py:101 msgid "Stop playback" msgstr "Přehrávat" #: ../quodlibet/cli.py:102 msgid "Turn up volume" msgstr "Zesílit hlasitost" #: ../quodlibet/cli.py:103 msgid "Turn down volume" msgstr "Snížit hlasitost" #: ../quodlibet/cli.py:104 msgid "Print player status" msgstr "Zobrazit stav přehrávače" #: ../quodlibet/cli.py:105 msgid "Hide main window" msgstr "Skrýt hlavní okno" #: ../quodlibet/cli.py:106 msgid "Show main window" msgstr "Obnovit hlavní okno" #: ../quodlibet/cli.py:107 msgid "Toggle main window visibility" msgstr "Přepnout viditelnost hlavního okna" #: ../quodlibet/cli.py:108 msgid "Focus the running player" msgstr "Zaměřit běžící přehrávač" #: ../quodlibet/cli.py:109 msgid "Remove active browser filters" msgstr "Odstranit aktivní fiiltry procházení" #: ../quodlibet/cli.py:110 msgid "Refresh and rescan library" msgstr "Obnovit a znovu načíst sbírku" #: ../quodlibet/cli.py:111 msgid "List available browsers" msgstr "Seznam dostupných prohlížečů" #: ../quodlibet/cli.py:112 msgid "Print the current playlist" msgstr "Zobrazit současný seznam skladeb" #: ../quodlibet/cli.py:113 msgid "Print the contents of the queue" msgstr "Zobrazit obsah fronty" #: ../quodlibet/cli.py:114 msgid "Print the active text query" msgstr "Tisk aktivního dotazu" #: ../quodlibet/cli.py:115 msgid "Start without plugins" msgstr "Start bez zásuvných modulů" #: ../quodlibet/cli.py:116 msgid "Start Quod Libet if it isn't running" msgstr "Spustit Quod Libet jestliže už neběží" #: ../quodlibet/cli.py:117 msgid "Exit Quod Libet" msgstr "Ukončit Quod Libet" #: ../quodlibet/cli.py:122 msgid "Seek within the playing song" msgstr "Vyhledávat v přehrávané skladbě" #: ../quodlibet/cli.py:122 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][ HH:] MM: SS" #: ../quodlibet/cli.py:123 msgid "Set or toggle shuffle mode" msgstr "Nastavit nebo prohodit mód promíchání" #: ../quodlibet/cli.py:124 msgid "Turn repeat off, on, or toggle it" msgstr "Vypnout/zapnout či přepnout opakování" #: ../quodlibet/cli.py:125 msgid "Set the volume" msgstr "Nastavit hlasitost" #: ../quodlibet/cli.py:126 msgid "Search your audio library" msgstr "Procházet sbírku skladeb" #: ../quodlibet/cli.py:126 ../quodlibet/cli.py:138 ../quodlibet/cli.py:142 #: ../quodlibet/cli.py:144 msgid "query" msgstr "dotaz" #: ../quodlibet/cli.py:127 msgid "Play a file" msgstr "Přehrát soubor" #: ../quodlibet/cli.py:127 ../quodlibet/cli.py:138 ../quodlibet/cli.py:144 msgctxt "command" msgid "filename" msgstr "název souboru" #: ../quodlibet/cli.py:128 msgid "Rate the playing song" msgstr "Ohodnotit přehrávanou skladbu" #: ../quodlibet/cli.py:129 msgid "Set the current browser" msgstr "Nastavit aktuální prohlížeč" #: ../quodlibet/cli.py:130 msgid "Stop after the playing song" msgstr "Zastavit přehrávání po skončení skladby" #: ../quodlibet/cli.py:131 msgid "Open a new browser" msgstr "Otevřít nový prohlížeč" #: ../quodlibet/cli.py:132 msgid "Show or hide the queue" msgstr "Zobrazit nebo skrýt frontu" #: ../quodlibet/cli.py:134 msgid "Show or hide the main song list (deprecated)" msgstr "Zobrazit nebo skrýt hlavní seznam skladeb (zastaralé)" #: ../quodlibet/cli.py:135 msgid "Filter on a random value" msgstr "Filtr s náhodnou hodnotou" #: ../quodlibet/cli.py:135 msgctxt "command" msgid "tag" msgstr "tag" #: ../quodlibet/cli.py:136 msgid "Filter on a tag value" msgstr "Filtr na hodnotu tagu" #: ../quodlibet/cli.py:136 msgid "tag=value" msgstr "tag=hodnota" #: ../quodlibet/cli.py:137 msgid "Enqueue a file or query" msgstr "Zařadit do fronty soubor nebo dotaz" #: ../quodlibet/cli.py:139 msgid "Enqueue comma-separated files" msgstr "Vyřadit z fronty soubory oddělené čárkou" #: ../quodlibet/cli.py:140 ../quodlibet/util/tags.py:159 msgid "filename" msgstr "název souboru" #: ../quodlibet/cli.py:141 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:143 msgid "Unqueue a file or query" msgstr "Vyřadit z fronty soubor nebo dotaz" #: ../quodlibet/cli.py:202 #, python-format msgid "Invalid argument for '%s'." msgstr "Neplatný argument pro ‚%s‘." #: ../quodlibet/cli.py:203 ../quodlibet/util/__init__.py:174 #, python-format msgid "Try %s --help." msgstr "Zkuste %s --help." #: ../quodlibet/errorreport/ui.py:59 msgid "An Error Occurred" msgstr "Vyskytla se chyba" #: ../quodlibet/errorreport/ui.py:61 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:70 ../quodlibet/errorreport/ui.py:86 msgid "Submit Error Report" msgstr "Potvrdit hlášení chyby" #: ../quodlibet/errorreport/ui.py:71 msgid "Quit Program" msgstr "Zavřít program" #: ../quodlibet/errorreport/ui.py:72 msgid "Ignore Error" msgstr "Ignorovat chybu" #: ../quodlibet/errorreport/ui.py:76 msgid "Error details:" msgstr "Podrobnosti o chybě:" #: ../quodlibet/errorreport/ui.py:88 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:96 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:105 msgid "_Send" msgstr "_Poslat" #: ../quodlibet/errorreport/ui.py:111 msgid "Short description…" msgstr "Krátký popis…" #: ../quodlibet/errorreport/ui.py:114 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:160 msgid "directory" msgstr "složka" #: ../quodlibet/exfalso.py:42 #, fuzzy msgid "Audio metadata editor" msgstr "Editor tagů" #: ../quodlibet/ext/covers/artwork_url.py:20 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 artwork_url tag. This works with the " "Soundcloud browser." msgstr "" "Stažení přebalů alb pomocí odkazu ve značce artwork_url. Funguje s " "prohlížečem Soundcloudu." #: ../quodlibet/ext/covers/discogs.py:26 msgid "Discogs Cover Source" msgstr "Přebaly alb z Discogs" #: ../quodlibet/ext/covers/discogs.py:27 msgid "Downloads covers from Discogs." msgstr "Stahování přebalů alb z Discogs." #: ../quodlibet/ext/covers/lastfm.py:23 msgid "Last.fm Cover Source" msgstr "Přebaly alb z Last.fm" #: ../quodlibet/ext/covers/lastfm.py:24 msgid "Downloads covers from Last.fm's cover art archive." msgstr "Stahují se přebaly z archivu Last.fm." #: ../quodlibet/ext/covers/musicbrainz.py:20 msgid "MusicBrainz Cover Source" msgstr "Zdroj přebalů MusicBrainz" #: ../quodlibet/ext/covers/musicbrainz.py:21 msgid "Downloads covers from MusicBrainz's cover art archive." msgstr "Stažení přebalů z archivu MusicBrainz." #: ../quodlibet/ext/editing/iconv.py:27 msgid "Convert Encodings" msgstr "Převést kódování" #: ../quodlibet/ext/editing/iconv.py:28 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:34 msgid "_Convert Encoding…" msgstr "_Převést kódování…" #: ../quodlibet/ext/editing/kakasi.py:27 msgid "Kana/Kanji Simple Inverter" msgstr "Kana/Kanji inverze" #: ../quodlibet/ext/editing/kakasi.py:28 msgid "Converts kana/kanji to romaji before renaming." msgstr "Převést kana/kanji na latinku." #: ../quodlibet/ext/editing/kakasi.py:37 msgid "Romanize _Japanese text" msgstr "_Japonský text na latinku" #: ../quodlibet/ext/editing/kakasi.py:69 msgid "Couldn't find the 'Kanji Kana Simple Inverter' (kakasi)." msgstr "Nelze najít 'Kanji Kana Simple Inventer' (kakasi)." #: ../quodlibet/ext/editing/resub.py:19 msgid "Regex Substitution" msgstr "Náhrada regulárním výrazem" #: ../quodlibet/ext/editing/resub.py:20 msgid "" "Allows arbitrary regex substitutions (s///) 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:21 msgid "Title Case" msgstr "Velikost písmen u názvů" #: ../quodlibet/ext/editing/titlecase.py:22 msgid "Title-cases tag values in the tag editor." msgstr "Velikosti písmen názvů v editoru." #: ../quodlibet/ext/editing/titlecase.py:41 msgid "Title-_case Value" msgstr "Velikost _písmen v názvech" #: ../quodlibet/ext/editing/titlecase.py:52 msgid "Allow _ALL-CAPS in tags" msgstr "Povolit _Všechna velká u tagů" #: ../quodlibet/ext/editing/titlecase.py:53 msgid "_Human title case" msgstr "_Běžná velká malá písmena" #: ../quodlibet/ext/editing/titlecase.py:54 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:69 msgid "Advanced Preferences" msgstr "Pokročilá nastavení" #: ../quodlibet/ext/events/advanced_preferences.py:70 msgid "Allow editing of advanced config settings." msgstr "Povolit konfiguraci pokročilých nastavení." #: ../quodlibet/ext/events/advanced_preferences.py:168 msgid "I know what I'm doing" msgstr "Vím, co dělám" #: ../quodlibet/ext/events/animosd/main.py:28 msgid "Animated On-Screen Display" msgstr "Animovaná obrazovka" #: ../quodlibet/ext/events/animosd/main.py:29 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:154 msgid "Top of screen" msgstr "Nahoru" #: ../quodlibet/ext/events/animosd/prefs.py:155 msgid "Middle of screen" msgstr "Uprostřed" #: ../quodlibet/ext/events/animosd/prefs.py:156 msgid "Bottom of screen" msgstr "Dolů" #: ../quodlibet/ext/events/animosd/prefs.py:159 msgid "_Position:" msgstr "_Poloha:" #: ../quodlibet/ext/events/animosd/prefs.py:172 msgid "_Cover size:" msgstr "_Velikost přebalu:" #: ../quodlibet/ext/events/animosd/prefs.py:178 #: ../quodlibet/ext/events/weblyrics.py:318 ../quodlibet/qltk/prefs.py:267 msgid "Display" msgstr "Zobrazení" #: ../quodlibet/ext/events/animosd/prefs.py:191 msgid "_Font:" msgstr "_Písmo:" #: ../quodlibet/ext/events/animosd/prefs.py:196 msgid "Left" msgstr "Vlevo" #: ../quodlibet/ext/events/animosd/prefs.py:197 msgid "Center" msgstr "Na střed" #: ../quodlibet/ext/events/animosd/prefs.py:198 msgid "Right" msgstr "Pravá" #: ../quodlibet/ext/events/animosd/prefs.py:201 msgid "_Align text:" msgstr "_Zarovnat text:" #: ../quodlibet/ext/events/animosd/prefs.py:207 msgid "Text" msgstr "Text" #: ../quodlibet/ext/events/animosd/prefs.py:218 msgid "_Text:" msgstr "_Text:" #: ../quodlibet/ext/events/animosd/prefs.py:228 msgid "_Fill:" msgstr "_Vyplnit:" #: ../quodlibet/ext/events/animosd/prefs.py:233 #: ../quodlibet/ext/events/synchronizedlyrics.py:67 msgid "Colors" msgstr "Barvy" #: ../quodlibet/ext/events/animosd/prefs.py:241 msgid "_Shadows" msgstr "_Stíny" #: ../quodlibet/ext/events/animosd/prefs.py:242 msgid "_Outline" msgstr "_Obrysy" #: ../quodlibet/ext/events/animosd/prefs.py:243 msgid "Rou_nded Corners" msgstr "O_blé rohy" #: ../quodlibet/ext/events/animosd/prefs.py:259 msgid "_Delay:" msgstr "_Zpoždění:" #: ../quodlibet/ext/events/animosd/prefs.py:265 #: ../quodlibet/qltk/pluginwin.py:173 msgid "Effects" msgstr "Efekty" #: ../quodlibet/ext/events/animosd/prefs.py:271 msgid "Ed_it Display Pattern…" msgstr "U_pravit vzor zobrazení…" #: ../quodlibet/ext/events/animosd/prefs.py:275 #: ../quodlibet/ext/events/trayicon/prefs.py:78 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 "Audio Backend" msgstr "Audio zdroje" #: ../quodlibet/ext/events/auto_library_update.py:137 msgid "Automatic Library Update" msgstr "Automatické obnovení spírky" #: ../quodlibet/ext/events/auto_library_update.py:138 #, 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." #: ../quodlibet/ext/events/automask.py:23 msgid "Automatic Masking" msgstr "Automatické maskování" #: ../quodlibet/ext/events/automask.py:24 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:16 msgid "Automatic Rating" msgstr "Automatické hodnocení" #: ../quodlibet/ext/events/autorating.py:17 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." #: ../quodlibet/ext/events/clock.py:25 msgid "Alarm Clock" msgstr "Budík" #: ../quodlibet/ext/events/clock.py:26 msgid "Wakes you up with loud music." msgstr "Probuzení hlasitou hudbou." #: ../quodlibet/ext/events/clock.py:120 msgid "Lullaby" msgstr "Ukolébavka" #: ../quodlibet/ext/events/clock.py:121 msgid "Fades out and pauses your music." msgstr "Ztlumí a pozastaví přehrávání." #: ../quodlibet/ext/events/equalizer.py:27 msgid "Flat" msgstr "Byt" #: ../quodlibet/ext/events/equalizer.py:28 msgid "Live" msgstr "Naživo" #: ../quodlibet/ext/events/equalizer.py:30 msgid "Full Bass & Treble" msgstr "Plný bas i výšky" #: ../quodlibet/ext/events/equalizer.py:33 msgid "Club" msgstr "Klub" #: ../quodlibet/ext/events/equalizer.py:35 msgid "Large Hall" msgstr "Velká hala" #: ../quodlibet/ext/events/equalizer.py:37 msgid "Party" msgstr "Párty" #: ../quodlibet/ext/events/equalizer.py:41 msgid "Soft" msgstr "Jemně" #: ../quodlibet/ext/events/equalizer.py:43 msgid "Full Bass" msgstr "Bohaté hloubky" #: ../quodlibet/ext/events/equalizer.py:49 msgid "Reggae" msgstr "Reggae" #: ../quodlibet/ext/events/equalizer.py:51 msgid "Headphones" msgstr "Sluchátka" #: ../quodlibet/ext/events/equalizer.py:54 msgid "Soft Rock" msgstr "Soft Rock" #: ../quodlibet/ext/events/equalizer.py:56 msgid "Full Treble" msgstr "Plné výšky" #: ../quodlibet/ext/events/equalizer.py:59 msgid "Dance" msgstr "Taneční" #: ../quodlibet/ext/events/equalizer.py:63 msgid "Techno" msgstr "Techno" #: ../quodlibet/ext/events/equalizer.py:65 msgid "Ska" msgstr "Ska" #: ../quodlibet/ext/events/equalizer.py:67 msgid "Laptop" msgstr "Notebook" #: ../quodlibet/ext/events/equalizer.py:98 msgid "Equalizer" msgstr "Ekvalizér" #: ../quodlibet/ext/events/equalizer.py:99 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:133 msgid "The current backend does not support equalization." msgstr "Současná obslužná aplikace na pozadí nepodporuje ekvalizér." #: ../quodlibet/ext/events/equalizer.py:139 #, python-format msgid "%.1f kHz" msgstr "%.1f kHz" #: ../quodlibet/ext/events/equalizer.py:140 #: ../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:174 #: ../quodlibet/ext/gstreamer/crossfeed.py:113 #, python-format msgid "%.1f dB" msgstr "%.1f dB" #: ../quodlibet/ext/events/equalizer.py:193 #: ../quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom" msgstr "Vlastní" #: ../quodlibet/ext/events/equalizer.py:200 msgid "_Clear" msgstr "_Vyčistit" #. 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:115 #: ../quodlibet/ext/events/mqtt.py:46 #: ../quodlibet/ext/events/telepathy_status.py:70 msgid "paused" msgstr "Zastaveno" #: ../quodlibet/ext/events/gajim_status.py:146 #, fuzzy msgid "Pattern:" msgstr "vzor" #: ../quodlibet/ext/events/gajim_status.py:155 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:158 #, fuzzy msgid "Accounts:" msgstr "Účet" #: ../quodlibet/ext/events/gajim_status.py:162 msgid "Add '[paused]'" msgstr "Přidat „[paused]“" #: ../quodlibet/ext/events/gajim_status.py:165 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:189 msgid "Statuses for which message will be changed" msgstr "Statusy, pro které bude změněna zpráva." #: ../quodlibet/ext/events/headphonemon.py:158 msgid "Pause on Headphone Unplug" msgstr "Zastavit přehrávání při odpojení sluchátek" #: ../quodlibet/ext/events/headphonemon.py:159 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:42 msgid "Inhibit Screensaver" msgstr "Potlačit spořič obrazovky" #: ../quodlibet/ext/events/inhibit.py:43 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." #: ../quodlibet/ext/events/inhibit.py:52 msgid "Music is playing" msgstr "Přehrává se" #: ../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:31 msgid "JEP-118" msgstr "JEP-118" #: ../quodlibet/ext/events/jep118.py:32 msgid "Outputs a Jabber User Tunes file to ~/.quodlibet/jabber." msgstr "Uloží soubor Jabber User Tunes do ~/.quodlibet/jabber." #: ../quodlibet/ext/events/language.py:22 msgid "Change Language" msgstr "Změnit jazyk" #: ../quodlibet/ext/events/language.py:23 msgid "Change the user interface language." msgstr "Změnit jazyk uživatelského rozhraní" #: ../quodlibet/ext/events/language.py:44 msgid "System Default" msgstr "Výchozí" #: ../quodlibet/ext/events/language.py:71 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:38 msgid "UPnP AV Media Server" msgstr "UPnP AV Mediální Server" #: ../quodlibet/ext/events/mediaserver.py:39 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/mpdserver/__init__.py:62 msgid "MPD Server" msgstr "MPD Server" #: ../quodlibet/ext/events/mpdserver/__init__.py:63 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:77 msgid "_Port:" msgstr "_Port:" #: ../quodlibet/ext/events/mpdserver/__init__.py:120 msgid "Local _IP:" msgstr "Lokální _IP adresa:" #: ../quodlibet/ext/events/mpdserver/__init__.py:126 msgid "P_assword:" msgstr "H_eslo:" #: ../quodlibet/ext/events/mpdserver/__init__.py:162 msgid "Connection" msgstr "Spojení" #: ../quodlibet/ext/events/mpdserver/__init__.py:164 msgid "Tested Clients" msgstr "Otestované klienty" #: ../quodlibet/ext/events/mpris/__init__.py:39 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 MPRIS 1.0/2.0 D-Bus Interface " "Specification." msgstr "" "Umožňuje kontrolu Quod Libet s použitím MPRIS 1.0/2.0 D-Bus specifikace " "rozhraní." #: ../quodlibet/ext/events/mpris/__init__.py:46 #: ../quodlibet/ext/events/trayicon/prefs.py:30 msgid "Hide main window on close" msgstr "Skrýt hlavní okno při zavření" #: ../quodlibet/ext/events/mpris/__init__.py:49 #: ../quodlibet/ext/events/themeswitcher.py:85 #: ../quodlibet/ext/gstreamer/compressor.py:100 #: ../quodlibet/ext/gstreamer/crossfeed.py:137 #: ../quodlibet/ext/gstreamer/karaoke.py:100 #: ../quodlibet/ext/gstreamer/pitch.py:84 ../quodlibet/qltk/prefs.py:689 msgid "Preferences" msgstr "Nastavení" #: ../quodlibet/ext/events/mqtt.py:51 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "Akceptuje QL vzory, např. %s" #: ../quodlibet/ext/events/mqtt.py:57 msgid "MQTT Publisher" msgstr "MQTT vydavatel" #: ../quodlibet/ext/events/mqtt.py:58 msgid "Publishes status messages to an MQTT topic." msgstr "Zveřejní status zprávy do tématu MQTT." #: ../quodlibet/ext/events/mqtt.py:123 msgid "Broker hostname" msgstr "Hostname zprostředkovatele" #: ../quodlibet/ext/events/mqtt.py:123 msgid "broker hostname / IP" msgstr "hostname / IP zprostředkovatele" #: ../quodlibet/ext/events/mqtt.py:125 msgid "Broker port" msgstr "Port zprostředkovatele" #: ../quodlibet/ext/events/mqtt.py:125 msgid "broker port" msgstr "port zprostředkovatele" #: ../quodlibet/ext/events/mqtt.py:127 msgid "Topic" msgstr "Téma" #: ../quodlibet/ext/events/mqtt.py:129 msgid "Playing Pattern" msgstr "Vzor pro přehrávání" #: ../quodlibet/ext/events/mqtt.py:131 msgid "Status text when a song is started." msgstr "Text statusu při začátku přehrávání." #: ../quodlibet/ext/events/mqtt.py:133 msgid "Paused Pattern" msgstr "Pozastavený vzor" #: ../quodlibet/ext/events/mqtt.py:135 msgid "Text when a song is paused." msgstr "Text při zastavení přehrávání." #: ../quodlibet/ext/events/mqtt.py:137 msgid "No-song Text" msgstr "Text, pokud se nic nepřehrává" #: ../quodlibet/ext/events/mqtt.py:139 msgid "Plain text for when there is no current song" msgstr "Text, když se nic nepřehrává" #: ../quodlibet/ext/events/mqtt.py:150 msgid "MQTT Configuration" msgstr "Nastavení MQTT" #: ../quodlibet/ext/events/mqtt.py:154 msgid "Status Text" msgstr "Text statusu" #: ../quodlibet/ext/events/mqtt.py:186 #, 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:190 #, 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:193 msgid "Connection error" msgstr "Chyba připojení" #: ../quodlibet/ext/events/notify.py:56 msgid "Notification text" msgstr "Oznamovací text" #: ../quodlibet/ext/events/notify.py:67 msgid "_Title:" msgstr "_Název:" #: ../quodlibet/ext/events/notify.py:78 ../quodlibet/ext/events/notify.py:114 msgid "Revert to default pattern" msgstr "Zpět na základní hodnotu" #: ../quodlibet/ext/events/notify.py:104 msgid "_Body:" msgstr "_Tělo:" #: ../quodlibet/ext/events/notify.py:124 msgid "_Show notification" msgstr "_Zobrazit notifikaci" #: ../quodlibet/ext/events/notify.py:142 msgid "Show notifications" msgstr "Zobrazovat notifikace" #: ../quodlibet/ext/events/notify.py:148 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:156 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:164 msgid "On <i>a_ll</i> song changes" msgstr "Při změně <i>_všech</i> skladeb" #: ../quodlibet/ext/events/notify.py:179 msgid "Only when the main window is not _focused" msgstr "Pouze když není _aktivní hlavní okno" #: ../quodlibet/ext/events/notify.py:187 msgid "Show \"_Next\" button" msgstr "Zobrazit tlačítko „_Další“" #: ../quodlibet/ext/events/notify.py:209 msgid "Connection Error" msgstr "Chyba připojení" #: ../quodlibet/ext/events/notify.py:210 ../quodlibet/ext/events/notify.py:364 #: ../quodlibet/ext/events/notify.py:406 msgid "Couldn't connect to notification daemon." msgstr "Nelze se připojit k oznamovacímu daemonu." #: ../quodlibet/ext/events/notify.py:224 msgid "Song Notifications" msgstr "Oznamování skladeb" #: ../quodlibet/ext/events/notify.py:225 msgid "Displays a notification when the song changes." msgstr "Zobrazení informace při změně skladby." #: ../quodlibet/ext/events/notify.py:388 ../quodlibet/qltk/unity.py:63 msgid "Next" msgstr "Další" #: ../quodlibet/ext/events/qlscrobbler.py:175 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:252 #, python-format msgid "Could not contact service '%s'." msgstr "Nelze se připojit ke službě ‚%s‘." #: ../quodlibet/ext/events/qlscrobbler.py:258 msgid "Authentication failed: invalid URL." msgstr "Autentizace selhala: neplatné URL." #: ../quodlibet/ext/events/qlscrobbler.py:275 #, 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:280 msgid "Client is banned. Contact the author." msgstr "Klient je zakázán, kontaktujte autora." #: ../quodlibet/ext/events/qlscrobbler.py:284 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:349 msgid "AudioScrobbler Submission" msgstr "Zasílání dat přes AudioScrobbler" #: ../quodlibet/ext/events/qlscrobbler.py:350 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:448 msgid "Authentication successful." msgstr "Autentizace proběhla úspěšně." #: ../quodlibet/ext/events/qlscrobbler.py:460 msgid "_Service:" msgstr "_Služba:" #: ../quodlibet/ext/events/qlscrobbler.py:460 msgid "_URL:" msgstr "_URL:" #: ../quodlibet/ext/events/qlscrobbler.py:460 msgid "User_name:" msgstr "_Jméno:" #: ../quodlibet/ext/events/qlscrobbler.py:461 msgid "_Password:" msgstr "_Heslo:" #. Translators: Other service #: ../quodlibet/ext/events/qlscrobbler.py:477 msgid "Other…" msgstr "Ostatní…" #. verify data #: ../quodlibet/ext/events/qlscrobbler.py:515 msgid "_Verify account data" msgstr "_Ověřit účet" #: ../quodlibet/ext/events/qlscrobbler.py:520 #: ../quodlibet/ext/songsmenu/lastfmsync.py:313 msgid "Account" msgstr "Účet" #: ../quodlibet/ext/events/qlscrobbler.py:528 msgid "_Artist pattern:" msgstr "_Vzor pro umělce:" #: ../quodlibet/ext/events/qlscrobbler.py:528 msgid "_Title pattern:" msgstr "_Vzor názvu skladeb:" #: ../quodlibet/ext/events/qlscrobbler.py:529 msgid "Exclude _filter:" msgstr "Vyloučit _filtr:" #: ../quodlibet/ext/events/qlscrobbler.py:547 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:557 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:566 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:574 msgid "_Offline mode (don't submit anything)" msgstr "_Offline mód (neodesílat žádné informace)" #: ../quodlibet/ext/events/qlscrobbler.py:578 msgid "Submission" msgstr "Odeslání" #: ../quodlibet/ext/events/radioadmute.py:21 msgid "Mute Radio Ads" msgstr "Ztlumit reklamy rádií" #: ../quodlibet/ext/events/radioadmute.py:22 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:28 msgid "Random Album Playback" msgstr "Přehrávání náhodného alba" #: ../quodlibet/ext/events/randomalbum.py:29 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:39 msgid "Rated higher" msgstr "Hodnoceno lépe" #: ../quodlibet/ext/events/randomalbum.py:40 msgid "Played more often" msgstr "Přehráváno častěji" #: ../quodlibet/ext/events/randomalbum.py:41 msgid "Skipped more often" msgstr "Přeskočeno častěji" #: ../quodlibet/ext/events/randomalbum.py:42 msgid "Played more recently" msgstr "Přehráváno nedávno" #: ../quodlibet/ext/events/randomalbum.py:43 msgid "Started more recently" msgstr "Spuštěno nedávno" #: ../quodlibet/ext/events/randomalbum.py:44 msgid "Added more recently" msgstr "Přidáno nedávno" #: ../quodlibet/ext/events/randomalbum.py:45 msgid "Longer albums" msgstr "Delší alba" #: ../quodlibet/ext/events/randomalbum.py:84 msgid "seconds before starting next album" msgstr "vteřiny před začátkem přehrávání alba" #: ../quodlibet/ext/events/randomalbum.py:88 msgid "Weights" msgstr "Rovnováha" #: ../quodlibet/ext/events/randomalbum.py:90 msgid "Play some albums more than others" msgstr "Přehrávat některá alba častěji než jiná" #: ../quodlibet/ext/events/randomalbum.py:104 msgid "avoid" msgstr "raději ne" #: ../quodlibet/ext/events/randomalbum.py:115 msgid "prefer" msgstr "upřednostnit" #: ../quodlibet/ext/events/randomalbum.py:202 msgid "Random Album" msgstr "Náhodné album" #: ../quodlibet/ext/events/randomalbum.py:203 #, python-format msgid "Waiting to start %s" msgstr "Čekání na začátek %s" #: ../quodlibet/ext/events/rbimport.py:115 msgid "Import Failed" msgstr "Import selhal" #: ../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/rbimport.py:133 msgid "Start Import" msgstr "Spustit import" #: ../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:74 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:80 msgid "GNOME Search Provider" msgstr "Poskytovatel prohledávání GNOME" #: ../quodlibet/ext/events/searchprovider.py:81 msgid "Allows GNOME Shell to search the library." msgstr "Povolit prohledávání sbírky přes GNOME Shell." #: ../quodlibet/ext/events/seekbar.py:123 msgid "Alternative Seek Bar" msgstr "Alternativní lišta prohledávání" #: ../quodlibet/ext/events/seekbar.py:124 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:21 #, fuzzy msgid "Seekpoint Bookmarks" msgstr "Žádné záložky" #: ../quodlibet/ext/events/seekpoints.py:25 msgid "" "Store Seekpoints A and/or B for tracks. Skip to time A and stop after time B " "when track is played.\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:109 #, fuzzy msgid "Bookmark name for point A" msgstr "Název záložky" #: ../quodlibet/ext/events/seekpoints.py:110 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:125 #, fuzzy msgid "Bookmark name for point B" msgstr "Název záložky" #: ../quodlibet/ext/events/seekpoints.py:126 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:29 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:58 #: ../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:59 #: ../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/synchronizedlyrics.py:35 msgid "Synchronized Lyrics" msgstr "Synchronizované texty" #: ../quodlibet/ext/events/synchronizedlyrics.py:36 msgid "Shows synchronized lyrics from .lrc file with same name as the track." msgstr "" "Zobrazení synchronizovaných textů z .lrc souboru s názvem stejným, jako je " "název skladby." #: ../quodlibet/ext/events/synchronizedlyrics.py:70 msgid "Text:" msgstr "Text:" #: ../quodlibet/ext/events/synchronizedlyrics.py:80 msgid "Background:" msgstr "Pozadí:" #: ../quodlibet/ext/events/synchronizedlyrics.py:91 msgid "Font" msgstr "Písmo" #: ../quodlibet/ext/events/synchronizedlyrics.py:94 msgid "Size (px):" msgstr "Velikost (px):" #: ../quodlibet/ext/events/telepathy_status.py:63 msgid "Telepathy Status Messages" msgstr "Status zprávy pro Telepathy" #: ../quodlibet/ext/events/telepathy_status.py:64 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:123 msgid "Playing:" msgstr "Přehrává se:" #: ../quodlibet/ext/events/telepathy_status.py:124 #, 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:140 msgid "Paused:" msgstr "Zastaveno:" #: ../quodlibet/ext/events/telepathy_status.py:141 #, 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:157 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:158 msgid "No song:" msgstr "Žádná skladba:" #. Frame #: ../quodlibet/ext/events/telepathy_status.py:165 msgid "Status Patterns" msgstr "Vzory statusu" #: ../quodlibet/ext/events/themeswitcher.py:26 msgid "Theme Switcher" msgstr "Změna tématu" #: ../quodlibet/ext/events/themeswitcher.py:27 msgid "Changes the active GTK+ theme." msgstr "Změna GTK+ tématu." #: ../quodlibet/ext/events/themeswitcher.py:50 msgid "_Theme:" msgstr "_Téma:" #: ../quodlibet/ext/events/themeswitcher.py:55 msgid "Default Theme" msgstr "Základní téma" #: ../quodlibet/ext/events/themeswitcher.py:67 msgid "Prefer dark theme version" msgstr "Upřednostit tmavou variantu" #: ../quodlibet/ext/events/toggle_menu.py:19 msgid "Toggle Menu Bar" msgstr "Prohodit lištu menu" #: ../quodlibet/ext/events/toggle_menu.py:20 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:78 #: ../quodlibet/ext/events/trayicon/prefs.py:98 #: ../quodlibet/ext/events/trayicon/systemtray.py:178 #: ../quodlibet/qltk/info.py:48 msgid "Not playing" msgstr "Nepřehrává se" #: ../quodlibet/ext/events/trayicon/__init__.py:54 msgid "Tray Icon" msgstr "Ikona v oznamovací oblasti" #: ../quodlibet/ext/events/trayicon/__init__.py:55 msgid "Controls Quod Libet from the system tray." msgstr "Ovládá Quod Libet ze systémové lišty." #: ../quodlibet/ext/events/trayicon/menu.py:42 #, python-format msgid "_Show %(application-name)s" msgstr "_Zobrazit %(application-name)s" #: ../quodlibet/ext/events/trayicon/menu.py:61 #: ../quodlibet/qltk/quodlibetwindow.py:185 #: ../quodlibet/qltk/quodlibetwindow.py:1083 #: ../quodlibet/qltk/quodlibetwindow.py:1275 msgid "_Play" msgstr "_Přehrávat" #: ../quodlibet/ext/events/trayicon/menu.py:64 #: ../quodlibet/qltk/quodlibetwindow.py:187 #: ../quodlibet/qltk/quodlibetwindow.py:1277 ../quodlibet/qltk/wlw.py:52 msgid "P_ause" msgstr "P_auza" #: ../quodlibet/ext/events/trayicon/menu.py:69 #: ../quodlibet/qltk/quodlibetwindow.py:192 #: ../quodlibet/qltk/quodlibetwindow.py:1078 msgid "Pre_vious" msgstr "_Předchozí" #: ../quodlibet/ext/events/trayicon/menu.py:72 #: ../quodlibet/qltk/quodlibetwindow.py:196 #: ../quodlibet/qltk/quodlibetwindow.py:1088 msgid "_Next" msgstr "_Další" #: ../quodlibet/ext/events/trayicon/menu.py:77 msgid "_Shuffle" msgstr "_Promíchat" #: ../quodlibet/ext/events/trayicon/menu.py:82 msgid "_Repeat" msgstr "_Opakovat" #: ../quodlibet/ext/events/trayicon/menu.py:87 msgid "Stop _After This Song" msgstr "Po této skladbě _zastavit přehrávání" #: ../quodlibet/ext/events/trayicon/menu.py:93 #: ../quodlibet/qltk/quodlibetwindow.py:1049 msgid "Open _Browser" msgstr "Otevřít _prohlížeč" #: ../quodlibet/ext/events/trayicon/menu.py:104 #: ../quodlibet/qltk/quodlibetwindow.py:1068 ../quodlibet/qltk/songsmenu.py:382 msgid "Edit _Tags" msgstr "Editovat _Tagy" #: ../quodlibet/ext/events/trayicon/menu.py:113 #: ../quodlibet/qltk/quodlibetwindow.py:1012 ../quodlibet/qltk/songsmenu.py:395 msgid "_Information" msgstr "_Informace" #: ../quodlibet/ext/events/trayicon/menu.py:115 #: ../quodlibet/qltk/songsmenu.py:323 msgid "Play_lists" msgstr "Seznamy _skladeb" #: ../quodlibet/ext/events/trayicon/menu.py:133 #: ../quodlibet/qltk/quodlibetwindow.py:1063 msgid "_Quit" msgstr "_Zavřít" #: ../quodlibet/ext/events/trayicon/prefs.py:32 ../quodlibet/qltk/prefs.py:70 msgid "Behavior" msgstr "Chování" #: ../quodlibet/ext/events/trayicon/prefs.py:42 msgid "Scroll wheel adjusts volume" msgstr "Ovládat hlasitost kolečkem myši" #: ../quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel changes song" msgstr "Přechod na další skladbu kolečkem myši" #: ../quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll _Wheel" msgstr "_Kolečko myši" #: ../quodlibet/ext/events/trayicon/prefs.py:84 msgid "Tooltip Display" msgstr "Zobrazení tipů" #: ../quodlibet/ext/events/viewlyrics.py:26 msgid "View Lyrics" msgstr "Zobrazit texty" #: ../quodlibet/ext/events/viewlyrics.py:27 #, 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:88 #, fuzzy, python-format msgid "" "No lyrics found for\n" " %s" msgstr "Ke skladbě nebyly nalezeny žádné texty." #: ../quodlibet/ext/events/viewlyrics.py:118 #: ../quodlibet/ext/events/weblyrics.py:193 msgid "No active song" msgstr "Žádné aktivní skladby" #: ../quodlibet/ext/events/visualisations.py:37 msgid "Launch Visualisations" msgstr "Spustit vizualizace" #: ../quodlibet/ext/events/visualisations.py:39 msgid "Launch external visualisations." msgstr "Spustit externí vizualizace." #: ../quodlibet/ext/events/visualisations.py:56 #, python-format msgid "Couldn't run visualisations using '%s'" msgstr "Nelze spustit vizualizace s použitím '%s'" #: ../quodlibet/ext/events/visualisations.py:58 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:45 msgid "Error" msgstr "Chyba" #: ../quodlibet/ext/events/visualisations.py:77 msgid "Visualiser executable:" msgstr "Spouštěcí příkaz vizualizéru:" #: ../quodlibet/ext/events/visualisations.py:92 msgid "Reload" msgstr "Znovu načíst" #: ../quodlibet/ext/events/waveformseekbar.py:545 msgid "Waveform Seek Bar" msgstr "Lišta hledání ve vlnové křivce skladby" #: ../quodlibet/ext/events/waveformseekbar.py:549 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:606 msgid "Override foreground color:" msgstr "Přepsat barvu popředí." #: ../quodlibet/ext/events/waveformseekbar.py:610 #, fuzzy msgid "Override hover color:" msgstr "Přepsat barvu popředí." #: ../quodlibet/ext/events/waveformseekbar.py:614 #, fuzzy msgid "Override remaining color:" msgstr "Přepsat barvu popředí." #: ../quodlibet/ext/events/waveformseekbar.py:618 #, fuzzy msgid "Show current position" msgstr "_Zobrazit notifikaci" #: ../quodlibet/ext/events/weblyrics.py:208 msgid "No lyrics found" msgstr "Žádné texty nenalezeny" #: ../quodlibet/ext/events/weblyrics.py:268 msgid "_Zoom level:" msgstr "_Úroveň přiblížení:" #: ../quodlibet/ext/events/weblyrics.py:286 msgid "URL:" msgstr "URL:" #: ../quodlibet/ext/events/weblyrics.py:291 msgid "Revert to default" msgstr "Vrátit na základní hodnotu" #: ../quodlibet/ext/events/weblyrics.py:306 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." #: ../quodlibet/ext/events/weblyrics.py:323 msgid "Alternate search" msgstr "Alternativní hledání" #: ../quodlibet/ext/events/weblyrics.py:332 #, fuzzy msgid "Web Lyrics" msgstr "Zobrazit texty" #: ../quodlibet/ext/events/weblyrics.py:333 #, fuzzy msgid "Shows a sidebar containing online lyrics of the playing song." msgstr "Zobrazení okna s textem právě přehrávané skladby." #: ../quodlibet/ext/events/write_cover.py:34 msgid "Picture Saver" msgstr "Ukládání obrázků" #: ../quodlibet/ext/events/write_cover.py:35 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:68 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 #, 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 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:17 msgid "Mono Downmix" msgstr "Sloučení kanálů (mono)" #: ../quodlibet/ext/gstreamer/mono.py:18 msgid "Downmixes audio channels to mono." msgstr "Sloučí oba kanály sterea do jednoho (mono)." #: ../quodlibet/ext/gstreamer/pitch.py:21 msgid "R_ate:" msgstr "_Hodnotit:" #: ../quodlibet/ext/gstreamer/pitch.py:22 msgid "_Tempo:" msgstr "_Tempo:" #: ../quodlibet/ext/gstreamer/pitch.py:23 msgid "_Pitch:" msgstr "_Zpomalení:" #: ../quodlibet/ext/gstreamer/pitch.py:90 msgid "Audio Pitch / Speed" msgstr "Audio zpomalení / rychlost" #: ../quodlibet/ext/gstreamer/pitch.py:91 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:139 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:100 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:157 msgid "Default filename pattern:" msgstr "_Základní vzor názvu souborů:" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:23 msgid "Export to Squeezebox" msgstr "Export pro Squeezbox" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:25 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 "" "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:79 msgid "Export playlist to Squeezebox" msgstr "Exportovat seznam skladeb do Squeezeboxu" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:80 msgid "Playlist name (will overwrite existing)" msgstr "Jméno seznamu skladeb (přepíše již existující)" #. Save button #: ../quodlibet/ext/playlist/export_to_squeezebox.py:81 #: ../quodlibet/ext/songsmenu/albumart.py:324 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:357 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:279 #: ../quodlibet/ext/songsmenu/html.py:77 #: ../quodlibet/ext/songsmenu/lastfmsync.py:220 #: ../quodlibet/ext/songsmenu/playlist.py:52 #: ../quodlibet/ext/songsmenu/replaygain.py:365 #: ../quodlibet/ext/songsmenu/tapbpm.py:183 ../quodlibet/qltk/_editutils.py:41 #: ../quodlibet/qltk/lyrics.py:35 ../quodlibet/qltk/msg.py:53 #: ../quodlibet/qltk/renamefiles.py:218 ../quodlibet/qltk/tagsfrompath.py:154 #: ../quodlibet/qltk/tracknumbers.py:114 msgid "_Save" msgstr "_Uložit" #: ../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:21 msgid "Remove Playlist Duplicates" msgstr "Odstranit duplicity ze seznamu skladeb" #: ../quodlibet/ext/playlist/remove_duplicates.py:22 msgid "Removes duplicate entries in a playlist." msgstr "Odstraní duplicity ze seznamu skladeb." #: ../quodlibet/ext/playlist/remove_duplicates.py:50 #, 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:53 #, 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:16 msgid "Shuffle Playlist" msgstr "Zamíchat seznam skladeb" #: ../quodlibet/ext/playlist/shuffle.py:17 msgid "Randomly shuffles a playlist." msgstr "Náhodně zamíchat seznam skladeb." #: ../quodlibet/ext/playorder/follow.py:19 msgid "Follow Cursor" msgstr "Zaměřit kurzor" #: ../quodlibet/ext/playorder/follow.py:21 msgid "" "Playback 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/playcounteq.py:23 msgid "Playcount Equalizer" msgstr "Ekvalizér počtu přehrání" #: ../quodlibet/ext/playorder/playcounteq.py:24 msgid "Shuffle, preferring songs with fewer total plays." msgstr "Zamíchat, upřednostnit skladby s menším počtem přehrání." #: ../quodlibet/ext/playorder/playcounteq.py:26 msgid "Prefer less played" msgstr "Upřednostnit málo hrané" #: ../quodlibet/ext/playorder/queue.py:20 msgid "Queue Only" msgstr "Pouze fronta" #: ../quodlibet/ext/playorder/queue.py:22 msgid "" "Limits playing of songs to the queue. 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/reverse.py:15 msgid "Reverse" msgstr "Opačně" #: ../quodlibet/ext/playorder/reverse.py:17 msgid "Reverses the play order of songs." msgstr "Inverze (převrácení) pořadí přehrávání skladeb" #: ../quodlibet/ext/playorder/skip_songs.py:26 msgid "Skip Songs" msgstr "Přeskočit skladby" #: ../quodlibet/ext/playorder/skip_songs.py:28 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." #: ../quodlibet/ext/playorder/track_repeat.py:31 msgid "Repeat Each Track" msgstr "Opakovat všechny skladby" #: ../quodlibet/ext/playorder/track_repeat.py:33 msgid "Shuffle songs, but repeat 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:52 msgid "Number of times to play each song:" msgstr "Počet přehrání pro každou skladbu:" #: ../quodlibet/ext/query/conditional.py:16 msgid "Conditional Query" msgstr "Podmíněný dotaz" #: ../quodlibet/ext/query/conditional.py:17 msgid "" "Chooses the query to match based on a condition query. Syntax is '@(if: " "condition, then, else)'." msgstr "" "Výběr dotazu hledání založený na podmíněném dotazu. Syntaxe je '@(if: " "condition, then, else)'." #: ../quodlibet/ext/query/pythonexpression.py:19 msgid "Python Query" msgstr "Dotaz v Pythonu" #: ../quodlibet/ext/query/pythonexpression.py:20 msgid "" "Use Python expressions in queries. Syntax is '@(python: expression)'. The " "variable 's' (or 'a') is the song / album being matched. '_ts' is a (real " "number) timestamp at start of query. Modules 'time' and 'random' are also " "available, and the class 'Random' (==random.Random) 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 msgid "" "Include the results of a saved search as part of another query. Syntax is " "'@(saved: search name)'." msgstr "" "Zahrnout výsledky uloženého hledání jako část jiného dotazu. Syntaxe je " "'@(saved: hledaný výraz)'." #: ../quodlibet/ext/_shared/squeezebox/base.py:78 #, 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:87 #, python-format msgid "Couldn't connect to %s" msgstr "Nelze se připojit k %s" #: ../quodlibet/ext/_shared/squeezebox/base.py:111 msgid "Hostname:" msgstr "Hostname:" #: ../quodlibet/ext/_shared/squeezebox/base.py:117 msgid "Port:" msgstr "Port:" #: ../quodlibet/ext/_shared/squeezebox/base.py:122 msgid "Username:" msgstr "Uživatel:" #: ../quodlibet/ext/_shared/squeezebox/base.py:127 msgid "Password:" msgstr "Heslo:" #: ../quodlibet/ext/_shared/squeezebox/base.py:131 msgid "Library directory the server connects to." msgstr "Složka sbírky, ke které se server připojuje." #: ../quodlibet/ext/_shared/squeezebox/base.py:133 msgid "Library path:" msgstr "Cesta ke sbírce:" #. Add verify button #: ../quodlibet/ext/_shared/squeezebox/base.py:142 msgid "_Verify settings" msgstr "O_věřit nastavení" #. Server settings Frame #: ../quodlibet/ext/_shared/squeezebox/base.py:148 msgid "Squeezebox Server" msgstr "Squeezebox server" #: ../quodlibet/ext/_shared/squeezebox/base.py:151 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:16 msgid "Choose Squeezebox player" msgstr "Vybrat přehrávač pro Squeezbox" #: ../quodlibet/ext/_shared/squeezebox/util.py:21 #: ../quodlibet/ext/songsmenu/importexport.py:39 #: ../quodlibet/qltk/getstring.py:22 msgid "_OK" msgstr "_OK" #: ../quodlibet/ext/_shared/squeezebox/util.py:27 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:331 msgid "Fit image to _window" msgstr "Přizpůsobit obrázek _oknu" #: ../quodlibet/ext/songsmenu/albumart.py:337 msgid "See '[plugins] cover_filenames' config entry for image filename strings" msgstr "" #. Both labels #: ../quodlibet/ext/songsmenu/albumart.py:343 msgid "_Program:" msgstr "_Program:" #: ../quodlibet/ext/songsmenu/albumart.py:348 msgid "_Edit image after saving" msgstr "_Upravit obrázek po uložení" #: ../quodlibet/ext/songsmenu/albumart.py:350 msgid "File_name:" msgstr "Náze_v souboru" #: ../quodlibet/ext/songsmenu/albumart.py:466 msgid "Saving failed" msgstr "Ukládání selhalo" #: ../quodlibet/ext/songsmenu/albumart.py:467 #, python-format msgid "Unable to save \"%s\"." msgstr "Nelze uložit ‚%s‘." #: ../quodlibet/ext/songsmenu/albumart.py:565 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "[albumart] HTTP chyba: %s" #: ../quodlibet/ext/songsmenu/albumart.py:622 msgid "Album Art Downloader" msgstr "Klient stahování přebalů" #: ../quodlibet/ext/songsmenu/albumart.py:675 #, python-format msgid "from %(source)s" msgstr "z %(source)s" #: ../quodlibet/ext/songsmenu/albumart.py:678 #, python-format msgid "Resolution: %s" msgstr "Rozlišení: %s" #: ../quodlibet/ext/songsmenu/albumart.py:681 #, python-format msgid "Size: %s" msgstr "Velikost: %s" #: ../quodlibet/ext/songsmenu/albumart.py:727 msgid "Per engine 'at best' results limit" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:737 msgid "_Search" msgstr "_Hledat" #: ../quodlibet/ext/songsmenu/albumart.py:819 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:453 msgid "Searching…" msgstr "Hledání…" #: ../quodlibet/ext/songsmenu/albumart.py:884 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:43 msgid "Done" msgstr "Hotovo" #: ../quodlibet/ext/songsmenu/albumart.py:1006 msgid "Download Album Art" msgstr "Stáhnout přebal" #: ../quodlibet/ext/songsmenu/albumart.py:1007 msgid "Downloads album covers from various websites." msgstr "Stahování přebalů alb z různých zdrojů." #: ../quodlibet/ext/songsmenu/albumart.py:1020 msgid "Sources" msgstr "Zdroje" #: ../quodlibet/ext/songsmenu/ape2id3.py:27 msgid "APEv2 to ID3v2" msgstr "Z APEv2 na ID3v2" #: ../quodlibet/ext/songsmenu/ape2id3.py:28 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:24 msgid "Go to Bookmark" msgstr "Přejít na záložku" #: ../quodlibet/ext/songsmenu/bookmarks.py:25 msgid "Manages bookmarks in the selected files." msgstr "Úprava záložek u vybraných souborů." #: ../quodlibet/ext/songsmenu/bookmarks.py:64 #: ../quodlibet/qltk/seekbutton.py:245 msgid "_Edit Bookmarks…" msgstr "_Upravit záložky..." #: ../quodlibet/ext/songsmenu/bookmarks.py:74 msgid "No Bookmarks" msgstr "Žádné záložky" #: ../quodlibet/ext/songsmenu/brainz/__init__.py:25 msgid "MusicBrainz Lookup" msgstr "Vyhledávání na MusicBrainz" #: ../quodlibet/ext/songsmenu/brainz/__init__.py:27 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:51 msgid "Only use year for \"date\" tag" msgstr "Pro „date“ tag pužít pouze rok" #: ../quodlibet/ext/songsmenu/brainz/__init__.py:52 msgid "Write \"_albumartist\" when needed" msgstr "Zapsat „_albumartist“, pokud bude třeba" #: ../quodlibet/ext/songsmenu/brainz/__init__.py:53 msgid "Write sort tags for artist names" msgstr "Zapsat tagy pro třídění umělců" #: ../quodlibet/ext/songsmenu/brainz/__init__.py:54 msgid "Write _standard MusicBrainz tags" msgstr "Zapsat _standardní tagy MusicBrainz" #: ../quodlibet/ext/songsmenu/brainz/__init__.py:55 msgid "Write \"labelid\" tag" msgstr "Uveďte tag \"labelid\"" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:131 msgid "Filename" msgstr "Název souboru" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:132 msgid "Disc" msgstr "Disk" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:133 #: ../quodlibet/ext/songsmenu/replaygain.py:404 #: ../quodlibet/qltk/tracknumbers.py:93 msgid "Track" msgstr "Skladba" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:134 msgid "Title" msgstr "Název" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:135 msgid "Artist" msgstr "Umělec" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:354 msgid "MusicBrainz lookup" msgstr "MusicBrainz vyhledávání" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:377 msgid "_Query:" msgstr "_Dotaz:" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:380 msgid "S_earch" msgstr "Vyhl_edávání" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:393 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:449 msgid "Please enter a query." msgstr "Vložte prosím dotaz." #: ../quodlibet/ext/songsmenu/brainz/widgets.py:467 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:498 msgid "Error encountered. Please retry." msgstr "Objevila se chyba. Zkuste to, prosím, znovu." #: ../quodlibet/ext/songsmenu/brainz/widgets.py:474 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:490 msgid "Loading result…" msgstr "Načítání výsledků…" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:477 msgid "No results found." msgstr "Žádné výsledky nenalezeny." #: ../quodlibet/ext/songsmenu/browsefolders.py:160 msgid "Browse Folders" msgstr "Procházet složky" #: ../quodlibet/ext/songsmenu/browsefolders.py:161 msgid "Opens the songs' folders in a file manager." msgstr "Otevření složky umístění skladby ve správci složek." #: ../quodlibet/ext/songsmenu/browsefolders.py:173 msgid "Unable to open folders" msgstr "Složky nelze otevřít" #: ../quodlibet/ext/songsmenu/browsefolders.py:174 msgid "No program available to open folders." msgstr "Pro otevírání složek není dostupný žádný program." #: ../quodlibet/ext/songsmenu/console.py:42 msgid "Python Console" msgstr "Konzole Pythonu" #: ../quodlibet/ext/songsmenu/console.py:43 #, 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:87 msgid "Your current working directory is:" msgstr "Aktuální pracovní složka:" #: ../quodlibet/ext/songsmenu/custom_commands.py:42 msgid "Command" msgstr "Příkaz" #: ../quodlibet/ext/songsmenu/custom_commands.py:45 msgid "name" msgstr "jméno" #: ../quodlibet/ext/songsmenu/custom_commands.py:45 msgid "The name of this command" msgstr "Jméno příkazu" #: ../quodlibet/ext/songsmenu/custom_commands.py:47 msgid "command" msgstr "příkaz" #: ../quodlibet/ext/songsmenu/custom_commands.py:47 msgid "The shell command syntax to run" msgstr "Spustit příkaz v syntaxi shellu" #: ../quodlibet/ext/songsmenu/custom_commands.py:49 msgid "parameter" msgstr "parametr" #: ../quodlibet/ext/songsmenu/custom_commands.py:50 #, 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 "pattern" msgstr "vzor" #: ../quodlibet/ext/songsmenu/custom_commands.py:57 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:62 msgid "unique" msgstr "unikátní" #: ../quodlibet/ext/songsmenu/custom_commands.py:63 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:66 msgid "max args" msgstr "max args" #: ../quodlibet/ext/songsmenu/custom_commands.py:67 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:92 msgid "Input value" msgstr "Vstupní hodnota" #: ../quodlibet/ext/songsmenu/custom_commands.py:93 #, python-format msgid "Value for %s?" msgstr "Hodnota %s?" #: ../quodlibet/ext/songsmenu/custom_commands.py:137 msgid "Custom Commands" msgstr "Vlastní příkazy" #: ../quodlibet/ext/songsmenu/custom_commands.py:138 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:189 #: ../quodlibet/ext/songsmenu/custom_commands.py:199 #: ../quodlibet/ext/songsmenu/custom_commands.py:253 msgid "Edit Custom Commands" msgstr "Upravit uživatelský příkazy" #: ../quodlibet/ext/songsmenu/custom_commands.py:200 msgid "" "Supports QL patterns\n" "eg <tt><~artist~title></tt>" msgstr "" "Podpora QL vzorů\n" "\vnapř. <tt><~artist~title>></tt>" #: ../quodlibet/ext/songsmenu/custom_commands.py:284 #, python-format msgid "Unable to run custom command %s" msgstr "Nelze spustit příkaz %s" #: ../quodlibet/ext/songsmenu/duplicates.py:289 #, 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:342 msgid "Collapse / Expand all" msgstr "Sbalit / Rozbalit vše" #: ../quodlibet/ext/songsmenu/duplicates.py:346 #, python-format msgid "Duplicate key expression is '%s'" msgstr "Duplicitní klíčový výraz je ‚%s‘" #: ../quodlibet/ext/songsmenu/duplicates.py:371 msgid "Duplicates Browser" msgstr "Duplikuje prohlížeč" #: ../quodlibet/ext/songsmenu/duplicates.py:372 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:410 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:412 msgid "_Group duplicates by:" msgstr "_Seskupit duplicity podle:" #: ../quodlibet/ext/songsmenu/duplicates.py:417 msgid "Duplicate Key" msgstr "Duplicitní klíč" #: ../quodlibet/ext/songsmenu/duplicates.py:422 msgid "Remove _Whitespace" msgstr "Odstranit _bílé znaky" #: ../quodlibet/ext/songsmenu/duplicates.py:423 msgid "Remove _Diacritics" msgstr "Odstranit _diakritiku" #: ../quodlibet/ext/songsmenu/duplicates.py:424 msgid "Remove _Punctuation" msgstr "Odstranit interpunkci" #: ../quodlibet/ext/songsmenu/duplicates.py:425 msgid "Case _Insensitive" msgstr "Nezohledňovat _velikost písmen" #: ../quodlibet/ext/songsmenu/duplicates.py:433 msgid "Matching options" msgstr "Souhlasící možnosti" #. Create a dialog. #: ../quodlibet/ext/songsmenu/editplaycount.py:20 #: ../quodlibet/ext/songsmenu/editplaycount.py:42 msgid "Edit Playcount" msgstr "Upravit počet přehání" #: ../quodlibet/ext/songsmenu/editplaycount.py:21 msgid "" "Edit a song's ~#playcount and ~#skipcount.\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's ~#playcount to 0, the ~#lastplayed and ~#laststarted " "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:69 msgid "Play Count" msgstr "Počet přehrání" #: ../quodlibet/ext/songsmenu/editplaycount.py:70 msgid "Skip Count" msgstr "Přeskočit počet" #: ../quodlibet/ext/songsmenu/embedded.py:25 msgid "Edit Embedded Images" msgstr "Upravit vložené obrázky" #: ../quodlibet/ext/songsmenu/embedded.py:26 msgid "Removes or replaces embedded images." msgstr "Odstranit nebo nahradit vložené obrázky." #: ../quodlibet/ext/songsmenu/embedded.py:79 msgid "_Remove all Images" msgstr "_Odstranit všechny obrázky" #: ../quodlibet/ext/songsmenu/embedded.py:83 msgid "_Embed Current Image" msgstr "_Vložit aktuální obrázek" #: ../quodlibet/ext/songsmenu/exact_rating.py:24 msgid "Set Exact Rating" msgstr "Nastavit přesné hodnocení" #: ../quodlibet/ext/songsmenu/exact_rating.py:25 msgid "Allows setting the rating of songs with a number." msgstr "Povolit nastavení hodnocení skladeb číslem." #: ../quodlibet/ext/songsmenu/exact_rating.py:37 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:81 msgid "Filter on Any Tag" msgstr "Nastavit filtr" #: ../quodlibet/ext/songsmenu/filterall.py:82 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:20 msgid "Filter on Directory" msgstr "Filtrovat složku" #: ../quodlibet/ext/songsmenu/filterbrowser.py:21 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:31 msgid "Acoustic Fingerprint Lookup" msgstr "Vyhledávání prstokladu pro akustiku" #: ../quodlibet/ext/songsmenu/fingerprint/__init__.py:32 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:52 #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:42 msgid "Submit Acoustic Fingerprints" msgstr "Potvrdit prstoklady pro akustiku" #: ../quodlibet/ext/songsmenu/fingerprint/__init__.py:53 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:61 msgid "API Key Missing" msgstr "Chybí API klíč" #: ../quodlibet/ext/songsmenu/fingerprint/__init__.py:62 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:76 msgid "Request API key" msgstr "Vyžádání API klíče" #: ../quodlibet/ext/songsmenu/fingerprint/__init__.py:83 msgid "API _key:" msgstr "API _klíč:" #: ../quodlibet/ext/songsmenu/fingerprint/__init__.py:90 msgid "AcoustID Web Service" msgstr "Webová služba AcoustID" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:37 msgid "Queued" msgstr "Zařazeno do fronty" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:39 msgid "Analyzing" msgstr "Vyhodnocování" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:41 msgid "Lookup" msgstr "Vyhledat" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:117 msgid "Write" msgstr "Zapsat" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:145 msgid "Status" msgstr "Status" #. Translators: album release ID #: ../quodlibet/ext/songsmenu/fingerprint/search.py:159 msgid "Release" msgstr "Vydání" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:291 msgid "Write MusicBrainz tags" msgstr "Zapsat tagy MusicBrainz" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:297 msgid "Group by directory" msgstr "Seskupit podle složek" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:306 msgid "Album Mode" msgstr "Režim alba" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:308 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:50 msgid "Generating fingerprints:" msgstr "Generování prstokladů:" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:66 msgid "_Details" msgstr "_Pordobnosti" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:89 msgid "_Submit" msgstr "_Provést" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:119 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:122 msgid "Fingerprints:" msgstr "Prstoklady:" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs with MBIDs:" msgstr "Skladby s MusicBrainz ID:" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:126 msgid "Songs with sufficient tags:" msgstr "Skladby s dostatečnými tagy:" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:128 msgid "Songs to submit:" msgstr "Skladby ke schválení:" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:166 #, 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:182 msgid "Submitting fingerprints:" msgstr "Potvrzování prstokladů:" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:190 msgid "Submitting…" msgstr "Potvrzování…" #: ../quodlibet/ext/songsmenu/forcewrite.py:18 msgid "Update Tags in Files" msgstr "_Aktualizovat tagy souborů" #: ../quodlibet/ext/songsmenu/forcewrite.py:19 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:67 ../quodlibet/ext/songsmenu/html.py:77 msgid "Export to HTML" msgstr "Exportovat do HTML" #: ../quodlibet/ext/songsmenu/html.py:68 msgid "Exports the selected song list to HTML." msgstr "Exportovat seznam vybraných skladeb do HTML." #: ../quodlibet/ext/songsmenu/id3tlen.py:22 msgid "Fix MP3 Duration" msgstr "Opravit trvání MP3" #: ../quodlibet/ext/songsmenu/id3tlen.py:23 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." #: ../quodlibet/ext/songsmenu/ifp.py:22 msgid "Send to iFP" msgstr "Poslat do iFP" #: ../quodlibet/ext/songsmenu/ifp.py:23 msgid "Uploads songs to an iRiver iFP device." msgstr "Nahrát skladby do zařízení iRiver iFP." #: ../quodlibet/ext/songsmenu/ifp.py:31 #, fuzzy msgid "No iFP device found" msgstr "Žádné texty nenalezeny" #: ../quodlibet/ext/songsmenu/ifp.py:32 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:40 #, fuzzy, python-format msgid "Uploading %(current)d/%(total)d" msgstr "Přesouvání %(current)d/%(total)d." #: ../quodlibet/ext/songsmenu/ifp.py:63 #, fuzzy msgid "Error uploading" msgstr "Chyba během synchronizace" #: ../quodlibet/ext/songsmenu/ifp.py:64 #, python-format msgid "" "Unable to upload <b>%s</b>. The device may be out of space, or turned off." msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:60 msgid "Export Metadata" msgstr "Exportovat metadata" #: ../quodlibet/ext/songsmenu/importexport.py:61 msgid "Exports metadata of selected songs as a .tags file." msgstr "Export metadata vybraných skladeb jako soubor .tags." #: ../quodlibet/ext/songsmenu/importexport.py:105 msgid "Import Metadata" msgstr "Importovat metadata" #: ../quodlibet/ext/songsmenu/importexport.py:106 msgid "Imports metadata for selected songs from a .tags file." msgstr "Import metadat ze souboru .tags pro vybrané skladby." #: ../quodlibet/ext/songsmenu/k3b.py:24 msgid "Burn CD" msgstr "Vypálit CD" #: ../quodlibet/ext/songsmenu/k3b.py:25 msgid "Burns CDs with K3b, Brasero or xfburn." msgstr "Vypálení CD s K3b, Braserem nebo xfburn." #: ../quodlibet/ext/songsmenu/lastfmsync.py:98 msgid "Updating chart list." msgstr "Aktualizace seznamu grafů." #. No charts to fetch, no update scheduled. #: ../quodlibet/ext/songsmenu/lastfmsync.py:117 msgid "Already up-to-date." msgstr "Není co aktualizovat." #: ../quodlibet/ext/songsmenu/lastfmsync.py:125 #, 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:147 msgid "Sync complete." msgstr "Synchronizace dokončena." #: ../quodlibet/ext/songsmenu/lastfmsync.py:153 msgid "Error during sync" msgstr "Chyba během synchronizace" #: ../quodlibet/ext/songsmenu/lastfmsync.py:218 #: ../quodlibet/ext/songsmenu/lastfmsync.py:248 msgid "Last.fm Sync" msgstr "Synchronizace s Last.fm" #: ../quodlibet/ext/songsmenu/lastfmsync.py:249 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:302 msgid "_Username:" msgstr "_Uživatel:" #: ../quodlibet/ext/songsmenu/makesorttags.py:37 msgid "Create Sort Tags" msgstr "Vytvořit tagy pro třídění" #: ../quodlibet/ext/songsmenu/makesorttags.py:38 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ě." #. Create a dialog. #: ../quodlibet/ext/songsmenu/migratemetadata.py:37 #: ../quodlibet/ext/songsmenu/migratemetadata.py:46 msgid "Migrate Metadata" msgstr "Přenést metadata" #: ../quodlibet/ext/songsmenu/migratemetadata.py:40 msgid "Copies the quodlibet-specific metadata between songs." msgstr "Zkopírovat pro Quod Libet specifická metadata mezi skladbami." #: ../quodlibet/ext/songsmenu/migratemetadata.py:53 msgid "_Copy" msgstr "_Kopírovat" #: ../quodlibet/ext/songsmenu/migratemetadata.py:55 msgid "_Paste" msgstr "_Vložit" #. Create the tag table. #: ../quodlibet/ext/songsmenu/migratemetadata.py:65 msgid "Information to copy/paste" msgstr "Informace ke zkopírování/vložení" #. Create the indexing box. #: ../quodlibet/ext/songsmenu/migratemetadata.py:87 msgid "Map tracks by disc and track number" msgstr "Mapovat skladby podle čísla disku a pořadového čísla skladby" #: ../quodlibet/ext/songsmenu/migratemetadata.py:88 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í." #: ../quodlibet/ext/songsmenu/migratemetadata.py:104 #, python-format 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." #: ../quodlibet/ext/songsmenu/playlist.py:32 msgid "Export as Playlist" msgstr "Exportovat jako seznam skladeb" #: ../quodlibet/ext/songsmenu/playlist.py:33 msgid "Exports songs to an M3U or PLS playlist." msgstr "Export skladeb do M3U nebo PLS." #: ../quodlibet/ext/songsmenu/playlist.py:78 msgid "Use relative paths" msgstr "Použít relativní cesty" #: ../quodlibet/ext/songsmenu/playlist.py:78 msgid "Use absolute paths" msgstr "Použít absolutní cesty" #: ../quodlibet/ext/songsmenu/playlist.py:133 msgid "Unable to export playlist" msgstr "Seznam skladeb nelze exportovat" #: ../quodlibet/ext/songsmenu/playlist.py:134 #, python-format msgid "Writing to <b>%s</b> failed." msgstr "Zápis do <b>%s</b> selhal." #. Translators: Plugin name #: ../quodlibet/ext/songsmenu/refresh.py:23 msgid "Rescan Songs" msgstr "Znovu načíst skladby" #: ../quodlibet/ext/songsmenu/refresh.py:24 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:32 msgid "Rescan songs" msgstr "Znovu načíst skladby" #: ../quodlibet/ext/songsmenu/replaygain.py:362 msgid "ReplayGain Analyzer" msgstr "ReplayGain analyzér" #: ../quodlibet/ext/songsmenu/replaygain.py:418 msgid "Progress" msgstr "Průběh" #: ../quodlibet/ext/songsmenu/replaygain.py:433 msgid "Gain" msgstr "Gain" #: ../quodlibet/ext/songsmenu/replaygain.py:448 msgid "Peak" msgstr "Peak" #: ../quodlibet/ext/songsmenu/replaygain.py:463 #, python-format msgid "There is <b>%(to-process)s</b> album to update (of %(all)s)" msgid_plural "There are <b>%(to-process)s</b> 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:579 msgid "Replay Gain" msgstr "Replay gain" #: ../quodlibet/ext/songsmenu/replaygain.py:580 msgid "" "Analyzes and updates ReplayGain information, using GStreamer. Results are " "grouped by album." msgstr "" "Analýza a aktualizace informací metodou ReplayGain (s pomocí GStreameru). " "Výsledky jsou slučovány podle alba." #: ../quodlibet/ext/songsmenu/replaygain.py:618 msgid "always" msgstr "vždy" #: ../quodlibet/ext/songsmenu/replaygain.py:619 msgid "if <b>any</b> RG tags are missing" msgstr "pokud <b>jakékoli</b> RG tagy chybí" #: ../quodlibet/ext/songsmenu/replaygain.py:621 msgid "if <b>album</b> RG tags are missing" msgstr "pokud chybí RG tagy pro <b>album</b>" #: ../quodlibet/ext/songsmenu/replaygain.py:638 msgid "_Process albums:" msgstr "_Zpracovat alba:" #. Server settings Frame #: ../quodlibet/ext/songsmenu/replaygain.py:650 msgid "Existing Tags" msgstr "Stávající tagy" #: ../quodlibet/ext/songsmenu/splitting.py:32 msgid "Split Tags" msgstr "Rozdělit tagy" #: ../quodlibet/ext/songsmenu/splitting.py:33 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:57 msgid "Split Album" msgstr "Rozdělit album" #: ../quodlibet/ext/songsmenu/splitting.py:58 msgid "Split out disc number." msgstr "Oddělit číslo disku." #. TRANSLATORS: BPM mean "beats per minute" #: ../quodlibet/ext/songsmenu/tapbpm.py:32 msgid "BPM:" msgstr "BPM:" #: ../quodlibet/ext/songsmenu/tapbpm.py:33 #: ../quodlibet/ext/songsmenu/tapbpm.py:62 msgid "n/a" msgstr "n/a" #: ../quodlibet/ext/songsmenu/tapbpm.py:37 msgid "Reset" msgstr "_Resetovat" #: ../quodlibet/ext/songsmenu/tapbpm.py:43 msgid "Tap" msgstr "Vyťukat" #: ../quodlibet/ext/songsmenu/tapbpm.py:173 #: ../quodlibet/ext/songsmenu/tapbpm.py:180 msgid "Tap BPM" msgstr "Vyťukat tempo pro vybranou skladbu." #: ../quodlibet/ext/songsmenu/tapbpm.py:174 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:37 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern-example)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:79 msgid "Search URL patterns" msgstr "Vyhledat URL vzory" #: ../quodlibet/ext/songsmenu/website_search.py:89 msgid "Edit search URLs" msgstr "Upravit URL" #. Add link to editor #: ../quodlibet/ext/songsmenu/website_search.py:115 msgid "Configure Searches…" msgstr "Konfigurovat vyhledávání…" #: ../quodlibet/ext/songsmenu/wikipedia.py:47 #, python-format msgid "Search at %(website)s" msgstr "Hledat na %(website)s" #: ../quodlibet/ext/songsmenu/wikipedia.py:64 msgid "Search Artist in Wikipedia" msgstr "Vyhledat umělce na Wikipedii" #: ../quodlibet/ext/songsmenu/wikipedia.py:65 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." #: ../quodlibet/ext/songsmenu/wikipedia.py:72 msgid "Search Album in Wikipedia" msgstr "Vyhledat album na Wikipedii" #: ../quodlibet/ext/songsmenu/wikipedia.py:73 msgid "" "Opens a browser window with Wikipedia article on the playing song album." msgstr "Otevřít okno prohlížeče a zobrazit stránku o albu na Wikipedii." #. then (try to) load all new files #: ../quodlibet/library/libraries.py:651 ../quodlibet/library/libraries.py:661 #: ../quodlibet/library/libraries.py:727 ../quodlibet/library/libraries.py:746 #: ../quodlibet/qltk/information.py:273 ../quodlibet/qltk/prefs.py:640 #: ../quodlibet/util/library.py:124 msgid "Library" msgstr "Sbírka" #: ../quodlibet/library/libraries.py:651 msgid "Checking mount points" msgstr "Kontrola přípojných bodů" #: ../quodlibet/library/libraries.py:661 msgid "Scanning library" msgstr "Načítání sbírky" #: ../quodlibet/library/libraries.py:726 #, python-format msgid "Scanning %s" msgstr "Načítání %s" #: ../quodlibet/library/libraries.py:746 msgid "Loading files" msgstr "Načítání souborů" #: ../quodlibet/main.py:51 #, 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:38 msgid "List tags" msgstr "Seznam tagů" #: ../quodlibet/operon/commands.py:43 ../quodlibet/operon/commands.py:82 #: ../quodlibet/operon/commands.py:462 msgid "Print terse output" msgstr "Tisk stručného výpisu" #: ../quodlibet/operon/commands.py:45 ../quodlibet/operon/commands.py:84 #: ../quodlibet/operon/commands.py:464 #, 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:48 ../quodlibet/operon/commands.py:87 msgid "Also list programmatic tags" msgstr "Zobrazit také programovací tagy" #: ../quodlibet/operon/commands.py:52 ../quodlibet/operon/commands.py:130 #: ../quodlibet/operon/commands.py:221 ../quodlibet/operon/commands.py:294 #: ../quodlibet/operon/commands.py:337 ../quodlibet/operon/commands.py:341 #: ../quodlibet/operon/commands.py:392 ../quodlibet/operon/commands.py:395 #: ../quodlibet/operon/commands.py:434 ../quodlibet/operon/commands.py:469 #: ../quodlibet/operon/commands.py:509 ../quodlibet/operon/commands.py:544 #: ../quodlibet/operon/commands.py:586 msgid "Not enough arguments" msgstr "Málo parametrů" #: ../quodlibet/operon/commands.py:54 ../quodlibet/operon/commands.py:91 #: ../quodlibet/operon/commands.py:132 ../quodlibet/operon/commands.py:223 #: ../quodlibet/operon/commands.py:471 msgid "Too many arguments" msgstr "Příliš mnoho parametrů" #: ../quodlibet/operon/commands.py:57 ../quodlibet/operon/commands.py:93 #: ../quodlibet/operon/commands.py:476 ../quodlibet/qltk/data_editors.py:354 msgid "Description" msgstr "Popis" #: ../quodlibet/operon/commands.py:57 ../quodlibet/operon/commands.py:476 #: ../quodlibet/qltk/edittags.py:455 msgid "Value" msgstr "Hodnota" #: ../quodlibet/operon/commands.py:77 msgid "List all common tags" msgstr "Vypsat všechny společné tagy" #: ../quodlibet/operon/commands.py:119 msgid "Copy tags from one file to another" msgstr "Zkopírovat tagy z jednoho souboru do druhého" #: ../quodlibet/operon/commands.py:124 ../quodlibet/operon/commands.py:165 #: ../quodlibet/operon/commands.py:290 ../quodlibet/operon/commands.py:325 #: ../quodlibet/operon/commands.py:385 msgid "Show changes, don't apply them" msgstr "Náhled změn, zatím neprovádět" #: ../quodlibet/operon/commands.py:126 msgid "Skip tags that can't be written" msgstr "Přeskočit tagy, které nemohou být zapsány" #: ../quodlibet/operon/commands.py:146 #, python-format msgid "Can't copy tag %r to file: %r" msgstr "Nelze zkopírovat tag %r do souboru: %r" #: ../quodlibet/operon/commands.py:158 msgid "Edit tags in a text editor" msgstr "Editovat tagy v textovém editoru" #: ../quodlibet/operon/commands.py:252 msgid "Editing aborted" msgstr "Editace zrušena" #: ../quodlibet/operon/commands.py:256 #, python-format msgid "Starting text editor '%(editor-name)s' failed." msgstr "Spuštění editoru '%(editor-name)s' selhalo." #: ../quodlibet/operon/commands.py:261 msgid "No changes detected" msgstr "Žáčné změny nenalezeny" #: ../quodlibet/operon/commands.py:285 msgid "Set a tag and remove existing values" msgstr "Nastavit tag a přepsat původní hodnoty" #: ../quodlibet/operon/commands.py:305 ../quodlibet/operon/commands.py:445 #: ../quodlibet/operon/commands.py:677 #, python-format msgid "Can not set %r" msgstr "Nelze nastavit %r" #: ../quodlibet/operon/commands.py:320 msgid "Remove tags" msgstr "Odstranit tagy" #: ../quodlibet/operon/commands.py:327 ../quodlibet/operon/commands.py:387 msgid "Value is a regular expression" msgstr "Hodnota je regulární výraz" #: ../quodlibet/operon/commands.py:329 msgid "Remove all tags" msgstr "Odstranit všechny tagy" #: ../quodlibet/operon/commands.py:333 msgid "Can't combine '--all' with '--regexp'" msgstr "Nelze kombinovat '--all' s '--regexp'" #: ../quodlibet/operon/commands.py:367 #, python-format msgid "Can't remove %r from %r" msgstr "Nelze odstranit %r z %r" #: ../quodlibet/operon/commands.py:380 msgid "Remove a tag value" msgstr "Odstranit hodnotu" #: ../quodlibet/operon/commands.py:429 msgid "Add a tag value" msgstr "Přidat hodnotu" #: ../quodlibet/operon/commands.py:457 msgid "List file information" msgstr "Zobrazit informace o souboru" #: ../quodlibet/operon/commands.py:503 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:516 #, python-format msgid "Failed to load image file: %r" msgstr "Načítání souboru %r selhalo" #: ../quodlibet/operon/commands.py:523 ../quodlibet/operon/commands.py:552 #, 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:539 msgid "Remove all embedded images" msgstr "Odstranit všechny vložené obrázky" #: ../quodlibet/operon/commands.py:569 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "Extrahovat z vložené obrázky do %(filepath)s" #: ../quodlibet/operon/commands.py:581 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:640 msgid "Rename files based on tags" msgstr "Přejmenovat soubory podle tagů" #: ../quodlibet/operon/commands.py:655 msgid "Fill tags based on the file path" msgstr "Vyplnit tagy podle cest k souborům" #: ../quodlibet/operon/commands.py:705 ../quodlibet/qltk/information.py:310 #: ../quodlibet/qltk/properties.py:85 ../quodlibet/qltk/renamefiles.py:226 #: ../quodlibet/qltk/tagsfrompath.py:230 ../quodlibet/qltk/tracknumbers.py:80 msgid "File" msgstr "Soubor" #: ../quodlibet/operon/commands.py:713 msgid "Fill tracknumbers for all files" msgstr "Vyplnit čísla skladeb u všech souborů" #: ../quodlibet/operon/commands.py:732 msgid "Print tags based on the given pattern" msgstr "Vytisknout tagy podle zadaného vzoru" #: ../quodlibet/operon/commands.py:769 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:31 msgid "_Unknown" msgstr "_Neznámé" #: ../quodlibet/order/__init__.py:143 msgid "In Order" msgstr "V pořadí" #: ../quodlibet/order/__init__.py:144 msgid "_In Order" msgstr "_V pořadí" #: ../quodlibet/order/reorder.py:24 msgid "Random" msgstr "Náhodně" #: ../quodlibet/order/reorder.py:25 ../quodlibet/qltk/queue.py:121 msgid "_Random" msgstr "_Náhodně" #: ../quodlibet/order/reorder.py:40 ../quodlibet/order/reorder.py:41 msgid "Prefer higher rated" msgstr "Přednostně lépe hodnocené" #: ../quodlibet/order/repeat.py:44 ../quodlibet/order/repeat.py:45 msgid "Repeat this track" msgstr "Opakovat skladbu" #: ../quodlibet/order/repeat.py:58 ../quodlibet/order/repeat.py:59 msgid "Repeat all" msgstr "Opakovat všechny" #: ../quodlibet/order/repeat.py:74 ../quodlibet/order/repeat.py:75 msgid "One Song" msgstr "Jedna skladba" #: ../quodlibet/player/gstbe/player.py:99 msgid "Stream" msgstr "Stream" #: ../quodlibet/player/gstbe/player.py:99 msgid "Buffering" msgstr "Načítání do vyrovnávací paměti" #: ../quodlibet/player/gstbe/player.py:447 msgid "Could not create GStreamer pipeline" msgstr "Nelze vytvořit rouru GStreameru" #: ../quodlibet/player/gstbe/player.py:669 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:670 #, python-format msgid "Media format: %(format-description)s" msgstr "Formát média: %(format-description)s" #: ../quodlibet/player/gstbe/plugins.py:36 #, 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 msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. In case 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:37 msgid "_Output pipeline:" msgstr "_Výstupní roura:" #: ../quodlibet/player/gstbe/prefs.py:44 #, python-format msgid "%.1f seconds" msgstr "%.1f vteřin" #: ../quodlibet/player/gstbe/prefs.py:58 msgid "_Buffer duration:" msgstr "_Délka mezipaměti:" #: ../quodlibet/player/gstbe/prefs.py:67 msgid "Disable _gapless playback" msgstr "Zakázat přehrávání _bez mezer" #: ../quodlibet/player/gstbe/prefs.py:71 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/util.py:104 msgid "No GStreamer audio sink found" msgstr "GStreamer audio sink nenalezen" #: ../quodlibet/player/gstbe/util.py:123 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:63 #, 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:72 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "Nelze najít element '{element}' GStreameru." #: ../quodlibet/plugins/playlist.py:24 #, 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:28 ../quodlibet/qltk/songsmenu.py:54 #: ../quodlibet/qltk/songsmenu.py:65 msgid "_Run Plugin" msgstr "_Spuarir zásuvný modul" #. Translators: Refers to the beginning of the playing song. #: ../quodlibet/qltk/bookmarks.py:28 msgid "Beginning" msgstr "Začátek" #: ../quodlibet/qltk/bookmarks.py:39 ../quodlibet/qltk/bookmarks.py:79 msgid "N/A" msgstr "N/A" #: ../quodlibet/qltk/bookmarks.py:84 msgid "Time" msgstr "Čas" #: ../quodlibet/qltk/bookmarks.py:90 ../quodlibet/qltk/bookmarks.py:125 msgid "Bookmark Name" msgstr "Název záložky" #: ../quodlibet/qltk/bookmarks.py:123 msgid "MM:SS" msgstr "MM:SS" #: ../quodlibet/qltk/bookmarks.py:211 ../quodlibet/qltk/information.py:133 msgid "Bookmarks" msgstr "Záložky" #: ../quodlibet/qltk/browser.py:57 msgid "_Filters" msgstr "_Filtry" #: ../quodlibet/qltk/browser.py:58 msgid "Recently _Played" msgstr "_Nedávno hrané" #: ../quodlibet/qltk/browser.py:60 msgid "Recently _Added" msgstr "Nedávno _Přidané" #: ../quodlibet/qltk/browser.py:62 msgid "_Top 40" msgstr "_Top 40" #: ../quodlibet/qltk/browser.py:64 msgid "All _Songs" msgstr "Všechny _skladby" #: ../quodlibet/qltk/browser.py:72 msgid "On Current _Genre(s)" msgstr "Podle právě přehrávaného žánru(ů)" #: ../quodlibet/qltk/browser.py:73 msgid "On Current _Artist(s)" msgstr "Podle právě přehrávaného _umělce/ů" #: ../quodlibet/qltk/browser.py:74 msgid "On Current Al_bum" msgstr "Podle právě přehrávaného al_ba" #: ../quodlibet/qltk/browser.py:82 msgid "Random _Genre" msgstr "Náhodný _Žánr" #: ../quodlibet/qltk/browser.py:83 msgid "Random _Artist" msgstr "Náhodný Umělec" #: ../quodlibet/qltk/browser.py:84 msgid "Random Al_bum" msgstr "Náhodné al_bum" #: ../quodlibet/qltk/browser.py:97 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:41 msgid "_Name:" msgstr "_Jméno:" #: ../quodlibet/qltk/cbes.py:49 ../quodlibet/qltk/edittags.py:312 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:118 #, python-format msgid "New %s" msgstr "Nový %s" #: ../quodlibet/qltk/data_editors.py:217 msgid "(unknown)" msgstr "(neznámé)" #: ../quodlibet/qltk/data_editors.py:346 msgid "Tag expression" msgstr "Výraz tagu" #: ../quodlibet/qltk/data_editors.py:373 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:374 msgid "Enter new tag" msgstr "Vložit nový tag" #: ../quodlibet/qltk/delete.py:38 msgid "Files:" msgstr "Soubory:" #: ../quodlibet/qltk/delete.py:64 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:73 msgid "The selected files will be deleted from disk." msgstr "Vybrané soubory budou smazány z disku." #: ../quodlibet/qltk/delete.py:77 #, 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:92 msgid "_Delete Files" msgstr "_Smazat soubory" #: ../quodlibet/qltk/delete.py:107 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:116 msgid "The selected files will be moved to the trash." msgstr "Vybrané soubory budou přesunuty do koše." #: ../quodlibet/qltk/delete.py:121 #, 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:135 ../quodlibet/qltk/delete.py:142 msgid "_Move to Trash" msgstr "_Přesunout do koše" #: ../quodlibet/qltk/delete.py:153 ../quodlibet/qltk/delete.py:188 #, python-format msgid "Moving %(current)d/%(total)d." msgstr "Přesouvání %(current)d/%(total)d." #: ../quodlibet/qltk/delete.py:174 ../quodlibet/qltk/delete.py:206 msgid "Unable to move to trash" msgstr "Nelze přesunout do koše" #: ../quodlibet/qltk/delete.py:175 ../quodlibet/qltk/delete.py:207 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:217 ../quodlibet/qltk/delete.py:251 #, python-format msgid "Deleting %(current)d/%(total)d." msgstr "Mazání %(current)d/%(total)d." #: ../quodlibet/qltk/delete.py:237 ../quodlibet/qltk/delete.py:270 msgid "Unable to delete files" msgstr "Soubory nezle smazat" #: ../quodlibet/qltk/delete.py:238 ../quodlibet/qltk/delete.py:271 msgid "Deleting one or more files failed." msgstr "Odstraňování jednoho nebo více souborů selhalo." #: ../quodlibet/qltk/edittags.py:64 ../quodlibet/qltk/edittags.py:75 #, 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:68 ../quodlibet/qltk/edittags.py:72 #, 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:194 msgid "Split into _Multiple Values" msgstr "Rozdělit do _Více položek" #: ../quodlibet/qltk/edittags.py:212 msgid "Split Disc out of _Album" msgstr "Oddělit disk od _Alba" #: ../quodlibet/qltk/edittags.py:229 msgid "Split _Version out of Title" msgstr "Oddělit _Verzi od názvu" #: ../quodlibet/qltk/edittags.py:260 msgid "Split Arranger out of Ar_tist" msgstr "Oddělit aranžmá od Umělce" #: ../quodlibet/qltk/edittags.py:265 msgid "Split _Performer out of Artist" msgstr "Oddělit _Interpreta od umělce" #: ../quodlibet/qltk/edittags.py:271 msgid "Split _Performer out of Title" msgstr "Oddělit _Interpreta od názvu" #: ../quodlibet/qltk/edittags.py:277 msgid "Split _Originalartist out of Title" msgstr "Oddalit _Původního umělce od názvu" #: ../quodlibet/qltk/edittags.py:284 msgid "Add a Tag" msgstr "Přidat tag" #: ../quodlibet/qltk/edittags.py:303 msgid "_Tag:" msgstr "_Tag:" #: ../quodlibet/qltk/edittags.py:405 msgid "Edit Tags" msgstr "Upravit tagy" #: ../quodlibet/qltk/edittags.py:478 msgid "Show _programmatic tags" msgstr "Ukázat _" #: ../quodlibet/qltk/edittags.py:479 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" #. Translators: Revert button in the tag editor #: ../quodlibet/qltk/edittags.py:509 msgctxt "edittags" msgid "_Revert" msgstr "_Obrátit pořadí" #. Translators: Save button in the tag editor #: ../quodlibet/qltk/edittags.py:514 msgctxt "edittags" msgid "_Save" msgstr "_Uložit" #: ../quodlibet/qltk/edittags.py:660 msgid "Unable to add tag" msgstr "Tag nelze přidat" #: ../quodlibet/qltk/edittags.py:661 #, python-format msgid "Unable to add <b>%s</b>" msgstr "Nelze přidat <b>%s</b>" #: ../quodlibet/qltk/edittags.py:663 #, python-format msgid "" "The files currently selected do not support multiple values for <b>%s</b>." 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:690 ../quodlibet/qltk/edittags.py:856 #: ../quodlibet/qltk/tagsfrompath.py:213 ../quodlibet/util/__init__.py:506 #: ../quodlibet/util/tags.py:243 msgid "Invalid tag" msgstr "Neplatný tag" #: ../quodlibet/qltk/edittags.py:691 ../quodlibet/qltk/edittags.py:857 #: ../quodlibet/qltk/tagsfrompath.py:214 #, python-format msgid "" "Invalid tag <b>%s</b>\n" "\n" "The files currently selected do not support editing this tag." msgstr "" "Neplatný tag %s\n" "\n" "Vybrané soubory nepodporují označení tímto tagem." #: ../quodlibet/qltk/edittags.py:828 ../quodlibet/qltk/edittags.py:868 msgid "Invalid value" msgstr "Neplatná hodnota" #: ../quodlibet/qltk/edittags.py:829 ../quodlibet/qltk/edittags.py:869 #, python-format msgid "" "Invalid value: <b>%(value)s</b>\n" "\n" "%(error)s" msgstr "" "Neplatná hodnota: %(value)s\n" "\n" "%(error)s" #: ../quodlibet/qltk/_editutils.py:30 msgid "Tag may not be accurate" msgstr "Tag nemusí být správně" #: ../quodlibet/qltk/_editutils.py:33 #, 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:49 msgid "Unable to save song" msgstr "Skladbu nelze uložit" #: ../quodlibet/qltk/_editutils.py:52 #, 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:96 #: ../quodlibet/qltk/quodlibetwindow.py:1103 msgid "_About" msgstr "_O Quod Libet" #: ../quodlibet/qltk/exfalsowindow.py:100 #: ../quodlibet/qltk/quodlibetwindow.py:1125 msgid "_Check for Updates…" msgstr "_Zkontrolovat aktualizace…" #: ../quodlibet/qltk/exfalsowindow.py:106 #: ../quodlibet/qltk/quodlibetwindow.py:1058 ../quodlibet/qltk/songsmenu.py:288 msgid "_Plugins" msgstr "_Zásuvné moduly" #: ../quodlibet/qltk/exfalsowindow.py:268 #, 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/exfalsowindow.py:290 ../quodlibet/qltk/prefs.py:599 msgid "Split _on:" msgstr "Rozdělit _v:" #: ../quodlibet/qltk/exfalsowindow.py:296 ../quodlibet/qltk/prefs.py:614 msgid "Tag Editing" msgstr "Úprava tagů" #: ../quodlibet/qltk/filesel.py:211 msgid "Folders" msgstr "Složky" #: ../quodlibet/qltk/filesel.py:266 msgid "_New Folder…" msgstr "_Nová složka…" #: ../quodlibet/qltk/filesel.py:275 msgid "_Select all Sub-Folders" msgstr "_Vybrat všechny podsložky" #: ../quodlibet/qltk/filesel.py:381 msgid "New Folder" msgstr "Nová složka" #: ../quodlibet/qltk/filesel.py:381 msgid "Enter a name for the new folder:" msgstr "Jméno nové složky:" #: ../quodlibet/qltk/filesel.py:394 msgid "Unable to create folder" msgstr "Složku nelze vytvořit" #: ../quodlibet/qltk/filesel.py:411 msgid "Unable to delete folder" msgstr "Složku nelze smazat" #: ../quodlibet/qltk/filesel.py:526 ../quodlibet/qltk/pluginwin.py:168 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:172 #: ../quodlibet/qltk/information.py:453 #, python-format msgid "Disc %s" msgstr "Disk %s" #: ../quodlibet/qltk/info.py:45 ../quodlibet/qltk/information.py:177 #, python-format msgid "Track %s" msgstr "Skladba %s" #: ../quodlibet/qltk/info.py:109 msgid "_Edit Display…" msgstr "_Upravit zobrazení…" #: ../quodlibet/qltk/information.py:107 msgid "No songs are selected." msgstr "Nejsou vybrány žádné skladby." #: ../quodlibet/qltk/information.py:108 msgid "No Songs" msgstr "Žádné skladby." #: ../quodlibet/qltk/information.py:123 ../quodlibet/qltk/information.py:343 #: ../quodlibet/qltk/information.py:476 ../quodlibet/qltk/information.py:536 msgid "Information" msgstr "Informace" #: ../quodlibet/qltk/information.py:128 msgid "Lyrics" msgstr "Texty" #: ../quodlibet/qltk/information.py:189 ../quodlibet/qltk/information.py:401 #, python-format msgid "Produced by %s" msgstr "Vydáno %s" #: ../quodlibet/qltk/information.py:204 ../quodlibet/util/tags.py:87 msgid "artist" msgstr "umělec" #: ../quodlibet/qltk/information.py:205 ../quodlibet/qltk/information.py:566 #: ../quodlibet/util/tags.py:87 msgid "artists" msgstr "umělci" #. for backwards compat #: ../quodlibet/qltk/information.py:226 ../quodlibet/util/tags.py:98 #: ../quodlibet/util/tags.py:126 msgid "performers" msgstr "interpreti" #: ../quodlibet/qltk/information.py:240 ../quodlibet/qltk/information.py:253 #: ../quodlibet/qltk/songlistcolumns.py:276 msgid "Never" msgstr "Nikdy" #: ../quodlibet/qltk/information.py:241 #, 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:259 ../quodlibet/util/tags.py:151 msgid "added" msgstr "přidáno" #: ../quodlibet/qltk/information.py:260 ../quodlibet/util/tags.py:152 msgid "last played" msgstr "naposledy hrané" #: ../quodlibet/qltk/information.py:261 ../quodlibet/util/tags.py:162 msgid "plays" msgstr "přehrání" #: ../quodlibet/qltk/information.py:262 ../quodlibet/util/tags.py:163 msgid "skips" msgstr "přeskočení" #: ../quodlibet/qltk/information.py:263 ../quodlibet/util/tags.py:168 msgid "rating" msgstr "hodnocení" #: ../quodlibet/qltk/information.py:292 msgid "path" msgstr "cesta" #: ../quodlibet/qltk/information.py:293 ../quodlibet/util/tags.py:166 msgid "length" msgstr "délka" #: ../quodlibet/qltk/information.py:294 msgid "format" msgstr "formát" #: ../quodlibet/qltk/information.py:295 ../quodlibet/util/tags.py:175 msgid "codec" msgstr "kodek" #: ../quodlibet/qltk/information.py:296 ../quodlibet/util/tags.py:176 msgid "encoding" msgstr "kódování" #: ../quodlibet/qltk/information.py:297 ../quodlibet/util/tags.py:172 msgid "bitrate" msgstr "bitrate" #: ../quodlibet/qltk/information.py:298 ../quodlibet/util/tags.py:173 msgid "file size" msgstr "velikost souboru" #: ../quodlibet/qltk/information.py:299 ../quodlibet/util/tags.py:161 msgid "modified" msgstr "naposledy změněno" #: ../quodlibet/qltk/information.py:336 msgid "Additional" msgstr "Dodatečné" #: ../quodlibet/qltk/information.py:388 #, 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:463 msgid "Track unavailable" msgstr "Skladba je nedostupná" #: ../quodlibet/qltk/information.py:469 msgid "Track List" msgstr "Seznam skladeb" #: ../quodlibet/qltk/information.py:510 ../quodlibet/qltk/information.py:583 #, 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:513 msgid "Selected Discography" msgstr "Vybraná diskografie" #: ../quodlibet/qltk/information.py:563 #, 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:591 ../quodlibet/util/tags.py:85 msgid "albums" msgstr "alba" #: ../quodlibet/qltk/information.py:604 msgid "Total length:" msgstr "Celková delka:" #: ../quodlibet/qltk/information.py:608 msgid "Total size:" msgstr "Celková velikost" #: ../quodlibet/qltk/information.py:611 msgid "Files" msgstr "Soubory" #: ../quodlibet/qltk/lyrics.py:37 #, fuzzy msgid "_View online" msgstr "online" #: ../quodlibet/qltk/lyrics.py:65 msgid "No lyrics found for this song." msgstr "Ke skladbě nebyly nalezeny žádné texty." #: ../quodlibet/qltk/lyrics.py:76 msgid "Searching for lyrics…" msgstr "Hledání textů..." #: ../quodlibet/qltk/maskedbox.py:21 msgid "Are you sure you want to remove all songs?" msgstr "Jste si jistí, že chcete odstranit všecny skladby?" #: ../quodlibet/qltk/maskedbox.py:22 msgid "The selected songs will be removed from the library." msgstr "Vybrané soubory budou odstraněny ze sbírky." #: ../quodlibet/qltk/maskedbox.py:45 msgid "Unhide" msgstr "Odkrýt" #: ../quodlibet/qltk/maskedbox.py:87 msgid "_Unhide" msgstr "_Odkrýt" #: ../quodlibet/qltk/msg.py:42 msgid "Discard tag changes?" msgstr "Zahodit změny v tagu?" #: ../quodlibet/qltk/msg.py:43 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:56 ../quodlibet/qltk/prefs.py:596 #: ../quodlibet/qltk/textedit.py:65 ../quodlibet/qltk/tracknumbers.py:118 msgid "_Revert" msgstr "_Obrátit" #: ../quodlibet/qltk/msg.py:105 msgid "File exists" msgstr "Soubor existuje" #: ../quodlibet/qltk/msg.py:107 #, python-format msgid "Replace %(file-name)s?" msgstr "Nahradit %(file-name)s?" #: ../quodlibet/qltk/msg.py:113 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:256 msgid "Toggle shuffle mode" msgstr "Prohodit mód promíchání" #: ../quodlibet/qltk/playorder.py:272 msgid "Toggle repeat mode" msgstr "Prohodit mód opakování" #: ../quodlibet/qltk/pluginwin.py:45 msgid "Plugin Errors" msgstr "Chyby zásuvného modulu" #: ../quodlibet/qltk/pluginwin.py:125 msgid "Enabled" msgstr "Povoleno" #: ../quodlibet/qltk/pluginwin.py:126 msgid "Disabled" msgstr "Zakázáno" #: ../quodlibet/qltk/pluginwin.py:132 msgid "No category" msgstr "Žádná kategorie" #: ../quodlibet/qltk/pluginwin.py:170 msgid "Events" msgstr "Události" #: ../quodlibet/qltk/pluginwin.py:171 msgid "Play Order" msgstr "Pořadí přehrávání:" #: ../quodlibet/qltk/pluginwin.py:172 msgid "Editing" msgstr "Úpravy" #: ../quodlibet/qltk/pluginwin.py:174 msgid "Covers" msgstr "Přebaly" #: ../quodlibet/qltk/pluginwin.py:310 msgid "No plugins found." msgstr "Nebyly nalezeny žádné zásuvné moduly." #: ../quodlibet/qltk/pluginwin.py:359 msgid "Plugins" msgstr "Zásuvné moduly" #: ../quodlibet/qltk/pluginwin.py:383 msgid "Filter by plugin state / tag" msgstr "" #: ../quodlibet/qltk/pluginwin.py:389 msgid "Filter by plugin type" msgstr "" #: ../quodlibet/qltk/pluginwin.py:395 msgid "Filter by plugin name or description" msgstr "" #: ../quodlibet/qltk/pluginwin.py:404 msgid "Show _Errors" msgstr "Ukázat _Chyby" #: ../quodlibet/qltk/prefs.py:46 msgid "_Disc" msgstr "_Disk" #: ../quodlibet/qltk/prefs.py:47 msgid "_Track" msgstr "_Skladba" #: ../quodlibet/qltk/prefs.py:48 msgid "Grou_ping" msgstr "_Sloučit" #: ../quodlibet/qltk/prefs.py:51 msgid "Al_bum" msgstr "Al_bum" #: ../quodlibet/qltk/prefs.py:56 msgid "_Filename" msgstr "_Název souboru" #: ../quodlibet/qltk/prefs.py:58 msgid "_Length" msgstr "_Délka" #: ../quodlibet/qltk/prefs.py:65 msgid "_Jump to playing song automatically" msgstr "_Rovnou automaticky přehrávat skladbu" #: ../quodlibet/qltk/prefs.py:67 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:83 msgid "_Others:" msgstr "_Ostatní:" #: ../quodlibet/qltk/prefs.py:89 msgid "_Edit…" msgstr "_Upravit..." #: ../quodlibet/qltk/prefs.py:92 msgid "Add or remove additional column headers" msgstr "Přidat nebo odstranit hlavičky sloupců" #: ../quodlibet/qltk/prefs.py:102 msgid "Visible Columns" msgstr "Viditelné položky" #: ../quodlibet/qltk/prefs.py:105 msgid "Title includes _version" msgstr "Název obsahuje _verzi" #: ../quodlibet/qltk/prefs.py:107 msgid "Artist includes all _people" msgstr "Umělec obsahuje všechny tvůrce" #: ../quodlibet/qltk/prefs.py:109 msgid "Album includes _disc subtitle" msgstr "Album obsahuje podnázev _disku" #: ../quodlibet/qltk/prefs.py:111 msgid "Filename includes _folder" msgstr "Název souboru obsahuje_složku" #: ../quodlibet/qltk/prefs.py:124 msgid "Column Preferences" msgstr "Nastavení sloupce" #: ../quodlibet/qltk/prefs.py:130 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:143 ../quodlibet/qltk/shortcuts.py:25 msgid "Song List" msgstr "Seznam skladeb" #: ../quodlibet/qltk/prefs.py:223 msgid "Edit Columns" msgstr "Upravit sloupce" #: ../quodlibet/qltk/prefs.py:260 msgid "Duration totals" msgstr "Celková délka" #: ../quodlibet/qltk/prefs.py:272 msgid "_Global filter:" msgstr "_Globální filtr:" #: ../quodlibet/qltk/prefs.py:278 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:284 msgctxt "heading" msgid "Search" msgstr "Vyhledávání" #: ../quodlibet/qltk/prefs.py:288 ../quodlibet/qltk/shortcuts.py:22 msgid "Browsers" msgstr "Prohlížeče" #: ../quodlibet/qltk/prefs.py:294 msgid "Confirm _multiple ratings" msgstr "Potvrdit _hromadné hodnocení" #: ../quodlibet/qltk/prefs.py:296 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:299 msgid "Enable _one-click ratings" msgstr "Povolit hodnocení _jedním klikem" #: ../quodlibet/qltk/prefs.py:301 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:307 ../quodlibet/qltk/prefs.py:617 msgid "Ratings" msgstr "Hodnocení" #. Filename choice algorithm config #: ../quodlibet/qltk/prefs.py:313 msgid "Prefer _embedded art" msgstr "Upřednostnit _vložené grafiky alb" #: ../quodlibet/qltk/prefs.py:315 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:320 msgid "_Fixed image filename:" msgstr "_Fixní název souboru obrázku:" #: ../quodlibet/qltk/prefs.py:322 msgid "The single image filename to use if selected" msgstr "Použít jméno obrázku, pokud je vybrán" #: ../quodlibet/qltk/prefs.py:328 msgid "The album art image file to use when forced" msgstr "Použít soubor grafiky alba vynuceně" #: ../quodlibet/qltk/prefs.py:337 msgid "Album Art" msgstr "Přebaly alb" #: ../quodlibet/qltk/prefs.py:358 msgid "Playback" msgstr "Přehrávání" #: ../quodlibet/qltk/prefs.py:363 msgid "Output Configuration" msgstr "Nastavení výstupu" #: ../quodlibet/qltk/prefs.py:374 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:377 msgid "_Fall-back gain (dB):" msgstr "_Vyrovnání hlasitosti (dB):" #: ../quodlibet/qltk/prefs.py:388 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:391 msgid "_Pre-amp gain (dB):" msgstr "_Předzesílení (dB):" #: ../quodlibet/qltk/prefs.py:396 msgid "_Enable Replay Gain volume adjustment" msgstr "_Povolit úpravu hlasitosti" #: ../quodlibet/qltk/prefs.py:421 msgid "Replay Gain Volume Adjustment" msgstr "Úprava hlasitosti" #: ../quodlibet/qltk/prefs.py:451 msgid "_Default rating:" msgstr "_Výchozí hodnocení:" #: ../quodlibet/qltk/prefs.py:494 msgid "Rating _scale:" msgstr "Stupnice h_odnocení:" #: ../quodlibet/qltk/prefs.py:543 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:548 msgid "_Bayesian averaging amount:" msgstr "Hodnota _Bayesovského průměru:" #: ../quodlibet/qltk/prefs.py:557 msgid "Save ratings and play _counts" msgstr "Uložit hodnocení a _počet přehrání" #: ../quodlibet/qltk/prefs.py:561 msgid "_Email:" msgstr "_Email:" #: ../quodlibet/qltk/prefs.py:563 msgid "Ratings and play counts will be set for this email address" msgstr "Hodnocení a počet přehrání budou nastaveny pro tuto emailovou adresu" #: ../quodlibet/qltk/prefs.py:578 msgid "Auto-save tag changes" msgstr "Automaticky ukládat změny tagů" #: ../quodlibet/qltk/prefs.py:580 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:588 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:611 msgid "Tags" msgstr "Tagy" #: ../quodlibet/qltk/prefs.py:632 msgid "Updating for new ratings" msgstr "Aktualizace nových hodnocení" #: ../quodlibet/qltk/prefs.py:642 msgid "Scan library _on start" msgstr "Načíst sbírku vždy při _startu" #: ../quodlibet/qltk/prefs.py:652 ../quodlibet/qltk/quodlibetwindow.py:1137 msgid "_Scan Library" msgstr "_Načíst sbírku" #: ../quodlibet/qltk/prefs.py:654 ../quodlibet/qltk/quodlibetwindow.py:1199 msgid "Check for changes in your library" msgstr "Zkontrolovat změny ve sbírce" #: ../quodlibet/qltk/prefs.py:659 msgid "Re_build Library" msgstr "_Znovu načíst sbírku" #: ../quodlibet/qltk/prefs.py:662 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:672 msgid "Scan Directories" msgstr "Pohledávat složky" #: ../quodlibet/qltk/prefs.py:678 msgid "Hidden Songs" msgstr "Skryté skladby" #: ../quodlibet/qltk/properties.py:159 ../quodlibet/util/collection.py:403 #, 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:163 ../quodlibet/qltk/properties.py:165 msgid "Properties" msgstr "Vlastnosti" #: ../quodlibet/qltk/queue.py:103 msgid "_Queue" msgstr "_Fronta" #: ../quodlibet/qltk/queue.py:127 msgid "Stop Once Empty" msgstr "Zastavit, pokud je prázdné" #: ../quodlibet/qltk/queue.py:131 msgid "_Clear Queue" msgstr "_Vyčistit frontu" #: ../quodlibet/qltk/queue.py:243 #, 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:200 msgid "_Browse Library" msgstr "_Procházet sbírku" #: ../quodlibet/qltk/quodlibetwindow.py:397 msgid "Toggle queue visibility" msgstr "Přepnout viditelnost fronty" #: ../quodlibet/qltk/quodlibetwindow.py:518 msgid "Playback Error" msgstr "Chyba přehrávání" #: ../quodlibet/qltk/quodlibetwindow.py:526 msgid "Set up library directories?" msgstr "Nastavit složky sbírky?" #: ../quodlibet/qltk/quodlibetwindow.py:527 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:533 msgid "_Not Now" msgstr "_Ne teď" #: ../quodlibet/qltk/quodlibetwindow.py:534 msgid "_Set Up" msgstr "_Nastavení" #: ../quodlibet/qltk/quodlibetwindow.py:993 msgid "Unable to add songs" msgstr "Nelze přidat skladby" #: ../quodlibet/qltk/quodlibetwindow.py:994 #: ../quodlibet/qltk/quodlibetwindow.py:1398 #, python-format msgid "%s uses an unsupported protocol." msgstr "%s používá nepodporovaný protokol." #: ../quodlibet/qltk/quodlibetwindow.py:1017 msgid "_Jump to Playing Song" msgstr "_Skočit na přehrávanou skladbu" #: ../quodlibet/qltk/quodlibetwindow.py:1023 msgid "_File" msgstr "_Soubor" #: ../quodlibet/qltk/quodlibetwindow.py:1024 msgid "_Song" msgstr "_Skladba" #: ../quodlibet/qltk/quodlibetwindow.py:1025 msgid "_View" msgstr "_Zobrazení" #: ../quodlibet/qltk/quodlibetwindow.py:1026 msgid "_Browse" msgstr "_Procházet" #: ../quodlibet/qltk/quodlibetwindow.py:1027 msgid "_Control" msgstr "_Ovládání" #: ../quodlibet/qltk/quodlibetwindow.py:1028 msgid "_Help" msgstr "_Pomoc" #: ../quodlibet/qltk/quodlibetwindow.py:1034 msgid "_Add a Folder…" msgstr "_Přidat složku..." #: ../quodlibet/qltk/quodlibetwindow.py:1039 msgid "_Add a File…" msgstr "_Přidat soubor..." #: ../quodlibet/qltk/quodlibetwindow.py:1044 msgid "_Add a Location…" msgstr "_Přidat umístění…" #: ../quodlibet/qltk/quodlibetwindow.py:1073 msgid "Edit Bookmarks…" msgstr "Upravit záložky..." #: ../quodlibet/qltk/quodlibetwindow.py:1093 msgid "Stop After This Song" msgstr "Po této skladbě zastavit přehrávání" #: ../quodlibet/qltk/quodlibetwindow.py:1099 msgid "_Keyboard Shortcuts" msgstr "_Klávesové zkratky" #: ../quodlibet/qltk/quodlibetwindow.py:1108 msgid "Online Help" msgstr "Online pomoc" #: ../quodlibet/qltk/quodlibetwindow.py:1117 msgid "Search Help" msgstr "Hledat pomoc" #: ../quodlibet/qltk/quodlibetwindow.py:1386 msgid "Add a Location" msgstr "Přidat umístění" #: ../quodlibet/qltk/quodlibetwindow.py:1387 msgid "Enter the location of an audio file:" msgstr "Zadejte umístění zvukového souboru:" #: ../quodlibet/qltk/quodlibetwindow.py:1392 #: ../quodlibet/qltk/quodlibetwindow.py:1397 msgid "Unable to add location" msgstr "Umístění nelze přidat" #: ../quodlibet/qltk/quodlibetwindow.py:1393 #, python-format msgid "%s is not a valid location." msgstr "%s není platné umístění." #: ../quodlibet/qltk/quodlibetwindow.py:1406 #: ../quodlibet/qltk/quodlibetwindow.py:1415 msgid "Add Music" msgstr "Přidat hudbu" #: ../quodlibet/qltk/quodlibetwindow.py:1406 ../quodlibet/qltk/scanbox.py:100 msgid "_Add Folders" msgstr "_Přidat složky" #: ../quodlibet/qltk/quodlibetwindow.py:1413 msgid "Music Files" msgstr "Hudební soubory" #: ../quodlibet/qltk/quodlibetwindow.py:1415 msgid "_Add Files" msgstr "_Přidat soubory" #: ../quodlibet/qltk/ratingsmenu.py:25 #, 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:27 msgid "The saved ratings will be removed" msgstr "Uložená hodnocení budou odstraněna" #: ../quodlibet/qltk/ratingsmenu.py:28 #, 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:58 ../quodlibet/qltk/ratingsmenu.py:112 msgid "_Remove Rating" msgstr "_Odstranit hodnocení" #: ../quodlibet/qltk/ratingsmenu.py:99 msgid "Change _Rating" msgstr "Změnit _hodnocení" #: ../quodlibet/qltk/renamefiles.py:53 msgid "Replace spaces with _underscores" msgstr "Nahradit mezery _podtržítky" #: ../quodlibet/qltk/renamefiles.py:63 msgid "Strip _Windows-incompatible characters" msgstr "Nahradit znaky nekompatibilní s _Windows" #: ../quodlibet/qltk/renamefiles.py:81 msgid "Strip _diacritical marks" msgstr "Nahradit _diakritiku" #: ../quodlibet/qltk/renamefiles.py:92 msgid "Strip non-_ASCII characters" msgstr "Nahradit ne-_ASCII znaky" #: ../quodlibet/qltk/renamefiles.py:102 msgid "Use only _lowercase characters" msgstr "Použít jen _malá písmena" #: ../quodlibet/qltk/renamefiles.py:130 msgid "Rename Files" msgstr "Přejmenovat soubory" #: ../quodlibet/qltk/renamefiles.py:148 ../quodlibet/qltk/tagsfrompath.py:117 msgid "Path Patterns" msgstr "Vzory cesty" #: ../quodlibet/qltk/renamefiles.py:149 ../quodlibet/qltk/tagsfrompath.py:118 msgid "Edit saved patterns…" msgstr "Upravit uložené vzory..." #: ../quodlibet/qltk/renamefiles.py:152 ../quodlibet/qltk/tagsfrompath.py:121 #: ../quodlibet/qltk/tracknumbers.py:59 msgid "_Preview" msgstr "_Náhled" #: ../quodlibet/qltk/renamefiles.py:179 #, fuzzy msgid "File names" msgstr "Název souboru" #: ../quodlibet/qltk/renamefiles.py:189 #, fuzzy msgid "_Move album art" msgstr "umělec alba" #: ../quodlibet/qltk/renamefiles.py:192 msgid "See '[albumart] filenames' config entry for image search strings" msgstr "" #: ../quodlibet/qltk/renamefiles.py:197 msgid "_Overwrite album art at target" msgstr "" #: ../quodlibet/qltk/renamefiles.py:205 #, fuzzy msgid "_Remove empty directories" msgstr "_Odstranit nepoužívané přebaly a složky" #: ../quodlibet/qltk/renamefiles.py:211 #, fuzzy msgid "Album art" msgstr "Přebaly alb" #: ../quodlibet/qltk/renamefiles.py:240 msgid "New Name" msgstr "Nový název" #: ../quodlibet/qltk/renamefiles.py:317 msgid "Unable to rename file" msgstr "Soubor nelze přejmenovat" #: ../quodlibet/qltk/renamefiles.py:318 #, python-format msgid "" "Renaming <b>%(old-name)s</b> to <b>%(new-name)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." 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:326 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:327 ../quodlibet/qltk/wlw.py:51 msgid "_Stop" msgstr "_Stop" #: ../quodlibet/qltk/renamefiles.py:329 msgid "_Continue" msgstr "_Pokračovat" #: ../quodlibet/qltk/renamefiles.py:442 msgid "Path is not absolute" msgstr "Uvedená cesta není absolutní" #: ../quodlibet/qltk/renamefiles.py:443 #, python-format msgid "" "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 ~/." 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:48 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:100 msgid "Select Directories" msgstr "Vybrané složky" #: ../quodlibet/qltk/searchbar.py:54 msgid "Saved Searches" msgstr "Uložené hodnoty" #: ../quodlibet/qltk/searchbar.py:55 msgid "Edit saved searches…" msgstr "Upravit uložená vyhledávání…" #: ../quodlibet/qltk/searchbar.py:77 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:133 msgid "Search after _typing" msgstr "Hledat po _psaní" #: ../quodlibet/qltk/searchbar.py:136 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:195 msgid "_Limit:" msgstr "_Limit:" #: ../quodlibet/qltk/searchbar.py:208 msgid "_Weight" msgstr "_Váha" #: ../quodlibet/qltk/seekbutton.py:239 msgid "Display remaining time" msgstr "Zobrazit zbývající čas" #: ../quodlibet/qltk/shortcuts.py:17 msgid "Main Window" msgstr "Hlavní okno" #: ../quodlibet/qltk/shortcuts.py:18 msgid "Seek backwards by 10 seconds" msgstr "Procházet zpět po 10 vteřinách" #: ../quodlibet/qltk/shortcuts.py:19 msgid "Seek forward by 10 seconds" msgstr "Procházet vpřed po 10 vteřinách" #: ../quodlibet/qltk/shortcuts.py:20 msgid "Focus the search entry" msgstr "Zaměřit na vyhledávané" #: ../quodlibet/qltk/shortcuts.py:23 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:27 msgid "Open the information window for the selected songs" msgstr "Otevřít informační okno k vybraným skladbám." #: ../quodlibet/qltk/shortcuts.py:28 msgid "Open the tag editor for the selected songs" msgstr "Otevřít editor tagů pro vybrané skladby" #: ../quodlibet/qltk/shortcuts.py:29 msgid "Queue the selected songs" msgstr "Zařadit vybrané skladby do fronty" #: ../quodlibet/qltk/shortcuts.py:30 msgid "Delete the selected songs" msgstr "Smazat vybrané skladby" #: ../quodlibet/qltk/shortcuts.py:31 msgid "Show the inline search entry" msgstr "Zobrazit hodnotu řádkového hledání" #: ../quodlibet/qltk/shortcuts.py:32 msgid "Left click on a column header" msgstr "Levý klik na hlavičku sloupce" #: ../quodlibet/qltk/shortcuts.py:33 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:35 msgid "Tree View" msgstr "Struktura složek" #: ../quodlibet/qltk/shortcuts.py:37 msgid "Collapses the element or select the parent element" msgstr "Sbalí prvek nebo vybere prvek rodičovský" #: ../quodlibet/qltk/shortcuts.py:38 msgid "Expands the element" msgstr "Rozbalí element" #: ../quodlibet/qltk/shortcuts.py:40 msgid "Text Entries" msgstr "Texty" #: ../quodlibet/qltk/shortcuts.py:42 #, fuzzy msgid "Undo the last change" msgstr "Znovu provést změnu" #: ../quodlibet/qltk/shortcuts.py:43 msgid "Redo the last undone change" msgstr "Znovu provést změnu" #: ../quodlibet/qltk/shortcuts.py:46 msgid "Select all songs in all panes" msgstr "Vybrat všechny skladby ve všech panelech." #: ../quodlibet/qltk/songlist.py:366 #, python-format msgid "_Filter on %s" msgstr "_Filtr na %s" #: ../quodlibet/qltk/songlist.py:1083 msgid "All _Headers" msgstr "Všechny _Hlavičky" #: ../quodlibet/qltk/songlist.py:1084 msgid "_Track Headers" msgstr "Hlavičky _Skladeb" #: ../quodlibet/qltk/songlist.py:1085 msgid "_Album Headers" msgstr "Hlavičky _Alb" #: ../quodlibet/qltk/songlist.py:1086 msgid "_People Headers" msgstr "Hlavičky _Lidí" #: ../quodlibet/qltk/songlist.py:1087 msgid "_Date Headers" msgstr "Hlavičky _Dat" #: ../quodlibet/qltk/songlist.py:1088 msgid "_File Headers" msgstr "Hlavičky _Souborů" #: ../quodlibet/qltk/songlist.py:1089 msgid "_Production Headers" msgstr "Hlavičky _Produkce" #: ../quodlibet/qltk/songlist.py:1104 msgid "_Customize Headers…" msgstr "_Upravit hlavičky..." #: ../quodlibet/qltk/songlist.py:1109 msgid "_Expand Column" msgstr "_Rozšířit sloupec" #: ../quodlibet/qltk/songsmenu.py:39 #, fuzzy, python-format msgid "Remove track: \"%(title)s\" from library?" msgid_plural "Remove %(count)d tracks from library?" msgstr[0] "_Odstranit ze sbírky" msgstr[1] "_Odstranit ze sbírky" msgstr[2] "_Odstranit ze sbírky" #: ../quodlibet/qltk/songsmenu.py:45 #, fuzzy msgid "Remove from Library" msgstr "_Odstranit ze sbírky" #: ../quodlibet/qltk/songsmenu.py:50 #, 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:61 #, 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:133 msgid "Configure Plugins…" msgstr "Nastavit zásuvné moduly…" #: ../quodlibet/qltk/songsmenu.py:328 msgid "Add to _Queue" msgstr "Přidat do _Fronty" #: ../quodlibet/qltk/songsmenu.py:348 #, fuzzy msgid "_Remove from Library…" msgstr "_Odstranit ze sbírky" #: ../quodlibet/qltk/tagsfrompath.py:48 msgid "Replace _underscores with spaces" msgstr "Nahradit _podtržítka mezerami" #: ../quodlibet/qltk/tagsfrompath.py:58 msgid "_Title-case tags" msgstr "_Tagy Kapitálkami" #: ../quodlibet/qltk/tagsfrompath.py:68 msgid "Split into multiple _values" msgstr "Rozdělit do více _hodnot" #: ../quodlibet/qltk/tagsfrompath.py:102 msgid "Tags From Path" msgstr "Tagy z cesty" #: ../quodlibet/qltk/tagsfrompath.py:139 msgid "Tags replace existing ones" msgstr "Nahradit existující tagy" #: ../quodlibet/qltk/tagsfrompath.py:140 msgid "Tags are added to existing ones" msgstr "Tagy jsou přidány k již existujícím" #: ../quodlibet/qltk/tagsfrompath.py:196 #, python-format msgid "" "The pattern\n" "\t<b>%s</b>\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/tagsfrompath.py:217 msgid "Invalid tags" msgstr "Neplatné tagy" #: ../quodlibet/qltk/tagsfrompath.py:218 #, 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ů." #: ../quodlibet/qltk/textedit.py:143 #, 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:159 msgid "Edit Display" msgstr "Upravit zobrazení" #: ../quodlibet/qltk/tracknumbers.py:40 msgid "Track Numbers" msgstr "Čísla skladeb" #: ../quodlibet/qltk/tracknumbers.py:43 msgid "Start fro_m:" msgstr "Začít _od:" #: ../quodlibet/qltk/tracknumbers.py:52 msgid "_Total tracks:" msgstr "_Celkem skladeb:" #: ../quodlibet/qltk/unity.py:53 msgid "Play/Pause" msgstr "Přehrávat/Pauza" #: ../quodlibet/qltk/unity.py:73 msgid "Previous" msgstr "Předchozí" #: ../quodlibet/qltk/views.py:924 #, python-format msgid "and %d more…" msgstr "a %d více..." #: ../quodlibet/qltk/wlw.py:201 msgid "Saving the songs you changed." msgstr "Ukládání změněných skladeb." #: ../quodlibet/qltk/wlw.py:202 #, 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:235 #, 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:425 msgid "Playlists must have a name" msgstr "Seznam skladeb musí mít jméno" #: ../quodlibet/util/collection.py:608 #, python-format msgid "A playlist named %s already exists." msgstr "Seznam skladeb s názvem %s již existuje." #: ../quodlibet/util/cover/built_in.py:27 msgid "Embedded album covers" msgstr "Vložené přebaly alb" #: ../quodlibet/util/cover/built_in.py:28 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:50 msgid "Filesystem cover" msgstr "Přebal ze systému souborů" #: ../quodlibet/util/cover/built_in.py:51 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/__init__.py:77 msgid "Display brief usage information" msgstr "Zobrazit stručné info o využití" #: ../quodlibet/util/__init__.py:79 msgid "Display version and copyright" msgstr "Zobrazit verzi a copyright" #: ../quodlibet/util/__init__.py:119 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "Využití: %(program)s %(usage)s" #: ../quodlibet/util/__init__.py:121 msgid "[options]" msgstr "[možnosti]" #: ../quodlibet/util/__init__.py:166 #, python-format msgid "Option %r not recognized." msgstr "Volba %r nerozpoznána." #: ../quodlibet/util/__init__.py:169 #, python-format msgid "Option %r requires an argument." msgstr "Volba %r vyžaduje parametry." #: ../quodlibet/util/__init__.py:172 #, python-format msgid "%r is not a unique prefix." msgstr "%r není jedinečný prefix." #: ../quodlibet/util/__init__.py:348 #, python-format msgid "%d kbps" msgstr "%d kbps" #: ../quodlibet/util/__init__.py:403 #, 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:416 msgid "No time information" msgstr "Informace o čase nejsou dostupné" #: ../quodlibet/util/__init__.py:419 #, 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:420 #, 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:421 #, 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:422 #, 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:423 #, 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:515 msgctxt "check" msgid "titlecase?" msgstr "Všude první velké?" #: ../quodlibet/util/massagers.py:116 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:131 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:152 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:174 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:196 msgid "" "MusicBrainz release status must be 'official', 'promotional', or 'bootleg'." msgstr "Status MusicBrainz musí být 'official', 'promotional', nebo 'bootleg'." #: ../quodlibet/util/massagers.py:209 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:117 msgid "Unable to edit song" msgstr "Skladbu nelze upravit" #: ../quodlibet/util/songwrapper.py:118 #, python-format msgid "" "Saving <b>%s</b> 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:35 #: ../quodlibet/util/string/__init__.py:45 msgid "[Invalid Encoding]" msgstr "[Neplatné kódování]" #: ../quodlibet/util/tags.py:85 msgid "album" msgstr "album" #: ../quodlibet/util/tags.py:86 msgid "arranger" msgstr "aranžmá" #: ../quodlibet/util/tags.py:86 msgid "arrangers" msgstr "aranžmá" #: ../quodlibet/util/tags.py:86 msgid "arrangement" msgstr "uspořádání" #: ../quodlibet/util/tags.py:88 msgid "author" msgstr "autor" #: ../quodlibet/util/tags.py:88 msgid "authors" msgstr "autoři" #: ../quodlibet/util/tags.py:89 #, fuzzy msgid "comment" msgstr "příkaz" #: ../quodlibet/util/tags.py:90 msgid "composer" msgstr "skladatel" #: ../quodlibet/util/tags.py:90 msgid "composers" msgstr "skladatelé" #: ../quodlibet/util/tags.py:90 msgid "composition" msgstr "skladatel" #. Translators: conducting as in conducting a musical performance #: ../quodlibet/util/tags.py:92 msgid "conductor" msgstr "dirigent" #: ../quodlibet/util/tags.py:92 msgid "conductors" msgstr "dirigenti" #: ../quodlibet/util/tags.py:92 msgid "conducting" msgstr "dirigent" #: ../quodlibet/util/tags.py:93 msgid "contact" msgstr "kontakt" #: ../quodlibet/util/tags.py:94 msgid "copyright" msgstr "copyright" #: ../quodlibet/util/tags.py:95 msgid "date" msgstr "rok" #: ../quodlibet/util/tags.py:96 msgid "description" msgstr "popis" #: ../quodlibet/util/tags.py:97 msgid "genre" msgstr "žánr" #: ../quodlibet/util/tags.py:97 msgid "genres" msgstr "žánry" #: ../quodlibet/util/tags.py:98 msgid "performer" msgstr "interpret" #: ../quodlibet/util/tags.py:98 #, fuzzy msgid "performance" msgstr "interpret" #: ../quodlibet/util/tags.py:99 msgid "grouping" msgstr "slučování" #: ../quodlibet/util/tags.py:100 msgid "language" msgstr "jazyk" #: ../quodlibet/util/tags.py:101 msgid "license" msgstr "licence" #: ../quodlibet/util/tags.py:102 msgid "location" msgstr "místo" #: ../quodlibet/util/tags.py:103 msgid "lyricist" msgstr "texty" #: ../quodlibet/util/tags.py:103 msgid "lyricists" msgstr "textaři" #: ../quodlibet/util/tags.py:103 msgid "lyrics" msgstr "texty" #. Translators: Also e.g. "record label", "publisher" #: ../quodlibet/util/tags.py:105 msgid "organization" msgstr "organizace" #: ../quodlibet/util/tags.py:106 msgid "title" msgstr "název" #: ../quodlibet/util/tags.py:107 msgid "version" msgstr "verze" #: ../quodlibet/util/tags.py:108 msgid "website" msgstr "webová stránka" #: ../quodlibet/util/tags.py:110 msgid "album artist" msgstr "umělec alba" #: ../quodlibet/util/tags.py:111 msgid "BPM" msgstr "BPM" #. Translators: This used to be called "part". #: ../quodlibet/util/tags.py:114 ../quodlibet/util/tags.py:115 msgid "disc subtitle" msgstr "podnázev disku" #: ../quodlibet/util/tags.py:116 ../quodlibet/util/tags.py:153 msgid "disc" msgstr "disk" #: ../quodlibet/util/tags.py:117 ../quodlibet/util/tags.py:155 msgid "track" msgstr "skladba" #: ../quodlibet/util/tags.py:118 msgid "label ID" msgstr "ID labelu" #: ../quodlibet/util/tags.py:119 msgid "original release date" msgstr "datum původního vydání" #: ../quodlibet/util/tags.py:120 msgid "original album" msgstr "původní album" #: ../quodlibet/util/tags.py:121 msgid "original artist" msgstr "původní umělec" #: ../quodlibet/util/tags.py:122 msgid "recording date" msgstr "datum nahrávání" #: ../quodlibet/util/tags.py:123 msgid "release country" msgstr "země vydání" #. 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:132 msgid "MusicBrainz recording ID" msgstr "ID skladby na MusicBrainz" #: ../quodlibet/util/tags.py:133 msgid "MusicBrainz release track ID" msgstr "ID vydání na MusicBrainz" #: ../quodlibet/util/tags.py:134 msgid "MusicBrainz release ID" msgstr "ID vydání na MusicBrainz" #: ../quodlibet/util/tags.py:135 msgid "MusicBrainz artist ID" msgstr "ID umělce na MusicBrainz" #: ../quodlibet/util/tags.py:136 msgid "MusicBrainz release artist ID" msgstr "ID umělce vydání na MusicBrainz" #: ../quodlibet/util/tags.py:137 msgid "MusicBrainz TRM ID" msgstr "ID TRM na MusicBrainz" #: ../quodlibet/util/tags.py:138 msgid "MusicIP PUID" msgstr "PUID MusicIP" #: ../quodlibet/util/tags.py:139 msgid "MusicBrainz album status" msgstr "Status alba na MusicBrainz" #: ../quodlibet/util/tags.py:140 msgid "MusicBrainz album type" msgstr "Typ alba na MusicBrainz" #: ../quodlibet/util/tags.py:141 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:144 msgid "track gain" msgstr "úprava hlasitosti skladby" #: ../quodlibet/util/tags.py:145 msgid "track peak" msgstr "nejvyšší hodnota u skladby" #. Translators: "gain" means a volume adjustment, not "to acquire". #: ../quodlibet/util/tags.py:147 msgid "album gain" msgstr "úprava hlasitosti alba" #: ../quodlibet/util/tags.py:148 msgid "album peak" msgstr "nejvyšší hodnota u alba" #: ../quodlibet/util/tags.py:149 msgid "reference loudness" msgstr "určující hlasitost" #: ../quodlibet/util/tags.py:154 msgid "discs" msgstr "disky" #: ../quodlibet/util/tags.py:156 msgid "tracks" msgstr "skladby" #: ../quodlibet/util/tags.py:157 msgid "last started" msgstr "poslední start" #: ../quodlibet/util/tags.py:158 msgid "full name" msgstr "celé jméno" #: ../quodlibet/util/tags.py:165 msgid "mount point" msgstr "přípojný bod" #: ../quodlibet/util/tags.py:167 msgid "people" msgstr "lidé" #: ../quodlibet/util/tags.py:169 msgid "year" msgstr "rok" #: ../quodlibet/util/tags.py:170 msgid "original release year" msgstr "rok původního vydání" #: ../quodlibet/util/tags.py:171 msgid "bookmark" msgstr "záložka" #: ../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 "channel count" msgstr "počet kanálů" #. Translators: e.g. "artist (sort)" #: ../quodlibet/util/tags.py:268 msgid "sort" msgstr "řadit" #. Translators: e.g. "performer (roles)" #: ../quodlibet/util/tags.py:276 msgid "roles" msgstr "role" #~ msgid "_Download…" #~ msgstr "_Stahování…" #~ msgid "Download Files" #~ msgstr "Stáhnout soubory" #~ msgid "Download File" #~ msgstr "Stáhnout soubor" #~ 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 "Could not find '%s'." #~ msgstr "‚%s‘ nelze nalézt." #~ 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 "Copy _album covers" #~ msgstr "Kopírovat _obaly alb" #~ 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 "_Edit" #~ msgstr "_Upravit" #~ 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 "Remove all songs from the queue" #~ msgstr "Odstranit všechny skladby z fronty" #~ msgid "Watch this folder for new songs" #~ msgstr "Hledat ve složce nové skladby" #~ 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 "_Create Database" #~ msgstr "_Vytvořit databázi" #~ msgid "_Volume Gain (dB):" #~ msgstr "Úprava _Hlasitosti (dB):" #~ msgid "Combine tags with _multiple values" #~ msgstr "_Kombinovat tagy s více hodnotami" #~ msgid "Model:" #~ msgstr "Model:" #~ msgid "Capacity:" #~ msgstr "Kapacita:" #~ msgid "Firmware:" #~ msgstr "Firmware:" #~ msgid "Removing orphaned iPod track" #~ msgstr "Odstraňování nezařazené skladby z iPodu" #~ 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 "Unable to open input files" #~ msgstr "Nelze otevřít vstupní data" #~ 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 "General" #~ msgstr "Obecné" #~ 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 "Choose New Stations" #~ msgstr "Vybrat nové stanice" #, fuzzy #~ msgid "Add" #~ msgstr "Přidat" #, fuzzy #~ msgid "Bitrate" #~ msgstr "Bitrate" #, fuzzy #~ msgid "_Stations..." #~ msgstr "_Stanice..." �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9471855 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/po/da.po����������������������������������������������������������������������������0000644�0001750�0001750�00000565637�00000000000�014066� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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: 2018-06-06 02:07+0200\n" "PO-Revision-Date: 2018-06-06 11:38+0200\n" "Last-Translator: scootergrisen\n" "Language-Team: Danish\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" #: ../data/exfalso.appdata.xml.in.h:1 ../data/exfalso.desktop.in.h:2 msgid "Edit tags in your audio files" msgstr "Rediger tags i dine lydfiler" #: ../data/exfalso.appdata.xml.in.h:2 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/exfalso.appdata.xml.in.h:3 #: ../data/io.github.quodlibet.QuodLibet.appdata.xml.in.h:3 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/exfalso.desktop.in.h:1 msgid "Audio tag editor" msgstr "Lyd-tag-editor" #: ../data/io.github.quodlibet.QuodLibet.appdata.xml.in.h:1 #: ../data/io.github.quodlibet.QuodLibet.desktop.in.h:2 msgid "Listen to, browse, or edit your audio collection" msgstr "Lyt til, gennemse eller rediger din lydsamling" #: ../data/io.github.quodlibet.QuodLibet.appdata.xml.in.h:2 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." #: ../data/io.github.quodlibet.QuodLibet.desktop.in.h:1 msgid "Music Player" msgstr "Musikafspiller" #: ../quodlibet/browsers/albums/main.py:186 #: ../quodlibet/browsers/covergrid/main.py:55 msgid "_Title" msgstr "_Titel" #: ../quodlibet/browsers/albums/main.py:187 #: ../quodlibet/browsers/covergrid/main.py:56 ../quodlibet/qltk/prefs.py:50 msgid "_Artist" msgstr "_Kunstner" #: ../quodlibet/browsers/albums/main.py:188 #: ../quodlibet/browsers/covergrid/main.py:57 ../quodlibet/qltk/prefs.py:55 msgid "_Date" msgstr "_Dato" #: ../quodlibet/browsers/albums/main.py:189 #: ../quodlibet/browsers/covergrid/main.py:58 ../quodlibet/qltk/prefs.py:54 msgid "_Genre" msgstr "_Genre" #: ../quodlibet/browsers/albums/main.py:190 #: ../quodlibet/browsers/covergrid/main.py:59 ../quodlibet/qltk/prefs.py:59 #: ../quodlibet/qltk/ratingsmenu.py:40 msgid "_Rating" msgstr "_Bedømmelse" #: ../quodlibet/browsers/albums/main.py:191 msgid "_Playcount" msgstr "_Antal afspilninger" #: ../quodlibet/browsers/albums/main.py:197 #: ../quodlibet/browsers/covergrid/main.py:65 msgid "Sort _by…" msgstr "Sortér _efter…" #: ../quodlibet/browsers/albums/main.py:218 #: ../quodlibet/browsers/covergrid/main.py:86 #: ../quodlibet/browsers/paned/prefs.py:167 #: ../quodlibet/browsers/playlists/main.py:667 #: ../quodlibet/qltk/exfalsowindow.py:110 ../quodlibet/qltk/pluginwin.py:342 #: ../quodlibet/qltk/quodlibetwindow.py:1007 msgid "_Preferences" msgstr "_Præferencer" #: ../quodlibet/browsers/albums/main.py:384 msgid "Album List" msgstr "Albumliste" #: ../quodlibet/browsers/albums/main.py:385 msgid "_Album List" msgstr "_Albumliste" #: ../quodlibet/browsers/albums/main.py:495 #: ../quodlibet/browsers/covergrid/main.py:281 #: ../quodlibet/browsers/covergrid/main.py:494 msgid "All Albums" msgstr "Alle album" #: ../quodlibet/browsers/albums/main.py:496 #: ../quodlibet/browsers/covergrid/main.py:282 #: ../quodlibet/browsers/covergrid/main.py:495 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d album" msgstr[1] "%d album" #: ../quodlibet/browsers/albums/main.py:677 #: ../quodlibet/browsers/covergrid/main.py:473 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:29 #: ../quodlibet/browsers/collection/models.py:18 #: ../quodlibet/browsers/covergrid/prefs.py:31 msgid "Songs not in an album" msgstr "Sange som ikke er i et album" #: ../quodlibet/browsers/albums/prefs.py:42 #: ../quodlibet/browsers/covergrid/prefs.py:44 #: ../quodlibet/browsers/playlists/prefs.py:36 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:100 #: ../quodlibet/qltk/information.py:386 ../quodlibet/util/collection.py:246 #, python-format msgid "%d track" msgid_plural "%d tracks" msgstr[0] "%d spor" msgstr[1] "%d spor" #: ../quodlibet/browsers/albums/prefs.py:43 #: ../quodlibet/browsers/covergrid/prefs.py:45 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:99 #: ../quodlibet/qltk/information.py:384 ../quodlibet/util/collection.py:250 #, python-format msgid "%d disc" msgid_plural "%d discs" msgstr[0] "%d disk" msgstr[1] "%d diske" #: ../quodlibet/browsers/albums/prefs.py:45 #: ../quodlibet/browsers/covergrid/prefs.py:47 msgid "An Example Album" msgstr "Et eksempel-album" #: ../quodlibet/browsers/albums/prefs.py:53 msgid "Album List Preferences" msgstr "Albumliste-præferencer" #: ../quodlibet/browsers/albums/prefs.py:62 msgid "Show album _covers" msgstr "Vis album_covere" #: ../quodlibet/browsers/albums/prefs.py:68 msgid "Inline _search includes people" msgstr "Indbygget _søgning inkluderer personer" #: ../quodlibet/browsers/albums/prefs.py:72 #: ../quodlibet/browsers/covergrid/prefs.py:121 #: ../quodlibet/ext/songsmenu/cover_download.py:243 msgid "Options" msgstr "Valgmuligheder" #: ../quodlibet/browsers/albums/prefs.py:75 #: ../quodlibet/browsers/covergrid/prefs.py:124 msgid "Album Display" msgstr "Album-visning" #: ../quodlibet/browsers/albums/prefs.py:79 #: ../quodlibet/browsers/covergrid/prefs.py:128 #: ../quodlibet/browsers/playlists/prefs.py:57 #: ../quodlibet/ext/songsmenu/albumart.py:328 #: ../quodlibet/ext/songsmenu/duplicates.py:349 #: ../quodlibet/ext/songsmenu/filterall.py:49 #: ../quodlibet/qltk/bookmarks.py:102 ../quodlibet/qltk/cbes.py:94 #: ../quodlibet/qltk/data_editors.py:98 ../quodlibet/qltk/data_editors.py:323 #: ../quodlibet/qltk/exfalsowindow.py:298 ../quodlibet/qltk/pluginwin.py:80 #: ../quodlibet/qltk/pluginwin.py:429 ../quodlibet/qltk/prefs.py:718 #: ../quodlibet/qltk/textedit.py:165 ../quodlibet/update.py:149 msgid "_Close" msgstr "_Luk" #: ../quodlibet/browsers/audiofeeds.py:53 #: ../quodlibet/browsers/audiofeeds.py:65 #: ../quodlibet/browsers/audiofeeds.py:67 #: ../quodlibet/browsers/audiofeeds.py:157 #: ../quodlibet/browsers/paned/models.py:87 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:47 #: ../quodlibet/formats/_audio.py:501 ../quodlibet/order/__init__.py:28 #: ../quodlibet/qltk/information.py:245 ../quodlibet/qltk/information.py:252 #: ../quodlibet/qltk/information.py:278 ../quodlibet/qltk/wlw.py:71 msgid "Unknown" msgstr "Ukendt" #: ../quodlibet/browsers/audiofeeds.py:248 msgid "New Feed" msgstr "Nyt feed" #: ../quodlibet/browsers/audiofeeds.py:249 msgid "Enter the location of an audio feed:" msgstr "Indtast placeringen af et lyd-feed:" #: ../quodlibet/browsers/audiofeeds.py:250 #: ../quodlibet/browsers/collection/prefs.py:91 #: ../quodlibet/browsers/iradio.py:355 ../quodlibet/browsers/paned/prefs.py:79 #: ../quodlibet/browsers/playlists/menu.py:97 #: ../quodlibet/browsers/playlists/util.py:54 ../quodlibet/qltk/bookmarks.py:63 #: ../quodlibet/qltk/cbes.py:56 ../quodlibet/qltk/data_editors.py:310 #: ../quodlibet/qltk/edittags.py:289 ../quodlibet/qltk/edittags.py:489 #: ../quodlibet/qltk/quodlibetwindow.py:1363 ../quodlibet/qltk/scanbox.py:62 msgid "_Add" msgstr "_Tilføj" #: ../quodlibet/browsers/audiofeeds.py:304 msgid "Audio Feeds" msgstr "Lyd-feeds" #: ../quodlibet/browsers/audiofeeds.py:305 msgid "_Audio Feeds" msgstr "_Lyd-feeds" #: ../quodlibet/browsers/audiofeeds.py:408 ../quodlibet/qltk/data_editors.py:95 msgid "_New" msgstr "_Ny" #: ../quodlibet/browsers/audiofeeds.py:468 #: ../quodlibet/browsers/audiofeeds.py:527 msgid "Unable to add feed" msgstr "Kan ikke tilføje feed" #: ../quodlibet/browsers/audiofeeds.py:469 #: ../quodlibet/browsers/audiofeeds.py:528 #, python-format msgid "" "%s could not be added. The server may be down, or the location may not be an " "audio feed." msgstr "" "%s kunne ikke tilføjes. Serveren kan være nede eller placeringen er måske " "ikke et lyd-feed." #: ../quodlibet/browsers/audiofeeds.py:476 ../quodlibet/qltk/filesel.py:272 #: ../quodlibet/qltk/pluginwin.py:415 msgid "_Refresh" msgstr "_Opdater" #: ../quodlibet/browsers/audiofeeds.py:477 #: ../quodlibet/browsers/playlists/main.py:488 #: ../quodlibet/browsers/playlists/util.py:45 ../quodlibet/qltk/delete.py:144 #: ../quodlibet/qltk/filesel.py:269 ../quodlibet/qltk/lyrics.py:36 #: ../quodlibet/qltk/maskedbox.py:29 ../quodlibet/qltk/songsmenu.py:366 msgid "_Delete" msgstr "_Slet" #: ../quodlibet/browsers/audiofeeds.py:544 msgid "" "The current audio backend does not support URLs, Audio Feeds browser " "disabled." msgstr "" "Den aktuelle lyd-backend understøtter ikke URL'er, lyd-feeds-browser " "deaktiveret." #: ../quodlibet/browsers/_base.py:148 ../quodlibet/browsers/_base.py:151 msgid "Library Browser" msgstr "Bibliotek-browser" #: ../quodlibet/browsers/_base.py:275 ../quodlibet/ext/songsmenu/console.py:47 #: ../quodlibet/ext/songsmenu/refresh.py:31 #: ../quodlibet/qltk/exfalsowindow.py:242 ../quodlibet/qltk/information.py:555 #: ../quodlibet/qltk/maskedbox.py:69 ../quodlibet/util/collection.py:532 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d sang" msgstr[1] "%d sange" #: ../quodlibet/browsers/_base.py:403 ../quodlibet/browsers/_base.py:408 #: ../quodlibet/qltk/tagsfrompath.py:195 ../quodlibet/qltk/textedit.py:142 #: ../quodlibet/util/__init__.py:574 msgid "Invalid pattern" msgstr "Ugyldigt mønster" #: ../quodlibet/browsers/collection/main.py:81 msgid "Album Collection" msgstr "Albumsamling" #: ../quodlibet/browsers/collection/main.py:82 msgid "Album _Collection" msgstr "Album_samling" #: ../quodlibet/browsers/collection/models.py:25 #, python-format msgid "Unknown %s" msgstr "Ukendt %s" #: ../quodlibet/browsers/collection/models.py:26 #, python-format msgid "Multiple %s Values" msgstr "Flere %s-værdier" #: ../quodlibet/browsers/collection/prefs.py:67 #: ../quodlibet/browsers/paned/prefs.py:52 msgid "_Custom" msgstr "_Brugerdefineret" #. Remove button #: ../quodlibet/browsers/collection/prefs.py:95 #: ../quodlibet/browsers/paned/prefs.py:83 #: ../quodlibet/browsers/playlists/menu.py:98 #: ../quodlibet/ext/playlist/remove_duplicates.py:61 #: ../quodlibet/qltk/bookmarks.py:98 ../quodlibet/qltk/bookmarks.py:128 #: ../quodlibet/qltk/cbes.py:83 ../quodlibet/qltk/cbes.py:90 #: ../quodlibet/qltk/data_editors.py:80 ../quodlibet/qltk/data_editors.py:93 #: ../quodlibet/qltk/data_editors.py:300 ../quodlibet/qltk/data_editors.py:313 #: ../quodlibet/qltk/data_editors.py:321 ../quodlibet/qltk/edittags.py:495 #: ../quodlibet/qltk/edittags.py:635 ../quodlibet/qltk/maskedbox.py:49 #: ../quodlibet/qltk/maskedbox.py:89 ../quodlibet/qltk/queue.py:413 #: ../quodlibet/qltk/scanbox.py:37 ../quodlibet/qltk/scanbox.py:64 msgid "_Remove" msgstr "_Fjern" #: ../quodlibet/browsers/collection/prefs.py:123 #: ../quodlibet/ext/songsmenu/filterall.py:35 #: ../quodlibet/operon/commands.py:57 ../quodlibet/operon/commands.py:93 #: ../quodlibet/qltk/edittags.py:432 msgid "Tag" msgstr "Tag" #: ../quodlibet/browsers/collection/prefs.py:129 msgid "Merge" msgstr "Forén" #: ../quodlibet/browsers/collection/prefs.py:189 msgid "Album Collection Preferences" msgstr "Albumsamling-præferencer" #: ../quodlibet/browsers/collection/prefs.py:196 #: ../quodlibet/browsers/paned/prefs.py:210 #: ../quodlibet/ext/songsmenu/editplaycount.py:46 #: ../quodlibet/ext/songsmenu/exact_rating.py:39 #: ../quodlibet/player/gstbe/prefs.py:41 ../quodlibet/qltk/prefs.py:128 #: ../quodlibet/qltk/textedit.py:66 msgid "_Apply" msgstr "_Anvend" #: ../quodlibet/browsers/collection/prefs.py:199 #: ../quodlibet/browsers/paned/prefs.py:214 #: ../quodlibet/browsers/playlists/menu.py:96 #: ../quodlibet/browsers/playlists/util.py:44 #: ../quodlibet/errorreport/ui.py:104 #: ../quodlibet/ext/playlist/export_to_folder.py:38 #: ../quodlibet/ext/playlist/remove_duplicates.py:60 #: ../quodlibet/ext/_shared/squeezebox/util.py:20 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:356 #: ../quodlibet/ext/songsmenu/editplaycount.py:45 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:282 #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:92 #: ../quodlibet/ext/songsmenu/importexport.py:40 #: ../quodlibet/ext/songsmenu/lastfmsync.py:219 #: ../quodlibet/ext/songsmenu/playlist.py:51 #: ../quodlibet/ext/songsmenu/replaygain.py:355 #: ../quodlibet/ext/songsmenu/tapbpm.py:187 ../quodlibet/qltk/chooser.py:189 #: ../quodlibet/qltk/chooser.py:210 ../quodlibet/qltk/chooser.py:234 #: ../quodlibet/qltk/chooser.py:258 ../quodlibet/qltk/delete.py:91 #: ../quodlibet/qltk/delete.py:134 ../quodlibet/qltk/edittags.py:288 #: ../quodlibet/qltk/_editutils.py:40 ../quodlibet/qltk/getstring.py:29 #: ../quodlibet/qltk/maskedbox.py:28 ../quodlibet/qltk/msg.py:55 #: ../quodlibet/qltk/msg.py:94 ../quodlibet/qltk/msg.py:112 #: ../quodlibet/qltk/ratingsmenu.py:34 ../quodlibet/update.py:95 msgid "_Cancel" msgstr "_Annuller" #: ../quodlibet/browsers/covergrid/main.py:127 msgid "Cover Grid" msgstr "Covergitter" #: ../quodlibet/browsers/covergrid/main.py:128 msgid "_Cover Grid" msgstr "_Covergitter" #: ../quodlibet/browsers/covergrid/prefs.py:55 msgid "Cover Grid Preferences" msgstr "Covergitter-præferencer" #: ../quodlibet/browsers/covergrid/prefs.py:65 msgid "Show album _text" msgstr "Vis album_tekst" #: ../quodlibet/browsers/covergrid/prefs.py:72 msgid "Show \"All Albums\" Item" msgstr "Vis \"Alle album\"-post" #: ../quodlibet/browsers/covergrid/prefs.py:79 msgid "Wide Mode" msgstr "Bred-tilstand" #: ../quodlibet/browsers/covergrid/prefs.py:111 #: ../quodlibet/browsers/covergrid/prefs.py:112 msgid "Cover Magnification" msgstr "Cover forstørrelse" #: ../quodlibet/browsers/filesystem.py:41 msgid "File System" msgstr "Filsystem" #: ../quodlibet/browsers/filesystem.py:42 msgid "_File System" msgstr "_Filsystem" #: ../quodlibet/browsers/filesystem.py:126 ../quodlibet/qltk/songlist.py:257 msgid "Unable to copy songs" msgstr "Kan ikke kopiere sange" #: ../quodlibet/browsers/filesystem.py:127 ../quodlibet/qltk/songlist.py:258 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:199 msgid "_Add to Library" msgstr "_Tilføj til bibliotek" #: ../quodlibet/browsers/iradio.py:182 msgid "Unsupported file type" msgstr "Ikke-understøttet filtype" #: ../quodlibet/browsers/iradio.py:183 #, 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:228 ../quodlibet/browsers/iradio.py:241 #: ../quodlibet/browsers/iradio.py:824 msgid "Unable to add station" msgstr "Kan ikke tilføje station" #: ../quodlibet/browsers/iradio.py:252 ../quodlibet/browsers/iradio.py:485 msgid "Internet Radio" msgstr "Internet-radio" #: ../quodlibet/browsers/iradio.py:252 msgid "Downloading station list" msgstr "Downloader stationsliste" #: ../quodlibet/browsers/iradio.py:353 msgid "New Station" msgstr "Ny station" #: ../quodlibet/browsers/iradio.py:354 msgid "Enter the location of an Internet radio station:" msgstr "Indtast placeringen af en internet-radiostation:" #: ../quodlibet/browsers/iradio.py:372 msgid "Electronic" msgstr "Elektronisk" #: ../quodlibet/browsers/iradio.py:375 msgid "Hip Hop / Rap" msgstr "Hiphop/rap" #: ../quodlibet/browsers/iradio.py:376 msgid "Oldies" msgstr "Oldies" #: ../quodlibet/browsers/iradio.py:377 msgid "R&B" msgstr "R&B" #: ../quodlibet/browsers/iradio.py:378 msgid "Japanese" msgstr "Japansk" #: ../quodlibet/browsers/iradio.py:379 msgid "Indian" msgstr "Indisk" #: ../quodlibet/browsers/iradio.py:381 msgid "Religious" msgstr "Religiøs" #: ../quodlibet/browsers/iradio.py:383 msgid "Charts" msgstr "Charts" #: ../quodlibet/browsers/iradio.py:384 msgid "Turkish" msgstr "Tyrkisk" #: ../quodlibet/browsers/iradio.py:385 msgid "Reggae / Dancehall" msgstr "Reggae/dancehall" #: ../quodlibet/browsers/iradio.py:386 msgid "Latin" msgstr "Latin" #: ../quodlibet/browsers/iradio.py:387 msgid "College Radio" msgstr "Skoleradio" #: ../quodlibet/browsers/iradio.py:388 msgid "Talk / News" msgstr "Snak/nyheder" #: ../quodlibet/browsers/iradio.py:389 msgid "Ambient" msgstr "Ambient" #: ../quodlibet/browsers/iradio.py:390 msgid "Jazz" msgstr "Jazz" #: ../quodlibet/browsers/iradio.py:391 ../quodlibet/ext/events/equalizer.py:46 msgid "Classical" msgstr "Klassisk" #: ../quodlibet/browsers/iradio.py:392 ../quodlibet/ext/events/equalizer.py:61 msgid "Pop" msgstr "Pop" #: ../quodlibet/browsers/iradio.py:393 msgid "Alternative" msgstr "Alternativ" #: ../quodlibet/browsers/iradio.py:394 msgid "Metal" msgstr "Metal" #: ../quodlibet/browsers/iradio.py:395 msgid "Country" msgstr "Country" #: ../quodlibet/browsers/iradio.py:396 msgid "News" msgstr "Nyheder" #: ../quodlibet/browsers/iradio.py:397 msgid "Schlager" msgstr "Slager" #: ../quodlibet/browsers/iradio.py:398 msgid "Funk" msgstr "Funk" #: ../quodlibet/browsers/iradio.py:399 msgid "Indie" msgstr "Indie" #: ../quodlibet/browsers/iradio.py:400 msgid "Blues" msgstr "Blues" #: ../quodlibet/browsers/iradio.py:401 msgid "Soul" msgstr "Soul" #: ../quodlibet/browsers/iradio.py:402 msgid "Lounge" msgstr "Lounge" #: ../quodlibet/browsers/iradio.py:403 msgid "Punk" msgstr "Punk" #: ../quodlibet/browsers/iradio.py:404 msgid "Reggaeton" msgstr "Reggaeton" #: ../quodlibet/browsers/iradio.py:406 msgid "Slavic" msgstr "Slavisk" #: ../quodlibet/browsers/iradio.py:408 msgid "Greek" msgstr "Græsk" #: ../quodlibet/browsers/iradio.py:409 msgid "Gothic" msgstr "Gotisk" #: ../quodlibet/browsers/iradio.py:410 ../quodlibet/ext/events/equalizer.py:39 msgid "Rock" msgstr "Rock" #: ../quodlibet/browsers/iradio.py:463 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:469 msgid "_Load Stations" msgstr "_Indlæs stationer" #: ../quodlibet/browsers/iradio.py:486 msgid "_Internet Radio" msgstr "_Internet-radio" #: ../quodlibet/browsers/iradio.py:552 msgid "_New Station…" msgstr "_Ny station…" #: ../quodlibet/browsers/iradio.py:555 msgid "_Update Stations" msgstr "_Opdater stationer" #: ../quodlibet/browsers/iradio.py:582 msgid "All Stations" msgstr "Alle stationer" #. TODO: support for ~#rating=!None etc (#1940) #: ../quodlibet/browsers/iradio.py:586 #: ../quodlibet/browsers/soundcloud/main.py:65 msgid "Favorites" msgstr "Favoritter" #: ../quodlibet/browsers/iradio.py:594 msgid "No Category" msgstr "Ingen kategori" #: ../quodlibet/browsers/iradio.py:816 msgid "No stations found" msgstr "Ingen stationer fundet" #: ../quodlibet/browsers/iradio.py:817 #, python-format msgid "No Internet radio stations were found at %s." msgstr "Ingen internet-radiostationer blev fundet hos %s." #: ../quodlibet/browsers/iradio.py:825 msgid "All stations listed are already in your library." msgstr "Alle viste stationer er allerede i dit bibliotek." #: ../quodlibet/browsers/iradio.py:842 msgid "Add to Favorites" msgstr "Tilføj til favoritter" #: ../quodlibet/browsers/iradio.py:846 msgid "Remove from Favorites" msgstr "Fjern fra favoritter" #: ../quodlibet/browsers/iradio.py:946 #, 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:42 ../quodlibet/qltk/shortcuts.py:45 msgid "Paned Browser" msgstr "Rude-browser" #: ../quodlibet/browsers/paned/main.py:43 msgid "_Paned Browser" msgstr "_Rude-browser" #: ../quodlibet/browsers/paned/main.py:93 msgid "Select _All" msgstr "Vælg _alle" #: ../quodlibet/browsers/paned/models.py:105 ../quodlibet/qltk/pluginwin.py:123 #: ../quodlibet/qltk/pluginwin.py:165 msgid "All" msgstr "Alle" #: ../quodlibet/browsers/paned/prefs.py:68 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "<tt>%s</tt>" msgstr "" "Tag-mønster med valgfri opmærkning. F.eks. <tt>composer</tt> eller\n" "<tt>%s</tt>" #: ../quodlibet/browsers/paned/prefs.py:163 msgid "_Wide Mode" msgstr "_Bred-tilstand" #: ../quodlibet/browsers/paned/prefs.py:198 msgid "Paned Browser Preferences" msgstr "Præferencer for rude-browser" #: ../quodlibet/browsers/paned/prefs.py:205 msgid "Equal pane width" msgstr "Ens rudebredde" #: ../quodlibet/browsers/playlists/main.py:50 #: ../quodlibet/browsers/playlists/main.py:603 #: ../quodlibet/qltk/pluginwin.py:169 msgid "Playlists" msgstr "Spilleliste" #: ../quodlibet/browsers/playlists/main.py:51 msgid "_Playlists" msgstr "_Spillelister" #: ../quodlibet/browsers/playlists/main.py:154 msgid "_Remove from Playlist" msgstr "_Fjern fra spilleliste" #: ../quodlibet/browsers/playlists/main.py:219 msgid "New" msgstr "Ny" #: ../quodlibet/browsers/playlists/main.py:223 msgid "Import" msgstr "Importér" #: ../quodlibet/browsers/playlists/main.py:444 msgid "Unable to import playlist" msgstr "Kan ikke importere spilleliste" #: ../quodlibet/browsers/playlists/main.py:445 msgid "Quod Libet can only import playlists in the M3U and PLS formats." msgstr "Quod Libet kan kun importere spillelister i formaterne M3U og PLS." #: ../quodlibet/browsers/playlists/main.py:495 msgid "_Rename" msgstr "_Omdøb" #: ../quodlibet/browsers/playlists/main.py:593 msgid "Unable to rename playlist" msgstr "Kan ikke omdøbe spilleliste" #: ../quodlibet/browsers/playlists/main.py:604 msgid "Import Playlist" msgstr "Importér spilleliste" #: ../quodlibet/browsers/playlists/main.py:604 msgid "_Import" msgstr "_Importér" #: ../quodlibet/browsers/playlists/menu.py:26 msgid "_New Playlist…" msgstr "_Ny spilleliste…" #: ../quodlibet/browsers/playlists/menu.py:87 #, 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:91 #, python-format msgid "Confirm action for playlist \"%s\"" msgstr "Bekræft handling for spillelisten \"%s\"" #: ../quodlibet/browsers/playlists/prefs.py:22 msgid "empty" msgstr "tom" #: ../quodlibet/browsers/playlists/prefs.py:40 msgid "Example Playlist" msgstr "Eksempel-spilleliste" #: ../quodlibet/browsers/playlists/prefs.py:48 msgid "Playlist Browser Preferences" msgstr "Præferencer for spilleliste-browser" #: ../quodlibet/browsers/playlists/prefs.py:53 msgid "Playlist display" msgstr "Spilleliste-visning" #: ../quodlibet/browsers/playlists/util.py:35 #, 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:37 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:52 #: ../quodlibet/browsers/playlists/util.py:127 #: ../quodlibet/util/collection.py:575 msgid "New Playlist" msgstr "Ny spilleliste" #: ../quodlibet/browsers/playlists/util.py:53 msgid "Enter a name for the new playlist:" msgstr "Indtast et navn til den nye spilleliste:" #: ../quodlibet/browsers/playlists/util.py:91 #, 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/search.py:32 msgid "_Limit Results" msgstr "_Begræns resultater" #: ../quodlibet/browsers/search.py:47 msgid "Search Library" msgstr "Søgebibliotek" #: ../quodlibet/browsers/search.py:48 msgid "_Search Library" msgstr "_Søgebibliotek" #: ../quodlibet/browsers/soundcloud/main.py:39 msgid "Soundcloud Browser" msgstr "Soundcloud-browser" #: ../quodlibet/browsers/soundcloud/main.py:40 msgid "Sound_cloud" msgstr "Sound_cloud" #: ../quodlibet/browsers/soundcloud/main.py:60 #: ../quodlibet/qltk/searchbar.py:79 msgid "Search" msgstr "Søgning" #: ../quodlibet/browsers/soundcloud/main.py:69 msgid "My tracks" msgstr "Mine spor" #: ../quodlibet/browsers/soundcloud/main.py:141 #, python-format msgid "Go to %s" msgstr "Gå til %s" #: ../quodlibet/browsers/soundcloud/main.py:393 msgid "Connected" msgstr "Tilsluttet" #: ../quodlibet/browsers/soundcloud/main.py:394 #, python-format msgid "Quod Libet is now connected, <b>%s</b>!" msgstr "Quod Libet er nu tilsluttet, <b>%s</b>!" #: ../quodlibet/browsers/soundcloud/main.py:406 #, python-format msgid "Log out of %s" msgstr "Log ud af %s" #: ../quodlibet/browsers/soundcloud/main.py:408 msgid "Enter code…" msgstr "Indtast kode…" #: ../quodlibet/browsers/soundcloud/main.py:409 #, python-format msgid "Log in to %s" msgstr "Log ind i %s" #: ../quodlibet/browsers/soundcloud/util.py:87 msgid "Soundcloud authorisation" msgstr "Soundcloud godkendelse" #: ../quodlibet/browsers/soundcloud/util.py:88 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 "Print player status" msgstr "Vis afspilningsstatus" #: ../quodlibet/cli.py:106 msgid "Hide main window" msgstr "Skjul hovedvindue" #: ../quodlibet/cli.py:107 msgid "Show main window" msgstr "Vis hovedvindue" #: ../quodlibet/cli.py:108 msgid "Toggle main window visibility" msgstr "Hovedvinduets synlighed til/fra" #: ../quodlibet/cli.py:109 msgid "Focus the running player" msgstr "Giv fokus til den kørende afspiller" #: ../quodlibet/cli.py:110 msgid "Remove active browser filters" msgstr "Fjern aktive browser-filtre" #: ../quodlibet/cli.py:111 msgid "Refresh and rescan library" msgstr "Opdater og genskan bibliotek" #: ../quodlibet/cli.py:112 msgid "List available browsers" msgstr "Vis tilgængelige browsere" #: ../quodlibet/cli.py:113 msgid "Print the current playlist" msgstr "Vis aktuelle spilleliste" #: ../quodlibet/cli.py:114 msgid "Print the contents of the queue" msgstr "Vis køens indhold" #: ../quodlibet/cli.py:115 msgid "Print the active text query" msgstr "Vis den aktive tekst-anmodning" #: ../quodlibet/cli.py:116 msgid "Start without plugins" msgstr "Start uden plugins" #: ../quodlibet/cli.py:117 msgid "Start Quod Libet if it isn't running" msgstr "Start Quod Libet hvis ikke den kører" #: ../quodlibet/cli.py:118 msgid "Exit Quod Libet" msgstr "Afslut Quod Libet" #: ../quodlibet/cli.py:123 msgid "Seek within the playing song" msgstr "Søg i sangen som afspilles" #: ../quodlibet/cli.py:123 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: ../quodlibet/cli.py:124 msgid "Set or toggle shuffle mode" msgstr "Sæt eller bland-tilstand til/fra" #: ../quodlibet/cli.py:125 msgid "Set shuffle mode type" msgstr "Sæt bland-tilstandstype" #: ../quodlibet/cli.py:126 msgid "Turn repeat off, on, or toggle it" msgstr "Slå gentag fra, til eller til/fra" #: ../quodlibet/cli.py:127 msgid "Set repeat mode type" msgstr "Sæt gentag-tilstandstype" #: ../quodlibet/cli.py:128 msgid "Set the volume" msgstr "Sæt lydstyrken" #: ../quodlibet/cli.py:129 msgid "Search your audio library" msgstr "Søg i dit lydbibliotek" #: ../quodlibet/cli.py:129 ../quodlibet/cli.py:141 ../quodlibet/cli.py:145 #: ../quodlibet/cli.py:147 msgid "query" msgstr "anmodning" #: ../quodlibet/cli.py:130 msgid "Play a file" msgstr "Afspil en fil" #: ../quodlibet/cli.py:130 ../quodlibet/cli.py:141 ../quodlibet/cli.py:147 msgctxt "command" msgid "filename" msgstr "filnavn" #: ../quodlibet/cli.py:131 msgid "Rate the playing song" msgstr "Bedøm sangen som afspilles" #: ../quodlibet/cli.py:132 msgid "Set the current browser" msgstr "Sæt den aktuelle browser" #: ../quodlibet/cli.py:133 msgid "Stop after the playing song" msgstr "Stop efter sangen som afspilles" #: ../quodlibet/cli.py:134 msgid "Open a new browser" msgstr "Åbn en ny browser" #: ../quodlibet/cli.py:135 msgid "Show or hide the queue" msgstr "Vis eller skjul køen" #: ../quodlibet/cli.py:137 msgid "Show or hide the main song list (deprecated)" msgstr "Vis eller skjul hovedsanglisten (udgået)" #: ../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:159 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:207 #, python-format msgid "Invalid argument for '%s'." msgstr "Ugyldigt argument for '%s'." #: ../quodlibet/cli.py:208 ../quodlibet/util/__init__.py:174 #, python-format msgid "Try %s --help." msgstr "Prøv %s --help." #: ../quodlibet/errorreport/ui.py:59 msgid "An Error Occurred" msgstr "Der opstod en fejl" #: ../quodlibet/errorreport/ui.py:61 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:70 ../quodlibet/errorreport/ui.py:86 msgid "Submit Error Report" msgstr "Indsend fejlrapport" #: ../quodlibet/errorreport/ui.py:71 msgid "Quit Program" msgstr "Afslut program" #: ../quodlibet/errorreport/ui.py:72 msgid "Ignore Error" msgstr "Ignorer fejl" #: ../quodlibet/errorreport/ui.py:76 msgid "Error details:" msgstr "Fejldetaljer:" #: ../quodlibet/errorreport/ui.py:88 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:96 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:105 msgid "_Send" msgstr "_Send" #: ../quodlibet/errorreport/ui.py:111 msgid "Short description…" msgstr "Kort beskrivelse…" #: ../quodlibet/errorreport/ui.py:114 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:160 msgid "directory" msgstr "mappe" #: ../quodlibet/exfalso.py:42 msgid "Audio metadata editor" msgstr "Lyd-metadata-editor" #: ../quodlibet/ext/covers/artwork_url.py:20 msgid "Artwork URL Cover Source" msgstr "Grafik URL-cover-kilde" #: ../quodlibet/ext/covers/artwork_url.py:21 msgid "" "Downloads covers linked to by the artwork_url tag. This works with the " "Soundcloud browser." msgstr "" "Downloader covere som der linkes til af artwork_url-tagget. Det virker med " "Soundcloud-browseren." #: ../quodlibet/ext/covers/discogs.py:29 msgid "Discogs Cover Source" msgstr "Discogs-cover-kilde" #: ../quodlibet/ext/covers/discogs.py:30 msgid "Downloads covers from Discogs." msgstr "Downloader covere fra Discogs." #: ../quodlibet/ext/covers/lastfm.py:21 msgid "Last.fm Cover Source" msgstr "Last.fm-cover-kilde" #: ../quodlibet/ext/covers/lastfm.py:22 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:27 msgid "Convert Encodings" msgstr "Konvertér kodninger" #: ../quodlibet/ext/editing/iconv.py:28 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:34 msgid "_Convert Encoding…" msgstr "_Konvertér kodning…" #: ../quodlibet/ext/editing/kakasi.py:27 msgid "Kana/Kanji Simple Inverter" msgstr "Kana/Kanji-simpel-omformer" #: ../quodlibet/ext/editing/kakasi.py:28 msgid "Converts kana/kanji to romaji before renaming." msgstr "Konverterer kana/kanji til romaji inden omdøbning." #: ../quodlibet/ext/editing/kakasi.py:37 msgid "Romanize _Japanese text" msgstr "Romanisér _japansk tekst" #: ../quodlibet/ext/editing/kakasi.py:69 msgid "Couldn't find the 'Kanji Kana Simple Inverter' (kakasi)." msgstr "Kunne ikke finde 'Kanji Kana-simpel-omformer' (kakasi)." #: ../quodlibet/ext/editing/resub.py:19 msgid "Regex Substitution" msgstr "Regex-erstatning" #: ../quodlibet/ext/editing/resub.py:20 msgid "" "Allows arbitrary regex substitutions (s///) when tagging or renaming files." msgstr "" "Tillader vilkårlige regex-erstatninger (s///) ved tagging eller omdøbning af " "filer." #: ../quodlibet/ext/editing/titlecase.py:21 msgid "Title Case" msgstr "Ord Med Stort" #: ../quodlibet/ext/editing/titlecase.py:22 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:41 msgid "Title-_case Value" msgstr "Skriv _ord med stort i værdi" #: ../quodlibet/ext/editing/titlecase.py:52 msgid "Allow _ALL-CAPS in tags" msgstr "Tillad tags som kun har _STORE BOGSTAVER" #: ../quodlibet/ext/editing/titlecase.py:53 msgid "_Human title case" msgstr "_Ord med stort som mennesker skriver det" #: ../quodlibet/ext/editing/titlecase.py:54 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:69 msgid "Advanced Preferences" msgstr "Avancerede præferencer" #: ../quodlibet/ext/events/advanced_preferences.py:70 msgid "Allow editing of advanced config settings." msgstr "Tillad redigering af avancerede konfigurationsindstillinger." #: ../quodlibet/ext/events/advanced_preferences.py:176 msgid "I know what I'm doing" msgstr "Jeg ved hvad jeg har gang i" #: ../quodlibet/ext/events/animosd/main.py:28 msgid "Animated On-Screen Display" msgstr "Animeret on-screen-visning" #: ../quodlibet/ext/events/animosd/main.py:29 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:154 msgid "Top of screen" msgstr "Øverst på skærmen" #: ../quodlibet/ext/events/animosd/prefs.py:155 msgid "Middle of screen" msgstr "Midt på skærmen" #: ../quodlibet/ext/events/animosd/prefs.py:156 msgid "Bottom of screen" msgstr "Nederst på skærmen" #: ../quodlibet/ext/events/animosd/prefs.py:159 msgid "_Position:" msgstr "_Placering:" #: ../quodlibet/ext/events/animosd/prefs.py:172 msgid "_Cover size:" msgstr "_Coverstørrelse:" #: ../quodlibet/ext/events/animosd/prefs.py:178 #: ../quodlibet/ext/events/weblyrics.py:318 ../quodlibet/qltk/prefs.py:267 msgid "Display" msgstr "Visning" #: ../quodlibet/ext/events/animosd/prefs.py:191 msgid "_Font:" msgstr "_Skrifttype:" #: ../quodlibet/ext/events/animosd/prefs.py:196 msgid "Left" msgstr "Venstre" #: ../quodlibet/ext/events/animosd/prefs.py:197 msgid "Center" msgstr "Centreret" #: ../quodlibet/ext/events/animosd/prefs.py:198 msgid "Right" msgstr "Højre" #: ../quodlibet/ext/events/animosd/prefs.py:201 msgid "_Align text:" msgstr "_Juster tekst:" #: ../quodlibet/ext/events/animosd/prefs.py:207 msgid "Text" msgstr "Tekst" #: ../quodlibet/ext/events/animosd/prefs.py:218 msgid "_Text:" msgstr "_Tekst:" #: ../quodlibet/ext/events/animosd/prefs.py:228 msgid "_Fill:" msgstr "_Udfyld:" #: ../quodlibet/ext/events/animosd/prefs.py:233 #: ../quodlibet/ext/events/synchronizedlyrics.py:67 msgid "Colors" msgstr "Farver" #: ../quodlibet/ext/events/animosd/prefs.py:241 msgid "_Shadows" msgstr "_Skygger" #: ../quodlibet/ext/events/animosd/prefs.py:242 msgid "_Outline" msgstr "_Omrids" #: ../quodlibet/ext/events/animosd/prefs.py:243 msgid "Rou_nded Corners" msgstr "_Afrundede hjørner" #: ../quodlibet/ext/events/animosd/prefs.py:259 msgid "_Delay:" msgstr "_Forsinkelse:" #: ../quodlibet/ext/events/animosd/prefs.py:265 #: ../quodlibet/qltk/pluginwin.py:173 msgid "Effects" msgstr "Effekter" #: ../quodlibet/ext/events/animosd/prefs.py:271 msgid "Ed_it Display Pattern…" msgstr "_Rediger visningsmønster…" #: ../quodlibet/ext/events/animosd/prefs.py:275 #: ../quodlibet/ext/events/trayicon/prefs.py:87 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_library_update.py:137 msgid "Automatic Library Update" msgstr "Automatisk opdatering af bibliotek" #: ../quodlibet/ext/events/auto_library_update.py:138 #, 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." #: ../quodlibet/ext/events/automask.py:23 msgid "Automatic Masking" msgstr "Automatisk maskering" #: ../quodlibet/ext/events/automask.py:24 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:16 msgid "Automatic Rating" msgstr "Automatisk bedømmelse" #: ../quodlibet/ext/events/autorating.py:17 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." #: ../quodlibet/ext/events/clock.py:25 msgid "Alarm Clock" msgstr "Vækkeur" #: ../quodlibet/ext/events/clock.py:26 msgid "Wakes you up with loud music." msgstr "Vækker dig med høj musik." #: ../quodlibet/ext/events/clock.py:120 msgid "Lullaby" msgstr "Godnatsang" #: ../quodlibet/ext/events/clock.py:121 msgid "Fades out and pauses your music." msgstr "Udtoner og sætter din musik på pause." #: ../quodlibet/ext/events/equalizer.py:27 msgid "Flat" msgstr "Flad" #: ../quodlibet/ext/events/equalizer.py:28 msgid "Live" msgstr "Live" #: ../quodlibet/ext/events/equalizer.py:30 msgid "Full Bass & Treble" msgstr "Fuld bas og diskant" #: ../quodlibet/ext/events/equalizer.py:33 msgid "Club" msgstr "Klub" #: ../quodlibet/ext/events/equalizer.py:35 msgid "Large Hall" msgstr "Stor hal" #: ../quodlibet/ext/events/equalizer.py:37 msgid "Party" msgstr "Fest" #: ../quodlibet/ext/events/equalizer.py:41 msgid "Soft" msgstr "Blød" #: ../quodlibet/ext/events/equalizer.py:43 msgid "Full Bass" msgstr "Fuld bas" #: ../quodlibet/ext/events/equalizer.py:49 msgid "Reggae" msgstr "Reggae" #: ../quodlibet/ext/events/equalizer.py:51 msgid "Headphones" msgstr "Hovedtelefoner" #: ../quodlibet/ext/events/equalizer.py:54 msgid "Soft Rock" msgstr "Blød rock" #: ../quodlibet/ext/events/equalizer.py:56 msgid "Full Treble" msgstr "Fuld diskant" #: ../quodlibet/ext/events/equalizer.py:59 msgid "Dance" msgstr "Dance" #: ../quodlibet/ext/events/equalizer.py:63 msgid "Techno" msgstr "Techno" #: ../quodlibet/ext/events/equalizer.py:65 msgid "Ska" msgstr "Ska" #: ../quodlibet/ext/events/equalizer.py:67 msgid "Laptop" msgstr "Bærbar" #: ../quodlibet/ext/events/equalizer.py:98 msgid "Equalizer" msgstr "Equalizer" #: ../quodlibet/ext/events/equalizer.py:99 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:133 msgid "The current backend does not support equalization." msgstr "Den aktuelle backend understøtter ikke equalizering." #: ../quodlibet/ext/events/equalizer.py:139 #, python-format msgid "%.1f kHz" msgstr "%.1f kHz" #: ../quodlibet/ext/events/equalizer.py:140 #: ../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:174 #: ../quodlibet/ext/gstreamer/crossfeed.py:113 #, python-format msgid "%.1f dB" msgstr "%.1f dB" #: ../quodlibet/ext/events/equalizer.py:193 #: ../quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom" msgstr "Brugerdefineret" #: ../quodlibet/ext/events/equalizer.py:200 msgid "_Clear" msgstr "_Ryd" #. 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:115 #: ../quodlibet/ext/events/mqtt.py:51 #: ../quodlibet/ext/events/telepathy_status.py:70 msgid "paused" msgstr "sat på pause" #: ../quodlibet/ext/events/gajim_status.py:146 msgid "Pattern:" msgstr "Mønster:" #: ../quodlibet/ext/events/gajim_status.py:155 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:158 msgid "Accounts:" msgstr "Konti:" #: ../quodlibet/ext/events/gajim_status.py:162 msgid "Add '[paused]'" msgstr "Tilføj '[sat på pause]'" #: ../quodlibet/ext/events/gajim_status.py:165 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:189 msgid "Statuses for which message will be changed" msgstr "Statusser for hvilken meddelelser der ændres" #: ../quodlibet/ext/events/headphonemon.py:158 msgid "Pause on Headphone Unplug" msgstr "Sæt på pause når stik til hovedtelefoner fjernes" #: ../quodlibet/ext/events/headphonemon.py:159 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:42 msgid "Inhibit Screensaver" msgstr "Blokér pauseskærm" #: ../quodlibet/ext/events/inhibit.py:43 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." #: ../quodlibet/ext/events/inhibit.py:52 msgid "Music is playing" msgstr "Musik afspiller" #: ../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:31 msgid "JEP-118" msgstr "JEP-118" #: ../quodlibet/ext/events/jep118.py:32 msgid "Outputs a Jabber User Tunes file to ~/.quodlibet/jabber." msgstr "Outputter en Jabber User Tunes-fil til ~/.quodlibet/jabber." #: ../quodlibet/ext/events/language.py:22 msgid "Change Language" msgstr "Skift sprog" #: ../quodlibet/ext/events/language.py:23 msgid "Change the user interface language." msgstr "Skrift brugerfladens sprog." #: ../quodlibet/ext/events/language.py:44 msgid "System Default" msgstr "Systemets standard" #: ../quodlibet/ext/events/language.py:71 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:38 msgid "UPnP AV Media Server" msgstr "UPnP AV-medieserver" #: ../quodlibet/ext/events/mediaserver.py:39 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/mpdserver/__init__.py:62 msgid "MPD Server" msgstr "MPD-server" #: ../quodlibet/ext/events/mpdserver/__init__.py:63 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:77 msgid "_Port:" msgstr "_Port:" #: ../quodlibet/ext/events/mpdserver/__init__.py:120 msgid "Local _IP:" msgstr "Lokal _IP:" #: ../quodlibet/ext/events/mpdserver/__init__.py:126 msgid "P_assword:" msgstr "_Adgangskode:" #: ../quodlibet/ext/events/mpdserver/__init__.py:162 msgid "Connection" msgstr "Forbindelse" #: ../quodlibet/ext/events/mpdserver/__init__.py:164 msgid "Tested Clients" msgstr "Testede klienter" #: ../quodlibet/ext/events/mpris/__init__.py:39 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 MPRIS 1.0/2.0 D-Bus Interface " "Specification." msgstr "" "Tillader styring af Quod Libet ved brug af D-Bus-grænsefladespecifikationen " "MPRIS 1.0/2.0." #: ../quodlibet/ext/events/mpris/__init__.py:46 #: ../quodlibet/ext/events/trayicon/prefs.py:37 msgid "Hide main window on close" msgstr "Skjul hovedvindue ved luk" #: ../quodlibet/ext/events/mpris/__init__.py:49 #: ../quodlibet/ext/events/themeswitcher.py:85 #: ../quodlibet/ext/gstreamer/compressor.py:100 #: ../quodlibet/ext/gstreamer/crossfeed.py:137 #: ../quodlibet/ext/gstreamer/karaoke.py:100 #: ../quodlibet/ext/gstreamer/pitch.py:84 ../quodlibet/qltk/prefs.py:699 msgid "Preferences" msgstr "Præferencer" #: ../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:128 msgid "Broker hostname" msgstr "Mægler-værtsnavn" #: ../quodlibet/ext/events/mqtt.py:128 msgid "broker hostname / IP" msgstr "mægler-værtsnavn/-IP" #: ../quodlibet/ext/events/mqtt.py:130 msgid "Broker port" msgstr "Mægler-port" #: ../quodlibet/ext/events/mqtt.py:130 msgid "broker port" msgstr "mægler-port" #: ../quodlibet/ext/events/mqtt.py:132 msgid "Topic" msgstr "Emne" #: ../quodlibet/ext/events/mqtt.py:134 msgid "Playing Pattern" msgstr "Afspiller-mønster" #: ../quodlibet/ext/events/mqtt.py:136 msgid "Status text when a song is started." msgstr "Statustekst når en sang er startet." #: ../quodlibet/ext/events/mqtt.py:138 msgid "Paused Pattern" msgstr "Sat på pause-mønster" #: ../quodlibet/ext/events/mqtt.py:140 msgid "Text when a song is paused." msgstr "Tekst når en sang er sat på pause." #: ../quodlibet/ext/events/mqtt.py:142 msgid "No-song Text" msgstr "Ingen sang-tekst" #: ../quodlibet/ext/events/mqtt.py:144 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:155 msgid "MQTT Configuration" msgstr "MQTT-konfiguration" #: ../quodlibet/ext/events/mqtt.py:159 msgid "Status Text" msgstr "Statustekst" #: ../quodlibet/ext/events/mqtt.py:191 #, 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:195 #, 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:198 msgid "Connection error" msgstr "Forbindelsesfejl" #: ../quodlibet/ext/events/notify.py:56 msgid "Notification text" msgstr "Notifikationstekst" #: ../quodlibet/ext/events/notify.py:67 msgid "_Title:" msgstr "_Titel:" #: ../quodlibet/ext/events/notify.py:78 ../quodlibet/ext/events/notify.py:114 msgid "Revert to default pattern" msgstr "Tilbagefør til standardmønster" #: ../quodlibet/ext/events/notify.py:104 msgid "_Body:" msgstr "_Krop:" #: ../quodlibet/ext/events/notify.py:124 msgid "_Show notification" msgstr "_Vis notifikationer" #: ../quodlibet/ext/events/notify.py:142 msgid "Show notifications" msgstr "Vis notifikationer" #: ../quodlibet/ext/events/notify.py:148 msgid "Only on <i>_manual</i> song changes" msgstr "Kun ved <i>_manuelle</i> skift af sange" #: ../quodlibet/ext/events/notify.py:156 msgid "Only on <i>_automatic</i> song changes" msgstr "Kun ved <i>_automatiske</i> skift af sange" #: ../quodlibet/ext/events/notify.py:164 msgid "On <i>a_ll</i> song changes" msgstr "Ved <i>a_lle</i> skift af sange" #: ../quodlibet/ext/events/notify.py:179 msgid "Only when the main window is not _focused" msgstr "Kun når hovedvinduet ikke har _fokus" #: ../quodlibet/ext/events/notify.py:187 msgid "Show \"_Next\" button" msgstr "Vis \"_Næste\"-knap" #: ../quodlibet/ext/events/notify.py:209 msgid "Connection Error" msgstr "Forbindelsesfejl" #: ../quodlibet/ext/events/notify.py:210 ../quodlibet/ext/events/notify.py:364 #: ../quodlibet/ext/events/notify.py:406 msgid "Couldn't connect to notification daemon." msgstr "Kunne ikke oprette forbindelse til notifikationsdæmon." #: ../quodlibet/ext/events/notify.py:224 msgid "Song Notifications" msgstr "Sang-notifikationer" #: ../quodlibet/ext/events/notify.py:225 msgid "Displays a notification when the song changes." msgstr "Viser en notifikation når sangen skiftes." #: ../quodlibet/ext/events/notify.py:388 ../quodlibet/qltk/unity.py:63 msgid "Next" msgstr "Næste" #: ../quodlibet/ext/events/qlscrobbler.py:176 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:253 #, python-format msgid "Could not contact service '%s'." msgstr "Kunne ikke kontakte tjenesten '%s'." #: ../quodlibet/ext/events/qlscrobbler.py:259 msgid "Authentication failed: invalid URL." msgstr "Godkendelse fejlede: ugyldig URL." #: ../quodlibet/ext/events/qlscrobbler.py:276 #, 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:281 msgid "Client is banned. Contact the author." msgstr "Klienten er udelukket. Kontakt forfatteren." #: ../quodlibet/ext/events/qlscrobbler.py:285 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:350 msgid "AudioScrobbler Submission" msgstr "AudioScrobbler-indsendelse" #: ../quodlibet/ext/events/qlscrobbler.py:351 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:456 msgid "Authentication successful." msgstr "Godkendelse lykkedes." #: ../quodlibet/ext/events/qlscrobbler.py:468 msgid "_Service:" msgstr "_Tjeneste:" #: ../quodlibet/ext/events/qlscrobbler.py:468 msgid "_URL:" msgstr "_URL:" #: ../quodlibet/ext/events/qlscrobbler.py:468 msgid "User_name:" msgstr "_Brugernavn:" #: ../quodlibet/ext/events/qlscrobbler.py:469 msgid "_Password:" msgstr "_Adgangskode:" #. Translators: Other service #: ../quodlibet/ext/events/qlscrobbler.py:485 msgid "Other…" msgstr "Anden…" #. verify data #: ../quodlibet/ext/events/qlscrobbler.py:523 msgid "_Verify account data" msgstr "_Bekræft kontodata" #: ../quodlibet/ext/events/qlscrobbler.py:528 #: ../quodlibet/ext/songsmenu/lastfmsync.py:313 msgid "Account" msgstr "Konto" #: ../quodlibet/ext/events/qlscrobbler.py:536 msgid "_Artist pattern:" msgstr "_Kunstner-mønster:" #: ../quodlibet/ext/events/qlscrobbler.py:536 msgid "_Title pattern:" msgstr "_Titel-mønster:" #: ../quodlibet/ext/events/qlscrobbler.py:537 msgid "Exclude _filter:" msgstr "Ekskluderings_filter:" #: ../quodlibet/ext/events/qlscrobbler.py:555 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:565 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:574 msgid "Songs matching this filter will not be submitted" msgstr "Sange som matcher dette filter vil ikke blive indsendt" #: ../quodlibet/ext/events/qlscrobbler.py:582 msgid "_Offline mode (don't submit anything)" msgstr "_Offline-tilstand (indsend ikke noget)" #: ../quodlibet/ext/events/qlscrobbler.py:586 msgid "Submission" msgstr "Indsendelse" #: ../quodlibet/ext/events/radioadmute.py:21 msgid "Mute Radio Ads" msgstr "Slå lyden fra i radioreklamer" #: ../quodlibet/ext/events/radioadmute.py:22 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:29 msgid "Random Album Playback" msgstr "Afspilning af tilfældigt album" #: ../quodlibet/ext/events/randomalbum.py:30 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:40 msgid "Rated higher" msgstr "Højere bedømt" #: ../quodlibet/ext/events/randomalbum.py:41 msgid "Played more often" msgstr "Afspillet oftere" #: ../quodlibet/ext/events/randomalbum.py:42 msgid "Skipped more often" msgstr "Sprunget over oftere" #: ../quodlibet/ext/events/randomalbum.py:43 msgid "Played more recently" msgstr "Afspillet mere nyligt" #: ../quodlibet/ext/events/randomalbum.py:44 msgid "Started more recently" msgstr "Startet mere nyligt" #: ../quodlibet/ext/events/randomalbum.py:45 msgid "Added more recently" msgstr "Tilføjet mere nyligt" #: ../quodlibet/ext/events/randomalbum.py:46 msgid "Longer albums" msgstr "Længere album" #: ../quodlibet/ext/events/randomalbum.py:85 msgid "seconds before starting next album" msgstr "sekunder før næste album startes" #: ../quodlibet/ext/events/randomalbum.py:89 msgid "Weights" msgstr "Vægtninger" #: ../quodlibet/ext/events/randomalbum.py:91 msgid "Play some albums more than others" msgstr "Afspil nogle album mere end andre" #: ../quodlibet/ext/events/randomalbum.py:105 msgid "avoid" msgstr "undgå" #: ../quodlibet/ext/events/randomalbum.py:116 msgid "prefer" msgstr "foretræk" #: ../quodlibet/ext/events/randomalbum.py:209 msgid "Random Album" msgstr "Tilfældigt album" #: ../quodlibet/ext/events/randomalbum.py:210 #, python-format msgid "Waiting to start %s" msgstr "Venter på at starte %s" #: ../quodlibet/ext/events/rbimport.py:115 msgid "Import Failed" msgstr "Import fejlede" #: ../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/rbimport.py:133 msgid "Start Import" msgstr "Start import" #: ../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:74 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:80 msgid "GNOME Search Provider" msgstr "GNOME-søgeudbyder" #: ../quodlibet/ext/events/searchprovider.py:81 msgid "Allows GNOME Shell to search the library." msgstr "Tillader GNOME Shell at søge i biblioteket." #: ../quodlibet/ext/events/seekbar.py:123 msgid "Alternative Seek Bar" msgstr "Alternativ søgelinje" #: ../quodlibet/ext/events/seekbar.py:124 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:21 msgid "Seekpoint Bookmarks" msgstr "Søgepunktsbogmærker" #: ../quodlibet/ext/events/seekpoints.py:25 msgid "" "Store Seekpoints A and/or B for tracks. Skip to time A and stop after time B " "when track is played.\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:109 msgid "Bookmark name for point A" msgstr "Bogmærkenavn til punkt A" #: ../quodlibet/ext/events/seekpoints.py:110 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:125 msgid "Bookmark name for point B" msgstr "Bogmærkenavn til punkt B" #: ../quodlibet/ext/events/seekpoints.py:126 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:29 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:58 #: ../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:59 #: ../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/synchronizedlyrics.py:35 msgid "Synchronized Lyrics" msgstr "Synkroniserede sangtekster" #: ../quodlibet/ext/events/synchronizedlyrics.py:36 msgid "Shows synchronized lyrics from .lrc file with same name as the track." msgstr "" "Viser synkroniserede sangtekster fra .lrc-fil med samme navn som sporet." #: ../quodlibet/ext/events/synchronizedlyrics.py:70 msgid "Text:" msgstr "Tekst:" #: ../quodlibet/ext/events/synchronizedlyrics.py:80 msgid "Background:" msgstr "Baggrund:" #: ../quodlibet/ext/events/synchronizedlyrics.py:91 msgid "Font" msgstr "Skrifttype" #: ../quodlibet/ext/events/synchronizedlyrics.py:94 msgid "Size (px):" msgstr "Størrelse (px):" #: ../quodlibet/ext/events/telepathy_status.py:63 msgid "Telepathy Status Messages" msgstr "Telepathy-statusmeddelelser" #: ../quodlibet/ext/events/telepathy_status.py:64 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:123 msgid "Playing:" msgstr "Afspiller:" #: ../quodlibet/ext/events/telepathy_status.py:124 #, 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:140 msgid "Paused:" msgstr "Sat på pause:" #: ../quodlibet/ext/events/telepathy_status.py:141 #, 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:157 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:158 msgid "No song:" msgstr "Ingen sang:" #. Frame #: ../quodlibet/ext/events/telepathy_status.py:165 msgid "Status Patterns" msgstr "Statusmønstre" #: ../quodlibet/ext/events/themeswitcher.py:26 msgid "Theme Switcher" msgstr "Tema-skifter" #: ../quodlibet/ext/events/themeswitcher.py:27 msgid "Changes the active GTK+ theme." msgstr "Skifter det aktive GTK+-tema." #: ../quodlibet/ext/events/themeswitcher.py:50 msgid "_Theme:" msgstr "_Tema:" #: ../quodlibet/ext/events/themeswitcher.py:55 msgid "Default Theme" msgstr "Standardtema" #: ../quodlibet/ext/events/themeswitcher.py:67 msgid "Prefer dark theme version" msgstr "Foretræk version med mørkt tema" #: ../quodlibet/ext/events/toggle_menu.py:19 msgid "Toggle Menu Bar" msgstr "Menulinje til/fra" #: ../quodlibet/ext/events/toggle_menu.py:20 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:78 #: ../quodlibet/ext/events/trayicon/prefs.py:107 #: ../quodlibet/ext/events/trayicon/systemtray.py:178 #: ../quodlibet/qltk/info.py:48 msgid "Not playing" msgstr "Afspiller ikke" #: ../quodlibet/ext/events/trayicon/__init__.py:54 msgid "Tray Icon" msgstr "Bakkeikon" #: ../quodlibet/ext/events/trayicon/__init__.py:55 msgid "Controls Quod Libet from the system tray." msgstr "Styrer Quod Libet fra systembakken." #: ../quodlibet/ext/events/trayicon/menu.py:42 #, python-format msgid "_Show %(application-name)s" msgstr "_Vis %(application-name)s" #: ../quodlibet/ext/events/trayicon/menu.py:61 #: ../quodlibet/qltk/quodlibetwindow.py:185 #: ../quodlibet/qltk/quodlibetwindow.py:1037 #: ../quodlibet/qltk/quodlibetwindow.py:1229 msgid "_Play" msgstr "_Afspil" #: ../quodlibet/ext/events/trayicon/menu.py:64 #: ../quodlibet/qltk/quodlibetwindow.py:187 #: ../quodlibet/qltk/quodlibetwindow.py:1231 ../quodlibet/qltk/wlw.py:52 msgid "P_ause" msgstr "_Pause" #: ../quodlibet/ext/events/trayicon/menu.py:69 #: ../quodlibet/qltk/quodlibetwindow.py:192 #: ../quodlibet/qltk/quodlibetwindow.py:1032 msgid "Pre_vious" msgstr "_Forrige" #: ../quodlibet/ext/events/trayicon/menu.py:72 #: ../quodlibet/qltk/quodlibetwindow.py:196 #: ../quodlibet/qltk/quodlibetwindow.py:1042 msgid "_Next" msgstr "_Næste" #: ../quodlibet/ext/events/trayicon/menu.py:77 msgid "_Shuffle" msgstr "_Bland" #: ../quodlibet/ext/events/trayicon/menu.py:82 msgid "_Repeat" msgstr "_Gentag" #: ../quodlibet/ext/events/trayicon/menu.py:87 msgid "Stop _After This Song" msgstr "Stop _efter denne sang" #: ../quodlibet/ext/events/trayicon/menu.py:93 #: ../quodlibet/qltk/quodlibetwindow.py:1003 msgid "Open _Browser" msgstr "Åbn _browser" #: ../quodlibet/ext/events/trayicon/menu.py:104 #: ../quodlibet/qltk/quodlibetwindow.py:1022 ../quodlibet/qltk/songsmenu.py:385 msgid "Edit _Tags" msgstr "Rediger _tags" #: ../quodlibet/ext/events/trayicon/menu.py:113 #: ../quodlibet/qltk/quodlibetwindow.py:965 ../quodlibet/qltk/songsmenu.py:398 msgid "_Information" msgstr "_Information" #: ../quodlibet/ext/events/trayicon/menu.py:115 #: ../quodlibet/qltk/songsmenu.py:326 msgid "Play_lists" msgstr "_Spillelister" #: ../quodlibet/ext/events/trayicon/menu.py:133 #: ../quodlibet/qltk/quodlibetwindow.py:1017 msgid "_Quit" msgstr "_Afslut" #: ../quodlibet/ext/events/trayicon/prefs.py:39 ../quodlibet/qltk/prefs.py:70 msgid "Behavior" msgstr "Adfærd" #: ../quodlibet/ext/events/trayicon/prefs.py:49 msgid "Scroll wheel adjusts volume" msgstr "Rullehjul justerer lydstyrke" #: ../quodlibet/ext/events/trayicon/prefs.py:55 msgid "Scroll wheel changes song" msgstr "Rullehjul skifter sang" #: ../quodlibet/ext/events/trayicon/prefs.py:63 msgid "Scroll _Wheel" msgstr "_Rullehjul" #: ../quodlibet/ext/events/trayicon/prefs.py:93 msgid "Tooltip Display" msgstr "Værktøjstip-visning" #: ../quodlibet/ext/events/viewlyrics.py:26 msgid "View Lyrics" msgstr "Vis sangtekster" #: ../quodlibet/ext/events/viewlyrics.py:27 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:88 #, python-format msgid "" "No lyrics found for\n" " %s" msgstr "" "Ingen sangtekster fundet til\n" " %s" #: ../quodlibet/ext/events/viewlyrics.py:118 #: ../quodlibet/ext/events/weblyrics.py:193 msgid "No active song" msgstr "Ingen aktiv sang" #: ../quodlibet/ext/events/visualisations.py:37 msgid "Launch Visualisations" msgstr "Start visualiseringer" #: ../quodlibet/ext/events/visualisations.py:39 msgid "Launch external visualisations." msgstr "Start eksterne visualiseringer." #: ../quodlibet/ext/events/visualisations.py:56 #, python-format msgid "Couldn't run visualisations using '%s'" msgstr "Kunne ikke køre visualiseringer ved brug af '%s'" #: ../quodlibet/ext/events/visualisations.py:58 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:45 msgid "Error" msgstr "Fejl" #: ../quodlibet/ext/events/visualisations.py:77 msgid "Visualiser executable:" msgstr "Visualiserer-eksekverbar:" #: ../quodlibet/ext/events/visualisations.py:92 msgid "Reload" msgstr "Genindlæs" #: ../quodlibet/ext/events/waveformseekbar.py:567 msgid "Waveform Seek Bar" msgstr "Bølgeform søgelinje" #: ../quodlibet/ext/events/waveformseekbar.py:571 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:628 msgid "Override foreground color:" msgstr "Tilsidesæt forgrundsfarve:" #: ../quodlibet/ext/events/waveformseekbar.py:632 msgid "Override hover color:" msgstr "Tilsidesæt pegefarve:" #: ../quodlibet/ext/events/waveformseekbar.py:636 msgid "Override remaining color:" msgstr "Tilsidesæt resterende farve:" #: ../quodlibet/ext/events/waveformseekbar.py:640 msgid "Show current position" msgstr "Vis nuværende placering" #: ../quodlibet/ext/events/weblyrics.py:208 msgid "No lyrics found" msgstr "Ingen sangtekster fundet" #: ../quodlibet/ext/events/weblyrics.py:268 msgid "_Zoom level:" msgstr "_Zoomniveau:" #: ../quodlibet/ext/events/weblyrics.py:286 msgid "URL:" msgstr "URL:" #: ../quodlibet/ext/events/weblyrics.py:291 msgid "Revert to default" msgstr "Tilbagefør til standard" #: ../quodlibet/ext/events/weblyrics.py:306 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." #: ../quodlibet/ext/events/weblyrics.py:323 msgid "Alternate search" msgstr "Alternativ søgning" #: ../quodlibet/ext/events/weblyrics.py:332 msgid "Web Lyrics" msgstr "Websangtekster" #: ../quodlibet/ext/events/weblyrics.py:333 msgid "Shows a sidebar containing online lyrics of the playing song." msgstr "Viser en sidebjælke med onlinesangtekster fra sangen som afspilles." #: ../quodlibet/ext/events/write_cover.py:34 msgid "Picture Saver" msgstr "Billede-gemmer" #: ../quodlibet/ext/events/write_cover.py:35 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:68 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 #, 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 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:17 msgid "Mono Downmix" msgstr "Mono nedmiks" #: ../quodlibet/ext/gstreamer/mono.py:18 msgid "Downmixes audio channels to mono." msgstr "Nedmikser lydkanaler til mono." #: ../quodlibet/ext/gstreamer/pitch.py:21 msgid "R_ate:" msgstr "_Hastighed:" #: ../quodlibet/ext/gstreamer/pitch.py:22 msgid "_Tempo:" msgstr "_Tempo:" #: ../quodlibet/ext/gstreamer/pitch.py:23 msgid "_Pitch:" msgstr "_Tonehøjde:" #: ../quodlibet/ext/gstreamer/pitch.py:90 msgid "Audio Pitch / Speed" msgstr "Lydtonehøjde/-hastighed" #: ../quodlibet/ext/gstreamer/pitch.py:91 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:139 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:100 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:157 msgid "Default filename pattern:" msgstr "Standardfilnavn-mønster:" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:23 msgid "Export to Squeezebox" msgstr "Eksportér til Squeezebox" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:25 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 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:79 msgid "Export playlist to Squeezebox" msgstr "Eksportér spilleliste til Squeezebox" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:80 msgid "Playlist name (will overwrite existing)" msgstr "Spillelistenavn (vil overskrive eksisterende)" #. Save button #: ../quodlibet/ext/playlist/export_to_squeezebox.py:81 #: ../quodlibet/ext/songsmenu/albumart.py:324 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:357 #: ../quodlibet/ext/songsmenu/cover_download.py:309 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:279 #: ../quodlibet/ext/songsmenu/html.py:77 #: ../quodlibet/ext/songsmenu/lastfmsync.py:220 #: ../quodlibet/ext/songsmenu/playlist.py:52 #: ../quodlibet/ext/songsmenu/replaygain.py:356 #: ../quodlibet/ext/songsmenu/tapbpm.py:188 ../quodlibet/qltk/_editutils.py:41 #: ../quodlibet/qltk/lyrics.py:35 ../quodlibet/qltk/msg.py:53 #: ../quodlibet/qltk/renamefiles.py:218 ../quodlibet/qltk/tagsfrompath.py:154 #: ../quodlibet/qltk/tracknumbers.py:114 msgid "_Save" msgstr "_Gem" #: ../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:21 msgid "Remove Playlist Duplicates" msgstr "Fjern duplikater fra spilleliste" #: ../quodlibet/ext/playlist/remove_duplicates.py:22 msgid "Removes duplicate entries in a playlist." msgstr "Fjerner duplikerede indtastninger i en spilleliste." #: ../quodlibet/ext/playlist/remove_duplicates.py:50 #, 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:53 #, 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:16 msgid "Shuffle Playlist" msgstr "Bland spilleliste" #: ../quodlibet/ext/playlist/shuffle.py:17 msgid "Randomly shuffles a playlist." msgstr "Blander tilfældigt en spilleliste." #: ../quodlibet/ext/playorder/follow.py:19 msgid "Follow Cursor" msgstr "Følg markør" #: ../quodlibet/ext/playorder/follow.py:21 msgid "" "Playback 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/playcounteq.py:23 msgid "Playcount Equalizer" msgstr "Playcount-equalizer" #: ../quodlibet/ext/playorder/playcounteq.py:24 msgid "Shuffle, preferring songs with fewer total plays." msgstr "Bland, foretræk sange med færre samlet afspilninger." #: ../quodlibet/ext/playorder/playcounteq.py:26 msgid "Prefer less played" msgstr "Foretræk færre afspilninger" #: ../quodlibet/ext/playorder/queue.py:20 msgid "Queue Only" msgstr "Sæt kun i kø" #: ../quodlibet/ext/playorder/queue.py:22 msgid "" "Limits playing of songs to the queue. 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/reverse.py:15 msgid "Reverse" msgstr "Omvend" #: ../quodlibet/ext/playorder/reverse.py:17 msgid "Reverses the play order of songs." msgstr "Vender om på afspilningsrækkefølgen af sange." #: ../quodlibet/ext/playorder/shufflebygrouping.py:32 #: ../quodlibet/ext/playorder/shufflebygrouping.py:94 msgid "Shuffle by Grouping" msgstr "Bland efter gruppering" #: ../quodlibet/ext/playorder/shufflebygrouping.py:33 msgid "" "Shuffles by a grouping of songs defined by a common tag instead of by track, " "similar to album shuffle. This is useful for shuffling multi-movement " "classical works while 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:95 msgid "Waiting to start new group…" msgstr "Venter på at starte ny gruppe…" #: ../quodlibet/ext/playorder/shufflebygrouping.py:145 msgid "Grouping tag:" msgstr "Grupperingstag:" #: ../quodlibet/ext/playorder/shufflebygrouping.py:149 msgid "Tag to group songs by" msgstr "Mærk for at gruppere sange efter" #: ../quodlibet/ext/playorder/shufflebygrouping.py:151 msgid "Filter tag:" msgstr "Filtertag:" #: ../quodlibet/ext/playorder/shufflebygrouping.py:156 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:161 msgid "Delay:" msgstr "Forsinkelse:" #: ../quodlibet/ext/playorder/shufflebygrouping.py:167 msgid "Time delay in seconds before starting next group" msgstr "Tidsforsinkelse i sekunder før næste gruppe startes" #: ../quodlibet/ext/playorder/shufflebygrouping.py:183 msgid "Reset to defaults" msgstr "Nulstil til standard" #: ../quodlibet/ext/playorder/skip_songs.py:26 msgid "Skip Songs" msgstr "Spring over sange" #: ../quodlibet/ext/playorder/skip_songs.py:28 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." #: ../quodlibet/ext/playorder/track_repeat.py:31 msgid "Repeat Each Track" msgstr "Gentag hvert spor" #: ../quodlibet/ext/playorder/track_repeat.py:33 msgid "Shuffle songs, but repeat every track a set number of times." msgstr "Blander sange, men gentager hvert spor et sat antal gange." #: ../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:16 msgid "Conditional Query" msgstr "Betinget anmodning" #: ../quodlibet/ext/query/conditional.py:17 msgid "" "Chooses the query to match based on a condition query. Syntax is '@(if: " "condition, then, else)'." msgstr "" "Vælger anmodningen som skal matches, baseret på en betingelsesanmodning. " "Syntaksen er '@(if: betingelse, then, else)'." #: ../quodlibet/ext/query/pythonexpression.py:19 msgid "Python Query" msgstr "Python-anmodning" #: ../quodlibet/ext/query/pythonexpression.py:20 msgid "" "Use Python expressions in queries. Syntax is '@(python: expression)'. The " "variable 's' (or 'a') is the song / album being matched. '_ts' is a (real " "number) timestamp at start of query. Modules 'time' and 'random' are also " "available, and the class 'Random' (==random.Random) 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 msgid "" "Include the results of a saved search as part of another query. Syntax is " "'@(saved: search name)'." msgstr "" "Inkluder resultaterne af en gemt søgning som del af en anden anmodning. " "Syntaksen er '@(saved: søgenavn)'." #: ../quodlibet/ext/_shared/squeezebox/base.py:78 #, python-format msgid "Squeezebox OK. Using the only player (%s)." msgstr "Squeezebox OK. Bruger den eneste afspiller (%s)." #: ../quodlibet/ext/_shared/squeezebox/base.py:87 #, python-format msgid "Couldn't connect to %s" msgstr "Kunne ikke oprette forbindelse til %s" #: ../quodlibet/ext/_shared/squeezebox/base.py:111 msgid "Hostname:" msgstr "Værtsnavn:" #: ../quodlibet/ext/_shared/squeezebox/base.py:117 msgid "Port:" msgstr "Port:" #: ../quodlibet/ext/_shared/squeezebox/base.py:122 msgid "Username:" msgstr "Brugernavn:" #: ../quodlibet/ext/_shared/squeezebox/base.py:127 msgid "Password:" msgstr "Adgangskode:" #: ../quodlibet/ext/_shared/squeezebox/base.py:131 msgid "Library directory the server connects to" msgstr "Biblioteksmappe som serveren opretter forbindelse til" #: ../quodlibet/ext/_shared/squeezebox/base.py:133 msgid "Library path:" msgstr "Bibliotekssti:" #. Add verify button #: ../quodlibet/ext/_shared/squeezebox/base.py:142 msgid "_Verify settings" msgstr "_Bekræft indstillinger" #. Server settings Frame #: ../quodlibet/ext/_shared/squeezebox/base.py:148 msgid "Squeezebox Server" msgstr "Squeezebox-server" #: ../quodlibet/ext/_shared/squeezebox/base.py:151 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:16 msgid "Choose Squeezebox player" msgstr "Vælg Squeezebox-afspiller" #: ../quodlibet/ext/_shared/squeezebox/util.py:21 #: ../quodlibet/ext/songsmenu/importexport.py:39 #: ../quodlibet/qltk/getstring.py:22 msgid "_OK" msgstr "_OK" #: ../quodlibet/ext/_shared/squeezebox/util.py:27 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" "Fandt Squeezebox-server.\n" "Vælg venligst afspilleren" #: ../quodlibet/ext/songsmenu/albumart.py:331 msgid "Fit image to _window" msgstr "Tilpas billede til _vindue" #: ../quodlibet/ext/songsmenu/albumart.py:337 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:343 msgid "_Program:" msgstr "_Program:" #: ../quodlibet/ext/songsmenu/albumart.py:348 msgid "_Edit image after saving" msgstr "_Rediger billede efter gemning" #: ../quodlibet/ext/songsmenu/albumart.py:350 msgid "File_name:" msgstr "_Filnavn:" #: ../quodlibet/ext/songsmenu/albumart.py:466 msgid "Saving failed" msgstr "Gemning fejlede" #: ../quodlibet/ext/songsmenu/albumart.py:467 #, python-format msgid "Unable to save \"%s\"." msgstr "Kan ikke gemme \"%s\"." #: ../quodlibet/ext/songsmenu/albumart.py:565 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "[albumart] HTTP-fejl: %s" #: ../quodlibet/ext/songsmenu/albumart.py:622 msgid "Album Art Downloader" msgstr "Albumgrafik-downloader" #: ../quodlibet/ext/songsmenu/albumart.py:675 #, python-format msgid "from %(source)s" msgstr "fra %(source)s" #: ../quodlibet/ext/songsmenu/albumart.py:678 #, python-format msgid "Resolution: %s" msgstr "Opløsning: %s" #: ../quodlibet/ext/songsmenu/albumart.py:681 #, python-format msgid "Size: %s" msgstr "Størrelse: %s" #: ../quodlibet/ext/songsmenu/albumart.py:727 msgid "Per engine 'at best' results limit" msgstr "Pr. motor 'bedste'-resultatsgrænse" #: ../quodlibet/ext/songsmenu/albumart.py:737 msgid "_Search" msgstr "_Søg" #: ../quodlibet/ext/songsmenu/albumart.py:819 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:453 msgid "Searching…" msgstr "Søger…" #: ../quodlibet/ext/songsmenu/albumart.py:884 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:43 msgid "Done" msgstr "Færdig" #: ../quodlibet/ext/songsmenu/albumart.py:1006 msgid "Download Album Art" msgstr "Download albumgrafik" #: ../quodlibet/ext/songsmenu/albumart.py:1007 msgid "Downloads album covers from various websites." msgstr "Downloader albumcovere fra diverse websteder." #: ../quodlibet/ext/songsmenu/albumart.py:1020 msgid "Sources" msgstr "Kilder" #: ../quodlibet/ext/songsmenu/ape2id3.py:27 msgid "APEv2 to ID3v2" msgstr "APEv2 til ID3v2" #: ../quodlibet/ext/songsmenu/ape2id3.py:28 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:24 msgid "Go to Bookmark" msgstr "Gå til bogmærke" #: ../quodlibet/ext/songsmenu/bookmarks.py:25 msgid "Manages bookmarks in the selected files." msgstr "Håndtér bogmærker i de valgte filer." #: ../quodlibet/ext/songsmenu/bookmarks.py:64 #: ../quodlibet/qltk/seekbutton.py:245 msgid "_Edit Bookmarks…" msgstr "_Rediger bogmærker…" #: ../quodlibet/ext/songsmenu/bookmarks.py:74 msgid "No Bookmarks" msgstr "Ingen bogmærker" #: ../quodlibet/ext/songsmenu/brainz/__init__.py:25 msgid "MusicBrainz Lookup" msgstr "MusicBrainz-opslag" #: ../quodlibet/ext/songsmenu/brainz/__init__.py:27 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:51 msgid "Only use year for \"date\" tag" msgstr "Brug kun år til \"date\"-tag" #: ../quodlibet/ext/songsmenu/brainz/__init__.py:52 msgid "Write \"_albumartist\" when needed" msgstr "Skriv \"_albumartist\" når det er nødvendigt" #: ../quodlibet/ext/songsmenu/brainz/__init__.py:53 msgid "Write sort tags for artist names" msgstr "Skriv sorterings-tags for kunstnernavne" #: ../quodlibet/ext/songsmenu/brainz/__init__.py:54 msgid "Write _standard MusicBrainz tags" msgstr "Skriv _standard-MusicBrainz-tags" #: ../quodlibet/ext/songsmenu/brainz/__init__.py:55 msgid "Write \"labelid\" tag" msgstr "Skriv \"labelid\"-tag" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:131 msgid "Filename" msgstr "Filnavn" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:132 msgid "Disc" msgstr "Disk" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:133 #: ../quodlibet/ext/songsmenu/replaygain.py:395 #: ../quodlibet/qltk/tracknumbers.py:93 msgid "Track" msgstr "Spor" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:134 msgid "Title" msgstr "Titel" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:135 msgid "Artist" msgstr "Kunstner" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:354 msgid "MusicBrainz lookup" msgstr "MusicBrainz-opslag" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:377 msgid "_Query:" msgstr "_Anmodning:" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:380 msgid "S_earch" msgstr "_Søg" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:393 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:449 msgid "Please enter a query." msgstr "Indtast venligst en anmodning." #: ../quodlibet/ext/songsmenu/brainz/widgets.py:467 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:498 msgid "Error encountered. Please retry." msgstr "Stødte på fejl. Prøv venligst igen." #: ../quodlibet/ext/songsmenu/brainz/widgets.py:474 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:490 msgid "Loading result…" msgstr "Indlæser resultat…" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:477 msgid "No results found." msgstr "Ingen resultater fundet." #: ../quodlibet/ext/songsmenu/console.py:42 msgid "Python Console" msgstr "Python-konsol" #: ../quodlibet/ext/songsmenu/console.py:43 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:87 msgid "Your current working directory is:" msgstr "Din aktuelle arbejdsmappe er:" #: ../quodlibet/ext/songsmenu/cover_download.py:119 msgid "Small" msgstr "Lille" #: ../quodlibet/ext/songsmenu/cover_download.py:120 msgid "Classic" msgstr "Klassisk" #: ../quodlibet/ext/songsmenu/cover_download.py:121 msgid "Large" msgstr "Stor" #: ../quodlibet/ext/songsmenu/cover_download.py:122 msgid "HD" msgstr "HD" #: ../quodlibet/ext/songsmenu/cover_download.py:123 msgid "Full HD" msgstr "Fuld HD" #: ../quodlibet/ext/songsmenu/cover_download.py:124 msgid "WQXGA" msgstr "WQXGA" #: ../quodlibet/ext/songsmenu/cover_download.py:125 msgid "4K UHD" msgstr "4K UHD" #: ../quodlibet/ext/songsmenu/cover_download.py:130 msgid "Cover Art Download" msgstr "Covergrafik-downloader" #: ../quodlibet/ext/songsmenu/cover_download.py:180 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "Indlæser %(source)s - %(dimensions)s…" #: ../quodlibet/ext/songsmenu/cover_download.py:231 #, python-format msgid "" "Nothing found for albums:\n" "<i>%(albums)s</i>.\n" "\n" "Providers used:\n" "<tt>%(providers)s</tt>" 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:234 msgid "No covers found" msgstr "Ingen covere fundet" #: ../quodlibet/ext/songsmenu/cover_download.py:254 #, python-format msgid "%(size)d ✕ %(size)d px" msgstr "%(size)d ✕ %(size)d px" #: ../quodlibet/ext/songsmenu/cover_download.py:267 msgid "Preview size" msgstr "Størrelse for forhåndsvisning" #: ../quodlibet/ext/songsmenu/cover_download.py:276 msgid "Save destination" msgstr "Gemmedestination" #: ../quodlibet/ext/songsmenu/cover_download.py:336 msgid "Download Cover Art" msgstr "Download covergrafik" #: ../quodlibet/ext/songsmenu/cover_download.py:337 msgid "Downloads high-quality album covers using cover plugins." msgstr "Downloader albumcovere i høj kvalitet med cover-plugins." #: ../quodlibet/ext/songsmenu/custom_commands.py:42 msgid "Command" msgstr "Kommando" #: ../quodlibet/ext/songsmenu/custom_commands.py:45 msgid "name" msgstr "navn" #: ../quodlibet/ext/songsmenu/custom_commands.py:45 msgid "The name of this command" msgstr "Navnet på denne kommando" #: ../quodlibet/ext/songsmenu/custom_commands.py:47 msgid "command" msgstr "kommando" #: ../quodlibet/ext/songsmenu/custom_commands.py:47 msgid "The shell command syntax to run" msgstr "Skal-kommando-syntaksen som skal køres" #: ../quodlibet/ext/songsmenu/custom_commands.py:49 msgid "parameter" msgstr "parameter" #: ../quodlibet/ext/songsmenu/custom_commands.py:50 #, 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 "pattern" msgstr "mønster" #: ../quodlibet/ext/songsmenu/custom_commands.py:57 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:62 msgid "unique" msgstr "unik" #: ../quodlibet/ext/songsmenu/custom_commands.py:63 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:66 msgid "max args" msgstr "maks. argumenter" #: ../quodlibet/ext/songsmenu/custom_commands.py:67 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:92 msgid "Input value" msgstr "Input-værdi" #: ../quodlibet/ext/songsmenu/custom_commands.py:93 #, python-format msgid "Value for %s?" msgstr "Værdi til %s?" #: ../quodlibet/ext/songsmenu/custom_commands.py:137 msgid "Custom Commands" msgstr "Brugerdefinerede kommandoer" #: ../quodlibet/ext/songsmenu/custom_commands.py:138 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:191 #: ../quodlibet/ext/songsmenu/custom_commands.py:201 #: ../quodlibet/ext/songsmenu/custom_commands.py:255 msgid "Edit Custom Commands" msgstr "Rediger brugerdefinerede kommandoer" #: ../quodlibet/ext/songsmenu/custom_commands.py:202 msgid "" "Supports QL patterns\n" "eg <tt><~artist~title></tt>" msgstr "" "Understøtter QL-mønstre.\n" "F.eks. <tt><~artist~title></tt>" #: ../quodlibet/ext/songsmenu/custom_commands.py:286 #, python-format msgid "Unable to run custom command %s" msgstr "Kan ikke køre brugerdefineret kommando %s" #: ../quodlibet/ext/songsmenu/duplicates.py:289 #, 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:342 msgid "Collapse / Expand all" msgstr "Sammenfold/udfold alle" #: ../quodlibet/ext/songsmenu/duplicates.py:346 #, python-format msgid "Duplicate key expression is '%s'" msgstr "Duplikeret nøgle-udtryk er '%s'" #: ../quodlibet/ext/songsmenu/duplicates.py:371 msgid "Duplicates Browser" msgstr "Duplikerer browser" #: ../quodlibet/ext/songsmenu/duplicates.py:372 msgid "Finds and displays similarly tagged versions of songs." msgstr "Finder og viser lignende taggede versioner af sange." #: ../quodlibet/ext/songsmenu/duplicates.py:410 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:412 msgid "_Group duplicates by:" msgstr "_Gruppér duplikater efter:" #: ../quodlibet/ext/songsmenu/duplicates.py:417 msgid "Duplicate Key" msgstr "Duplikér nøgle" #: ../quodlibet/ext/songsmenu/duplicates.py:422 msgid "Remove _Whitespace" msgstr "Fjern _blanktegn" #: ../quodlibet/ext/songsmenu/duplicates.py:423 msgid "Remove _Diacritics" msgstr "Fjern _diakritiske" #: ../quodlibet/ext/songsmenu/duplicates.py:424 msgid "Remove _Punctuation" msgstr "Fjern _tegnsætning" #: ../quodlibet/ext/songsmenu/duplicates.py:425 msgid "Case _Insensitive" msgstr "Der skelnes _ikke mellem store og små bogstaver" #: ../quodlibet/ext/songsmenu/duplicates.py:433 msgid "Matching options" msgstr "Sammenhørende valgmuligheder" #. Create a dialog. #: ../quodlibet/ext/songsmenu/editplaycount.py:20 #: ../quodlibet/ext/songsmenu/editplaycount.py:42 msgid "Edit Playcount" msgstr "Rediger playcount" #: ../quodlibet/ext/songsmenu/editplaycount.py:21 msgid "" "Edit a song's ~#playcount and ~#skipcount.\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's ~#playcount to 0, the ~#lastplayed and ~#laststarted " "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:69 msgid "Play Count" msgstr "Antal afspilninger" #: ../quodlibet/ext/songsmenu/editplaycount.py:70 msgid "Skip Count" msgstr "Antal overspring" #: ../quodlibet/ext/songsmenu/embedded.py:25 msgid "Edit Embedded Images" msgstr "Rediger indlejrede billeder" #: ../quodlibet/ext/songsmenu/embedded.py:26 msgid "Removes or replaces embedded images." msgstr "Fjerner eller erstatter indlejret billeder." #: ../quodlibet/ext/songsmenu/embedded.py:79 msgid "_Remove all Images" msgstr "_Fjern alle billeder" #: ../quodlibet/ext/songsmenu/embedded.py:83 msgid "_Embed Current Image" msgstr "_Indlejr aktuelle billede" #: ../quodlibet/ext/songsmenu/exact_rating.py:24 msgid "Set Exact Rating" msgstr "Sæt præcist bedømmelse" #: ../quodlibet/ext/songsmenu/exact_rating.py:25 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:37 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:81 msgid "Filter on Any Tag" msgstr "Filtrér efter vilkårlig tag" #: ../quodlibet/ext/songsmenu/filterall.py:82 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:20 msgid "Filter on Directory" msgstr "Filtrér efter mappe" #: ../quodlibet/ext/songsmenu/filterbrowser.py:21 msgid "Filters on directory in a new browser window." msgstr "Filtrerer efter mappe i et nyt browservindue." #: ../quodlibet/ext/songsmenu/fingerprint/__init__.py:31 msgid "Acoustic Fingerprint Lookup" msgstr "Akustisk fingeraftryk-opslag" #: ../quodlibet/ext/songsmenu/fingerprint/__init__.py:32 msgid "Looks up song metadata through acoustic fingerprinting." msgstr "Foretager opslag af sangens metadata gennem akustisk fingeraftryk." #: ../quodlibet/ext/songsmenu/fingerprint/__init__.py:52 #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:42 msgid "Submit Acoustic Fingerprints" msgstr "Indsend akustisk fingeraftryk" #: ../quodlibet/ext/songsmenu/fingerprint/__init__.py:53 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:61 msgid "API Key Missing" msgstr "API-nøgle mangler" #: ../quodlibet/ext/songsmenu/fingerprint/__init__.py:62 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:76 msgid "Request API key" msgstr "Anmod om API-nøgle" #: ../quodlibet/ext/songsmenu/fingerprint/__init__.py:83 msgid "API _key:" msgstr "API-_nøgle:" #: ../quodlibet/ext/songsmenu/fingerprint/__init__.py:90 msgid "AcoustID Web Service" msgstr "AcoustID-webtjeneste" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:37 msgid "Queued" msgstr "Sat i kø" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:39 msgid "Analyzing" msgstr "Analyserer" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:41 msgid "Lookup" msgstr "Opslag" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:117 msgid "Write" msgstr "Skriv" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:145 msgid "Status" msgstr "Status" #. Translators: album release ID #: ../quodlibet/ext/songsmenu/fingerprint/search.py:159 msgid "Release" msgstr "Udgivelse" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:291 msgid "Write MusicBrainz tags" msgstr "Skriv MusicBrainz-tags" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:297 msgid "Group by directory" msgstr "Gruppér efter mappe" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:306 msgid "Album Mode" msgstr "Album-tilstand" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:308 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:50 msgid "Generating fingerprints:" msgstr "Genererer fingeraftryk:" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:66 msgid "_Details" msgstr "_Detaljer" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:89 msgid "_Submit" msgstr "_Indsend" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:119 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:122 msgid "Fingerprints:" msgstr "Fingeraftryk:" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs with MBIDs:" msgstr "Sange med MBID'er:" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:126 msgid "Songs with sufficient tags:" msgstr "Sange med tilstrækkelige tags:" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:128 msgid "Songs to submit:" msgstr "Sange som skal indsendes:" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:166 #, 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:182 msgid "Submitting fingerprints:" msgstr "Indsender fingeraftryk:" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:190 msgid "Submitting…" msgstr "Indsender…" #: ../quodlibet/ext/songsmenu/forcewrite.py:18 msgid "Update Tags in Files" msgstr "Opdater tags i filer" #: ../quodlibet/ext/songsmenu/forcewrite.py:19 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:67 ../quodlibet/ext/songsmenu/html.py:77 msgid "Export to HTML" msgstr "Eksportér til HTML" #: ../quodlibet/ext/songsmenu/html.py:68 msgid "Exports the selected song list to HTML." msgstr "Eksporterer den valgte sangliste til HTML." #: ../quodlibet/ext/songsmenu/ifp.py:22 msgid "Send to iFP" msgstr "Send til iFP" #: ../quodlibet/ext/songsmenu/ifp.py:23 msgid "Uploads songs to an iRiver iFP device." msgstr "Uploader sange til en iRiver iFP-enhed." #: ../quodlibet/ext/songsmenu/ifp.py:31 msgid "No iFP device found" msgstr "Ingen iFP-enhed fundet" #: ../quodlibet/ext/songsmenu/ifp.py:32 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:40 #, python-format msgid "Uploading %(current)d/%(total)d" msgstr "Uploader %(current)d/%(total)d" #: ../quodlibet/ext/songsmenu/ifp.py:63 msgid "Error uploading" msgstr "Fejl under upload" #: ../quodlibet/ext/songsmenu/ifp.py:64 #, python-format msgid "" "Unable to upload <b>%s</b>. 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/importexport.py:60 msgid "Export Metadata" msgstr "Eksportér metadata" #: ../quodlibet/ext/songsmenu/importexport.py:61 msgid "Exports metadata of selected songs as a .tags file." msgstr "Eksporterer metadata af valgte sange som en .tags-fil." #: ../quodlibet/ext/songsmenu/importexport.py:105 msgid "Import Metadata" msgstr "Importér metadata" #: ../quodlibet/ext/songsmenu/importexport.py:106 msgid "Imports metadata for selected songs from a .tags file." msgstr "Importerer metadata til valgte sange from en .tags-fil." #: ../quodlibet/ext/songsmenu/k3b.py:24 msgid "Burn CD" msgstr "Brænd CD" #: ../quodlibet/ext/songsmenu/k3b.py:25 msgid "Burns CDs with K3b, Brasero or xfburn." msgstr "Brænder CD'er med K3b, Brasero eller xfburn." #: ../quodlibet/ext/songsmenu/lastfmsync.py:98 msgid "Updating chart list." msgstr "Opdaterer chartliste." #. No charts to fetch, no update scheduled. #: ../quodlibet/ext/songsmenu/lastfmsync.py:117 msgid "Already up-to-date." msgstr "Allerede up-to-date." #: ../quodlibet/ext/songsmenu/lastfmsync.py:125 #, python-format msgid "Fetching chart for week of %s." msgstr "Henter chart for uge af %s." #: ../quodlibet/ext/songsmenu/lastfmsync.py:147 msgid "Sync complete." msgstr "Synkronisering fuldført." #: ../quodlibet/ext/songsmenu/lastfmsync.py:153 msgid "Error during sync" msgstr "Fejl under synkronisering" #: ../quodlibet/ext/songsmenu/lastfmsync.py:218 #: ../quodlibet/ext/songsmenu/lastfmsync.py:248 msgid "Last.fm Sync" msgstr "Last.fm-synkronisering" #: ../quodlibet/ext/songsmenu/lastfmsync.py:249 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:302 msgid "_Username:" msgstr "_Brugernavn:" #: ../quodlibet/ext/songsmenu/makesorttags.py:37 msgid "Create Sort Tags" msgstr "Opret sorterings-tags" #: ../quodlibet/ext/songsmenu/makesorttags.py:38 msgid "Converts album and artist names to sort names, poorly." msgstr "Konverterer album- og kunstnernavne til sorteringsnavne, dårligt." #. Create a dialog. #: ../quodlibet/ext/songsmenu/migratemetadata.py:37 #: ../quodlibet/ext/songsmenu/migratemetadata.py:46 msgid "Migrate Metadata" msgstr "Migrér metadata" #: ../quodlibet/ext/songsmenu/migratemetadata.py:40 msgid "Copies the quodlibet-specific metadata between songs." msgstr "Kopierer de quodlibet-specifikke metadata mellem sange." #: ../quodlibet/ext/songsmenu/migratemetadata.py:53 msgid "_Copy" msgstr "_Kopiér" #: ../quodlibet/ext/songsmenu/migratemetadata.py:55 msgid "_Paste" msgstr "_Indsæt" #. Create the tag table. #: ../quodlibet/ext/songsmenu/migratemetadata.py:65 msgid "Information to copy/paste" msgstr "Information til kopiér/indsæt" #. Create the indexing box. #: ../quodlibet/ext/songsmenu/migratemetadata.py:87 msgid "Map tracks by disc and track number" msgstr "Kortlæg spor efter disk- og spornummer" #: ../quodlibet/ext/songsmenu/migratemetadata.py:88 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." #: ../quodlibet/ext/songsmenu/migratemetadata.py:104 #, python-format 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." #: ../quodlibet/ext/songsmenu/playlist.py:32 msgid "Export as Playlist" msgstr "Eksportér som spilleliste" #: ../quodlibet/ext/songsmenu/playlist.py:33 msgid "Exports songs to an M3U or PLS playlist." msgstr "Eksporterer sange til en M3U- eller PLS-spilleliste." #: ../quodlibet/ext/songsmenu/playlist.py:78 msgid "Use relative paths" msgstr "Brug relative stier" #: ../quodlibet/ext/songsmenu/playlist.py:78 msgid "Use absolute paths" msgstr "Brug absolutte stier" #: ../quodlibet/ext/songsmenu/playlist.py:133 msgid "Unable to export playlist" msgstr "Kan ikke eksportere spilleliste" #: ../quodlibet/ext/songsmenu/playlist.py:134 #, python-format msgid "Writing to <b>%s</b> failed." msgstr "Skrivning til <b>%s</b> fejlede." #. Translators: Plugin name #: ../quodlibet/ext/songsmenu/refresh.py:23 msgid "Rescan Songs" msgstr "Genskan sange" #: ../quodlibet/ext/songsmenu/refresh.py:24 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:32 msgid "Rescan songs" msgstr "Genskan sange" #: ../quodlibet/ext/songsmenu/replaygain.py:353 msgid "ReplayGain Analyzer" msgstr "ReplayGain-analysator" #: ../quodlibet/ext/songsmenu/replaygain.py:409 msgid "Progress" msgstr "Forløb" #: ../quodlibet/ext/songsmenu/replaygain.py:424 msgid "Gain" msgstr "Forstærkning" #: ../quodlibet/ext/songsmenu/replaygain.py:439 msgid "Peak" msgstr "Spidspunkt" #: ../quodlibet/ext/songsmenu/replaygain.py:454 #, python-format msgid "There is <b>%(to-process)s</b> album to update (of %(all)s)" msgid_plural "There are <b>%(to-process)s</b> 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:570 msgid "Replay Gain" msgstr "Replay Gain" #: ../quodlibet/ext/songsmenu/replaygain.py:571 msgid "" "Analyzes and updates ReplayGain 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:609 msgid "always" msgstr "altid" #: ../quodlibet/ext/songsmenu/replaygain.py:610 msgid "if <b>any</b> RG tags are missing" msgstr "hvis <b>nogen</b> RG-tags mangler" #: ../quodlibet/ext/songsmenu/replaygain.py:612 msgid "if <b>album</b> RG tags are missing" msgstr "hvis <b>album</b> RG-tags mangler" #: ../quodlibet/ext/songsmenu/replaygain.py:629 msgid "_Process albums:" msgstr "_Behandl album:" #. Server settings Frame #: ../quodlibet/ext/songsmenu/replaygain.py:641 msgid "Existing Tags" msgstr "Eksisterende tags" #: ../quodlibet/ext/songsmenu/splitting.py:32 msgid "Split Tags" msgstr "Opdel tags" #: ../quodlibet/ext/songsmenu/splitting.py:33 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:57 msgid "Split Album" msgstr "Opdel album" #: ../quodlibet/ext/songsmenu/splitting.py:58 msgid "Split out disc number." msgstr "Opdel disknummer." #: ../quodlibet/ext/songsmenu/tapbpm.py:24 #: ../quodlibet/ext/songsmenu/tapbpm.py:33 #: ../quodlibet/ext/songsmenu/tapbpm.py:62 msgid "n/a" msgstr "utilgængelig" #. TRANSLATORS: BPM mean "beats per minute" #: ../quodlibet/ext/songsmenu/tapbpm.py:32 msgid "BPM:" msgstr "BPM:" #: ../quodlibet/ext/songsmenu/tapbpm.py:37 msgid "Reset" msgstr "Nulstil" #: ../quodlibet/ext/songsmenu/tapbpm.py:43 msgid "Tap" msgstr "Tryk" #: ../quodlibet/ext/songsmenu/tapbpm.py:178 #: ../quodlibet/ext/songsmenu/tapbpm.py:185 msgid "Tap BPM" msgstr "Tap BPM" #: ../quodlibet/ext/songsmenu/tapbpm.py:179 msgid "Tap BPM for the selected song." msgstr "Tap BPM for den valgt sang." #: ../quodlibet/ext/songsmenu/website_search.py:38 msgid "Website Search" msgstr "Websted-søgning" #: ../quodlibet/ext/songsmenu/website_search.py:39 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern-example)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:81 msgid "Search URL patterns" msgstr "Søger i URL-mønstre" #: ../quodlibet/ext/songsmenu/website_search.py:91 msgid "Edit search URLs" msgstr "Rediger søge-URL'er" #. Add link to editor #: ../quodlibet/ext/songsmenu/website_search.py:117 msgid "Configure Searches…" msgstr "Konfigurér søgninger…" #: ../quodlibet/ext/songsmenu/wikipedia.py:48 #, python-format msgid "Search at %(website)s" msgstr "Søg hos %(website)s" #: ../quodlibet/ext/songsmenu/wikipedia.py:65 msgid "Search Artist in Wikipedia" msgstr "Søg efter kunstner på Wikipedia" #: ../quodlibet/ext/songsmenu/wikipedia.py:66 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." #: ../quodlibet/ext/songsmenu/wikipedia.py:73 msgid "Search Album in Wikipedia" msgstr "Søg efter album på Wikipedia" #: ../quodlibet/ext/songsmenu/wikipedia.py:74 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." #: ../quodlibet/ext/songsmenu/wikipedia.py:81 msgid "Search Composer in Wikipedia" msgstr "Søg efter komponist på Wikipedia" #: ../quodlibet/ext/songsmenu/wikipedia.py:82 msgid "" "Opens a browser window with the Wikipedia article on the playing song's " "composer." msgstr "" "Åbner et browservindue med Wikipedia-artiklen om komponisten af sangen som " "afspilles." #. then (try to) load all new files #: ../quodlibet/library/libraries.py:654 ../quodlibet/library/libraries.py:664 #: ../quodlibet/library/libraries.py:730 ../quodlibet/library/libraries.py:749 #: ../quodlibet/qltk/information.py:273 ../quodlibet/qltk/prefs.py:650 #: ../quodlibet/util/library.py:124 msgid "Library" msgstr "Bibliotek" #: ../quodlibet/library/libraries.py:654 msgid "Checking mount points" msgstr "Tjekker monteringspunkter" #: ../quodlibet/library/libraries.py:664 msgid "Scanning library" msgstr "Skanner bibliotek" #: ../quodlibet/library/libraries.py:729 #, python-format msgid "Scanning %s" msgstr "Skanner %s" #: ../quodlibet/library/libraries.py:749 msgid "Loading files" msgstr "Indlæser filer" #: ../quodlibet/main.py:51 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:38 msgid "List tags" msgstr "Vis tags" #: ../quodlibet/operon/commands.py:43 ../quodlibet/operon/commands.py:82 #: ../quodlibet/operon/commands.py:462 msgid "Print terse output" msgstr "Vis kortfattet output" #: ../quodlibet/operon/commands.py:45 ../quodlibet/operon/commands.py:84 #: ../quodlibet/operon/commands.py:464 #, 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:48 ../quodlibet/operon/commands.py:87 msgid "Also list programmatic tags" msgstr "Vis også programmatiske tags" #: ../quodlibet/operon/commands.py:52 ../quodlibet/operon/commands.py:130 #: ../quodlibet/operon/commands.py:221 ../quodlibet/operon/commands.py:294 #: ../quodlibet/operon/commands.py:337 ../quodlibet/operon/commands.py:341 #: ../quodlibet/operon/commands.py:392 ../quodlibet/operon/commands.py:395 #: ../quodlibet/operon/commands.py:434 ../quodlibet/operon/commands.py:469 #: ../quodlibet/operon/commands.py:509 ../quodlibet/operon/commands.py:544 #: ../quodlibet/operon/commands.py:586 msgid "Not enough arguments" msgstr "Ikke nok argumenter" #: ../quodlibet/operon/commands.py:54 ../quodlibet/operon/commands.py:91 #: ../quodlibet/operon/commands.py:132 ../quodlibet/operon/commands.py:223 #: ../quodlibet/operon/commands.py:471 msgid "Too many arguments" msgstr "For mange argumenter" #: ../quodlibet/operon/commands.py:57 ../quodlibet/operon/commands.py:93 #: ../quodlibet/operon/commands.py:476 ../quodlibet/qltk/data_editors.py:354 msgid "Description" msgstr "Beskrivelse" #: ../quodlibet/operon/commands.py:57 ../quodlibet/operon/commands.py:476 #: ../quodlibet/qltk/edittags.py:455 msgid "Value" msgstr "Værdi" #: ../quodlibet/operon/commands.py:77 msgid "List all common tags" msgstr "Vis alle almindelige tags" #: ../quodlibet/operon/commands.py:119 msgid "Copy tags from one file to another" msgstr "Kopiér tags fra en fil til en anden" #: ../quodlibet/operon/commands.py:124 ../quodlibet/operon/commands.py:165 #: ../quodlibet/operon/commands.py:290 ../quodlibet/operon/commands.py:325 #: ../quodlibet/operon/commands.py:385 msgid "Show changes, don't apply them" msgstr "Vis ændringer, anvend dem ikke" #: ../quodlibet/operon/commands.py:126 msgid "Skip tags that can't be written" msgstr "Spring over tags som ikke kan skrives" #: ../quodlibet/operon/commands.py:146 #, python-format msgid "Can't copy tag %r to file: %r" msgstr "Kan ikke kopiere tagget %r til filen: %r" #: ../quodlibet/operon/commands.py:158 msgid "Edit tags in a text editor" msgstr "Rediger tags i et tekstredigeringsprogram" #: ../quodlibet/operon/commands.py:252 msgid "Editing aborted" msgstr "Redigering afbrudt" #: ../quodlibet/operon/commands.py:256 #, python-format msgid "Starting text editor '%(editor-name)s' failed." msgstr "Start af tekstredigeringsprogrammet '%(editor-name)s' fejlede." #: ../quodlibet/operon/commands.py:261 msgid "No changes detected" msgstr "Ingen ændringer detekteret" #: ../quodlibet/operon/commands.py:285 msgid "Set a tag and remove existing values" msgstr "Sæt et tag og fjern eksisterende værdier" #: ../quodlibet/operon/commands.py:305 ../quodlibet/operon/commands.py:445 #: ../quodlibet/operon/commands.py:677 #, python-format msgid "Can not set %r" msgstr "Kan ikke sætte %r" #: ../quodlibet/operon/commands.py:320 msgid "Remove tags" msgstr "Fjern tags" #: ../quodlibet/operon/commands.py:327 ../quodlibet/operon/commands.py:387 msgid "Value is a regular expression" msgstr "Værdi er et regulært udtryk" #: ../quodlibet/operon/commands.py:329 msgid "Remove all tags" msgstr "Fjern alle tags" #: ../quodlibet/operon/commands.py:333 msgid "Can't combine '--all' with '--regexp'" msgstr "Kan ikke kombinere '--all' med '--regexp'" #: ../quodlibet/operon/commands.py:367 #, python-format msgid "Can't remove %r from %r" msgstr "Kan ikke fjerne %r fra %r" #: ../quodlibet/operon/commands.py:380 msgid "Remove a tag value" msgstr "Fjern en tag-værdi" #: ../quodlibet/operon/commands.py:429 msgid "Add a tag value" msgstr "Tilføj en tag-værdi" #: ../quodlibet/operon/commands.py:457 msgid "List file information" msgstr "Vis filinformation" #: ../quodlibet/operon/commands.py:503 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:516 #, python-format msgid "Failed to load image file: %r" msgstr "Kunne ikke indlæse billedfilen: %r" #: ../quodlibet/operon/commands.py:523 ../quodlibet/operon/commands.py:552 #, 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:539 msgid "Remove all embedded images" msgstr "Fejl alle indlejrede billeder" #: ../quodlibet/operon/commands.py:569 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "Udtræk indlejrede billeder til %(filepath)s" #: ../quodlibet/operon/commands.py:581 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:640 msgid "Rename files based on tags" msgstr "Omdøb filer baseret på tags" #: ../quodlibet/operon/commands.py:655 msgid "Fill tags based on the file path" msgstr "Udfyld tags baseret på filstien" #: ../quodlibet/operon/commands.py:705 ../quodlibet/qltk/information.py:310 #: ../quodlibet/qltk/properties.py:85 ../quodlibet/qltk/renamefiles.py:226 #: ../quodlibet/qltk/tagsfrompath.py:230 ../quodlibet/qltk/tracknumbers.py:80 msgid "File" msgstr "Fil" #: ../quodlibet/operon/commands.py:713 msgid "Fill tracknumbers for all files" msgstr "Udfyld spornumre for alle filer" #: ../quodlibet/operon/commands.py:732 msgid "Print tags based on the given pattern" msgstr "Vis tags baseret på det givne mønster" #: ../quodlibet/operon/commands.py:769 msgid "Display help information" msgstr "Viser hjælpinformation" #: ../quodlibet/operon/util.py:43 #, 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:31 msgid "_Unknown" msgstr "_Ukendt" #: ../quodlibet/order/__init__.py:143 msgid "In Order" msgstr "I rækkefølge" #: ../quodlibet/order/__init__.py:144 msgid "_In Order" msgstr "_I rækkefølge" #: ../quodlibet/order/reorder.py:24 msgid "Random" msgstr "Tilfældig" #: ../quodlibet/order/reorder.py:25 ../quodlibet/qltk/queue.py:123 msgid "_Random" msgstr "_Tilfældig" #: ../quodlibet/order/reorder.py:42 ../quodlibet/order/reorder.py:43 msgid "Prefer higher rated" msgstr "Foretræk højere bedømmelse" #: ../quodlibet/order/repeat.py:44 ../quodlibet/order/repeat.py:45 msgid "Repeat this track" msgstr "Gentag dette spor" #: ../quodlibet/order/repeat.py:58 ../quodlibet/order/repeat.py:59 msgid "Repeat all" msgstr "Gentag alle" #: ../quodlibet/order/repeat.py:74 ../quodlibet/order/repeat.py:75 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:454 msgid "Could not create GStreamer pipeline" msgstr "Kunne ikke oprette GStreamer-pipeline" #: ../quodlibet/player/gstbe/player.py:653 msgid "No GStreamer element found to handle media format" msgstr "Intet GStreamer-element fundet til håndtering af medieformat" #: ../quodlibet/player/gstbe/player.py:654 #, python-format msgid "Media format: %(format-description)s" msgstr "Medieformat: %(format-description)s" #: ../quodlibet/player/gstbe/plugins.py:36 #, 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 msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. In case 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:37 msgid "_Output pipeline:" msgstr "_Output-pipeline:" #: ../quodlibet/player/gstbe/prefs.py:44 #, python-format msgid "%.1f seconds" msgstr "%.1f sekunder" #: ../quodlibet/player/gstbe/prefs.py:58 msgid "_Buffer duration:" msgstr "_Bufferens varighed:" #: ../quodlibet/player/gstbe/prefs.py:67 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/util.py:103 msgid "No GStreamer audio sink found" msgstr "Intet GStreamer-lydsink fundet" #: ../quodlibet/player/gstbe/util.py:122 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:63 #, 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:72 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "Kunne ikke finde GStreamer-element '{element}'." #: ../quodlibet/plugins/playlist.py:24 #, 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:28 ../quodlibet/qltk/songsmenu.py:57 #: ../quodlibet/qltk/songsmenu.py:68 msgid "_Run Plugin" msgstr "_Kør plugin" #. Translators: Refers to the beginning of the playing song. #: ../quodlibet/qltk/bookmarks.py:28 msgid "Beginning" msgstr "Begyndelse" #: ../quodlibet/qltk/bookmarks.py:39 ../quodlibet/qltk/bookmarks.py:79 msgid "N/A" msgstr "Utilgængelig" #: ../quodlibet/qltk/bookmarks.py:84 msgid "Time" msgstr "Tidspunkt" #: ../quodlibet/qltk/bookmarks.py:90 ../quodlibet/qltk/bookmarks.py:125 msgid "Bookmark Name" msgstr "Bogmærkenavn" #: ../quodlibet/qltk/bookmarks.py:123 msgid "MM:SS" msgstr "MM:SS" #: ../quodlibet/qltk/bookmarks.py:211 ../quodlibet/qltk/information.py:133 msgid "Bookmarks" msgstr "Bogmærker" #: ../quodlibet/qltk/browser.py:57 msgid "_Filters" msgstr "_Filtrér" #: ../quodlibet/qltk/browser.py:58 msgid "Recently _Played" msgstr "Nyligt _afspillet" #: ../quodlibet/qltk/browser.py:60 msgid "Recently _Added" msgstr "Nyligt _tilføjet" #: ../quodlibet/qltk/browser.py:62 msgid "_Top 40" msgstr "_Top 40" #: ../quodlibet/qltk/browser.py:64 msgid "All _Songs" msgstr "Alle _sange" #: ../quodlibet/qltk/browser.py:72 msgid "On Current _Genre(s)" msgstr "Efter aktuelle _genre(r)" #: ../quodlibet/qltk/browser.py:73 msgid "On Current _Artist(s)" msgstr "Efter aktuelle _kunstner(e)" #: ../quodlibet/qltk/browser.py:74 msgid "On Current Al_bum" msgstr "Efter aktuelle _album" #: ../quodlibet/qltk/browser.py:82 msgid "Random _Genre" msgstr "Tilfældig _genre" #: ../quodlibet/qltk/browser.py:83 msgid "Random _Artist" msgstr "Tilfældig _kunstner" #: ../quodlibet/qltk/browser.py:84 msgid "Random Al_bum" msgstr "Tilfældigt _album" #: ../quodlibet/qltk/browser.py:97 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:41 msgid "_Name:" msgstr "_Navn:" #: ../quodlibet/qltk/cbes.py:49 ../quodlibet/qltk/edittags.py:312 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:118 #, python-format msgid "New %s" msgstr "Ny %s" #: ../quodlibet/qltk/data_editors.py:217 msgid "(unknown)" msgstr "(ukendt)" #: ../quodlibet/qltk/data_editors.py:346 msgid "Tag expression" msgstr "Tag-udtryk" #: ../quodlibet/qltk/data_editors.py:373 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:374 msgid "Enter new tag" msgstr "Indtast nyt tag" #: ../quodlibet/qltk/delete.py:38 msgid "Files:" msgstr "Filer:" #: ../quodlibet/qltk/delete.py:64 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:73 msgid "The selected files will be deleted from disk." msgstr "De valgte filer vil blive slettet fra disken." #: ../quodlibet/qltk/delete.py:77 #, 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:92 msgid "_Delete Files" msgstr "_Slet filer" #: ../quodlibet/qltk/delete.py:107 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:116 msgid "The selected files will be moved to the trash." msgstr "De valgte filer vil blive flyttet til papirkurven." #: ../quodlibet/qltk/delete.py:121 #, 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:135 ../quodlibet/qltk/delete.py:142 msgid "_Move to Trash" msgstr "_Flyt til papirkurv" #: ../quodlibet/qltk/delete.py:153 ../quodlibet/qltk/delete.py:188 #, python-format msgid "Moving %(current)d/%(total)d." msgstr "Flyttede %(current)d/%(total)d." #: ../quodlibet/qltk/delete.py:174 ../quodlibet/qltk/delete.py:206 msgid "Unable to move to trash" msgstr "Kan ikke flytte til papirkurv" #: ../quodlibet/qltk/delete.py:175 ../quodlibet/qltk/delete.py:207 msgid "Moving one or more files to the trash failed." msgstr "Flytning af en eller flere filer til papirkurven fejlede." #: ../quodlibet/qltk/delete.py:217 ../quodlibet/qltk/delete.py:251 #, python-format msgid "Deleting %(current)d/%(total)d." msgstr "Sletter %(current)d/%(total)d." #: ../quodlibet/qltk/delete.py:237 ../quodlibet/qltk/delete.py:270 msgid "Unable to delete files" msgstr "Kan ikke slette filer" #: ../quodlibet/qltk/delete.py:238 ../quodlibet/qltk/delete.py:271 msgid "Deleting one or more files failed." msgstr "Sletning af en eller flere filer fejlede." #: ../quodlibet/qltk/edittags.py:64 ../quodlibet/qltk/edittags.py:75 #, 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:68 ../quodlibet/qltk/edittags.py:72 #, 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:194 msgid "Split into _Multiple Values" msgstr "Opdel i _flere værdier" #: ../quodlibet/qltk/edittags.py:212 msgid "Split Disc out of _Album" msgstr "Opdel disk ud af _album" #: ../quodlibet/qltk/edittags.py:229 msgid "Split _Version out of Title" msgstr "Opdel _version ud af titel" #: ../quodlibet/qltk/edittags.py:260 msgid "Split Arranger out of Ar_tist" msgstr "Opdel arrangør ud af _kunstner" #: ../quodlibet/qltk/edittags.py:265 msgid "Split _Performer out of Artist" msgstr "Opdel _performer ud af kunstner" #: ../quodlibet/qltk/edittags.py:271 msgid "Split _Performer out of Title" msgstr "Opdel _performer ud af titel" #: ../quodlibet/qltk/edittags.py:277 msgid "Split _Originalartist out of Title" msgstr "Opdel _original kunstner ud af titel" #: ../quodlibet/qltk/edittags.py:284 msgid "Add a Tag" msgstr "Tilføj et tag" #: ../quodlibet/qltk/edittags.py:303 msgid "_Tag:" msgstr "_Tag:" #: ../quodlibet/qltk/edittags.py:405 msgid "Edit Tags" msgstr "Rediger tags" #: ../quodlibet/qltk/edittags.py:478 msgid "Show _programmatic tags" msgstr "Vis _programmatiske tags" #: ../quodlibet/qltk/edittags.py:479 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" #. Translators: Revert button in the tag editor #: ../quodlibet/qltk/edittags.py:509 msgctxt "edittags" msgid "_Revert" msgstr "_Tilbagefør" #. Translators: Save button in the tag editor #: ../quodlibet/qltk/edittags.py:514 msgctxt "edittags" msgid "_Save" msgstr "_Gem" #: ../quodlibet/qltk/edittags.py:660 msgid "Unable to add tag" msgstr "Kan ikke tilføje tag" #: ../quodlibet/qltk/edittags.py:661 #, python-format msgid "Unable to add <b>%s</b>" msgstr "Kan ikke tilføje <b>%s</b>" #: ../quodlibet/qltk/edittags.py:663 #, python-format msgid "" "The files currently selected do not support multiple values for <b>%s</b>." msgstr "De valgte filer understøtter ikke flere værdier for <b>%s</b>." #. Can't add the new tag. #: ../quodlibet/qltk/edittags.py:690 ../quodlibet/qltk/edittags.py:858 #: ../quodlibet/qltk/tagsfrompath.py:213 ../quodlibet/util/__init__.py:506 #: ../quodlibet/util/tags.py:245 msgid "Invalid tag" msgstr "Ugyldigt tag" #: ../quodlibet/qltk/edittags.py:691 ../quodlibet/qltk/edittags.py:859 #: ../quodlibet/qltk/tagsfrompath.py:214 #, python-format msgid "" "Invalid tag <b>%s</b>\n" "\n" "The files currently selected do not support editing this tag." msgstr "" "Ugyldigt tag <b>%s</b>\n" "\n" "De valgte filer understøtter ikke redigering af dette tag." #: ../quodlibet/qltk/edittags.py:829 ../quodlibet/qltk/edittags.py:870 msgid "Invalid value" msgstr "Ugyldig værdi" #: ../quodlibet/qltk/edittags.py:830 ../quodlibet/qltk/edittags.py:871 #, python-format msgid "" "Invalid value: <b>%(value)s</b>\n" "\n" "%(error)s" msgstr "" "Ugyldig værdi: <b>%(value)s</b>\n" "\n" "%(error)s" #: ../quodlibet/qltk/_editutils.py:30 msgid "Tag may not be accurate" msgstr "Tag er måske ikke korrekt" #: ../quodlibet/qltk/_editutils.py:33 #, 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:49 msgid "Unable to save song" msgstr "Kan ikke gemme sang" #: ../quodlibet/qltk/_editutils.py:52 #, 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:96 #: ../quodlibet/qltk/quodlibetwindow.py:1057 msgid "_About" msgstr "_Om" #: ../quodlibet/qltk/exfalsowindow.py:100 #: ../quodlibet/qltk/quodlibetwindow.py:1079 msgid "_Check for Updates…" msgstr "_Søg efter opdateringer…" #: ../quodlibet/qltk/exfalsowindow.py:106 #: ../quodlibet/qltk/quodlibetwindow.py:1012 ../quodlibet/qltk/songsmenu.py:291 msgid "_Plugins" msgstr "_Plugins" #: ../quodlibet/qltk/exfalsowindow.py:268 #, 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/exfalsowindow.py:290 ../quodlibet/qltk/prefs.py:609 msgid "Split _on:" msgstr "_Opdel ved:" #: ../quodlibet/qltk/exfalsowindow.py:296 ../quodlibet/qltk/prefs.py:624 msgid "Tag Editing" msgstr "Tag-redigering" #: ../quodlibet/qltk/filesel.py:211 msgid "Folders" msgstr "Mapper" #: ../quodlibet/qltk/filesel.py:266 msgid "_New Folder…" msgstr "_Ny mappe…" #: ../quodlibet/qltk/filesel.py:275 msgid "_Select all Sub-Folders" msgstr "_Vælg alle undermapper" #: ../quodlibet/qltk/filesel.py:381 msgid "New Folder" msgstr "Ny mappe" #: ../quodlibet/qltk/filesel.py:381 msgid "Enter a name for the new folder:" msgstr "Indtast et navn til den nye mappe:" #: ../quodlibet/qltk/filesel.py:394 msgid "Unable to create folder" msgstr "Kan ikke oprette mappe" #: ../quodlibet/qltk/filesel.py:411 msgid "Unable to delete folder" msgstr "Kan ikke slette mappe" #: ../quodlibet/qltk/filesel.py:526 ../quodlibet/qltk/pluginwin.py:168 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:172 #: ../quodlibet/qltk/information.py:453 #, python-format msgid "Disc %s" msgstr "Disk %s" #: ../quodlibet/qltk/info.py:45 ../quodlibet/qltk/information.py:177 #, python-format msgid "Track %s" msgstr "Spor %s" #: ../quodlibet/qltk/info.py:109 msgid "_Edit Display…" msgstr "_Rediger visning…" #: ../quodlibet/qltk/information.py:107 msgid "No songs are selected." msgstr "Ingen sang er valgt." #: ../quodlibet/qltk/information.py:108 msgid "No Songs" msgstr "Ingen sange" #: ../quodlibet/qltk/information.py:123 ../quodlibet/qltk/information.py:343 #: ../quodlibet/qltk/information.py:476 ../quodlibet/qltk/information.py:544 msgid "Information" msgstr "Information" #: ../quodlibet/qltk/information.py:128 msgid "Lyrics" msgstr "Sangtekster" #: ../quodlibet/qltk/information.py:189 ../quodlibet/qltk/information.py:401 #, python-format msgid "Produced by %s" msgstr "Produceret af %s" #: ../quodlibet/qltk/information.py:204 ../quodlibet/util/tags.py:87 msgid "artist" msgstr "kunstner" #: ../quodlibet/qltk/information.py:205 ../quodlibet/qltk/information.py:574 #: ../quodlibet/util/tags.py:87 msgid "artists" msgstr "kunstnere" #. for backwards compat #: ../quodlibet/qltk/information.py:226 ../quodlibet/util/tags.py:98 #: ../quodlibet/util/tags.py:126 msgid "performers" msgstr "performere" #: ../quodlibet/qltk/information.py:240 ../quodlibet/qltk/information.py:253 #: ../quodlibet/qltk/songlistcolumns.py:278 msgid "Never" msgstr "Aldrig" #: ../quodlibet/qltk/information.py:241 #, 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:259 ../quodlibet/util/tags.py:151 msgid "added" msgstr "tilføjet" #: ../quodlibet/qltk/information.py:260 ../quodlibet/util/tags.py:152 msgid "last played" msgstr "sidst afspillet" #: ../quodlibet/qltk/information.py:261 ../quodlibet/util/tags.py:162 msgid "plays" msgstr "afspiller" #: ../quodlibet/qltk/information.py:262 ../quodlibet/util/tags.py:163 msgid "skips" msgstr "springer over" #: ../quodlibet/qltk/information.py:263 ../quodlibet/util/tags.py:168 msgid "rating" msgstr "bedømmelse" #: ../quodlibet/qltk/information.py:292 msgid "path" msgstr "sti" #: ../quodlibet/qltk/information.py:293 ../quodlibet/util/tags.py:166 msgid "length" msgstr "længde" #: ../quodlibet/qltk/information.py:294 msgid "format" msgstr "format" #: ../quodlibet/qltk/information.py:295 ../quodlibet/util/tags.py:176 msgid "codec" msgstr "codec" #: ../quodlibet/qltk/information.py:296 ../quodlibet/util/tags.py:177 msgid "encoding" msgstr "kodning" #: ../quodlibet/qltk/information.py:297 ../quodlibet/util/tags.py:173 msgid "bitrate" msgstr "bithastighed" #: ../quodlibet/qltk/information.py:298 ../quodlibet/util/tags.py:174 msgid "file size" msgstr "filstørrelse" #: ../quodlibet/qltk/information.py:299 ../quodlibet/util/tags.py:161 msgid "modified" msgstr "ændret" #: ../quodlibet/qltk/information.py:336 msgid "Additional" msgstr "Yderligere" #: ../quodlibet/qltk/information.py:388 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d valgt" msgstr[1] "%d valgt" #: ../quodlibet/qltk/information.py:463 msgid "Track unavailable" msgstr "Spor utilgængeligt" #: ../quodlibet/qltk/information.py:469 msgid "Track List" msgstr "Sporliste" #: ../quodlibet/qltk/information.py:501 ../quodlibet/qltk/information.py:591 #, 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:504 msgid "Selected Discography" msgstr "Valgt diskografi" #: ../quodlibet/qltk/information.py:571 #, 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:599 ../quodlibet/util/tags.py:85 msgid "albums" msgstr "album" #: ../quodlibet/qltk/information.py:612 msgid "Total length:" msgstr "Samlet længde:" #: ../quodlibet/qltk/information.py:616 msgid "Total size:" msgstr "Samlet størrelse:" #: ../quodlibet/qltk/information.py:619 msgid "Files" msgstr "Filer" #: ../quodlibet/qltk/lyrics.py:37 msgid "_View online" msgstr "_Vis online" #: ../quodlibet/qltk/lyrics.py:65 msgid "No lyrics found for this song." msgstr "Ingen sangtekster fundet til denne sang." #: ../quodlibet/qltk/lyrics.py:76 msgid "Searching for lyrics…" msgstr "Søger efter sangtekster…" #: ../quodlibet/qltk/maskedbox.py:21 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:22 msgid "The selected songs will be removed from the library." msgstr "De valgte sange vil blive fjernet fra biblioteket." #: ../quodlibet/qltk/maskedbox.py:45 msgid "Unhide" msgstr "Fjern fra skjul" #: ../quodlibet/qltk/maskedbox.py:87 msgid "_Unhide" msgstr "_Fjern fra skjul" #: ../quodlibet/qltk/msg.py:42 msgid "Discard tag changes?" msgstr "Forkast ændringer af tag?" #: ../quodlibet/qltk/msg.py:43 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:56 ../quodlibet/qltk/prefs.py:606 #: ../quodlibet/qltk/textedit.py:65 ../quodlibet/qltk/tracknumbers.py:118 msgid "_Revert" msgstr "_Tilbagefør" #: ../quodlibet/qltk/msg.py:105 msgid "File exists" msgstr "Filen findes" #: ../quodlibet/qltk/msg.py:107 #, python-format msgid "Replace %(file-name)s?" msgstr "Erstat %(file-name)s?" #: ../quodlibet/qltk/msg.py:113 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:257 msgid "Toggle shuffle mode" msgstr "Bland-tilstand til/fra" #: ../quodlibet/qltk/playorder.py:273 msgid "Toggle repeat mode" msgstr "Gentag-tilstand til/fra" #: ../quodlibet/qltk/pluginwin.py:45 msgid "Plugin Errors" msgstr "Pluginfejl" #: ../quodlibet/qltk/pluginwin.py:125 msgid "Enabled" msgstr "Aktiveret" #: ../quodlibet/qltk/pluginwin.py:126 msgid "Disabled" msgstr "Deaktiveret" #: ../quodlibet/qltk/pluginwin.py:132 msgid "No category" msgstr "Ingen kategori" #: ../quodlibet/qltk/pluginwin.py:170 msgid "Events" msgstr "Begivenheder" #: ../quodlibet/qltk/pluginwin.py:171 msgid "Play Order" msgstr "Afspilningsrækkefølge" #: ../quodlibet/qltk/pluginwin.py:172 msgid "Editing" msgstr "Redigering" #: ../quodlibet/qltk/pluginwin.py:174 msgid "Covers" msgstr "Covere" #: ../quodlibet/qltk/pluginwin.py:310 msgid "No plugins found." msgstr "Ingen plugins fundet." #: ../quodlibet/qltk/pluginwin.py:359 msgid "Plugins" msgstr "Plugins" #: ../quodlibet/qltk/pluginwin.py:383 msgid "Filter by plugin state / tag" msgstr "Filtrér efter plugintilstand/tag" #: ../quodlibet/qltk/pluginwin.py:389 msgid "Filter by plugin type" msgstr "Filtrér efter plugintype" #: ../quodlibet/qltk/pluginwin.py:395 msgid "Filter by plugin name or description" msgstr "Filtrér efter pluginnavn eller -beskrivelse" #: ../quodlibet/qltk/pluginwin.py:404 msgid "Show _Errors" msgstr "Vis _fejl" #: ../quodlibet/qltk/prefs.py:46 msgid "_Disc" msgstr "_Disk" #: ../quodlibet/qltk/prefs.py:47 msgid "_Track" msgstr "_Spor" #: ../quodlibet/qltk/prefs.py:48 msgid "Grou_ping" msgstr "_Gruppering" #: ../quodlibet/qltk/prefs.py:51 msgid "Al_bum" msgstr "_Album" #: ../quodlibet/qltk/prefs.py:56 msgid "_Filename" msgstr "_Filnavn" #: ../quodlibet/qltk/prefs.py:58 msgid "_Length" msgstr "_Længde" #: ../quodlibet/qltk/prefs.py:65 msgid "_Jump to playing song automatically" msgstr "_Hop automatisk til sangen som afspilles" #: ../quodlibet/qltk/prefs.py:67 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:83 msgid "_Others:" msgstr "_Andre:" #: ../quodlibet/qltk/prefs.py:89 msgid "_Edit…" msgstr "_Rediger…" #: ../quodlibet/qltk/prefs.py:92 msgid "Add or remove additional column headers" msgstr "Tilføj eller fjern yderligere kolonne-headere" #: ../quodlibet/qltk/prefs.py:102 msgid "Visible Columns" msgstr "Synlige kolonner" #: ../quodlibet/qltk/prefs.py:105 msgid "Title includes _version" msgstr "Titel inkluderer _version" #: ../quodlibet/qltk/prefs.py:107 msgid "Artist includes all _people" msgstr "Kunstner inkluderer alle _personer" #: ../quodlibet/qltk/prefs.py:109 msgid "Album includes _disc subtitle" msgstr "Album inkluderer _disk-undertitel" #: ../quodlibet/qltk/prefs.py:111 msgid "Filename includes _folder" msgstr "Filnavn inkluderer _mappe" #: ../quodlibet/qltk/prefs.py:124 msgid "Column Preferences" msgstr "Kolonne-præferencer" #: ../quodlibet/qltk/prefs.py:130 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:143 ../quodlibet/qltk/shortcuts.py:25 msgid "Song List" msgstr "Sangliste" #: ../quodlibet/qltk/prefs.py:223 msgid "Edit Columns" msgstr "Rediger kolonner" #: ../quodlibet/qltk/prefs.py:260 msgid "Duration totals" msgstr "Samlet varighed" #: ../quodlibet/qltk/prefs.py:272 msgid "_Global filter:" msgstr "_Globalt filter:" #: ../quodlibet/qltk/prefs.py:278 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:284 msgctxt "heading" msgid "Search" msgstr "Søgning" #: ../quodlibet/qltk/prefs.py:288 ../quodlibet/qltk/shortcuts.py:22 msgid "Browsers" msgstr "Browsere" #: ../quodlibet/qltk/prefs.py:294 msgid "Confirm _multiple ratings" msgstr "Bekræft _flere bedømmelser" #: ../quodlibet/qltk/prefs.py:296 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:299 msgid "Enable _one-click ratings" msgstr "Aktivér bedømmelser med ét _klik" #: ../quodlibet/qltk/prefs.py:301 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:307 ../quodlibet/qltk/prefs.py:627 msgid "Ratings" msgstr "Bedømmelser" #. Filename choice algorithm config #: ../quodlibet/qltk/prefs.py:313 msgid "Prefer _embedded art" msgstr "Foretræk _indlejret grafik" #: ../quodlibet/qltk/prefs.py:315 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:320 msgid "_Fixed image filename:" msgstr "_Fast billedfilnavn:" #: ../quodlibet/qltk/prefs.py:322 msgid "The single image filename to use if selected" msgstr "Det eneste billedfilnavn der skal bruges hvis valgt" #: ../quodlibet/qltk/prefs.py:328 msgid "The album art image file to use when forced (supports wildcards)" msgstr "" "Albumgrafik-billedefil som skal bruges når tvunget (understøtter jokertegn)" #: ../quodlibet/qltk/prefs.py:338 msgid "Album Art" msgstr "Albumgrafik" #: ../quodlibet/qltk/prefs.py:359 msgid "Playback" msgstr "Afspilning" #: ../quodlibet/qltk/prefs.py:364 msgid "Output Configuration" msgstr "Output-konfiguration" #: ../quodlibet/qltk/prefs.py:375 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:378 msgid "_Fall-back gain (dB):" msgstr "_Fall-back forstærkning (dB):" #: ../quodlibet/qltk/prefs.py:389 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:392 msgid "_Pre-amp gain (dB):" msgstr "_Pre-amp forstærkning (dB):" #: ../quodlibet/qltk/prefs.py:397 msgid "_Enable Replay Gain volume adjustment" msgstr "_Aktivér justering af lydstyrke for Replay Gain" #: ../quodlibet/qltk/prefs.py:422 msgid "Replay Gain Volume Adjustment" msgstr "Justering af lydstyrke for Replay Gain" #: ../quodlibet/qltk/prefs.py:452 msgid "_Default rating:" msgstr "_Standardbedømmelse:" #: ../quodlibet/qltk/prefs.py:495 msgid "Rating _scale:" msgstr "Bedømmelses_skalering:" #: ../quodlibet/qltk/prefs.py:544 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:549 msgid "_Bayesian averaging amount:" msgstr "_Bayesian gennemsnitlig mængde:" #: ../quodlibet/qltk/prefs.py:558 msgid "Save ratings and play _counts in tags" msgstr "Gem bedømmelser og _antal afspilninger i tags" #: ../quodlibet/qltk/prefs.py:566 msgid "_Email:" msgstr "_E-mail:" #: ../quodlibet/qltk/prefs.py:568 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:588 msgid "Auto-save tag changes" msgstr "Gem automatisk ændringer af tag" #: ../quodlibet/qltk/prefs.py:590 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:598 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:621 msgid "Tags" msgstr "Tags" #: ../quodlibet/qltk/prefs.py:642 msgid "Updating for new ratings" msgstr "Opdaterer for nye bedømmelser" #: ../quodlibet/qltk/prefs.py:652 msgid "Scan library _on start" msgstr "_Skan bibliotek ved start" #: ../quodlibet/qltk/prefs.py:662 ../quodlibet/qltk/quodlibetwindow.py:1091 msgid "_Scan Library" msgstr "_Skan bibliotek" #: ../quodlibet/qltk/prefs.py:664 ../quodlibet/qltk/quodlibetwindow.py:1153 msgid "Check for changes in your library" msgstr "Søg efter ændringer i dit bibliotek" #: ../quodlibet/qltk/prefs.py:669 msgid "Re_build Library" msgstr "_Genbyg bibliotek" #: ../quodlibet/qltk/prefs.py:672 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:682 msgid "Scan Directories" msgstr "Mapper som skal skannes" #: ../quodlibet/qltk/prefs.py:688 msgid "Hidden Songs" msgstr "Skjulte sange" #: ../quodlibet/qltk/properties.py:159 ../quodlibet/util/collection.py:403 #, 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:163 ../quodlibet/qltk/properties.py:165 msgid "Properties" msgstr "Egenskaber" #: ../quodlibet/qltk/queue.py:105 msgid "_Queue" msgstr "_Kø" #: ../quodlibet/qltk/queue.py:129 msgid "Stop at End" msgstr "Stop ved slutningen" #: ../quodlibet/qltk/queue.py:134 msgid "Ignore" msgstr "Ignorer" #: ../quodlibet/qltk/queue.py:139 msgid "Keep Songs" msgstr "Bevar sange" #: ../quodlibet/qltk/queue.py:142 msgid "Keep songs in the queue after playing them" msgstr "Bevar sange i køen efter de er blevet afspillet" #: ../quodlibet/qltk/queue.py:146 msgid "_Clear Queue" msgstr "_Ryd kø" #: ../quodlibet/qltk/queue.py:269 #, 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:200 msgid "_Browse Library" msgstr "_Gennemse bibliotek" #: ../quodlibet/qltk/quodlibetwindow.py:350 msgid "Toggle queue visibility" msgstr "Køens synlighed til/fra" #: ../quodlibet/qltk/quodlibetwindow.py:471 msgid "Playback Error" msgstr "Fejl ved afspilning" #: ../quodlibet/qltk/quodlibetwindow.py:479 msgid "Set up library directories?" msgstr "Opsæt biblioteksmapper?" #: ../quodlibet/qltk/quodlibetwindow.py:480 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:486 msgid "_Not Now" msgstr "_Ikke nu" #: ../quodlibet/qltk/quodlibetwindow.py:487 msgid "_Set Up" msgstr "_Sæt op" #: ../quodlibet/qltk/quodlibetwindow.py:946 msgid "Unable to add songs" msgstr "Kan ikke tilføje sange" #: ../quodlibet/qltk/quodlibetwindow.py:947 #: ../quodlibet/qltk/quodlibetwindow.py:1373 #, python-format msgid "%s uses an unsupported protocol." msgstr "%s bruger en ikke-understøttet protokol." #: ../quodlibet/qltk/quodlibetwindow.py:970 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:977 msgid "_File" msgstr "_Arkiv" #: ../quodlibet/qltk/quodlibetwindow.py:978 msgid "_Song" msgstr "_Sang" #: ../quodlibet/qltk/quodlibetwindow.py:979 msgid "_View" msgstr "_Visning" #: ../quodlibet/qltk/quodlibetwindow.py:980 msgid "_Browse" msgstr "_Gennemse" #: ../quodlibet/qltk/quodlibetwindow.py:981 msgid "_Control" msgstr "_Betjening" #: ../quodlibet/qltk/quodlibetwindow.py:982 msgid "_Help" msgstr "_Hjælp" #: ../quodlibet/qltk/quodlibetwindow.py:988 msgid "_Add a Folder…" msgstr "_Tilføj en mappe…" #: ../quodlibet/qltk/quodlibetwindow.py:993 msgid "_Add a File…" msgstr "_Tilføj en fil…" #: ../quodlibet/qltk/quodlibetwindow.py:998 msgid "_Add a Location…" msgstr "_Tilføj en placering…" #: ../quodlibet/qltk/quodlibetwindow.py:1027 msgid "Edit Bookmarks…" msgstr "Rediger bogmærker…" #: ../quodlibet/qltk/quodlibetwindow.py:1047 msgid "Stop After This Song" msgstr "Stop efter denne sang" #: ../quodlibet/qltk/quodlibetwindow.py:1053 msgid "_Keyboard Shortcuts" msgstr "_Tastaturgenveje" #: ../quodlibet/qltk/quodlibetwindow.py:1062 msgid "Online Help" msgstr "Onlinehjælp" #: ../quodlibet/qltk/quodlibetwindow.py:1071 msgid "Search Help" msgstr "Søgehjælp" #: ../quodlibet/qltk/quodlibetwindow.py:1361 msgid "Add a Location" msgstr "Tilføj en placering" #: ../quodlibet/qltk/quodlibetwindow.py:1362 msgid "Enter the location of an audio file:" msgstr "Indtast placeringen af en lydfil:" #: ../quodlibet/qltk/quodlibetwindow.py:1367 #: ../quodlibet/qltk/quodlibetwindow.py:1372 msgid "Unable to add location" msgstr "Kan ikke tilføje placering" #: ../quodlibet/qltk/quodlibetwindow.py:1368 #, python-format msgid "%s is not a valid location." msgstr "%s er ikke en gyldig placering." #: ../quodlibet/qltk/quodlibetwindow.py:1381 #: ../quodlibet/qltk/quodlibetwindow.py:1390 msgid "Add Music" msgstr "Tilføj musik" #: ../quodlibet/qltk/quodlibetwindow.py:1381 ../quodlibet/qltk/scanbox.py:100 msgid "_Add Folders" msgstr "_Tilføj mapper" #: ../quodlibet/qltk/quodlibetwindow.py:1388 msgid "Music Files" msgstr "Musikfiler" #: ../quodlibet/qltk/quodlibetwindow.py:1390 msgid "_Add Files" msgstr "_Tilføj filer" #: ../quodlibet/qltk/ratingsmenu.py:25 #, 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:27 msgid "The saved ratings will be removed" msgstr "De gemte bedømmelser vil blive fjernet" #: ../quodlibet/qltk/ratingsmenu.py:28 #, 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:58 ../quodlibet/qltk/ratingsmenu.py:112 msgid "_Remove Rating" msgstr "_Fjern bedømmelse" #: ../quodlibet/qltk/ratingsmenu.py:99 msgid "Change _Rating" msgstr "_Skift bedømmelse" #: ../quodlibet/qltk/renamefiles.py:53 msgid "Replace spaces with _underscores" msgstr "Erstat mellemrum med _understregningstegn" #: ../quodlibet/qltk/renamefiles.py:63 msgid "Strip _Windows-incompatible characters" msgstr "Fjern tegn som er inkompatible med _Windows" #: ../quodlibet/qltk/renamefiles.py:81 msgid "Strip _diacritical marks" msgstr "Fjern _diakritiske tegn" #: ../quodlibet/qltk/renamefiles.py:92 msgid "Strip non-_ASCII characters" msgstr "Fjern ikke-_ACSII-tegn" #: ../quodlibet/qltk/renamefiles.py:102 msgid "Use only _lowercase characters" msgstr "Brug kun _små bogstaver" #: ../quodlibet/qltk/renamefiles.py:130 msgid "Rename Files" msgstr "Omdøb filer" #: ../quodlibet/qltk/renamefiles.py:148 ../quodlibet/qltk/tagsfrompath.py:117 msgid "Path Patterns" msgstr "Sti-mønstre" #: ../quodlibet/qltk/renamefiles.py:149 ../quodlibet/qltk/tagsfrompath.py:118 msgid "Edit saved patterns…" msgstr "Rediger gemte mønstre…" #: ../quodlibet/qltk/renamefiles.py:152 ../quodlibet/qltk/tagsfrompath.py:121 #: ../quodlibet/qltk/tracknumbers.py:59 msgid "_Preview" msgstr "_Forhåndsvis" #: ../quodlibet/qltk/renamefiles.py:179 msgid "File names" msgstr "Filnavne" #: ../quodlibet/qltk/renamefiles.py:189 msgid "_Move album art" msgstr "_Flyt albumgrafik" #: ../quodlibet/qltk/renamefiles.py:192 msgid "See '[albumart] filenames' config entry for image search strings" msgstr "" "Se '[albumart] filnavne'-konfigurationsindtastning for billedsøgningsstrenge" #: ../quodlibet/qltk/renamefiles.py:197 msgid "_Overwrite album art at target" msgstr "_Overskriv albumgrafik ved mål" #: ../quodlibet/qltk/renamefiles.py:205 msgid "_Remove empty directories" msgstr "_Fjern tomme mapper" #: ../quodlibet/qltk/renamefiles.py:211 msgid "Album art" msgstr "Albumgrafik" #: ../quodlibet/qltk/renamefiles.py:240 msgid "New Name" msgstr "Nyt navn" #: ../quodlibet/qltk/renamefiles.py:317 msgid "Unable to rename file" msgstr "Kan ikke omdøbe fil" #: ../quodlibet/qltk/renamefiles.py:318 #, python-format msgid "" "Renaming <b>%(old-name)s</b> to <b>%(new-name)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." 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:326 msgid "Ignore _All Errors" msgstr "Ignorer _alle fejl" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: ../quodlibet/qltk/renamefiles.py:327 ../quodlibet/qltk/wlw.py:51 msgid "_Stop" msgstr "_Stop" #: ../quodlibet/qltk/renamefiles.py:329 msgid "_Continue" msgstr "_Fortsæt" #: ../quodlibet/qltk/renamefiles.py:442 msgid "Path is not absolute" msgstr "Stien er ikke absolut" #: ../quodlibet/qltk/renamefiles.py:443 #, python-format msgid "" "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 ~/." 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:48 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:100 msgid "Select Directories" msgstr "Vælg mapper" #: ../quodlibet/qltk/searchbar.py:55 msgid "Saved Searches" msgstr "Gemte søgninger" #: ../quodlibet/qltk/searchbar.py:56 msgid "Edit saved searches…" msgstr "Rediger gemte søgninger…" #: ../quodlibet/qltk/searchbar.py:80 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:142 msgid "Search after _typing" msgstr "Søg efter _skrivning" #: ../quodlibet/qltk/searchbar.py:145 msgid "Show search results after the user stops typing" msgstr "Vis søgeresultater når brugeren stopper med at skrive" #: ../quodlibet/qltk/searchbar.py:212 msgid "_Limit:" msgstr "_Grænse:" #: ../quodlibet/qltk/searchbar.py:225 msgid "_Weight" msgstr "_Vægtning" #: ../quodlibet/qltk/seekbutton.py:239 msgid "Display remaining time" msgstr "Vis resterende tid" #: ../quodlibet/qltk/shortcuts.py:17 msgid "Main Window" msgstr "Hovedvindue" #: ../quodlibet/qltk/shortcuts.py:18 msgid "Seek backwards by 10 seconds" msgstr "Søg baglæns 10 sekunder" #: ../quodlibet/qltk/shortcuts.py:19 msgid "Seek forward by 10 seconds" msgstr "Søg fremad 10 sekunder" #: ../quodlibet/qltk/shortcuts.py:20 msgid "Focus the search entry" msgstr "Giv fokus til søgeindtastningen" #: ../quodlibet/qltk/shortcuts.py:23 msgid "Reset filters and jump to the playing song" msgstr "Nulstil filtre og hop til sangen som afspilles" #: ../quodlibet/qltk/shortcuts.py:27 msgid "Open the information window for the selected songs" msgstr "Åbn informationsvinduet for de valgte sange" #: ../quodlibet/qltk/shortcuts.py:28 msgid "Open the tag editor for the selected songs" msgstr "Åbn tag-editoren for de valgte sange" #: ../quodlibet/qltk/shortcuts.py:29 msgid "Queue the selected songs" msgstr "Sæt de valgte sange i kø" #: ../quodlibet/qltk/shortcuts.py:30 msgid "Delete the selected songs" msgstr "Slet de valgte sange" #: ../quodlibet/qltk/shortcuts.py:31 msgid "Show the inline search entry" msgstr "Vis den indbyggede søgeindtastning" #: ../quodlibet/qltk/shortcuts.py:32 msgid "Left click on a column header" msgstr "Venstreklik på en kolonne-header" #: ../quodlibet/qltk/shortcuts.py:33 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:35 msgid "Tree View" msgstr "Træ-visning" #: ../quodlibet/qltk/shortcuts.py:37 msgid "Collapses the element or select the parent element" msgstr "Sammenfold elementet eller vælg forælder-elementet" #: ../quodlibet/qltk/shortcuts.py:38 msgid "Expands the element" msgstr "Udfold elementet" #: ../quodlibet/qltk/shortcuts.py:40 msgid "Text Entries" msgstr "Tekstindtastninger" #: ../quodlibet/qltk/shortcuts.py:42 msgid "Undo the last change" msgstr "Omgør den sidste ændring" #: ../quodlibet/qltk/shortcuts.py:43 msgid "Redo the last undone change" msgstr "Omgør den sidste fortryd-ændring" #: ../quodlibet/qltk/shortcuts.py:46 msgid "Select all songs in all panes" msgstr "Vælg alle sange i alle ruder" #: ../quodlibet/qltk/songlist.py:377 #, python-format msgid "_Filter on %s" msgstr "_Filtrér efter %s" #: ../quodlibet/qltk/songlist.py:1095 msgid "All _Headers" msgstr "Alle _headere" #: ../quodlibet/qltk/songlist.py:1096 msgid "_Track Headers" msgstr "_Spor-headere" #: ../quodlibet/qltk/songlist.py:1097 msgid "_Album Headers" msgstr "_Album-headere" #: ../quodlibet/qltk/songlist.py:1098 msgid "_People Headers" msgstr "_Personer-headere" #: ../quodlibet/qltk/songlist.py:1099 msgid "_Date Headers" msgstr "_Dato-headere" #: ../quodlibet/qltk/songlist.py:1100 msgid "_File Headers" msgstr "_Fil-headere" #: ../quodlibet/qltk/songlist.py:1101 msgid "_Production Headers" msgstr "_Produktion-headere" #: ../quodlibet/qltk/songlist.py:1116 msgid "_Customize Headers…" msgstr "_Brugerdefinerede headere…" #: ../quodlibet/qltk/songlist.py:1121 msgid "_Expand Column" msgstr "_Udfold kolonne" #: ../quodlibet/qltk/songsmenu.py:42 #, python-format msgid "Remove track: \"%%(title)s\" from library?" msgid_plural "Remove %(count)d tracks from library?" msgstr[0] "Fjern spor: \"%%(title)s\" fra bibliotek?" msgstr[1] "Fjern %(count)d spor fra bibliotek?" #: ../quodlibet/qltk/songsmenu.py:48 msgid "Remove from Library" msgstr "Fjern fra bibliotek" #: ../quodlibet/qltk/songsmenu.py:53 #, 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:64 #, 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:136 msgid "Configure Plugins…" msgstr "Konfigurér plugins…" #: ../quodlibet/qltk/songsmenu.py:331 msgid "Add to _Queue" msgstr "Tilføj til _kø" #: ../quodlibet/qltk/songsmenu.py:351 msgid "_Remove from Library…" msgstr "Fjern fra bibliotek…" #: ../quodlibet/qltk/songsmenu.py:415 msgid "Unable to show files" msgstr "Kan ikke vise filer" #: ../quodlibet/qltk/songsmenu.py:416 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:423 #, 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/tagsfrompath.py:48 msgid "Replace _underscores with spaces" msgstr "Erstat _understregningstegn med mellemrum" #: ../quodlibet/qltk/tagsfrompath.py:58 msgid "_Title-case tags" msgstr "_Foretag title-case af tags" #: ../quodlibet/qltk/tagsfrompath.py:68 msgid "Split into multiple _values" msgstr "Opdel i flere _værdier" #: ../quodlibet/qltk/tagsfrompath.py:102 msgid "Tags From Path" msgstr "Tags fra sti" #: ../quodlibet/qltk/tagsfrompath.py:139 msgid "Tags replace existing ones" msgstr "Tags erstatter de eksisterende" #: ../quodlibet/qltk/tagsfrompath.py:140 msgid "Tags are added to existing ones" msgstr "Tags tilføjes til de eksisterende" #: ../quodlibet/qltk/tagsfrompath.py:196 #, python-format msgid "" "The pattern\n" "\t<b>%s</b>\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/tagsfrompath.py:217 msgid "Invalid tags" msgstr "Ugyldige tags" #: ../quodlibet/qltk/tagsfrompath.py:218 #, 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." #: ../quodlibet/qltk/textedit.py:143 #, 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:159 msgid "Edit Display" msgstr "Rediger visning" #: ../quodlibet/qltk/tracknumbers.py:40 msgid "Track Numbers" msgstr "Spornumre" #: ../quodlibet/qltk/tracknumbers.py:43 msgid "Start fro_m:" msgstr "Start _fra:" #: ../quodlibet/qltk/tracknumbers.py:52 msgid "_Total tracks:" msgstr "_Samlet spor:" #: ../quodlibet/qltk/unity.py:53 msgid "Play/Pause" msgstr "Afspil/pause" #: ../quodlibet/qltk/unity.py:73 msgid "Previous" msgstr "Forrige" #: ../quodlibet/qltk/views.py:924 #, python-format msgid "and %d more…" msgstr "og %d mere…" #: ../quodlibet/qltk/wlw.py:201 msgid "Saving the songs you changed." msgstr "Gemmer sangene du ændrede." #: ../quodlibet/qltk/wlw.py:202 #, 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:235 #, 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:425 msgid "Playlists must have a name" msgstr "Spillelister skal have et navn" #: ../quodlibet/util/collection.py:608 #, python-format msgid "A playlist named %s already exists." msgstr "En spilleliste ved navn %s findes allerede." #: ../quodlibet/util/cover/built_in.py:33 msgid "Embedded album covers" msgstr "Indlejrede albumcovere" #: ../quodlibet/util/cover/built_in.py:34 msgid "Uses covers embedded into audio files." msgstr "Bruger covere som er indlejrede i lydfiler." #: ../quodlibet/util/cover/built_in.py:56 msgid "Filesystem cover" msgstr "Filsystemets cover" #: ../quodlibet/util/cover/built_in.py:57 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:231 msgid "Cover Art" msgstr "Covergrafik" #: ../quodlibet/util/cover/manager.py:231 msgid "Querying album art providers" msgstr "Forespørger albumgrafik-udbydere" #: ../quodlibet/util/__init__.py:77 msgid "Display brief usage information" msgstr "Vis kortfattet forbrugsinformation" #: ../quodlibet/util/__init__.py:79 msgid "Display version and copyright" msgstr "Vis version og ophavsret" #: ../quodlibet/util/__init__.py:80 msgid "Print debugging information" msgstr "Vis fejlretningsinformation" #: ../quodlibet/util/__init__.py:119 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "Anvendelse: %(program)s %(usage)s" #: ../quodlibet/util/__init__.py:121 msgid "[options]" msgstr "[valgmulighed]" #: ../quodlibet/util/__init__.py:166 #, python-format msgid "Option %r not recognized." msgstr "Valgmuligheden %r genkendes ikke." #: ../quodlibet/util/__init__.py:169 #, python-format msgid "Option %r requires an argument." msgstr "Valgmuligheden %r kræver et argument." #: ../quodlibet/util/__init__.py:172 #, python-format msgid "%r is not a unique prefix." msgstr "%r er ikke et unikt præfiks." #: ../quodlibet/util/__init__.py:348 #, python-format msgid "%d kbps" msgstr "%d kbps" #: ../quodlibet/util/__init__.py:403 #, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%s sekund" msgstr[1] "%s sekunder" #: ../quodlibet/util/__init__.py:416 msgid "No time information" msgstr "Ingen information om tid" #: ../quodlibet/util/__init__.py:419 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d sekund" msgstr[1] "%d sekunder" #: ../quodlibet/util/__init__.py:420 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d minut" msgstr[1] "%d minutter" #: ../quodlibet/util/__init__.py:421 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d time" msgstr[1] "%d timer" #: ../quodlibet/util/__init__.py:422 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d dag" msgstr[1] "%d dage" #: ../quodlibet/util/__init__.py:423 #, 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:515 msgctxt "check" msgid "titlecase?" msgstr "Pølse!" #: ../quodlibet/util/massagers.py:116 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:131 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:152 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:174 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:196 msgid "" "MusicBrainz release status must be 'official', 'promotional', or 'bootleg'." msgstr "" "MusicBrainz-udgivelsesstatus skal være 'official', 'promotional', eller " "'bootleg'." #: ../quodlibet/util/massagers.py:209 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:117 msgid "Unable to edit song" msgstr "Kan ikke redigere sang" #: ../quodlibet/util/songwrapper.py:118 #, python-format msgid "" "Saving <b>%s</b> 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:35 #: ../quodlibet/util/string/__init__.py:45 msgid "[Invalid Encoding]" msgstr "[ugyldig kodning]" #: ../quodlibet/util/tags.py:85 msgid "album" msgstr "album" #: ../quodlibet/util/tags.py:86 msgid "arranger" msgstr "arrangør" #: ../quodlibet/util/tags.py:86 msgid "arrangers" msgstr "arrangører" #: ../quodlibet/util/tags.py:86 msgid "arrangement" msgstr "arrangement" #: ../quodlibet/util/tags.py:88 msgid "author" msgstr "forfatter" #: ../quodlibet/util/tags.py:88 msgid "authors" msgstr "forfattere" #: ../quodlibet/util/tags.py:89 msgid "comment" msgstr "kommentar" #: ../quodlibet/util/tags.py:90 msgid "composer" msgstr "komponist" #: ../quodlibet/util/tags.py:90 msgid "composers" msgstr "komponister" #: ../quodlibet/util/tags.py:90 msgid "composition" msgstr "komposition" #. Translators: conducting as in conducting a musical performance #: ../quodlibet/util/tags.py:92 msgid "conductor" msgstr "dirigent" #: ../quodlibet/util/tags.py:92 msgid "conductors" msgstr "dirigenter" #: ../quodlibet/util/tags.py:92 msgid "conducting" msgstr "dirigering" #: ../quodlibet/util/tags.py:93 msgid "contact" msgstr "kontakt" #: ../quodlibet/util/tags.py:94 msgid "copyright" msgstr "ophavsret" #: ../quodlibet/util/tags.py:95 msgid "date" msgstr "dato" #: ../quodlibet/util/tags.py:96 msgid "description" msgstr "beskrivelse" #: ../quodlibet/util/tags.py:97 msgid "genre" msgstr "genre" #: ../quodlibet/util/tags.py:97 msgid "genres" msgstr "genrer" #: ../quodlibet/util/tags.py:98 msgid "performer" msgstr "performer" #: ../quodlibet/util/tags.py:98 msgid "performance" msgstr "optræden" #: ../quodlibet/util/tags.py:99 msgid "grouping" msgstr "gruppering" #: ../quodlibet/util/tags.py:100 msgid "language" msgstr "sprog" #: ../quodlibet/util/tags.py:101 msgid "license" msgstr "licens" #: ../quodlibet/util/tags.py:102 msgid "location" msgstr "sted" #: ../quodlibet/util/tags.py:103 msgid "lyricist" msgstr "tekstforfatter" #: ../quodlibet/util/tags.py:103 msgid "lyricists" msgstr "tekstforfattere" #: ../quodlibet/util/tags.py:103 msgid "lyrics" msgstr "sangtekster" #. Translators: Also e.g. "record label", "publisher" #: ../quodlibet/util/tags.py:105 msgid "organization" msgstr "organisation" #: ../quodlibet/util/tags.py:106 msgid "title" msgstr "titel" #: ../quodlibet/util/tags.py:107 msgid "version" msgstr "version" #: ../quodlibet/util/tags.py:108 msgid "website" msgstr "websted" #: ../quodlibet/util/tags.py:110 msgid "album artist" msgstr "albumkunstner" #: ../quodlibet/util/tags.py:111 msgid "BPM" msgstr "BPM" #. Translators: This used to be called "part". #: ../quodlibet/util/tags.py:114 ../quodlibet/util/tags.py:115 msgid "disc subtitle" msgstr "disk-undertitel" #: ../quodlibet/util/tags.py:116 ../quodlibet/util/tags.py:153 msgid "disc" msgstr "disk" #: ../quodlibet/util/tags.py:117 ../quodlibet/util/tags.py:155 msgid "track" msgstr "spor" #: ../quodlibet/util/tags.py:118 msgid "label ID" msgstr "etiket-ID" #: ../quodlibet/util/tags.py:119 msgid "original release date" msgstr "original udgivelsesdato" #: ../quodlibet/util/tags.py:120 msgid "original album" msgstr "originalt album" #: ../quodlibet/util/tags.py:121 msgid "original artist" msgstr "original kunstner" #: ../quodlibet/util/tags.py:122 msgid "recording date" msgstr "optagelsesdato" #: ../quodlibet/util/tags.py:123 msgid "release country" msgstr "udgivelsesland" #. 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:132 msgid "MusicBrainz recording ID" msgstr "MusicBrainz optagelse-ID" #: ../quodlibet/util/tags.py:133 msgid "MusicBrainz release track ID" msgstr "MusicBrainz udgivelsesspor-ID" #: ../quodlibet/util/tags.py:134 msgid "MusicBrainz release ID" msgstr "MusicBrainz udgivelse-ID" #: ../quodlibet/util/tags.py:135 msgid "MusicBrainz artist ID" msgstr "MusicBrainz kunstner-ID" #: ../quodlibet/util/tags.py:136 msgid "MusicBrainz release artist ID" msgstr "MusicBrainz udgivelseskunstner-ID" #: ../quodlibet/util/tags.py:137 msgid "MusicBrainz TRM ID" msgstr "MusicBrainz TRM-ID" #: ../quodlibet/util/tags.py:138 msgid "MusicIP PUID" msgstr "MusicIP PUID" #: ../quodlibet/util/tags.py:139 msgid "MusicBrainz album status" msgstr "MusicBrainz albumstatus" #: ../quodlibet/util/tags.py:140 msgid "MusicBrainz album type" msgstr "MusicBrainz albumtype" #: ../quodlibet/util/tags.py:141 msgid "MusicBrainz release group ID" msgstr "MusicBrainz udgivelsesgruppe-ID" #. Translators: "gain" means a volume adjustment, not "to acquire". #: ../quodlibet/util/tags.py:144 msgid "track gain" msgstr "sporets forstærkning" #: ../quodlibet/util/tags.py:145 msgid "track peak" msgstr "sporets spidspunkt" #. Translators: "gain" means a volume adjustment, not "to acquire". #: ../quodlibet/util/tags.py:147 msgid "album gain" msgstr "albummets forstærkning" #: ../quodlibet/util/tags.py:148 msgid "album peak" msgstr "albummets spidspunkt" #: ../quodlibet/util/tags.py:149 msgid "reference loudness" msgstr "reference loudness" #: ../quodlibet/util/tags.py:154 msgid "discs" msgstr "diske" #: ../quodlibet/util/tags.py:156 msgid "tracks" msgstr "spor" #: ../quodlibet/util/tags.py:157 msgid "last started" msgstr "sidst startet" #: ../quodlibet/util/tags.py:158 msgid "full name" msgstr "fulde navn" #: ../quodlibet/util/tags.py:165 msgid "mount point" msgstr "monteringspunkt" #: ../quodlibet/util/tags.py:167 msgid "people" msgstr "personer" #: ../quodlibet/util/tags.py:169 msgid "year" msgstr "år" #: ../quodlibet/util/tags.py:170 msgid "original release year" msgstr "originalt udgivelsesår" #: ../quodlibet/util/tags.py:171 msgid "bookmark" msgstr "bogmærke" #: ../quodlibet/util/tags.py:172 msgid "bitdepth" msgstr "bitdybde" #: ../quodlibet/util/tags.py:175 msgid "file format" msgstr "filformat" #: ../quodlibet/util/tags.py:178 msgid "playlists" msgstr "spillelister" #: ../quodlibet/util/tags.py:179 msgid "sample rate" msgstr "datapunktsfrekvens" #: ../quodlibet/util/tags.py:180 msgid "channel count" msgstr "antal kanaler" #. Translators: e.g. "artist (sort)" #: ../quodlibet/util/tags.py:270 msgid "sort" msgstr "slags" #. Translators: e.g. "performer (roles)" #: ../quodlibet/util/tags.py:278 msgid "roles" msgstr "roller" �������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9511857 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/po/de.po����������������������������������������������������������������������������0000644�0001750�0001750�00000633462�00000000000�014062� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 4.3\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2019-07-17 19:56+0200\n" "PO-Revision-Date: 2019-07-17 22:02+0200\n" "Last-Translator: Till Berger <till@mellthas.de>\n" "Language-Team: GERMAN <LL@li.org>\n" "Language: de_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-Poedit-SourceCharset: UTF-8\n" "X-Generator: Poedit 2.0.6\n" "X-Poedit-Basepath: .\n" #: quodlibet/browsers/albums/main.py:206 #: quodlibet/browsers/covergrid/main.py:54 msgid "_Title" msgstr "_Titel" #: quodlibet/browsers/albums/main.py:207 #: quodlibet/browsers/covergrid/main.py:55 quodlibet/qltk/prefs.py:49 msgid "_Artist" msgstr "_Künstler" #: quodlibet/browsers/albums/main.py:208 #: quodlibet/browsers/covergrid/main.py:56 quodlibet/qltk/prefs.py:54 msgid "_Date" msgstr "Dat_um" #: quodlibet/browsers/albums/main.py:209 msgid "_Original Date" msgstr "_Originaldatum" #: quodlibet/browsers/albums/main.py:210 #: quodlibet/browsers/covergrid/main.py:57 quodlibet/qltk/prefs.py:53 msgid "_Genre" msgstr "_Genre" #: quodlibet/browsers/albums/main.py:211 #: quodlibet/browsers/covergrid/main.py:58 quodlibet/qltk/prefs.py:58 #: quodlibet/qltk/ratingsmenu.py:39 msgid "_Rating" msgstr "_Bewertung" #: quodlibet/browsers/albums/main.py:212 msgid "_Playcount" msgstr "_Wiedergabeanzahl" #: quodlibet/browsers/albums/main.py:218 #: quodlibet/browsers/covergrid/main.py:64 msgid "Sort _by…" msgstr "Sortieren _nach …" #: quodlibet/browsers/albums/main.py:239 #: quodlibet/browsers/covergrid/main.py:85 #: quodlibet/browsers/paned/prefs.py:203 #: quodlibet/browsers/playlists/main.py:667 quodlibet/qltk/exfalsowindow.py:108 #: quodlibet/qltk/pluginwin.py:341 quodlibet/qltk/quodlibetwindow.py:906 msgid "_Preferences" msgstr "_Einstellungen" #: quodlibet/browsers/albums/main.py:409 msgid "Album List" msgstr "Albenliste" #: quodlibet/browsers/albums/main.py:410 msgid "_Album List" msgstr "_Albenliste" #: quodlibet/browsers/albums/main.py:524 #: quodlibet/browsers/covergrid/main.py:285 #: quodlibet/browsers/covergrid/main.py:501 msgid "All Albums" msgstr "Alle Alben" #: quodlibet/browsers/albums/main.py:525 #: quodlibet/browsers/covergrid/main.py:286 #: quodlibet/browsers/covergrid/main.py:502 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d Album" msgstr[1] "%d Alben" #: quodlibet/browsers/albums/main.py:706 #: quodlibet/browsers/covergrid/main.py:480 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:16 #: 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:385 quodlibet/util/collection.py:247 #, 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:383 quodlibet/util/collection.py:251 #, 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:124 #: quodlibet/ext/songsmenu/cover_download.py:243 msgid "Options" msgstr "Optionen" #: quodlibet/browsers/albums/prefs.py:74 #: quodlibet/browsers/covergrid/prefs.py:127 msgid "Album Display" msgstr "Alben-Anzeige" #: quodlibet/browsers/albums/prefs.py:78 #: quodlibet/browsers/covergrid/prefs.py:131 #: quodlibet/browsers/playlists/prefs.py:56 #: quodlibet/ext/songsmenu/albumart.py:328 #: quodlibet/ext/songsmenu/duplicates.py:345 #: quodlibet/ext/songsmenu/filterall.py:48 quodlibet/qltk/bookmarks.py:101 #: quodlibet/qltk/cbes.py:93 quodlibet/qltk/data_editors.py:96 #: quodlibet/qltk/data_editors.py:321 quodlibet/qltk/exfalsowindow.py:286 #: quodlibet/qltk/pluginwin.py:79 quodlibet/qltk/pluginwin.py:428 #: quodlibet/qltk/prefs.py:764 quodlibet/qltk/textedit.py:163 #: quodlibet/update.py:149 msgid "_Close" msgstr "S_chließen" #: quodlibet/browsers/audiofeeds.py:52 quodlibet/browsers/audiofeeds.py:64 #: quodlibet/browsers/audiofeeds.py:66 quodlibet/browsers/audiofeeds.py:156 #: quodlibet/browsers/paned/models.py:85 #: quodlibet/ext/songsmenu/fingerprint/search.py:46 #: quodlibet/formats/_audio.py:488 quodlibet/order/__init__.py:27 #: quodlibet/qltk/information.py:244 quodlibet/qltk/information.py:251 #: quodlibet/qltk/information.py:277 quodlibet/qltk/wlw.py:69 msgid "Unknown" msgstr "Unbekannt" #: quodlibet/browsers/audiofeeds.py:247 msgid "New Feed" msgstr "Neuer Feed" #: quodlibet/browsers/audiofeeds.py:248 msgid "Enter the location of an audio feed:" msgstr "Geben Sie die URL des Audio-Feeds an:" #: quodlibet/browsers/audiofeeds.py:249 #: quodlibet/browsers/collection/prefs.py:89 quodlibet/browsers/iradio.py:356 #: quodlibet/browsers/paned/prefs.py:120 #: quodlibet/browsers/playlists/menu.py:96 #: quodlibet/browsers/playlists/util.py:52 quodlibet/qltk/bookmarks.py:62 #: quodlibet/qltk/cbes.py:55 quodlibet/qltk/data_editors.py:308 #: quodlibet/qltk/edittags.py:327 quodlibet/qltk/edittags.py:527 #: quodlibet/qltk/quodlibetwindow.py:1276 quodlibet/qltk/scanbox.py:61 msgid "_Add" msgstr "_Hinzufügen" #: quodlibet/browsers/audiofeeds.py:303 msgid "Audio Feeds" msgstr "Audio-Feeds" #: quodlibet/browsers/audiofeeds.py:304 msgid "_Audio Feeds" msgstr "_Audio-Feeds" #: quodlibet/browsers/audiofeeds.py:407 quodlibet/qltk/data_editors.py:93 msgid "_New" msgstr "_Neu" #: quodlibet/browsers/audiofeeds.py:467 quodlibet/browsers/audiofeeds.py:526 msgid "Unable to add feed" msgstr "Feed konnte nicht hinzugefügt werden" #: quodlibet/browsers/audiofeeds.py:468 quodlibet/browsers/audiofeeds.py:527 #, python-format msgid "" "%s could not be added. The server may be down, or the location may not be an " "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 Audio-Feed." #: quodlibet/browsers/audiofeeds.py:475 quodlibet/qltk/filesel.py:260 #: quodlibet/qltk/pluginwin.py:414 msgid "_Refresh" msgstr "_Aktualisieren" #: quodlibet/browsers/audiofeeds.py:476 #: quodlibet/browsers/playlists/main.py:487 #: quodlibet/browsers/playlists/util.py:43 quodlibet/qltk/delete.py:143 #: quodlibet/qltk/filesel.py:257 quodlibet/qltk/lyrics.py:35 #: quodlibet/qltk/maskedbox.py:28 quodlibet/qltk/songsmenu.py:364 msgid "_Delete" msgstr "_Löschen" #: quodlibet/browsers/audiofeeds.py:543 msgid "" "The current audio backend does not support URLs, Audio Feeds browser " "disabled." msgstr "" "Das aktuelle Audio-Backend unterstützt keine URLs, der Browser für Audio-" "Feeds wurde deaktiviert." #: quodlibet/browsers/_base.py:146 quodlibet/browsers/_base.py:149 msgid "Library Browser" msgstr "Bibliothek-Browser" #: quodlibet/browsers/_base.py:273 quodlibet/ext/songsmenu/console.py:45 #: quodlibet/ext/songsmenu/refresh.py:30 quodlibet/qltk/exfalsowindow.py:240 #: quodlibet/qltk/information.py:554 quodlibet/qltk/maskedbox.py:68 #: quodlibet/util/collection.py:532 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d Titel" msgstr[1] "%d Titel" #: quodlibet/browsers/_base.py:401 quodlibet/browsers/_base.py:406 #: quodlibet/qltk/tagsfrompath.py:193 quodlibet/qltk/textedit.py:140 #: quodlibet/util/__init__.py:573 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:23 #, python-format msgid "Unknown %s" msgstr "%s ist unbekannt" #: quodlibet/browsers/collection/models.py:24 #, 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" #. Remove button #: quodlibet/browsers/collection/prefs.py:93 #: quodlibet/browsers/paned/prefs.py:124 #: quodlibet/browsers/playlists/menu.py:97 #: quodlibet/ext/playlist/remove_duplicates.py:60 #: quodlibet/qltk/bookmarks.py:97 quodlibet/qltk/bookmarks.py:127 #: quodlibet/qltk/cbes.py:82 quodlibet/qltk/cbes.py:89 #: quodlibet/qltk/data_editors.py:78 quodlibet/qltk/data_editors.py:91 #: quodlibet/qltk/data_editors.py:298 quodlibet/qltk/data_editors.py:311 #: quodlibet/qltk/data_editors.py:319 quodlibet/qltk/edittags.py:533 #: quodlibet/qltk/edittags.py:710 quodlibet/qltk/maskedbox.py:48 #: quodlibet/qltk/maskedbox.py:88 quodlibet/qltk/queue.py:427 #: quodlibet/qltk/scanbox.py:36 quodlibet/qltk/scanbox.py:63 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:470 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:247 #: quodlibet/ext/songsmenu/editplaycount.py:45 #: quodlibet/ext/songsmenu/exact_rating.py:38 #: quodlibet/player/gstbe/prefs.py:40 quodlibet/qltk/prefs.py:127 #: quodlibet/qltk/textedit.py:64 msgid "_Apply" msgstr "_Anwenden" #: quodlibet/browsers/collection/prefs.py:197 #: quodlibet/browsers/paned/prefs.py:251 #: quodlibet/browsers/playlists/menu.py:95 #: quodlibet/browsers/playlists/util.py:42 quodlibet/errorreport/ui.py:103 #: quodlibet/ext/playlist/export_to_folder.py:38 #: 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:44 #: quodlibet/ext/songsmenu/fingerprint/search.py:281 #: quodlibet/ext/songsmenu/fingerprint/submit.py:90 #: quodlibet/ext/songsmenu/importexport.py:40 #: quodlibet/ext/songsmenu/lastfmsync.py:218 #: quodlibet/ext/songsmenu/playlist.py:50 #: 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:326 #: quodlibet/qltk/_editutils.py:39 quodlibet/qltk/getstring.py:28 #: quodlibet/qltk/maskedbox.py:27 quodlibet/qltk/msg.py:54 #: quodlibet/qltk/msg.py:93 quodlibet/qltk/msg.py:111 #: quodlibet/qltk/ratingsmenu.py:33 quodlibet/update.py:95 msgid "_Cancel" msgstr "_Abbrechen" #: quodlibet/browsers/covergrid/main.py:126 msgid "Cover Grid" msgstr "Albenraster" #: quodlibet/browsers/covergrid/main.py:127 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:71 msgid "Show \"All Albums\" Item" msgstr "Eintrag »Alle Alben« anzeigen" #: quodlibet/browsers/covergrid/prefs.py:82 msgid "Wide Mode" msgstr "Breitbildmodus" #: quodlibet/browsers/covergrid/prefs.py:114 #: quodlibet/browsers/covergrid/prefs.py:115 msgid "Cover Magnification" msgstr "Cover-Skalierung" #: quodlibet/browsers/filesystem.py:39 msgid "File System" msgstr "Dateisystem" #: quodlibet/browsers/filesystem.py:40 msgid "_File System" msgstr "Dateis_ystem" #: quodlibet/browsers/filesystem.py:124 quodlibet/qltk/songlist.py:255 msgid "Unable to copy songs" msgstr "Titel konnten nicht kopiert werden" #: quodlibet/browsers/filesystem.py:125 quodlibet/qltk/songlist.py:256 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:197 msgid "_Add to Library" msgstr "_Zur Bibliothek hinzufügen" #: quodlibet/browsers/iradio.py:181 msgid "Unsupported file type" msgstr "Dateityp wird nicht unterstützt" #: quodlibet/browsers/iradio.py:182 #, 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:229 quodlibet/browsers/iradio.py:242 #: quodlibet/browsers/iradio.py:835 msgid "Unable to add station" msgstr "Sender konnte nicht hinzugefügt werden" #: quodlibet/browsers/iradio.py:253 quodlibet/browsers/iradio.py:486 msgid "Internet Radio" msgstr "Internet-Radio" #: quodlibet/browsers/iradio.py:253 msgid "Downloading station list" msgstr "Senderliste wird heruntergeladen" #: quodlibet/browsers/iradio.py:354 msgid "New Station" msgstr "Neuer Sender" #: quodlibet/browsers/iradio.py:355 msgid "Enter the location of an Internet radio station:" msgstr "Bitte geben Sie die URL eines Internet-Radiosenders ein:" #: quodlibet/browsers/iradio.py:373 msgid "Electronic" msgstr "Electronic" #: quodlibet/browsers/iradio.py:376 msgid "Hip Hop / Rap" msgstr "HipHop / Rap" #: quodlibet/browsers/iradio.py:377 msgid "Oldies" msgstr "Oldies" #: quodlibet/browsers/iradio.py:378 msgid "R&B" msgstr "R&B" #: quodlibet/browsers/iradio.py:379 msgid "Japanese" msgstr "Japanisch" #: quodlibet/browsers/iradio.py:380 msgid "Indian" msgstr "Indisch" #: quodlibet/browsers/iradio.py:382 msgid "Religious" msgstr "Religion" #: quodlibet/browsers/iradio.py:384 msgid "Charts" msgstr "Charts" #: quodlibet/browsers/iradio.py:385 msgid "Turkish" msgstr "Türkisch" #: quodlibet/browsers/iradio.py:386 msgid "Reggae / Dancehall" msgstr "Reggae / Dancehall" #: quodlibet/browsers/iradio.py:387 msgid "Latin" msgstr "Latin" #: quodlibet/browsers/iradio.py:388 msgid "College Radio" msgstr "Campusradio" #: quodlibet/browsers/iradio.py:389 msgid "Talk / News" msgstr "Talk / News" #: quodlibet/browsers/iradio.py:390 msgid "Ambient" msgstr "Ambient" #: quodlibet/browsers/iradio.py:391 msgid "Jazz" msgstr "Jazz" #: quodlibet/browsers/iradio.py:392 quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "Klassik" #: quodlibet/browsers/iradio.py:393 quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "Pop" #: quodlibet/browsers/iradio.py:394 msgid "Alternative" msgstr "Alternative" #: quodlibet/browsers/iradio.py:395 msgid "Metal" msgstr "Metal" #: quodlibet/browsers/iradio.py:396 msgid "Country" msgstr "Country" #: quodlibet/browsers/iradio.py:397 msgid "News" msgstr "News" #: quodlibet/browsers/iradio.py:398 msgid "Schlager" msgstr "Schlager" #: quodlibet/browsers/iradio.py:399 msgid "Funk" msgstr "Funk" #: quodlibet/browsers/iradio.py:400 msgid "Indie" msgstr "Indie" #: quodlibet/browsers/iradio.py:401 msgid "Blues" msgstr "Blues" #: quodlibet/browsers/iradio.py:402 msgid "Soul" msgstr "Soul" #: quodlibet/browsers/iradio.py:403 msgid "Lounge" msgstr "Lounge" #: quodlibet/browsers/iradio.py:404 msgid "Punk" msgstr "Punk" #: quodlibet/browsers/iradio.py:405 msgid "Reggaeton" msgstr "Reggaeton" #: quodlibet/browsers/iradio.py:407 msgid "Slavic" msgstr "Slawisch" #: quodlibet/browsers/iradio.py:409 msgid "Greek" msgstr "Griechisch" #: quodlibet/browsers/iradio.py:410 msgid "Gothic" msgstr "Gothic" #: quodlibet/browsers/iradio.py:411 quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "Rock" #: quodlibet/browsers/iradio.py:464 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:470 msgid "_Load Stations" msgstr "Sender _laden" #: quodlibet/browsers/iradio.py:487 msgid "_Internet Radio" msgstr "Internet-_Radio" #: quodlibet/browsers/iradio.py:560 msgid "_New Station…" msgstr "_Neuer Sender …" #: quodlibet/browsers/iradio.py:563 msgid "_Update Stations" msgstr "Sender akt_ualisieren" #: quodlibet/browsers/iradio.py:590 msgid "All Stations" msgstr "Alle Sender" #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:594 quodlibet/browsers/soundcloud/main.py:65 msgid "Favorites" msgstr "Favoriten" #: quodlibet/browsers/iradio.py:602 msgid "No Category" msgstr "Keine Kategorie" #: quodlibet/browsers/iradio.py:827 msgid "No stations found" msgstr "Keine Sender gefunden" #: quodlibet/browsers/iradio.py:828 #, python-format msgid "No Internet radio stations were found at %s." msgstr "Unter %s wurden keine Internet-Radiosender gefunden." #: quodlibet/browsers/iradio.py:836 msgid "All stations listed are already in your library." msgstr "Alle aufgelisteten Sender befinden sich bereits in Ihrer Bibliothek." #: quodlibet/browsers/iradio.py:853 msgid "Add to Favorites" msgstr "Zu Favoriten hinzufügen" #: quodlibet/browsers/iradio.py:857 msgid "Remove from Favorites" msgstr "Aus Favoriten entfernen" #: quodlibet/browsers/iradio.py:957 #, 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:103 quodlibet/qltk/pluginwin.py:122 #: quodlibet/qltk/pluginwin.py:164 msgid "All" msgstr "Alle" #: quodlibet/browsers/paned/prefs.py:41 #: quodlibet/ext/songsmenu/cover_download.py:118 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" "<tt>%s</tt>" msgstr "" "Feldmuster mit optionalem Markup, z.B. <tt>composer</tt> oder\n" "<tt>%s</tt>" #: quodlibet/browsers/paned/prefs.py:231 msgid "Paned Browser Preferences" msgstr "Einstellungen des Browsers" #: quodlibet/browsers/paned/prefs.py:236 msgid "Column layout" msgstr "Spaltenlayout" #: quodlibet/browsers/paned/prefs.py:240 msgid "Column content" msgstr "Spalteninhalt" #: quodlibet/browsers/paned/prefs.py:242 msgid "Equal pane width" msgstr "Gleichmäßige Leistenbreite" #: quodlibet/browsers/playlists/main.py:48 #: quodlibet/browsers/playlists/main.py:603 quodlibet/qltk/pluginwin.py:168 msgid "Playlists" msgstr "Wiedergabelisten" #: quodlibet/browsers/playlists/main.py:49 msgid "_Playlists" msgstr "Wieder_gabelisten" #: quodlibet/browsers/playlists/main.py:152 msgid "_Remove from Playlist" msgstr "Aus der Wiede_rgabeliste entfernen" #: quodlibet/browsers/playlists/main.py:217 msgid "New" msgstr "Neu" #: quodlibet/browsers/playlists/main.py:221 msgid "Import" msgstr "Importieren" #: quodlibet/browsers/playlists/main.py:443 msgid "Unable to import playlist" msgstr "Die Wiedergabeliste konnte nicht importiert werden" #: quodlibet/browsers/playlists/main.py:444 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:494 msgid "_Rename" msgstr "_Umbenennen" #: quodlibet/browsers/playlists/main.py:592 msgid "Unable to rename playlist" msgstr "Die Wiedergabeliste konnte nicht umbenannt werden" #: quodlibet/browsers/playlists/main.py:604 msgid "Import Playlist" msgstr "Wiedergabeliste importieren" #: quodlibet/browsers/playlists/main.py:604 msgid "_Import" msgstr "_Importieren" #: quodlibet/browsers/playlists/menu.py:25 msgid "_New Playlist…" msgstr "Wiedergabeliste a_nlegen …" #: quodlibet/browsers/playlists/menu.py:86 #, 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:90 #, 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:33 #, 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:35 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:50 #: quodlibet/browsers/playlists/util.py:125 quodlibet/util/collection.py:575 msgid "New Playlist" msgstr "Neue Wiedergabeliste" #: quodlibet/browsers/playlists/util.py:51 msgid "Enter a name for the new playlist:" msgstr "Geben Sie einen Namen für die neue Wiedergabeliste ein:" #: quodlibet/browsers/playlists/util.py:89 #, 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/search.py:32 msgid "_Limit Results" msgstr "Ergebnisse _beschränken" #: quodlibet/browsers/search.py:37 msgid "_Allow multiple queries" msgstr "Mehrere _Abfragen erlauben" #: quodlibet/browsers/search.py:53 msgid "Search Library" msgstr "Bibliothek durchsuchen" #: quodlibet/browsers/search.py:54 msgid "_Search Library" msgstr "Bibliothek d_urchsuchen" #: quodlibet/browsers/soundcloud/main.py:39 msgid "Soundcloud Browser" msgstr "Soundcloud-Browser" #: quodlibet/browsers/soundcloud/main.py:40 msgid "Sound_cloud" msgstr "Sound_cloud" #: quodlibet/browsers/soundcloud/main.py:60 quodlibet/qltk/searchbar.py:81 msgid "Search" msgstr "Suchen" #: quodlibet/browsers/soundcloud/main.py:69 msgid "My tracks" msgstr "Eigene Titel" #: quodlibet/browsers/soundcloud/main.py:141 #, python-format msgid "Go to %s" msgstr "Zu %s gehen" #: quodlibet/browsers/soundcloud/main.py:443 msgid "Connected" msgstr "Verbunden" #: quodlibet/browsers/soundcloud/main.py:444 #, python-format msgid "Quod Libet is now connected, <b>%s</b>!" msgstr "Quod Libet ist nun verbunden, <b>%s</b>!" #: quodlibet/browsers/soundcloud/main.py:456 #, python-format msgid "Log out of %s" msgstr "Von %s abmelden" #: quodlibet/browsers/soundcloud/main.py:458 msgid "Enter code…" msgstr "Code eingeben …" #: quodlibet/browsers/soundcloud/main.py:459 #, python-format msgid "Log in to %s" msgstr "Zu %s anmelden" #: quodlibet/browsers/soundcloud/util.py:86 msgid "Soundcloud authorisation" msgstr "Soundcloud-Autorisierung" #: quodlibet/browsers/soundcloud/util.py:87 msgid "Enter Soundcloud auth code:" msgstr "Geben Sie den Soundcloud-Autorisierungs-Code ein:" #: quodlibet/cli.py:50 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:86 msgid "a music library and player" msgstr "Musikbibliothek und Musikwiedergabe" #: quodlibet/cli.py:87 msgid "[option]" msgstr "[Option]" #: quodlibet/cli.py:89 msgid "Print the playing song and exit" msgstr "Momentan gespielten Titel anzeigen" #: quodlibet/cli.py:90 msgid "Begin playing immediately" msgstr "Wiedergabe sofort starten" #: quodlibet/cli.py:91 msgid "Don't show any windows on start" msgstr "Keine Fenster beim Programmstart anzeigen" #: quodlibet/cli.py:94 msgid "Jump to next song" msgstr "Nächsten Titel abspielen" #: quodlibet/cli.py:96 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:97 msgid "Jump to previous song" msgstr "Vorherigen Titel abspielen" #: quodlibet/cli.py:98 msgid "Start playback" msgstr "Wiedergabe starten" #: quodlibet/cli.py:99 msgid "Pause playback" msgstr "Wiedergabe pausieren" #: quodlibet/cli.py:100 msgid "Toggle play/pause mode" msgstr "Zwischen Wiedergabe/Pause umschalten" #: quodlibet/cli.py:101 msgid "Stop playback" msgstr "Wiedergabe stoppen" #: quodlibet/cli.py:102 msgid "Turn up volume" msgstr "Lautstärke erhöhen" #: quodlibet/cli.py:103 msgid "Turn down volume" msgstr "Lautstärke senken" #: quodlibet/cli.py:104 msgid "Increase rating of playing song by one star" msgstr "" "Die Bewertung des aktuell wiedergegebenen Titels um einen Stern erhöhen" #: quodlibet/cli.py:105 msgid "Decrease rating of playing song by one star" msgstr "" "Die Bewertung des aktuell wiedergegebenen Titels um einen Stern verringern" #: quodlibet/cli.py:106 msgid "Print player status" msgstr "Wiedergabestatus anzeigen" #: quodlibet/cli.py:107 msgid "Hide main window" msgstr "Hauptfenster verbergen" #: quodlibet/cli.py:108 msgid "Show main window" msgstr "Hauptfenster anzeigen" #: quodlibet/cli.py:109 msgid "Toggle main window visibility" msgstr "Hauptfenster anzeigen/verbergen" #: quodlibet/cli.py:110 msgid "Focus the running player" msgstr "Fokus auf laufenden Player setzen" #: quodlibet/cli.py:111 msgid "Remove active browser filters" msgstr "Aktive Browserfilter entfernen" #: quodlibet/cli.py:112 msgid "Refresh and rescan library" msgstr "Bibliothek aktualisieren und neu einlesen" #: quodlibet/cli.py:113 msgid "List available browsers" msgstr "Verfügbare Browser auflisten" #: quodlibet/cli.py:114 msgid "Print the current playlist" msgstr "Aktuelle Wiedergabeliste anzeigen" #: quodlibet/cli.py:115 msgid "Print the contents of the queue" msgstr "Aktuelle Warteschlange anzeigen" #: quodlibet/cli.py:116 msgid "Print the active text query" msgstr "Den aktuellen Abfragetext anzeigen" #: quodlibet/cli.py:117 msgid "Start without plugins" msgstr "Ohne Plugins starten" #: quodlibet/cli.py:118 msgid "Start Quod Libet if it isn't running" msgstr "Quod Libet starten, wenn es nicht läuft" #: quodlibet/cli.py:119 msgid "Exit Quod Libet" msgstr "Quod Libet beenden" #: quodlibet/cli.py:124 msgid "Seek within the playing song" msgstr "Zu einer bestimmten Position im momentan abgespielten Titel gehen" #: quodlibet/cli.py:124 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: quodlibet/cli.py:125 msgid "Set or toggle shuffle mode" msgstr "Zufallsmodus setzen oder umschalten" #: quodlibet/cli.py:126 msgid "Set shuffle mode type" msgstr "Art des Zufallsmodus setzen" #: quodlibet/cli.py:127 msgid "Turn repeat off, on, or toggle it" msgstr "Endlosschleife ein-, aus-, oder zwischen beiden Modi umschalten" #: quodlibet/cli.py:128 msgid "Set repeat mode type" msgstr "Art des Endlosschleifenmodus setzen" #: quodlibet/cli.py:129 msgid "Set the volume" msgstr "Lautstärke einstellen" #: quodlibet/cli.py:130 msgid "Search your audio library" msgstr "Audio-Bibliothek durchsuchen" #: quodlibet/cli.py:130 quodlibet/cli.py:140 quodlibet/cli.py:144 #: quodlibet/cli.py:146 msgid "query" msgstr "Abfrage" #: quodlibet/cli.py:131 msgid "Play a file" msgstr "Datei abspielen" #: quodlibet/cli.py:131 quodlibet/cli.py:140 quodlibet/cli.py:146 msgctxt "command" msgid "filename" msgstr "Dateiname" #: quodlibet/cli.py:132 msgid "Set rating of playing song" msgstr "Die Bewertung des aktuell wiedergegebenen Titels setzen" #: quodlibet/cli.py:133 msgid "Set the current browser" msgstr "Aktuellen Browser einstellen" #: quodlibet/cli.py:134 msgid "Stop after the playing song" msgstr "Nach dem momentan gespielten Titel stoppen" #: quodlibet/cli.py:135 msgid "Open a new browser" msgstr "Neuen Browser öffnen" #: quodlibet/cli.py:136 msgid "Show or hide the queue" msgstr "Warteschlange anzeigen oder verbergen" #: quodlibet/cli.py:137 msgid "Filter on a random value" msgstr "Nach zufälligem Wert filtern" #: quodlibet/cli.py:137 msgctxt "command" msgid "tag" msgstr "Feld" #: quodlibet/cli.py:138 msgid "Filter on a tag value" msgstr "Nach Metadatenfeldwert filtern" #: quodlibet/cli.py:138 msgid "tag=value" msgstr "tag=Wert" #: quodlibet/cli.py:139 msgid "Enqueue a file or query" msgstr "Eine Datei oder eine Abfrage zur Warteschlange hinzufügen" #: quodlibet/cli.py:141 msgid "Enqueue comma-separated files" msgstr "" "Mehrere Dateien – durch Kommata getrennt – zur Warteschlange hinzufügen" #: quodlibet/cli.py:142 quodlibet/util/tags.py:157 msgid "filename" msgstr "Dateiname" # Klingt genauso wackelig wie das Englische. Was meinst? #: quodlibet/cli.py:143 msgid "Print filenames of results of query to stdout" msgstr "Dateinamen von Abfrageergebnissen auf Standardausgabe ausgeben" #: quodlibet/cli.py:145 msgid "Unqueue a file or query" msgstr "Eine Datei oder eine Abfrage aus Warteschlange entfernen" #: quodlibet/cli.py:147 msgid "Add a file or directory to the library" msgstr "Eine Datei oder ein Verzeichnis zur Bibliothek hinzufügen" #: quodlibet/cli.py:148 quodlibet/util/tags.py:100 msgid "location" msgstr "URL" #: quodlibet/cli.py:213 #, python-format msgid "Invalid argument for '%s'." msgstr "Argument für »%s« ungültig." #: quodlibet/cli.py:214 quodlibet/util/__init__.py:173 #, 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 "Quit Program" msgstr "Programm beenden" #: 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:34 msgid "an audio tag editor" msgstr "ein Editor für Audio-Metadaten" #: quodlibet/exfalso.py:34 quodlibet/util/tags.py:158 msgid "directory" msgstr "Verzeichnis" #: quodlibet/exfalso.py:41 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:20 msgid "" "Downloads covers linked to by the artwork_url tag. This works with the " "Soundcloud browser." msgstr "" "Lädt Cover, die über das Metadatenfeld »artwork_url« verlinkt sind, " "herunter. Funktioniert mit dem Soundcloud-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:20 msgid "MusicBrainz Cover Source" msgstr "MusicBrainz-Cover-Quelle" #: quodlibet/ext/covers/musicbrainz.py:21 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:19 msgid "" "Allows arbitrary regex substitutions (s///) when tagging or renaming files." msgstr "" "Erlaubt beliebige Ersetzungen mit regulären Ausdrücken (s///) 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:67 msgid "Advanced Preferences" msgstr "Erweiterte Einstellungen" #: quodlibet/ext/events/advanced_preferences.py:68 msgid "Allow editing of advanced config settings." msgstr "Erweiterte Konfigurationseinstellungen anpassen." #: quodlibet/ext/events/advanced_preferences.py:180 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/ext/events/weblyrics.py:318 quodlibet/qltk/prefs.py:266 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:66 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:172 msgid "Effects" msgstr "Effekte" #: quodlibet/ext/events/animosd/prefs.py:288 msgid "Ed_it Display Pattern…" msgstr "Anzeigemuster b_earbeiten …" #: quodlibet/ext/events/animosd/prefs.py:292 #: 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_library_update.py:138 msgid "Automatic Library Update" msgstr "Automatische Bibliotheks-Aktualisierung" #: quodlibet/ext/events/auto_library_update.py:139 #, python-format msgid "Keeps your library up to date with inotify. Requires %s." msgstr "Hält die Bibliothek mit inotify aktuell. Benötigt %s." #: 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 by Brian Nelson." msgstr "" "Bewertet Titel automatisch, wenn sie abgespielt oder übersprungen werden. " "Benutzt den »beschleunigten« Algorithmus aus vux von Brian Nelson." #: quodlibet/ext/events/bansheeimport.py:106 msgid "Specified Banshee database is malformed or missing" msgstr "Die angegebene Banshee-Datenbank ist ungültig oder nicht vorhanden" #: quodlibet/ext/events/bansheeimport.py:111 #: quodlibet/ext/events/rbimport.py:114 msgid "Import Failed" msgstr "Import fehlgeschlagen" #: quodlibet/ext/events/bansheeimport.py:117 #, 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:126 msgid "Banshee Import" msgstr "Banshee-Import" #: quodlibet/ext/events/bansheeimport.py:127 msgid "Imports ratings and song statistics from Banshee." msgstr "Bewertungen und Titelstatistiken von Banshee importieren." #: quodlibet/ext/events/bansheeimport.py:136 msgid "_Database path:" msgstr "_Datenbankpfad:" #: quodlibet/ext/events/bansheeimport.py:164 #: quodlibet/ext/events/rbimport.py:132 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/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:93 #: quodlibet/ext/gstreamer/karaoke.py:95 #, python-format msgid "%d Hz" msgstr "%d Hz" #: quodlibet/ext/events/equalizer.py:198 #: quodlibet/ext/gstreamer/crossfeed.py:112 #, 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/playlist/export_to_squeezebox.py:80 #: quodlibet/ext/songsmenu/albumart.py:324 #: quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/cover_download.py:309 #: quodlibet/ext/songsmenu/fingerprint/search.py:278 #: quodlibet/ext/songsmenu/html.py:75 quodlibet/ext/songsmenu/lastfmsync.py:219 #: quodlibet/ext/songsmenu/playlist.py:51 #: quodlibet/ext/songsmenu/replaygain.py:354 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/_editutils.py:40 #: quodlibet/qltk/lyrics.py:34 quodlibet/qltk/msg.py:52 #: quodlibet/qltk/renamefiles.py:216 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:42 msgid "Inhibit Screensaver" msgstr "Bildschirmschoner blockieren" #: quodlibet/ext/events/inhibit.py:43 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." #: quodlibet/ext/events/inhibit.py:52 msgid "Music is playing" msgstr "Musik wird wiedergegeben" #: quodlibet/ext/events/iradiolog.py:16 msgid "Internet Radio Log" msgstr "Internet-Radio-Log" #: quodlibet/ext/events/iradiolog.py:17 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:31 msgid "Outputs a Jabber User Tunes file to ~/.quodlibet/jabber." msgstr "Speichert eine Jabber-User-Tunes-Datei in ~/.quodlibet/jabber." #: 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 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:37 msgid "MPRIS D-Bus Support" msgstr "MPRIS-D-Bus-Unterstützung" #: quodlibet/ext/events/mpris/__init__.py:38 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." #: quodlibet/ext/events/mpris/__init__.py:44 #: quodlibet/ext/events/trayicon/prefs.py:36 msgid "Hide main window on close" msgstr "Hauptfenster beim Schließen verbergen" #: quodlibet/ext/events/mpris/__init__.py:47 #: quodlibet/ext/events/themeswitcher.py:84 #: quodlibet/ext/gstreamer/compressor.py:99 #: quodlibet/ext/gstreamer/crossfeed.py:136 #: quodlibet/ext/gstreamer/karaoke.py:99 quodlibet/ext/gstreamer/pitch.py:89 #: quodlibet/qltk/prefs.py:741 msgid "Preferences" msgstr "Einstellungen" #: quodlibet/ext/events/mqtt.py:54 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "Akzeptiert QL-Muster, z.B. %s" #: quodlibet/ext/events/mqtt.py:60 msgid "MQTT Publisher" msgstr "MQTT-Publisher" #: quodlibet/ext/events/mqtt.py:61 msgid "Publishes status messages to an MQTT topic." msgstr "Veröffentlicht Statusnachrichten an ein MQTT-Thema." #: quodlibet/ext/events/mqtt.py:128 msgid "Broker hostname" msgstr "Broker-Hostname" #: quodlibet/ext/events/mqtt.py:129 msgid "broker hostname / IP (defaults to localhost)" msgstr "Broker-Hostname / IP (Vorgabe ist localhost)" #: quodlibet/ext/events/mqtt.py:131 msgid "Broker port" msgstr "Broker-Port" #: quodlibet/ext/events/mqtt.py:131 msgid "broker port (defaults to 1883)" msgstr "Broker-Port (Vorgabe ist 1883)" #: quodlibet/ext/events/mqtt.py:133 msgid "Topic" msgstr "Thema" #: quodlibet/ext/events/mqtt.py:135 msgid "Playing Pattern" msgstr "Muster für Wiedergabe" #: quodlibet/ext/events/mqtt.py:137 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:139 msgid "Paused Pattern" msgstr "Muster für Pause" #: quodlibet/ext/events/mqtt.py:141 msgid "Text when a song is paused." msgstr "Statustext für den Fall, dass die Wiedergabe pausiert ist." #: quodlibet/ext/events/mqtt.py:143 msgid "No-song Text" msgstr "Text bei gestoppter Wiedergabe" #: quodlibet/ext/events/mqtt.py:145 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:156 msgid "MQTT Configuration" msgstr "MQTT-Konfiguration" #: quodlibet/ext/events/mqtt.py:160 msgid "Status Text" msgstr "Statustext" #: quodlibet/ext/events/mqtt.py:192 #, 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:196 #, 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:199 msgid "Connection error" msgstr "Verbindungsfehler" #: 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/qlscrobbler.py:175 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:252 #, python-format msgid "Could not contact service '%s'." msgstr "Konnte den Service »%s« nicht kontaktieren." #: quodlibet/ext/events/qlscrobbler.py:258 msgid "Authentication failed: invalid URL." msgstr "Authentifizierung fehlgeschlagen: Ungültige URL." #: quodlibet/ext/events/qlscrobbler.py:275 #, 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:280 msgid "Client is banned. Contact the author." msgstr "Client wurde verboten. Kontaktieren Sie den Autor." #: quodlibet/ext/events/qlscrobbler.py:284 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:349 msgid "AudioScrobbler Submission" msgstr "Audioscrobbler-Einsendung" #: quodlibet/ext/events/qlscrobbler.py:350 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:455 msgid "Authentication successful." msgstr "Authentifizierung erfolgreich." #: quodlibet/ext/events/qlscrobbler.py:467 msgid "_Service:" msgstr "_Service:" #: quodlibet/ext/events/qlscrobbler.py:467 msgid "_URL:" msgstr "_URL:" #: quodlibet/ext/events/qlscrobbler.py:467 msgid "User_name:" msgstr "Benutzer_name:" #: quodlibet/ext/events/qlscrobbler.py:468 msgid "_Password:" msgstr "_Passwort:" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:484 msgid "Other…" msgstr "Anderer …" #. verify data #: quodlibet/ext/events/qlscrobbler.py:522 msgid "_Verify account data" msgstr "Kontodaten _verifizieren" #: quodlibet/ext/events/qlscrobbler.py:527 #: quodlibet/ext/songsmenu/lastfmsync.py:312 msgid "Account" msgstr "Konto" #: quodlibet/ext/events/qlscrobbler.py:535 msgid "_Artist pattern:" msgstr "_Künstler-Muster:" #: quodlibet/ext/events/qlscrobbler.py:535 msgid "_Title pattern:" msgstr "_Titel-Muster:" #: quodlibet/ext/events/qlscrobbler.py:536 msgid "Exclude _filter:" msgstr "Ausschluss_filter:" #: quodlibet/ext/events/qlscrobbler.py:554 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:564 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:573 msgid "Songs matching this filter will not be submitted" msgstr "Titel, die diesem Filter entsprechen, werden nicht eingesendet" #: quodlibet/ext/events/qlscrobbler.py:581 msgid "_Offline mode (don't submit anything)" msgstr "_Offlinemodus (nichts einsenden)" #: quodlibet/ext/events/qlscrobbler.py:585 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:28 msgid "Random Album Playback" msgstr "Zufälliges Album wiedergeben" #: quodlibet/ext/events/randomalbum.py:29 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:39 msgid "Rated higher" msgstr "Höher bewertet" #: quodlibet/ext/events/randomalbum.py:40 msgid "Played more often" msgstr "Häufiger abgespielt" #: quodlibet/ext/events/randomalbum.py:41 msgid "Skipped more often" msgstr "Häufiger übersprungen" #: quodlibet/ext/events/randomalbum.py:42 msgid "Played more recently" msgstr "Kürzlich abgespielt" #: quodlibet/ext/events/randomalbum.py:43 msgid "Started more recently" msgstr "Kürzlich angespielt" #: quodlibet/ext/events/randomalbum.py:44 msgid "Added more recently" msgstr "Kürzlich hinzugefügt" #: quodlibet/ext/events/randomalbum.py:45 msgid "Longer albums" msgstr "Längere Alben" #: quodlibet/ext/events/randomalbum.py:84 msgid "seconds before starting next album" msgstr "Sekunden, bevor das nächste Album gestartet wird" #: quodlibet/ext/events/randomalbum.py:88 msgid "Weights" msgstr "Gewichte" #: quodlibet/ext/events/randomalbum.py:90 msgid "Play some albums more than others" msgstr "Einige Alben häufiger als andere abspielen" #: quodlibet/ext/events/randomalbum.py:104 msgid "avoid" msgstr "vermeiden" #: quodlibet/ext/events/randomalbum.py:115 msgid "prefer" msgstr "bevorzugen" #: quodlibet/ext/events/randomalbum.py:219 msgid "Random Album" msgstr "Zufälliges Album" #: quodlibet/ext/events/randomalbum.py:220 #, python-format msgid "Waiting to start %s" msgstr "Warte bis zum Start von %s" #: quodlibet/ext/events/rbimport.py:119 #, 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:127 msgid "Rhythmbox Import" msgstr "Rhythmbox-Import" #: quodlibet/ext/events/rbimport.py:128 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:73 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:79 msgid "GNOME Search Provider" msgstr "GNOME-Suchprovider" #: quodlibet/ext/events/searchprovider.py:80 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" "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" "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:29 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:57 #: quodlibet/ext/playlist/export_to_squeezebox.py:89 msgid "Error finding Squeezebox server" msgstr "Fehler beim Finden des Squeezebox-Servers" #: quodlibet/ext/events/squeezebox_sync.py:58 #: quodlibet/ext/playlist/export_to_squeezebox.py:90 #, python-format msgid "Error finding %s. Please check settings" msgstr "Fehler beim Finden von %s. Bitte überprüfen Sie die Einstellungen" #: quodlibet/ext/events/synchronizedlyrics.py:34 msgid "Synchronized Lyrics" msgstr "Synchronisierte Liedtexte" #: quodlibet/ext/events/synchronizedlyrics.py:35 msgid "Shows synchronized lyrics from .lrc file with same name as the track." msgstr "" "Zeigt Liedtexte aus einer .lrc-Datei mit demselben Namen wie der abgespielte " "Titel synchron an." #: quodlibet/ext/events/synchronizedlyrics.py:69 msgid "Text:" msgstr "Text:" #: quodlibet/ext/events/synchronizedlyrics.py:79 msgid "Background:" msgstr "Hintergrund:" #: quodlibet/ext/events/synchronizedlyrics.py:90 msgid "Font" msgstr "Schrift" #: quodlibet/ext/events/synchronizedlyrics.py:93 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:145 msgid "Paused:" msgstr "Pausiert:" #: quodlibet/ext/events/telepathy_status.py:146 #, 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:162 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:163 msgid "No song:" msgstr "Keine Wiedergabe:" #. Frame #: quodlibet/ext/events/telepathy_status.py:170 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:91 msgid "Thumb Rating" msgstr "Daumen-Bewertung" #: quodlibet/ext/events/thumbrating.py:92 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 '~#score'." 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 »~#score« 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:47 msgid "Not playing" msgstr "Keine Wiedergabe" #: quodlibet/ext/events/trayicon/__init__.py:53 msgid "Tray Icon" msgstr "Taskleistensymbol" #: quodlibet/ext/events/trayicon/__init__.py:54 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:183 quodlibet/qltk/quodlibetwindow.py:936 #: quodlibet/qltk/quodlibetwindow.py:1142 msgid "_Play" msgstr "Abs_pielen" #: quodlibet/ext/events/trayicon/menu.py:63 #: quodlibet/qltk/quodlibetwindow.py:185 quodlibet/qltk/quodlibetwindow.py:1144 #: quodlibet/qltk/wlw.py:50 msgid "P_ause" msgstr "P_ause" #: quodlibet/ext/events/trayicon/menu.py:68 #: quodlibet/qltk/quodlibetwindow.py:190 quodlibet/qltk/quodlibetwindow.py:931 msgid "Pre_vious" msgstr "_Vorheriger" #: quodlibet/ext/events/trayicon/menu.py:71 #: quodlibet/qltk/quodlibetwindow.py:194 quodlibet/qltk/quodlibetwindow.py:941 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:902 msgid "Open _Browser" msgstr "_Browser öffnen" #: quodlibet/ext/events/trayicon/menu.py:103 #: quodlibet/qltk/quodlibetwindow.py:921 quodlibet/qltk/songsmenu.py:383 msgid "Edit _Tags" msgstr "_Metadaten bearbeiten" #: quodlibet/ext/events/trayicon/menu.py:112 #: quodlibet/qltk/quodlibetwindow.py:864 quodlibet/qltk/songsmenu.py:396 msgid "_Information" msgstr "_Informationen" #: quodlibet/ext/events/trayicon/menu.py:114 quodlibet/qltk/songsmenu.py:324 msgid "Play_lists" msgstr "Wieder_gabelisten" #: quodlibet/ext/events/trayicon/menu.py:132 #: quodlibet/qltk/quodlibetwindow.py:916 msgid "_Quit" msgstr "_Beenden" #: quodlibet/ext/events/trayicon/prefs.py:38 quodlibet/qltk/prefs.py:69 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 quodlibet/ext/events/weblyrics.py:193 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:603 msgid "Waveform Seek Bar" msgstr "Wellenform-Titelpositionsleiste" #: quodlibet/ext/events/waveformseekbar.py:607 msgid "A seekbar in the shape of the waveform of the current song." msgstr "" "Eine Titelpositionsleiste in der Gestalt der Wellenform des aktuell " "abgespielten Titels." #: quodlibet/ext/events/waveformseekbar.py:676 msgid "Override foreground color:" msgstr "Vordergrund-Farbe überschreiben:" #: quodlibet/ext/events/waveformseekbar.py:680 msgid "Override hover color:" msgstr "Mouse-over-Farbe überschreiben:" #: quodlibet/ext/events/waveformseekbar.py:684 msgid "Override remaining color:" msgstr "Farbe für die verbleibende Zeit überschreiben:" #: quodlibet/ext/events/waveformseekbar.py:688 msgid "Show current position" msgstr "Aktuelle Position anzeigen" #: quodlibet/ext/events/waveformseekbar.py:693 msgid "Show time labels" msgstr "Zeitmarken anzeigen" #: quodlibet/ext/events/waveformseekbar.py:701 msgid "Seek amount when scrolling (milliseconds):" msgstr "Titelpositionsbetrag beim Scrollen (Millisekunden):" #: quodlibet/ext/events/weblyrics.py:208 msgid "No lyrics found" msgstr "Kein Liedtext gefunden" #: quodlibet/ext/events/weblyrics.py:268 msgid "_Zoom level:" msgstr "_Vergößerungsfaktor:" #: quodlibet/ext/events/weblyrics.py:286 msgid "URL:" msgstr "URL:" #: quodlibet/ext/events/weblyrics.py:291 msgid "Revert to default" msgstr "Standard wiederherstellen" #: quodlibet/ext/events/weblyrics.py:306 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." #: quodlibet/ext/events/weblyrics.py:323 msgid "Alternate search" msgstr "Alternative Suche" #: quodlibet/ext/events/weblyrics.py:332 msgid "Web Lyrics" msgstr "Web-Liedtext" #: quodlibet/ext/events/weblyrics.py:333 msgid "Shows a sidebar containing online lyrics of the playing song." msgstr "" "Zeigt eine Seitenleiste mit Online-Liedtext des aktuell wiedergegebenen " "Titels an." # »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:20 msgid "_Threshold:" msgstr "_Schwellenwert:" #: quodlibet/ext/gstreamer/compressor.py:21 msgid "Threshold until the filter is activated" msgstr "Schwellenwert, ab dem der Filter aktiviert wird" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "R_atio:" msgstr "R_ate:" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "Compression ratio" msgstr "Kompressionsrate" #: quodlibet/ext/gstreamer/compressor.py:74 #: quodlibet/ext/gstreamer/karaoke.py:91 #, python-format msgid "%d %%" msgstr "%d %%" #: quodlibet/ext/gstreamer/compressor.py:105 msgid "Audio Compressor" msgstr "Audiokompressor" #: quodlibet/ext/gstreamer/compressor.py:106 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:19 msgid "_Preset:" msgstr "_Vorgabe:" #: quodlibet/ext/gstreamer/crossfeed.py:19 msgid "Filter preset" msgstr "Filtervorgabe" #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Frequency cut:" msgstr "Grenz_frequenz:" #: quodlibet/ext/gstreamer/crossfeed.py:20 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:21 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:21 msgid "Feed level" msgstr "Einspeispegel" #: quodlibet/ext/gstreamer/crossfeed.py:25 msgid "Default" msgstr "Standard" #: quodlibet/ext/gstreamer/crossfeed.py:26 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:27 msgid "Chu Moy" msgstr "Chu Moy" #: quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "Ähnlich zu Chu Moys Crossfeeder (beliebt)" #: quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Jan Meier" msgstr "Jan Meier" #: quodlibet/ext/gstreamer/crossfeed.py:30 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:31 msgid "Custom" msgstr "Benutzerdefiniert" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Custom settings" msgstr "Benutzerdefinierte Einstellungen" #: quodlibet/ext/gstreamer/crossfeed.py:152 msgid "Crossfeed" msgstr "Crossfeed" #: quodlibet/ext/gstreamer/crossfeed.py:153 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:20 msgid "Filter _band:" msgstr "Filter_band:" #: quodlibet/ext/gstreamer/karaoke.py:21 msgid "The Frequency band of the filter" msgstr "Das Frequenzband des Filters" #: quodlibet/ext/gstreamer/karaoke.py:22 msgid "Filter _width:" msgstr "Filterb_reite:" #: quodlibet/ext/gstreamer/karaoke.py:23 msgid "The Frequency width of the filter" msgstr "Die Frequenzbreite des Filters" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "_Level:" msgstr "_Grad:" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "Level of the effect" msgstr "Grad des Effekts" #: quodlibet/ext/gstreamer/karaoke.py:105 msgid "Karaoke" msgstr "Karaoke" #: quodlibet/ext/gstreamer/karaoke.py:106 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:21 msgid "R_ate:" msgstr "R_ate:" #: quodlibet/ext/gstreamer/pitch.py:22 msgid "_Tempo:" msgstr "_Tempo:" #: quodlibet/ext/gstreamer/pitch.py:23 msgid "_Pitch:" msgstr "Ton_höhe:" #: quodlibet/ext/gstreamer/pitch.py:95 msgid "Audio Pitch / Speed" msgstr "Audio-Tonhöhe/-Geschwindigkeit" #: quodlibet/ext/gstreamer/pitch.py:96 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:147 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:100 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:121 #: quodlibet/ext/songsmenu/playlist.py:132 msgid "Unable to export playlist" msgstr "Die Wiedergabeliste konnte nicht exportiert werden" #: quodlibet/ext/playlist/export_to_folder.py:122 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:165 msgid "Default filename pattern:" msgstr "Standardmuster für Dateinamen:" #: 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. Shares configuration with <a href=" "\"quodlibet:///prefs/plugins/Squeezebox Output\">Squeezebox Sync plugin</a>." msgstr "" "Exportiert dynamisch die Wiedergabeliste zu einer Logitech-Squeezebox-" "Wiedergabeliste. Dafür müssen beide dieselbe Verzeichnisstruktur teilen. " "Teilt die Konfiguration mit dem <a href=\"quodlibet:///prefs/plugins/" "Squeezebox Output\">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:96 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 "" "Playback follows your selection, or the next song in the list once exhausted." msgstr "" "Die Wiedergabe folgt der Auswahl. Ist die Auswahl erschöpft, wird der " "nächste Titel in der Liste wiedergegeben." #: quodlibet/ext/playorder/playcounteq.py:21 msgid "Playcount Equalizer" msgstr "Wiedergabeanzahl ausgleichen" #: quodlibet/ext/playorder/playcounteq.py:22 msgid "Shuffle, preferring songs with fewer total plays." msgstr "" "Zufallsmodus, bei dem Titel bevorzugt werden, die seltener wiedergegeben " "wurden." #: quodlibet/ext/playorder/playcounteq.py:24 msgid "Prefer less played" msgstr "Seltener wiedergegebene bevorzugen" #: quodlibet/ext/playorder/queue.py:19 msgid "Queue Only" msgstr "Nur Warteschlange" #: quodlibet/ext/playorder/queue.py:21 msgid "" "Limits playing of songs to the queue. 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. 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/reverse.py:14 msgid "Reverse" msgstr "Umkehren" #: quodlibet/ext/playorder/reverse.py:16 msgid "Reverses the play order of songs." msgstr "Kehrt die Wiedergabereihenfolge von Titeln um." #: quodlibet/ext/playorder/shufflebygrouping.py:31 #: quodlibet/ext/playorder/shufflebygrouping.py:93 msgid "Shuffle by Grouping" msgstr "Zufällige Wiedergabe nach Gruppierung" #: quodlibet/ext/playorder/shufflebygrouping.py:32 msgid "" "Shuffles by a grouping of songs defined by a common tag instead of by track, " "similar to album shuffle. This is useful for shuffling multi-movement " "classical works while making sure all movements play in order before " "shuffling to the next piece." msgstr "" "Gibt über ein gemeinsames Metadatenfeld definierte Gruppierungen von Titeln " "statt einzelne Titel per Zufall wieder, ähnlich dem Modus »Zufälliges Album " "wiedergeben«. 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:38 msgid "Shuffle by grouping" msgstr "Zufall nach Gruppierung" #: quodlibet/ext/playorder/shufflebygrouping.py:94 msgid "Waiting to start new group…" msgstr "Warte auf den Start einer neuen Gruppe …" #: quodlibet/ext/playorder/shufflebygrouping.py:144 msgid "Grouping tag:" msgstr "Gruppierungsfeld:" #: quodlibet/ext/playorder/shufflebygrouping.py:148 msgid "Tag to group songs by" msgstr "Feld, nach dem Titel gruppiert werden" #: quodlibet/ext/playorder/shufflebygrouping.py:150 msgid "Filter tag:" msgstr "Filterfeld:" #: quodlibet/ext/playorder/shufflebygrouping.py:155 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:160 msgid "Delay:" msgstr "Verzögerung:" #: quodlibet/ext/playorder/shufflebygrouping.py:166 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:182 msgid "Reset to defaults" msgstr "Standardwerte wiederherstellen" #: quodlibet/ext/playorder/skip_songs.py:25 msgid "Skip Songs" msgstr "Titel überspringen" #: quodlibet/ext/playorder/skip_songs.py:27 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." #: quodlibet/ext/playorder/track_repeat.py:30 msgid "Repeat Each Track" msgstr "Jeden Titel wiederholen" #: quodlibet/ext/playorder/track_repeat.py:32 msgid "Shuffle songs, but repeat every track a set number of times." msgstr "" "Titel in zufälliger Reihenfolge wiedergeben, wobei jeder Titel eine feste " "Anzahl von Malen wiederholt wird." #: quodlibet/ext/playorder/track_repeat.py:51 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. Syntax is '@(if: " "condition, then, else)'." msgstr "" "Erlaubt es der Abfrage, Ergebnisse basierend auf einer Bedingungsabfrage zu " "finden. Die Syntax ist »@(if: Bedingung, dann, sonst)«." #: quodlibet/ext/query/missing.py:15 msgid "Missing Query" msgstr "Abfrage nach fehlenden Metadaten" #: quodlibet/ext/query/missing.py:16 msgid "Matches songs without the given tag." msgstr "Titel ohne das angegebene Metadatenfeld finden." #: quodlibet/ext/query/missing.py:27 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. Syntax is '@(python: expression)'. The " "variable 's' (or 'a') is the song / album being matched. '_ts' is a (real " "number) timestamp at start of query. Modules 'time' and 'random' are also " "available, and the class 'Random' (==random.Random) too." msgstr "" "Erlaubt es, Python-Ausdrücke in Abfragen zu benutzen. Die Syntax ist " "»@(python: Ausdruck)«. Die Variable »s« (oder »a«) ist der Titel (bzw. das " "Album), auf dem die Abfrage aktuell arbeitet. »_ts« ist ein Zeitstempel " "(reelle Zahl) zu Beginn der Abfrage. Die Module »time« und »random« sind " "verfügbar, ebenso wie die Klasse »Random« (random.Random)." #: quodlibet/ext/query/savedsearch.py:19 msgid "Include Saved Search" msgstr "Gespeicherten Suchlauf einschließen" #: quodlibet/ext/query/savedsearch.py:20 msgid "" "Include the results of a saved search as part of another query. Syntax is " "'@(saved: search name)'." msgstr "" "Die Ergebnisse eines gespeicherten Suchlaufs als Teil einer anderen Abfrage " "einschließen. Die Syntax ist »@(saved: Name des Suchlaufs)«." #: 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:116 msgid "Port:" msgstr "Port:" #: quodlibet/ext/_shared/squeezebox/base.py:121 msgid "Username:" msgstr "Benutzername:" #: quodlibet/ext/_shared/squeezebox/base.py:126 msgid "Password:" msgstr "Passwort:" #: quodlibet/ext/_shared/squeezebox/base.py:130 msgid "Library directory the server connects to" msgstr "Bibliotheksverzeichnis, mit dem sich der Server verbindet" #: quodlibet/ext/_shared/squeezebox/base.py:132 msgid "Library path:" msgstr "Bibliothekspfad:" #. Add verify button #: quodlibet/ext/_shared/squeezebox/base.py:141 msgid "_Verify settings" msgstr "Einstellungen _verifizieren" #. Server settings Frame #: quodlibet/ext/_shared/squeezebox/base.py:147 msgid "Squeezebox Server" msgstr "Squeezebox-Server" #: quodlibet/ext/_shared/squeezebox/base.py:150 msgid "Debug" msgstr "Debug" #: quodlibet/ext/_shared/squeezebox/server.py:26 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "Squeezebox-Server unter {hostname}:{port}" #: quodlibet/ext/_shared/squeezebox/server.py:28 msgid "unidentified Squeezebox server" msgstr "Unidentifizierter Squeezebox-Server" #: quodlibet/ext/_shared/squeezebox/server.py:37 #, 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:20 #: quodlibet/ext/songsmenu/importexport.py:39 quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "_OK" #: 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:331 msgid "Fit image to _window" msgstr "Grafik an _Fenster anpassen" #: quodlibet/ext/songsmenu/albumart.py:337 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:343 msgid "_Program:" msgstr "_Programm:" #: quodlibet/ext/songsmenu/albumart.py:348 msgid "_Edit image after saving" msgstr "Bild nach Speichern b_earbeiten" #: quodlibet/ext/songsmenu/albumart.py:350 msgid "File_name:" msgstr "Datei_name:" #: quodlibet/ext/songsmenu/albumart.py:466 msgid "Saving failed" msgstr "Speichern fehlgeschlagen" #: quodlibet/ext/songsmenu/albumart.py:467 #, python-format msgid "Unable to save \"%s\"." msgstr "»%s« konnte nicht gespeichert werden." #: quodlibet/ext/songsmenu/albumart.py:565 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "[albumart] HTTP-Fehler: %s" #: quodlibet/ext/songsmenu/albumart.py:622 msgid "Album Art Downloader" msgstr "Album-Cover-Downloader" #: quodlibet/ext/songsmenu/albumart.py:675 #, python-format msgid "from %(source)s" msgstr "von %(source)s" #: quodlibet/ext/songsmenu/albumart.py:678 #, python-format msgid "Resolution: %s" msgstr "Auflösung: %s" #: quodlibet/ext/songsmenu/albumart.py:681 #, python-format msgid "Size: %s" msgstr "Größe: %s" #: quodlibet/ext/songsmenu/albumart.py:727 msgid "Per engine 'at best' results limit" msgstr "Ergebnis-Limit pro Suchengine" #: quodlibet/ext/songsmenu/albumart.py:737 msgid "_Search" msgstr "_Suche" #: quodlibet/ext/songsmenu/albumart.py:819 #: quodlibet/ext/songsmenu/brainz/widgets.py:451 msgid "Searching…" msgstr "Suche läuft …" #: quodlibet/ext/songsmenu/albumart.py:884 #: quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "Fertig" #: quodlibet/ext/songsmenu/albumart.py:1006 msgid "Download Album Art" msgstr "Alben-Cover herunterladen" #: quodlibet/ext/songsmenu/albumart.py:1007 msgid "Downloads album covers from various websites." msgstr "Alben-Cover von verschiedenen Websites herunterladen." #: quodlibet/ext/songsmenu/albumart.py:1020 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 msgid "Disc" msgstr "CD" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 #: quodlibet/ext/songsmenu/replaygain.py:393 quodlibet/qltk/tracknumbers.py:91 msgid "Track" msgstr "Titel-Nr." #: quodlibet/ext/songsmenu/brainz/widgets.py:132 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:447 msgid "Please enter a query." msgstr "Bitte geben Sie eine Abfrage ein." #: quodlibet/ext/songsmenu/brainz/widgets.py:465 #: quodlibet/ext/songsmenu/brainz/widgets.py:496 msgid "Error encountered. Please retry." msgstr "Es ist ein Fehler aufgetreten. Bitte versuchen Sie es erneut." #: quodlibet/ext/songsmenu/brainz/widgets.py:472 #: quodlibet/ext/songsmenu/brainz/widgets.py:488 msgid "Loading result…" msgstr "Lade Ergebnis …" #: quodlibet/ext/songsmenu/brainz/widgets.py:475 msgid "No results found." msgstr "Keine Ergebnisse gefunden." #: quodlibet/ext/songsmenu/console.py:40 msgid "Python Console" msgstr "Python-Konsole" #: quodlibet/ext/songsmenu/console.py:41 msgid "Interactive Python console. Opens a new window." msgstr "Interaktive Python-Konsole. Öffnet ein neues Fenster." #: quodlibet/ext/songsmenu/console.py:48 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "{plugin_name} für {songs} ({app})" #: quodlibet/ext/songsmenu/console.py:55 msgid "Python Console Sidebar" msgstr "Python-Konsole-Seitenleiste" #: quodlibet/ext/songsmenu/console.py:56 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:75 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:85 msgid "Your current working directory is:" msgstr "Ihr aktuelles Arbeitsverzeichnis ist:" #: quodlibet/ext/songsmenu/cover_download.py:119 msgid "Classic" msgstr "Klassisch" #: quodlibet/ext/songsmenu/cover_download.py:120 msgid "Large" msgstr "Groß" #: quodlibet/ext/songsmenu/cover_download.py:121 msgid "HD" msgstr "HD" #: quodlibet/ext/songsmenu/cover_download.py:122 msgid "Full HD" msgstr "Full HD" #: quodlibet/ext/songsmenu/cover_download.py:123 msgid "WQXGA" msgstr "WQXGA" #: quodlibet/ext/songsmenu/cover_download.py:124 msgid "4K UHD" msgstr "4K UHD" #: quodlibet/ext/songsmenu/cover_download.py:129 msgid "Cover Art Download" msgstr "Cover-Art-Downloader" #: quodlibet/ext/songsmenu/cover_download.py:180 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "%(source)s – %(dimensions)s wird geladen …" #: quodlibet/ext/songsmenu/cover_download.py:231 #, python-format msgid "" "Nothing found for albums:\n" "<i>%(albums)s</i>.\n" "\n" "Providers used:\n" "<tt>%(providers)s</tt>" msgstr "" "Keine Ergebnisse für die folgenden Alben:\n" "<i>%(albums)s</i>.\n" "\n" "Verwendete Provider:\n" "<tt>%(providers)s</tt>" #: quodlibet/ext/songsmenu/cover_download.py:234 msgid "No covers found" msgstr "Keine Cover gefunden" #: quodlibet/ext/songsmenu/cover_download.py:254 #, python-format msgid "%(size)d ✕ %(size)d px" msgstr "%(size)d ✕ %(size)d px" #: quodlibet/ext/songsmenu/cover_download.py:267 msgid "Preview size" msgstr "Vorschaugröße" #: quodlibet/ext/songsmenu/cover_download.py:276 msgid "Save destination" msgstr "Speicherort" #: quodlibet/ext/songsmenu/cover_download.py:336 msgid "Download Cover Art" msgstr "Cover-Art herunterladen" #: quodlibet/ext/songsmenu/cover_download.py:337 msgid "Downloads high-quality album covers using cover plugins." msgstr "Lädt Alben-Cover in hoher Qualität über Cover-Plugins herunter." #: 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:55 msgid "pattern" msgstr "Muster" #: 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:91 msgid "Input value" msgstr "Eingabewert" #: quodlibet/ext/songsmenu/custom_commands.py:92 #, python-format msgid "Value for %s?" msgstr "Wert für %s?" #: quodlibet/ext/songsmenu/custom_commands.py:136 msgid "Custom Commands" msgstr "Benutzerdefinierte Befehle" #: quodlibet/ext/songsmenu/custom_commands.py:137 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:196 #: quodlibet/ext/songsmenu/custom_commands.py:206 #: quodlibet/ext/songsmenu/custom_commands.py:258 msgid "Edit Custom Commands" msgstr "Benutzerdefinierte Befehle bearbeiten" #: quodlibet/ext/songsmenu/custom_commands.py:289 #, 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:397 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:399 msgid "_Group duplicates by:" msgstr "Duplikate _gruppieren nach:" #: quodlibet/ext/songsmenu/duplicates.py:404 msgid "Duplicate Key" msgstr "Duplikatschlüssel" #: quodlibet/ext/songsmenu/duplicates.py:409 msgid "Remove _Whitespace" msgstr "_Leerräume entfernen" #: quodlibet/ext/songsmenu/duplicates.py:410 msgid "Remove _Diacritics" msgstr "_Diakritische Zeichen entfernen" #: quodlibet/ext/songsmenu/duplicates.py:411 msgid "Remove _Punctuation" msgstr "_Interpunktion entfernen" #: quodlibet/ext/songsmenu/duplicates.py:412 msgid "Case _Insensitive" msgstr "Groß-/Kleinschreibung _nicht beachten" #: quodlibet/ext/songsmenu/duplicates.py:420 msgid "Matching options" msgstr "Optionen für die Übereinstimmung" #. Create a dialog. #: quodlibet/ext/songsmenu/editplaycount.py:19 #: quodlibet/ext/songsmenu/editplaycount.py:41 msgid "Edit Playcount" msgstr "Wiedergabeanzahl bearbeiten" #: quodlibet/ext/songsmenu/editplaycount.py:20 msgid "" "Edit a song's ~#playcount and ~#skipcount.\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's ~#playcount to 0, the ~#lastplayed and ~#laststarted " "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 " "(~#playcount bzw. ~#skipcount).\n" "\n" "Sind mehrere Titel ausgewählt, werden die Anzahlen inkrementiert statt " "gesetzt.\n" "\n" "Wird ~#playcount für einen Titel auf 0 gesetzt, werden die Einträge " "~#lastplayed und ~#laststarted geleert. Wenn allerdings ein Titel mit 0 " "Wiedergaben auf eine positive Anzahl gesetzt wird, werden keine " "Wiedergabezeiten erzeugt." #: quodlibet/ext/songsmenu/editplaycount.py:68 msgid "Play Count" msgstr "Anzahl der Wiedergaben" #: quodlibet/ext/songsmenu/editplaycount.py:69 msgid "Skip Count" msgstr "Anzahl übersprungen" #: quodlibet/ext/songsmenu/embedded.py:25 msgid "Edit Embedded Images" msgstr "Eingebettete Bilder bearbeiten" #: quodlibet/ext/songsmenu/embedded.py:26 msgid "Removes or replaces embedded images." msgstr "Entfernt oder ersetzt eingebettete Bilder." #: quodlibet/ext/songsmenu/embedded.py:81 msgid "_Remove all Images" msgstr "Alle Bilder entfe_rnen" #: quodlibet/ext/songsmenu/embedded.py:85 msgid "_Embed Current Image" msgstr "Aktuelles Bild _einbetten" #: 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/exact_rating.py:54 quodlibet/qltk/ratingsmenu.py:98 msgid "Change _Rating" msgstr "Bewertung _ändern" #: 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" #: quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" msgstr "Status" #. 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:65 quodlibet/ext/songsmenu/html.py:75 msgid "Export to HTML" msgstr "Nach HTML exportieren" #: quodlibet/ext/songsmenu/html.py:66 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:62 msgid "Error uploading" msgstr "Fehler während des Hochladens" #: quodlibet/ext/songsmenu/ifp.py:63 #, python-format msgid "" "Unable to upload <b>%s</b>. The device may be out of space, or turned off." msgstr "" "<b>%s</b> konnte nicht hochgeladen werden. Das Gerät hat möglicherweise " "keinen Speicherplatz mehr oder ist ausgeschaltet." #: quodlibet/ext/songsmenu/importexport.py:60 msgid "Export Metadata" msgstr "Metadaten exportieren" #: quodlibet/ext/songsmenu/importexport.py:61 msgid "Exports metadata of selected songs as a .tags file." msgstr "Exportiert die Metadaten der ausgewählten Titel in eine .tags-Datei." #: quodlibet/ext/songsmenu/importexport.py:105 msgid "Import Metadata" msgstr "Metadaten importieren" #: quodlibet/ext/songsmenu/importexport.py:106 msgid "Imports metadata for selected songs from a .tags file." msgstr "Importiert Metadaten für die ausgewählten Titel aus einer .tags-Datei." #: quodlibet/ext/songsmenu/k3b.py:23 msgid "Burn CD" msgstr "CD brennen" #: quodlibet/ext/songsmenu/k3b.py:24 msgid "Burns CDs with K3b, Brasero or xfburn." msgstr "Brennt CDs mit K3b, Brasero oder xfburn." #: quodlibet/ext/songsmenu/lastfmsync.py:97 msgid "Updating chart list." msgstr "Aktualisiere die Aufstellungsliste." #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:116 msgid "Already up-to-date." msgstr "Schon auf dem neusten Stand." #: quodlibet/ext/songsmenu/lastfmsync.py:124 #, python-format msgid "Fetching chart for week of %s." msgstr "Rufe Aufstellung für die Woche vom %s ab." #: quodlibet/ext/songsmenu/lastfmsync.py:146 msgid "Sync complete." msgstr "Synchronisierung abgeschlossen." #: quodlibet/ext/songsmenu/lastfmsync.py:152 msgid "Error during sync" msgstr "Fehler während der Synchronisierung" #: quodlibet/ext/songsmenu/lastfmsync.py:217 #: quodlibet/ext/songsmenu/lastfmsync.py:247 msgid "Last.fm Sync" msgstr "Last.fm-Synchronisierung" #: quodlibet/ext/songsmenu/lastfmsync.py:248 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:301 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." #. Create a dialog. #: quodlibet/ext/songsmenu/migratemetadata.py:36 #: quodlibet/ext/songsmenu/migratemetadata.py:45 msgid "Migrate Metadata" msgstr "Metadaten übertragen" #: quodlibet/ext/songsmenu/migratemetadata.py:39 msgid "Copies the quodlibet-specific metadata between songs." msgstr "Überträgt die Quod-Libet-spezifischen Metadaten zwischen Titeln." #: quodlibet/ext/songsmenu/migratemetadata.py:52 msgid "_Copy" msgstr "_Kopieren" #: quodlibet/ext/songsmenu/migratemetadata.py:54 msgid "_Paste" msgstr "_Einfügen" #. Create the tag table. #: quodlibet/ext/songsmenu/migratemetadata.py:64 msgid "Information to copy/paste" msgstr "Informationen, die kopiert/eingefügt werden sollen" #. Create the indexing box. #: quodlibet/ext/songsmenu/migratemetadata.py:86 msgid "Map tracks by disc and track number" msgstr "Titel über CD- und Titelnummer zuordnen" #: quodlibet/ext/songsmenu/migratemetadata.py:87 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." #: quodlibet/ext/songsmenu/migratemetadata.py:103 #, python-format 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." #: quodlibet/ext/songsmenu/playlist.py:31 msgid "Export as Playlist" msgstr "Als Wiedergabeliste exportieren" #: quodlibet/ext/songsmenu/playlist.py:32 msgid "Exports songs to an M3U or PLS playlist." msgstr "Exportiert Titel in eine M3U- oder PLS-Wiedergabeliste." #: quodlibet/ext/songsmenu/playlist.py:77 msgid "Use relative paths" msgstr "Relative Pfade benutzen" #: quodlibet/ext/songsmenu/playlist.py:77 msgid "Use absolute paths" msgstr "Absolute Pfade benutzen" #: quodlibet/ext/songsmenu/playlist.py:133 #, python-format msgid "Writing to <b>%s</b> failed." msgstr "Schreiben nach <b>%s</b> 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" #: quodlibet/ext/songsmenu/replaygain.py:407 msgid "Progress" msgstr "Fortschritt" #: quodlibet/ext/songsmenu/replaygain.py:422 msgid "Gain" msgstr "Verstärkung" #: quodlibet/ext/songsmenu/replaygain.py:437 msgid "Peak" msgstr "Spitzenpegel" #: quodlibet/ext/songsmenu/replaygain.py:452 #, python-format msgid "There is <b>%(to-process)s</b> album to update (of %(all)s)" msgid_plural "There are <b>%(to-process)s</b> albums to update (of %(all)s)" msgstr[0] "<b>%(to-process)s</b> Album zu aktualisieren (von %(all)s)" msgstr[1] "<b>%(to-process)s</b> Alben zu aktualisieren (von %(all)s)" #: quodlibet/ext/songsmenu/replaygain.py:568 msgid "Replay Gain" msgstr "ReplayGain-Lautstärkeanpassung" #: quodlibet/ext/songsmenu/replaygain.py:569 msgid "" "Analyzes and updates ReplayGain information, using GStreamer. Results are " "grouped by album." msgstr "" "Analysiert und aktualisiert ReplayGain-Informationen unter der Verwendung " "von GStreamer. Die Ergebnisse werden nach Album gruppiert." #: quodlibet/ext/songsmenu/replaygain.py:607 msgid "always" msgstr "immer" #: quodlibet/ext/songsmenu/replaygain.py:608 msgid "if <b>any</b> RG tags are missing" msgstr "wenn <b>irgendwelche</b> RG-Felder fehlen" #: quodlibet/ext/songsmenu/replaygain.py:610 msgid "if <b>album</b> RG tags are missing" msgstr "wenn <b>Album</b>-RG-Felder fehlen" #: quodlibet/ext/songsmenu/replaygain.py:627 msgid "_Process albums:" msgstr "Alben _verarbeiten:" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:639 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:37 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-example)s." msgstr "" "Durchsucht die ausgewählte Website mithilfe beliebiger Metadaten.\n" "Unterstützt Muster, z.B. %(pattern-example)s." #: quodlibet/ext/songsmenu/website_search.py:80 msgid "Search URL patterns" msgstr "Such-URL-Muster" #: quodlibet/ext/songsmenu/website_search.py:90 msgid "Edit search URLs" msgstr "Such-URLs bearbeiten" #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:116 msgid "Configure Searches…" msgstr "Suchen bearbeiten …" #: quodlibet/ext/songsmenu/wikipedia.py:35 msgid "Search Tag in Wikipedia" msgstr "Metadaten auf Wikipedia suchen" #: quodlibet/ext/songsmenu/wikipedia.py:36 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:56 #, python-format msgid "Search at %(website)s" msgstr "Suche auf %(website)s" #: quodlibet/ext/songsmenu/wikipedia.py:70 #: quodlibet/ext/songsmenu/wikipedia.py:76 quodlibet/qltk/edittags.py:443 msgid "Edit Tags" msgstr "Metadaten bearbeiten" #: quodlibet/ext/songsmenu/wikipedia.py:111 msgid "Search failed" msgstr "Suche fehlgeschlagen" #: quodlibet/ext/songsmenu/wikipedia.py:112 #, python-format msgid "Tag \"%s\" not found." msgstr "Feld »%s« wurde nicht gefunden." #. then (try to) load all new files #: quodlibet/library/libraries.py:651 quodlibet/library/libraries.py:661 #: quodlibet/library/libraries.py:727 quodlibet/library/libraries.py:746 #: quodlibet/qltk/information.py:272 quodlibet/qltk/prefs.py:692 #: quodlibet/util/library.py:123 msgid "Library" msgstr "Bibliothek" #: quodlibet/library/libraries.py:651 msgid "Checking mount points" msgstr "Prüfe Einhängepunkte" #: quodlibet/library/libraries.py:661 msgid "Scanning library" msgstr "Audio-Bibliothek wird eingelesen" #: quodlibet/library/libraries.py:726 #, python-format msgid "Scanning %s" msgstr "%s wird eingelesen" #: quodlibet/library/libraries.py:746 msgid "Loading files" msgstr "Lade Dateien" #: quodlibet/main.py:50 msgid "Music player and music library manager" msgstr "Musikwiedergabe und Musikbibliotheksverwaltung" #: quodlibet/operon/base.py:70 #, python-format msgid "Failed to load file: %r" msgstr "Datei konnte nicht geladen werden: %r" #: quodlibet/operon/commands.py:36 msgid "List tags" msgstr "Tags auflisten" #: quodlibet/operon/commands.py:41 quodlibet/operon/commands.py:80 #: quodlibet/operon/commands.py:462 msgid "Print terse output" msgstr "Knappe Ausgabe anzeigen" #: quodlibet/operon/commands.py:43 quodlibet/operon/commands.py:82 #: quodlibet/operon/commands.py:464 #, 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 Tags 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:336 quodlibet/operon/commands.py:340 #: quodlibet/operon/commands.py:392 quodlibet/operon/commands.py:395 #: quodlibet/operon/commands.py:434 quodlibet/operon/commands.py:469 #: quodlibet/operon/commands.py:509 quodlibet/operon/commands.py:544 #: quodlibet/operon/commands.py:586 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:471 msgid "Too many arguments" msgstr "Zu viele Argumente" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:91 #: quodlibet/operon/commands.py:476 quodlibet/qltk/data_editors.py:352 msgid "Description" msgstr "Beschreibung" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:476 #: quodlibet/qltk/edittags.py:493 msgid "Value" msgstr "Wert" #: quodlibet/operon/commands.py:75 msgid "List all common tags" msgstr "Alle allgemeinen Tags auflisten" #: quodlibet/operon/commands.py:117 msgid "Copy tags from one file to another" msgstr "Tags 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:324 #: quodlibet/operon/commands.py:385 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 Tags ü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 "Tags 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 Tag setzen und existierende Werte entfernen" #: quodlibet/operon/commands.py:304 quodlibet/operon/commands.py:445 #: quodlibet/operon/commands.py:677 #, python-format msgid "Can not set %r" msgstr "%r kann nicht gesetzt werden" #: quodlibet/operon/commands.py:319 msgid "Remove tags" msgstr "Tags entfernen" #: quodlibet/operon/commands.py:326 quodlibet/operon/commands.py:387 msgid "Value is a regular expression" msgstr "Wert ist ein regulärer Ausdruck" #: quodlibet/operon/commands.py:328 msgid "Remove all tags" msgstr "Alle Tags entfernen" #: quodlibet/operon/commands.py:332 msgid "Can't combine '--all' with '--regexp'" msgstr "»--all« kann nicht mit »--regexp« kombiniert werden" #: quodlibet/operon/commands.py:366 #, python-brace-format msgid "Can't remove {tagname} from {filename}" msgstr "»{tagname}« kann nicht aus »{filename}« entfernt werden" #: quodlibet/operon/commands.py:380 msgid "Remove a tag value" msgstr "Einen Tagwert entfernen" #: quodlibet/operon/commands.py:429 msgid "Add a tag value" msgstr "Einen Tagwert hinzufügen" #: quodlibet/operon/commands.py:457 msgid "List file information" msgstr "Dateiinformationen anzeigen" # Was genau bedeutet hier 'provided'? #: quodlibet/operon/commands.py:503 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" "Bereitgestelltes Bild als Hauptbild einbetten und alle anderen eingebetteten " "Bilder entfernen" #: quodlibet/operon/commands.py:516 #, python-format msgid "Failed to load image file: %r" msgstr "Die Bilddatei konnte nicht geladen werden: %r" #: quodlibet/operon/commands.py:523 quodlibet/operon/commands.py:552 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" "Das Editieren von Bildern wird nicht unterstützt in %(file_name)s " "(%(file_format)s)" #: quodlibet/operon/commands.py:539 msgid "Remove all embedded images" msgstr "Alle eingebetteten Bilder entfernen" #: quodlibet/operon/commands.py:569 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "Eingebettete Bilder nach %(filepath)s extrahieren" #: quodlibet/operon/commands.py:581 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" "Pfad, in den die Bilder gespeichert werden (Vorgabe ist das " "Arbeitsverzeichnis)" #: quodlibet/operon/commands.py:640 msgid "Rename files based on tags" msgstr "Dateien anhand von Tags umbenennen" #: quodlibet/operon/commands.py:655 msgid "Fill tags based on the file path" msgstr "Tags anhand des Dateipfads ausfüllen" #: quodlibet/operon/commands.py:705 quodlibet/qltk/information.py:309 #: quodlibet/qltk/properties.py:83 quodlibet/qltk/renamefiles.py:224 #: quodlibet/qltk/tagsfrompath.py:228 quodlibet/qltk/tracknumbers.py:78 msgid "File" msgstr "Datei" #: quodlibet/operon/commands.py:713 msgid "Fill tracknumbers for all files" msgstr "Titelnummern in allen Dateien einfügen" #: quodlibet/operon/commands.py:732 msgid "Print tags based on the given pattern" msgstr "Tags basierend auf dem angegebenen Muster ausgeben" #: quodlibet/operon/commands.py:769 msgid "Display help information" msgstr "Hilfeinformationen anzeigen" #: quodlibet/operon/util.py:42 #, 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:30 msgid "_Unknown" msgstr "_Unbekannt" #: quodlibet/order/__init__.py:142 msgid "In Order" msgstr "Normal" #: quodlibet/order/__init__.py:143 msgid "_In Order" msgstr "_Normal" #: quodlibet/order/reorder.py:22 msgid "Random" msgstr "Zufall" #: quodlibet/order/reorder.py:23 quodlibet/qltk/queue.py:147 msgid "_Random" msgstr "_Zufall" #: quodlibet/order/reorder.py:40 quodlibet/order/reorder.py:41 msgid "Prefer higher rated" msgstr "Höher bewertete bevorzugen" #: quodlibet/order/repeat.py:43 quodlibet/order/repeat.py:44 msgid "Repeat this track" msgstr "Diesen Titel wiederholen" #: quodlibet/order/repeat.py:57 quodlibet/order/repeat.py:58 msgid "Repeat all" msgstr "Alle Titel wiederholen" #: quodlibet/order/repeat.py:73 quodlibet/order/repeat.py:74 msgid "One Song" msgstr "Einzelner Titel" #: quodlibet/player/gstbe/player.py:98 msgid "Stream" msgstr "Stream" #: quodlibet/player/gstbe/player.py:98 msgid "Buffering" msgstr "Puffer wird gefüllt" #: quodlibet/player/gstbe/player.py:452 msgid "Could not create GStreamer pipeline" msgstr "GStreamer-Pipeline konnte nicht angelegt werden" #: quodlibet/player/gstbe/player.py:651 msgid "No GStreamer element found to handle media format" msgstr "Kein GStreamer-Element für das Medienformat gefunden" #: quodlibet/player/gstbe/player.py:652 #, 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:25 msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. In case 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:36 msgid "_Output pipeline:" msgstr "_Audio-Pipeline:" #: quodlibet/player/gstbe/prefs.py:43 #, python-format msgid "%.1f seconds" msgstr "%.1f Sekunden" #: quodlibet/player/gstbe/prefs.py:57 msgid "_Buffer duration:" msgstr "_Pufferdauer:" #: quodlibet/player/gstbe/prefs.py:66 msgid "Disable _gapless playback" msgstr "Über_gangslose Wiedergabe deaktivieren" #: quodlibet/player/gstbe/prefs.py:70 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/util.py:101 msgid "No GStreamer audio sink found" msgstr "Keine GStreamer-Audiosenke gefunden" #: quodlibet/player/gstbe/util.py:120 msgid "Invalid GStreamer output pipeline" msgstr "Ungültige GStreamer-Ausgabe-Pipeline" #: quodlibet/player/xinebe/player.py:90 msgid "Unable to create audio output" msgstr "Der Audioausgang konnte nicht angelegt werden" #: quodlibet/player/xinebe/player.py:91 #, 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:61 #, 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?" # verknüpft? #: quodlibet/plugins/__init__.py:70 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "Das GStreamer-Element »{element}« wurde nicht gefunden." #: 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:55 #: quodlibet/qltk/songsmenu.py:66 msgid "_Run Plugin" msgstr "Plugin ausfüh_ren" #. 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:40 msgid "_Name:" msgstr "_Name:" #: quodlibet/qltk/cbes.py:48 quodlibet/qltk/edittags.py:350 msgid "_Value:" msgstr "_Wert:" #: quodlibet/qltk/cbes.py:263 msgid "Saved Values" msgstr "Gespeicherte Werte" #: quodlibet/qltk/cbes.py:264 msgid "Edit saved values…" msgstr "Gespeicherte Werte bearbeiten …" #: quodlibet/qltk/controls.py:111 msgid "Auto_matic" msgstr "Auto_matisch" #: quodlibet/qltk/controls.py:112 msgid "_Track Mode" msgstr "_Titel-Modus" #: quodlibet/qltk/controls.py:113 msgid "_Album Mode" msgstr "_Album-Modus" #. Translators: player state, no action #: quodlibet/qltk/controls.py:122 msgid "_Mute" msgstr "_Stumm" #: quodlibet/qltk/controls.py:128 msgid "_Replay Gain Mode" msgstr "_ReplayGain-Modus" #. Translators: New Command/Entry/Item/... #: quodlibet/qltk/data_editors.py:116 #, python-format msgid "New %s" msgstr "Neuer %s" #: quodlibet/qltk/data_editors.py:215 msgid "(unknown)" msgstr "(unbekannt)" #: quodlibet/qltk/data_editors.py:344 msgid "Tag expression" msgstr "Feldausdruck" #: quodlibet/qltk/data_editors.py:371 msgid "Tag expression e.g. people:real or ~album~year" msgstr "Feldausdruck, z.B. people:real oder ~album~year" #: quodlibet/qltk/data_editors.py:372 msgid "Enter new tag" msgstr "Neues Metadatenfeld eingeben" #: 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 "Konnte nicht in den Müll verschieben" #: 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/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:197 msgid "Split into _Multiple Values" msgstr "In _mehrere Werte aufteilen" #: quodlibet/qltk/edittags.py:219 msgid "Split Disc out of _Album" msgstr "CD von _Album trennen" #: quodlibet/qltk/edittags.py:243 msgid "Split _Version out of Title" msgstr "_Version von Titel trennen" #: quodlibet/qltk/edittags.py:298 msgid "Split Arranger out of Ar_tist" msgstr "Arrangeur von Küns_tler trennen" #: quodlibet/qltk/edittags.py:303 msgid "Split _Performer out of Artist" msgstr "_Interpret von Künstler trennen" #: quodlibet/qltk/edittags.py:309 msgid "Split _Performer out of Title" msgstr "_Interpret von Titel trennen" #: quodlibet/qltk/edittags.py:315 msgid "Split _Originalartist out of Title" msgstr "_Originalkünstler von Titel trennen" #: quodlibet/qltk/edittags.py:322 msgid "Add a Tag" msgstr "Feld hinzufügen" #: quodlibet/qltk/edittags.py:341 msgid "_Tag:" msgstr "_Feld:" #: quodlibet/qltk/edittags.py:516 msgid "Show _programmatic tags" msgstr "_Programmatische Felder anzeigen" #: quodlibet/qltk/edittags.py:517 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" #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:547 msgctxt "edittags" msgid "_Revert" msgstr "Zu_rücksetzen" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:552 msgctxt "edittags" msgid "_Save" msgstr "_Speichern" #: quodlibet/qltk/edittags.py:681 msgid "_Configure" msgstr "_Konfigurieren" #: quodlibet/qltk/edittags.py:696 msgid "_Split Tag" msgstr "Feld _aufteilen" #: quodlibet/qltk/edittags.py:705 msgid "_Copy Value(s)" msgstr "Wert(e) _kopieren" #: quodlibet/qltk/edittags.py:736 msgid "Unable to add tag" msgstr "Feld konnte nicht hinzugefügt werden" #: quodlibet/qltk/edittags.py:737 #, python-format msgid "Unable to add <b>%s</b>" msgstr "<b>%s</b> konnte nicht hinzugefügt werden" #: quodlibet/qltk/edittags.py:739 #, python-format msgid "" "The files currently selected do not support multiple values for <b>%s</b>." msgstr "" "Die momentan ausgewählten Dateien unterstützen keine mehrfachen Werte für <b>" "%s</b>." #. Can't add the new tag. #: quodlibet/qltk/edittags.py:766 quodlibet/qltk/edittags.py:947 #: quodlibet/qltk/tagsfrompath.py:211 quodlibet/util/__init__.py:505 #: quodlibet/util/tags.py:243 msgid "Invalid tag" msgstr "Ungültiges Feld" #: quodlibet/qltk/edittags.py:767 quodlibet/qltk/edittags.py:948 #: quodlibet/qltk/tagsfrompath.py:212 #, python-format msgid "" "Invalid tag <b>%s</b>\n" "\n" "The files currently selected do not support editing this tag." msgstr "" "Ungültiges Feld <b>%s</b>\n" "\n" "Die ausgewählten Dateien unterstützen das Bearbeiten dieses Feldes nicht." #: quodlibet/qltk/edittags.py:918 quodlibet/qltk/edittags.py:959 msgid "Invalid value" msgstr "Ungültiger Wert" #: quodlibet/qltk/edittags.py:919 quodlibet/qltk/edittags.py:960 #, python-format msgid "" "Invalid value: <b>%(value)s</b>\n" "\n" "%(error)s" msgstr "" "Ungültiger Wert: <b>%(value)s</b>\n" "\n" "%(error)s" #: quodlibet/qltk/_editutils.py:29 msgid "Tag may not be accurate" msgstr "Feld ist möglicherweise ungenau" #: quodlibet/qltk/_editutils.py:32 #, 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:48 msgid "Unable to save song" msgstr "Der Titel konnte nicht gespeichert werden" #: quodlibet/qltk/_editutils.py:51 #, 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:143 msgid "_More options…" msgstr "_Weitere Optionen …" #: quodlibet/qltk/entry.py:78 msgid "_Undo" msgstr "_Rückgängig" #: quodlibet/qltk/entry.py:80 msgid "_Redo" msgstr "_Wiederholen" #: quodlibet/qltk/exfalsowindow.py:94 quodlibet/qltk/quodlibetwindow.py:956 msgid "_About" msgstr "_Info" #: quodlibet/qltk/exfalsowindow.py:98 quodlibet/qltk/quodlibetwindow.py:978 msgid "_Check for Updates…" msgstr "Nach Aktualisierungen _suchen …" #: quodlibet/qltk/exfalsowindow.py:104 quodlibet/qltk/quodlibetwindow.py:911 #: quodlibet/qltk/songsmenu.py:289 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:278 msgid "Ex Falso Preferences" msgstr "Ex-Falso-Einstellungen" #: quodlibet/qltk/exfalsowindow.py:284 quodlibet/qltk/prefs.py:666 msgid "Tag Editing" msgstr "Metadaten-Bearbeitung" #: 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:386 msgid "Unable to create folder" msgstr "Ordner konnte nicht angelegt werden" #: quodlibet/qltk/filesel.py:403 msgid "Unable to delete folder" msgstr "Ordner konnte nicht gelöscht werden" #: quodlibet/qltk/filesel.py:519 quodlibet/qltk/pluginwin.py:167 msgid "Songs" msgstr "Titel" #. Translators: As in "by Artist Name" #: quodlibet/qltk/info.py:42 #, python-format msgid "by %s" msgstr "von %s" #: quodlibet/qltk/info.py:43 quodlibet/qltk/information.py:171 #: quodlibet/qltk/information.py:452 #, python-format msgid "Disc %s" msgstr "CD %s" #: quodlibet/qltk/info.py:44 quodlibet/qltk/information.py:176 #, python-format msgid "Track %s" msgstr "Titel %s" #: quodlibet/qltk/info.py:108 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:342 #: quodlibet/qltk/information.py:475 quodlibet/qltk/information.py:543 msgid "Information" msgstr "Informationen" #: quodlibet/qltk/information.py:127 msgid "Lyrics" msgstr "Texte" #: quodlibet/qltk/information.py:188 quodlibet/qltk/information.py:400 #, python-format msgid "Produced by %s" msgstr "Produziert von %s" #: quodlibet/qltk/information.py:203 quodlibet/util/tags.py:85 msgid "artist" msgstr "Künstler" #: quodlibet/qltk/information.py:204 quodlibet/qltk/information.py:573 #: quodlibet/util/tags.py:85 msgid "artists" msgstr "Künstler" #. for backwards compat #: quodlibet/qltk/information.py:225 quodlibet/util/tags.py:96 #: quodlibet/util/tags.py:124 msgid "performers" msgstr "Interpreten" #: quodlibet/qltk/information.py:239 quodlibet/qltk/information.py:252 #: quodlibet/qltk/songlistcolumns.py:276 msgid "Never" msgstr "Nie" #: quodlibet/qltk/information.py:240 #, 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:258 quodlibet/util/tags.py:149 msgid "added" msgstr "Hinzugefügt" #: quodlibet/qltk/information.py:259 quodlibet/util/tags.py:150 msgid "last played" msgstr "Letzte Wiedergabe" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:160 msgid "plays" msgstr "Wiedergegeben" #: quodlibet/qltk/information.py:261 quodlibet/util/tags.py:161 msgid "skips" msgstr "Übersprungen" #: quodlibet/qltk/information.py:262 quodlibet/util/tags.py:166 msgid "rating" msgstr "Bewertung" #: quodlibet/qltk/information.py:291 msgid "path" msgstr "Pfad" #: quodlibet/qltk/information.py:292 quodlibet/util/tags.py:164 msgid "length" msgstr "Dauer" #: quodlibet/qltk/information.py:293 msgid "format" msgstr "Format" #: quodlibet/qltk/information.py:294 quodlibet/util/tags.py:174 msgid "codec" msgstr "Codec" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:175 msgid "encoding" msgstr "Kodierung" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:171 msgid "bitrate" msgstr "Bitrate" #: quodlibet/qltk/information.py:297 quodlibet/util/tags.py:172 msgid "file size" msgstr "Dateigröße" #: quodlibet/qltk/information.py:298 quodlibet/util/tags.py:159 msgid "modified" msgstr "Geändert" #: quodlibet/qltk/information.py:335 msgid "Additional" msgstr "Weiteres" #: quodlibet/qltk/information.py:387 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d ausgewählt" msgstr[1] "%d ausgewählt" #: quodlibet/qltk/information.py:462 msgid "Track unavailable" msgstr "Titel nicht verfügbar" #: quodlibet/qltk/information.py:468 msgid "Track List" msgstr "Titel-Liste" #: quodlibet/qltk/information.py:500 quodlibet/qltk/information.py:590 #, 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:503 msgid "Selected Discography" msgstr "Ausgewählte Diskographie" #: quodlibet/qltk/information.py:570 #, 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:598 quodlibet/util/tags.py:83 msgid "albums" msgstr "Alben" #: quodlibet/qltk/information.py:611 msgid "Total length:" msgstr "Gesamtdauer:" #: quodlibet/qltk/information.py:615 msgid "Total size:" msgstr "Gesamtgröße:" #: quodlibet/qltk/information.py:618 msgid "Files" msgstr "Dateien" #: quodlibet/qltk/lyrics.py:36 msgid "_View online" msgstr "Online _anzeigen" #: quodlibet/qltk/lyrics.py:64 msgid "No lyrics found for this song." msgstr "Für diesen Titel wurde kein Liedtext gefunden." #: quodlibet/qltk/lyrics.py:75 msgid "Searching for lyrics…" msgstr "Liedtext wird gesucht …" #: 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/msg.py:41 msgid "Discard tag changes?" msgstr "Änderungen an den Metadaten verwerfen?" #: quodlibet/qltk/msg.py:42 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:55 quodlibet/qltk/prefs.py:628 #: quodlibet/qltk/prefs.py:635 quodlibet/qltk/textedit.py:63 #: quodlibet/qltk/tracknumbers.py:116 msgid "_Revert" msgstr "Zu_rücksetzen" #: quodlibet/qltk/msg.py:104 msgid "File exists" msgstr "Datei existiert" #: quodlibet/qltk/msg.py:106 #, python-format msgid "Replace %(file-name)s?" msgstr "»%(file-name)s« ersetzen?" #: quodlibet/qltk/msg.py:112 msgid "_Replace File" msgstr "Datei e_rsetzen" #: quodlibet/qltk/notif.py:182 msgid "Active tasks" msgstr "Aktive Prozesse" #: quodlibet/qltk/notif.py:188 #, python-format msgid "%d tasks running" msgstr "%d aktive Prozesse" #: quodlibet/qltk/playorder.py:256 msgid "Toggle shuffle mode" msgstr "Zufallsmodus ein-/ausschalten" #: quodlibet/qltk/playorder.py:272 msgid "Toggle repeat mode" msgstr "Endlosschleife ein-/ausschalten" #: quodlibet/qltk/pluginwin.py:44 msgid "Plugin Errors" msgstr "Plugin-Fehler" #: quodlibet/qltk/pluginwin.py:124 msgid "Enabled" msgstr "Aktiviert" #: quodlibet/qltk/pluginwin.py:125 msgid "Disabled" msgstr "Deaktiviert" #: quodlibet/qltk/pluginwin.py:131 msgid "No category" msgstr "Keine Kategorie" #: quodlibet/qltk/pluginwin.py:169 msgid "Events" msgstr "Ereignisse" #: quodlibet/qltk/pluginwin.py:170 msgid "Play Order" msgstr "Wiedergabereihenfolge" #: quodlibet/qltk/pluginwin.py:171 msgid "Editing" msgstr "Bearbeitung" #: quodlibet/qltk/pluginwin.py:173 msgid "Covers" msgstr "Cover" #: quodlibet/qltk/pluginwin.py:309 msgid "No plugins found." msgstr "Keine Plugins gefunden." #: quodlibet/qltk/pluginwin.py:358 msgid "Plugins" msgstr "Plugins" #: quodlibet/qltk/pluginwin.py:382 msgid "Filter by plugin state / tag" msgstr "Nach Pluginstatus filtern" #: quodlibet/qltk/pluginwin.py:388 msgid "Filter by plugin type" msgstr "Nach Pluginart filtern" #: quodlibet/qltk/pluginwin.py:394 msgid "Filter by plugin name or description" msgstr "Nach Pluginname oder -beschreibung filtern" #: quodlibet/qltk/pluginwin.py:403 msgid "Show _Errors" msgstr "_Fehler anzeigen" #: quodlibet/qltk/prefs.py:45 msgid "_Disc" msgstr "_CD" #: quodlibet/qltk/prefs.py:46 msgid "_Track" msgstr "_Titel-Nr." #: quodlibet/qltk/prefs.py:47 msgid "Grou_ping" msgstr "Gru_ppieren" #: quodlibet/qltk/prefs.py:50 msgid "Al_bum" msgstr "_Album" #: quodlibet/qltk/prefs.py:55 msgid "_Filename" msgstr "Datei_name" #: quodlibet/qltk/prefs.py:57 msgid "_Length" msgstr "Dau_er" #: quodlibet/qltk/prefs.py:64 msgid "_Jump to playing song automatically" msgstr "Automatisch zu aktuellem Titel _springen" #: quodlibet/qltk/prefs.py:66 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:82 msgid "_Others:" msgstr "_Weitere:" #: quodlibet/qltk/prefs.py:88 msgid "_Edit…" msgstr "B_earbeiten …" #: quodlibet/qltk/prefs.py:91 msgid "Add or remove additional column headers" msgstr "Weitere Listenspalten hinzufügen oder entfernen" #: quodlibet/qltk/prefs.py:101 msgid "Visible Columns" msgstr "Anzuzeigende Listenspalten" #: quodlibet/qltk/prefs.py:104 msgid "Title includes _version" msgstr "Titel mit _Version" #: quodlibet/qltk/prefs.py:106 msgid "Artist includes all _people" msgstr "Künstler mit allen _Mitwirkenden" #: quodlibet/qltk/prefs.py:108 msgid "Album includes _disc subtitle" msgstr "Albu_m mit CD-Untertitel" #: quodlibet/qltk/prefs.py:110 msgid "Filename includes _folder" msgstr "Dateiname mit _Pfad" #: quodlibet/qltk/prefs.py:123 msgid "Column Preferences" msgstr "Einstellungen für Listenspalten" #: quodlibet/qltk/prefs.py:129 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:142 quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Titelliste" #: quodlibet/qltk/prefs.py:222 msgid "Edit Columns" msgstr "Listenspalten bearbeiten" #: quodlibet/qltk/prefs.py:259 msgid "Duration totals" msgstr "Gesamtdauer" #: quodlibet/qltk/prefs.py:271 msgid "_Global filter:" msgstr "_Globaler Filter:" #: quodlibet/qltk/prefs.py:277 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:283 msgctxt "heading" msgid "Search" msgstr "Suche" #: quodlibet/qltk/prefs.py:287 quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Browser" #: quodlibet/qltk/prefs.py:293 msgid "Confirm _multiple ratings" msgstr "Gleichzeitiges Bewerten _mehrerer Titel bestätigen" #: quodlibet/qltk/prefs.py:295 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:298 msgid "Enable _one-click ratings" msgstr "Bewertungen mit _einfachem Klick zulassen" #: quodlibet/qltk/prefs.py:300 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:306 quodlibet/qltk/prefs.py:669 msgid "Ratings" msgstr "Bewertungen" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:312 msgid "Prefer _embedded art" msgstr "_Eingebettete Coverbilder bevorzugen" #: quodlibet/qltk/prefs.py:314 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:319 msgid "_Fixed image filename:" msgstr "_Festgelegter Dateiname für Bilddatei:" #: quodlibet/qltk/prefs.py:321 msgid "The single image filename to use if selected" msgstr "Der für die Bilddatei zu verwendende Dateiname" #: quodlibet/qltk/prefs.py:327 msgid "The album art image file to use when forced (supports wildcards)" msgstr "Die zwingend zu verwendende Bilddatei (unterstützt Platzhaltersymbole)" #: quodlibet/qltk/prefs.py:337 msgid "Album Art" msgstr "Alben-Cover" #: quodlibet/qltk/prefs.py:358 msgid "Playback" msgstr "Wiedergabe" #: quodlibet/qltk/prefs.py:363 msgid "Output Configuration" msgstr "Konfiguration der Tonausgabe" #: quodlibet/qltk/prefs.py:374 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:377 msgid "_Fall-back gain (dB):" msgstr "_Standardverstärkung (dB):" #: quodlibet/qltk/prefs.py:388 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:391 msgid "_Pre-amp gain (dB):" msgstr "_Vorverstärkung (dB):" #: quodlibet/qltk/prefs.py:396 msgid "_Enable Replay Gain volume adjustment" msgstr "ReplayGain-Lautstärkeanpassung _aktivieren" #: quodlibet/qltk/prefs.py:421 msgid "Replay Gain Volume Adjustment" msgstr "ReplayGain-Lautstärkeanpassung" #: quodlibet/qltk/prefs.py:428 msgid "_Continue playback on startup" msgstr "Wiedergabe beim Programmstart _fortsetzen" #: quodlibet/qltk/prefs.py:430 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:434 msgid "Startup" msgstr "Start" #: quodlibet/qltk/prefs.py:461 msgid "_Default rating:" msgstr "_Standardbewertung:" #: quodlibet/qltk/prefs.py:504 msgid "Rating _scale:" msgstr "Bewertungs_skala:" #: quodlibet/qltk/prefs.py:553 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:558 msgid "_Bayesian averaging amount:" msgstr "_Bayesscher Mittelwert:" #: quodlibet/qltk/prefs.py:567 msgid "Save ratings and play _counts in tags" msgstr "Bewertungen und Wiedergabe_anzahl in Metadaten speichern" #: quodlibet/qltk/prefs.py:575 msgid "_Email:" msgstr "_E-Mail:" #: quodlibet/qltk/prefs.py:577 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:597 msgid "Auto-save tag changes" msgstr "Änderungen an Metadaten automatisch speichern" #: quodlibet/qltk/prefs.py:599 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:608 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:618 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:631 msgid "Split _tag on:" msgstr "Trenne _Felder nach:" #: quodlibet/qltk/prefs.py:638 msgid "Split _subtag on:" msgstr "Trenne _Unterfelder nach:" #: quodlibet/qltk/prefs.py:663 msgid "Tags" msgstr "Metadaten" #: quodlibet/qltk/prefs.py:684 msgid "Updating for new ratings" msgstr "Aktualisiere Bewertungen" #: quodlibet/qltk/prefs.py:694 msgid "Scan library _on start" msgstr "Bibliothek beim _Programmstart aktualisieren" # »Einlesen« würde nach einem aufwendigeren Vorgang klingen #: quodlibet/qltk/prefs.py:704 quodlibet/qltk/quodlibetwindow.py:990 msgid "_Scan Library" msgstr "Bibliothek aktuali_sieren" #: quodlibet/qltk/prefs.py:706 quodlibet/qltk/quodlibetwindow.py:1052 msgid "Check for changes in your library" msgstr "Bibliothek auf Änderungen überprüfen" #: quodlibet/qltk/prefs.py:711 msgid "Re_build Library" msgstr "Bibliothek neu auf_bauen" #: quodlibet/qltk/prefs.py:714 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:724 msgid "Scan Directories" msgstr "Ordner einlesen" #: quodlibet/qltk/prefs.py:730 msgid "Hidden Songs" msgstr "Ausgeblendete Titel" #: quodlibet/qltk/properties.py:157 quodlibet/util/collection.py:403 #, 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:104 msgid "_Queue" msgstr "_Warteschlange" #: quodlibet/qltk/queue.py:124 msgid "Ephemeral" msgstr "Flüchtig" #: quodlibet/qltk/queue.py:125 msgid "Remove songs from the queue after playing them" msgstr "Titel nach Wiedergabe aus der Warteschlange entfernen" #: quodlibet/qltk/queue.py:133 msgid "Persistent" msgstr "Persistent" #: quodlibet/qltk/queue.py:134 msgid "Keep songs in the queue after playing them" msgstr "Titel nach Wiedergabe in der Warteschlange behalten" #: quodlibet/qltk/queue.py:142 msgid "Mode" msgstr "Modus" #: quodlibet/qltk/queue.py:153 msgid "Stop at End" msgstr "Am Ende anhalten" #: quodlibet/qltk/queue.py:157 msgid "_Clear Queue" msgstr "Warteschlange l_eeren" #: quodlibet/qltk/queue.py:178 msgid "Disable queue - the queue will be ignored when playing" msgstr "" "Warteschlange deaktivieren – die Warteschlange wird bei der Wiedergabe " "ignoriert" #: quodlibet/qltk/queue.py:290 #, 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:198 msgid "_Browse Library" msgstr "Bibli_othek durchsuchen" #: quodlibet/qltk/quodlibetwindow.py:348 msgid "Toggle queue visibility" msgstr "Warteschlange anzeigen/verbergen" #: quodlibet/qltk/quodlibetwindow.py:376 msgid "Playback Error" msgstr "Wiedergabefehler" #: quodlibet/qltk/quodlibetwindow.py:384 msgid "Set up library directories?" msgstr "Ordner für Bibliothek einrichten?" #: quodlibet/qltk/quodlibetwindow.py:385 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:391 msgid "_Not Now" msgstr "_Nicht jetzt" #: quodlibet/qltk/quodlibetwindow.py:392 msgid "_Set Up" msgstr "_Einrichten" #: quodlibet/qltk/quodlibetwindow.py:845 msgid "Unable to add songs" msgstr "Titel konnten nicht hinzugefügt werden" #: quodlibet/qltk/quodlibetwindow.py:846 quodlibet/qltk/quodlibetwindow.py:1286 #, python-format msgid "%s uses an unsupported protocol." msgstr "%s verwendet ein nicht unterstütztes Protokoll." #: quodlibet/qltk/quodlibetwindow.py:869 msgid "_Jump to Playing Song" msgstr "_Zum abgespielten Titel springen" #: quodlibet/qltk/quodlibetwindow.py:876 msgid "_File" msgstr "_Datei" #: quodlibet/qltk/quodlibetwindow.py:877 msgid "_Song" msgstr "_Titel" #: quodlibet/qltk/quodlibetwindow.py:878 msgid "_View" msgstr "_Ansicht" #: quodlibet/qltk/quodlibetwindow.py:879 msgid "_Browse" msgstr "D_urchsuchen" #: quodlibet/qltk/quodlibetwindow.py:880 msgid "_Control" msgstr "_Steuerung" #: quodlibet/qltk/quodlibetwindow.py:881 msgid "_Help" msgstr "_Hilfe" #: quodlibet/qltk/quodlibetwindow.py:887 msgid "_Add a Folder…" msgstr "_Ordner hinzufügen …" #: quodlibet/qltk/quodlibetwindow.py:892 msgid "_Add a File…" msgstr "_Datei hinzufügen …" #: quodlibet/qltk/quodlibetwindow.py:897 msgid "_Add a Location…" msgstr "_URL hinzufügen …" #: quodlibet/qltk/quodlibetwindow.py:926 msgid "Edit Bookmarks…" msgstr "_Lesezeichen bearbeiten …" #: quodlibet/qltk/quodlibetwindow.py:946 msgid "Stop After This Song" msgstr "Nach diesem Titel _stoppen" #: quodlibet/qltk/quodlibetwindow.py:952 msgid "_Keyboard Shortcuts" msgstr "_Tastenkürzel" #: quodlibet/qltk/quodlibetwindow.py:961 msgid "Online Help" msgstr "Online-Hilfe" #: quodlibet/qltk/quodlibetwindow.py:970 msgid "Search Help" msgstr "Hilfe zu Sucheingaben" #: quodlibet/qltk/quodlibetwindow.py:1274 msgid "Add a Location" msgstr "URL hinzufügen" #: quodlibet/qltk/quodlibetwindow.py:1275 msgid "Enter the location of an audio file:" msgstr "Geben Sie die URL einer Audio-Datei an:" #: quodlibet/qltk/quodlibetwindow.py:1280 #: quodlibet/qltk/quodlibetwindow.py:1285 msgid "Unable to add location" msgstr "Die URL konnte nicht hinzugefügt werden" #: quodlibet/qltk/quodlibetwindow.py:1281 #, python-format msgid "%s is not a valid location." msgstr "%s ist keine gültige URL." #: quodlibet/qltk/quodlibetwindow.py:1294 #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "Add Music" msgstr "Musik hinzufügen" #: quodlibet/qltk/quodlibetwindow.py:1294 quodlibet/qltk/scanbox.py:99 msgid "_Add Folders" msgstr "_Ordner hinzufügen" #: quodlibet/qltk/quodlibetwindow.py:1301 msgid "Music Files" msgstr "Musikdateien" #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "_Add Files" msgstr "_Dateien hinzufügen" #: quodlibet/qltk/ratingsmenu.py:24 #, 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:26 msgid "The saved ratings will be removed" msgstr "Die gespeicherten Bewertungen werden entfernt" #: quodlibet/qltk/ratingsmenu.py:27 #, python-format msgid "The rating of all selected songs will be changed to '%s'" msgstr "Die Bewertung aller ausgewählten Titel wird geändert zu »%s«" #: quodlibet/qltk/ratingsmenu.py:57 quodlibet/qltk/ratingsmenu.py:111 msgid "_Remove Rating" msgstr "Bewertung entfe_rnen" #: quodlibet/qltk/renamefiles.py:51 msgid "Replace spaces with _underscores" msgstr "Leerzeichen durch _Unterstriche ersetzen" #: quodlibet/qltk/renamefiles.py:61 msgid "Strip _Windows-incompatible characters" msgstr "Von MS _Windows nicht unterstützte Zeichen entfernen" #: quodlibet/qltk/renamefiles.py:79 msgid "Strip _diacritical marks" msgstr "_Diakritische Zeichen entfernen" #: quodlibet/qltk/renamefiles.py:90 msgid "Strip non-_ASCII characters" msgstr "Nicht-_ASCII-Zeichen entfernen" #: quodlibet/qltk/renamefiles.py:100 msgid "Use only _lowercase characters" msgstr "Nur _Kleinschreibung verwenden" #: quodlibet/qltk/renamefiles.py:128 msgid "Rename Files" msgstr "Dateien umbenennen" # Unter Tagging, 'Tags aus Pfad erzeugen'. # 'Pfad' gefällt mir nicht, 'Muster' ('Profil'?) auch nicht ;) # –> Mir gefiel 'Pfad' auch nicht. ;-) # Kann es sein, dass 'path' etwas unglücklich formuliert ist? Es handelt sich doch um den Dateinamen. Allerdings gibt es auch noch '_Filename Pattern:'. #: quodlibet/qltk/renamefiles.py:146 quodlibet/qltk/tagsfrompath.py:115 msgid "Path Patterns" msgstr "Muster für Dateipfade" # Für mich sieht das eher nach 'Profile' aus. # –> Jo, wesentlich besser. Global geändert. #: quodlibet/qltk/renamefiles.py:147 quodlibet/qltk/tagsfrompath.py:116 msgid "Edit saved patterns…" msgstr "Gespeicherte Muster bearbeiten …" #: quodlibet/qltk/renamefiles.py:150 quodlibet/qltk/tagsfrompath.py:119 #: quodlibet/qltk/tracknumbers.py:57 msgid "_Preview" msgstr "_Voransicht" #: quodlibet/qltk/renamefiles.py:177 msgid "File names" msgstr "Dateinamen" #: quodlibet/qltk/renamefiles.py:187 msgid "_Move album art" msgstr "Alben-Cover _verschieben" #: quodlibet/qltk/renamefiles.py:190 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:195 msgid "_Overwrite album art at target" msgstr "Album-Cover am Zielort _überschreiben" #: quodlibet/qltk/renamefiles.py:203 msgid "_Remove empty directories" msgstr "Leere Verzeichnisse _entfernen" #: quodlibet/qltk/renamefiles.py:209 msgid "Album art" msgstr "Alben-Cover" #: quodlibet/qltk/renamefiles.py:238 msgid "New Name" msgstr "Neuer Name" #: quodlibet/qltk/renamefiles.py:315 msgid "Unable to rename file" msgstr "Die Datei konnte nicht umbenannt werden" #: quodlibet/qltk/renamefiles.py:316 #, python-format msgid "" "Renaming <b>%(old-name)s</b> to <b>%(new-name)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." msgstr "" "Umbenennen von <b>%(old-name)s</b> nach <b>%(new-name)s</b> 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:324 msgid "Ignore _All Errors" msgstr "_Alle Fehler ignorieren" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: quodlibet/qltk/renamefiles.py:325 quodlibet/qltk/wlw.py:49 msgid "_Stop" msgstr "_Stop" #: quodlibet/qltk/renamefiles.py:327 msgid "_Continue" msgstr "_Fortfahren" #: quodlibet/qltk/renamefiles.py:440 msgid "Path is not absolute" msgstr "Der Pfad ist nicht absolut" #: quodlibet/qltk/renamefiles.py:441 #, python-format msgid "" "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 ~/." msgstr "" "Die Vorlage\n" "\t<b>%s</b>\n" "enthält »/«, startet aber nicht vom Stammverzeichnis. Um zu vermeiden, dass " "Ordner falsch benannt werden, sollte die Vorlage entweder mit »/« oder mit " "»~/« beginnen." #: quodlibet/qltk/scanbox.py:47 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:99 msgid "Select Directories" msgstr "Ordner auswählen" #: quodlibet/qltk/searchbar.py:57 msgid "Saved Searches" msgstr "Gespeicherte Suchläufe" #: quodlibet/qltk/searchbar.py:58 msgid "Edit saved searches…" msgstr "Gespeicherte Suchläufe bearbeiten …" #: quodlibet/qltk/searchbar.py:82 msgid "Search your library, using free text or QL queries" msgstr "Bibliothek mit Freitexteingaben oder QL-Abfragen durchsuchen" #: quodlibet/qltk/searchbar.py:144 msgid "Search after _typing" msgstr "Suche bei Eingabe _starten" #: quodlibet/qltk/searchbar.py:147 msgid "Show search results after the user stops typing" msgstr "Suchergebnisse umgehend nach Beenden der Eingabe anzeigen" #: quodlibet/qltk/searchbar.py:215 msgid "_Limit:" msgstr "_Limit:" #: quodlibet/qltk/searchbar.py:228 msgid "_Weight" msgstr "_Bewertung" #: quodlibet/qltk/searchbar.py:355 msgid "Add query" msgstr "Abfrage hinzufügen" #: quodlibet/qltk/searchbar.py:356 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 breaks 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:375 #, python-format msgid "_Filter on %s" msgstr "Nach %s _filtern" #: quodlibet/qltk/songlist.py:1093 msgid "All _Headers" msgstr "_Alle Listenspalten" #: quodlibet/qltk/songlist.py:1094 msgid "_Track Headers" msgstr "Listenspalten zu _Titeln" #: quodlibet/qltk/songlist.py:1095 msgid "_Album Headers" msgstr "Listenspalten zu _Alben" #: quodlibet/qltk/songlist.py:1096 msgid "_People Headers" msgstr "Listenspalten zu _Mitwirkenden" #: quodlibet/qltk/songlist.py:1097 msgid "_Date Headers" msgstr "Listenspalten zum _Datum" #: quodlibet/qltk/songlist.py:1098 msgid "_File Headers" msgstr "Listenspalten zu _Dateien" #: quodlibet/qltk/songlist.py:1099 msgid "_Production Headers" msgstr "Listenspalten zur _Produktion" #: quodlibet/qltk/songlist.py:1114 msgid "_Customize Headers…" msgstr "Listenspalten _anpassen …" #: quodlibet/qltk/songlist.py:1119 msgid "_Expand Column" msgstr "Listenspalte ausd_ehnen" #: quodlibet/qltk/songsmenu.py:40 #, python-format msgid "Remove track: \"%%(title)s\" from library?" msgid_plural "Remove %(count)d tracks from library?" msgstr[0] "Möchten Sie den Titel »%%(title)s« aus der Bibliothek entfernen?" msgstr[1] "Möchten Sie die %(count)d Titel aus der Bibliothek entfernen?" #: quodlibet/qltk/songsmenu.py:46 msgid "Remove from Library" msgstr "Aus der Bibliothek entfernen" #: quodlibet/qltk/songsmenu.py:51 #, 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:62 #, 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:134 msgid "Configure Plugins…" msgstr "Plugins konfigurieren …" #: quodlibet/qltk/songsmenu.py:329 msgid "Add to _Queue" msgstr "Zur _Warteschlange hinzufügen" #: quodlibet/qltk/songsmenu.py:349 msgid "_Remove from Library…" msgstr "Aus der Bibliothek entfe_rnen …" #: quodlibet/qltk/songsmenu.py:414 msgid "Unable to show files" msgstr "Die Dateien konnten nicht angezeigt werden" #: quodlibet/qltk/songsmenu.py:415 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:422 #, 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/tagsfrompath.py:46 msgid "Replace _underscores with spaces" msgstr "_Unterstriche durch Leerzeichen ersetzen" #: quodlibet/qltk/tagsfrompath.py:56 msgid "_Title-case tags" msgstr "Titel_anfang in Großbuchstaben" #: quodlibet/qltk/tagsfrompath.py:66 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<b>%s</b>\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" "Das Muster\n" "\t<b>%s</b>\n" "ist ungültig. Möglicherweise enthält es das gleiche Feld zweimal, oder es " "enthält nicht zueinander passende Klammern (< / >)." #: quodlibet/qltk/tagsfrompath.py:215 msgid "Invalid tags" msgstr "Ungültige Felder" #: quodlibet/qltk/tagsfrompath.py:216 #, 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." #: 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:923 #, python-format msgid "and %d more…" msgstr "und %d weitere …" #: quodlibet/qltk/wlw.py:199 msgid "Saving the songs you changed." msgstr "Geänderte Titel werden gespeichert." #: quodlibet/qltk/wlw.py:200 #, 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:233 #, 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:425 msgid "Playlists must have a name" msgstr "Wiedergabelisten müssen einen Namen haben" #: quodlibet/util/collection.py:608 #, python-format msgid "A playlist named %s already exists." msgstr "Eine Wiedergabeliste mit dem Namen »%s« existiert bereits." #: quodlibet/util/cover/built_in.py:32 msgid "Embedded album covers" msgstr "Eingebettete Album-Cover" #: quodlibet/util/cover/built_in.py:33 msgid "Uses covers embedded into audio files." msgstr "In Audiodateien eingebettete Coverbilder verwenden." #: quodlibet/util/cover/built_in.py:55 msgid "Filesystem cover" msgstr "Dateisystem-Cover" #: quodlibet/util/cover/built_in.py:56 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:76 msgid "Display brief usage information" msgstr "Kurzinfo zur Benutzung anzeigen" #: quodlibet/util/__init__.py:78 msgid "Display version and copyright" msgstr "Info zu Version und Copyright anzeigen" #: quodlibet/util/__init__.py:79 msgid "Print debugging information" msgstr "Debugginginformationen ausgeben" #: quodlibet/util/__init__.py:118 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "Verwendung: %(program)s %(usage)s" #: quodlibet/util/__init__.py:120 msgid "[options]" msgstr "[Optionen]" #: quodlibet/util/__init__.py:165 #, python-format msgid "Option %r not recognized." msgstr "Die Option %r ist ungültig." #: quodlibet/util/__init__.py:168 #, python-format msgid "Option %r requires an argument." msgstr "Die Option %r erfordert ein Argument." #: quodlibet/util/__init__.py:171 #, python-format msgid "%r is not a unique prefix." msgstr "%r ist kein eindeutiger Präfix." #: quodlibet/util/__init__.py:347 #, python-format msgid "%d kbps" msgstr "%d kbit/s" #: quodlibet/util/__init__.py:402 #, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%s Sekunde" msgstr[1] "%s Sekunden" #: quodlibet/util/__init__.py:415 msgid "No time information" msgstr "Keine Informationen zur Abspieldauer" #: quodlibet/util/__init__.py:418 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d Sekunde" msgstr[1] "%d Sekunden" #: quodlibet/util/__init__.py:419 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d Minute" msgstr[1] "%d Minuten" #: quodlibet/util/__init__.py:420 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d Stunde" msgstr[1] "%d Stunden" #: quodlibet/util/__init__.py:421 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d Tag" msgstr[1] "%d Tage" #: quodlibet/util/__init__.py:422 #, 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:514 msgctxt "check" msgid "titlecase?" msgstr "no title-casing" #: quodlibet/util/massagers.py:114 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:129 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:150 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:172 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:194 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:207 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:116 msgid "Unable to edit song" msgstr "Der Titel kann nicht bearbeitet werden" #: quodlibet/util/songwrapper.py:117 #, python-format msgid "" "Saving <b>%s</b> failed. The file may be read-only, corrupted, or you do not " "have permission to edit it." msgstr "" "Speichern von <b>%s</b> 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 "Gruppieren" #: 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:151 msgid "disc" msgstr "CD" #: quodlibet/util/tags.py:115 quodlibet/util/tags.py:153 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" #. 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:130 msgid "MusicBrainz recording ID" msgstr "MusicBrainz Aufnahme-ID" #: quodlibet/util/tags.py:131 msgid "MusicBrainz release track ID" msgstr "MusicBrainz Veröffentlichungs-Titel-ID" #: quodlibet/util/tags.py:132 msgid "MusicBrainz release ID" msgstr "MusicBrainz Veröffentlichungs-ID" #: quodlibet/util/tags.py:133 msgid "MusicBrainz artist ID" msgstr "MusicBrainz Künstler-ID" #: quodlibet/util/tags.py:134 msgid "MusicBrainz release artist ID" msgstr "MusicBrainz Veröffentlichungs-Künstler-ID" #: quodlibet/util/tags.py:135 msgid "MusicBrainz TRM ID" msgstr "MusicBrainz TRM-ID" #: quodlibet/util/tags.py:136 msgid "MusicIP PUID" msgstr "MusicIP PUID" #: quodlibet/util/tags.py:137 msgid "MusicBrainz album status" msgstr "MusicBrainz Albumstatus" #: quodlibet/util/tags.py:138 msgid "MusicBrainz album type" msgstr "MusicBrainz Albumtyp" #: quodlibet/util/tags.py:139 msgid "MusicBrainz release group ID" msgstr "MusicBrainz Veröffentlichungsgruppen-ID" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:142 msgid "track gain" msgstr "Lautstärkeverstärkung per Titel" #: quodlibet/util/tags.py:143 msgid "track peak" msgstr "Titel-Spitzenpegel" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:145 msgid "album gain" msgstr "Lautstärkeverstärkung per Album" #: quodlibet/util/tags.py:146 msgid "album peak" msgstr "Album-Spitzenpegel" #: quodlibet/util/tags.py:147 msgid "reference loudness" msgstr "Referenzlautstärke" #: quodlibet/util/tags.py:152 msgid "discs" msgstr "CDs" #: quodlibet/util/tags.py:154 msgid "tracks" msgstr "Titel" #: quodlibet/util/tags.py:155 msgid "last started" msgstr "Zuletzt angespielt" #: quodlibet/util/tags.py:156 msgid "full name" msgstr "Vollst. Dateiname" #: quodlibet/util/tags.py:163 msgid "mount point" msgstr "Einhängepunkt" #: quodlibet/util/tags.py:165 msgid "people" msgstr "Mitwirkende" #: quodlibet/util/tags.py:167 msgid "year" msgstr "Jahr" #: quodlibet/util/tags.py:168 msgid "original release year" msgstr "Jahr der Erstveröffentlichung" #: quodlibet/util/tags.py:169 msgid "bookmark" msgstr "Lesezeichen" #: quodlibet/util/tags.py:170 msgid "bitdepth" msgstr "Bittiefe" #: quodlibet/util/tags.py:173 msgid "file format" msgstr "Dateiformat" #: quodlibet/util/tags.py:176 msgid "playlists" msgstr "Wiedergabelisten" #: quodlibet/util/tags.py:177 msgid "sample rate" msgstr "Abtastrate" #: quodlibet/util/tags.py:178 msgid "channel count" msgstr "Anzahl der Kanäle" #. Translators: e.g. "artist (sort)" #: quodlibet/util/tags.py:268 msgid "sort" msgstr "sortieren" #. Translators: e.g. "performer (roles)" #: quodlibet/util/tags.py:276 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 "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 "_Download…" #~ msgstr "_Download …" #~ msgid "Download Files" #~ msgstr "Dateien herunterladen" #~ msgid "Download File" #~ msgstr "Datei herunterladen" #~ 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 "_Edit" #~ msgstr "B_earbeiten" #~ 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 "Could not find '%s'." #~ msgstr "»%s« konnte nicht gefunden werden." #~ 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 "Watch this folder for new songs" #~ msgstr "Diesen Ordner auf neue Titel prüfen" #~ 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 "Removing orphaned iPod track" #~ msgstr "Verwaister iPod-Titel wird entfernt" #~ 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9511857 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/po/el.po����������������������������������������������������������������������������0000644�0001750�0001750�00000724554�00000000000�014075� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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: 2017-05-17 18:58+0200\n" "PO-Revision-Date: 2015-09-14 22:31+0300\n" "Last-Translator: Dimitris Papageorgiou <dipap@gmx.com>\n" "Language-Team: Greek\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" #: ../data/exfalso.appdata.xml.in.h:1 ../data/exfalso.desktop.in.h:2 msgid "Edit tags in your audio files" msgstr "Επεξεργάσου τις ετικέτες στα αρχεία μουσικής σου" #: ../data/exfalso.appdata.xml.in.h:2 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/exfalso.appdata.xml.in.h:3 ../data/quodlibet.appdata.xml.in.h:3 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/exfalso.desktop.in.h:1 msgid "Audio tag editor" msgstr "Επεξεργαστής ετικετών μουσικής" #: ../data/quodlibet.appdata.xml.in.h:1 ../data/quodlibet.desktop.in.h:2 msgid "Listen to, browse, or edit your audio collection" msgstr "Ακούστε, περιηγηθείτε ή επεξεργαστείτε την μουσική σας συλλογή" #: ../data/quodlibet.appdata.xml.in.h:2 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 είναι ένα πρόγραμμα διαχείρισης της μουσικής σας. Παρέχει " "πολλούς διαφορετικούς τρόπους προβολής της μουσικοθήκης σας, καθώς και " "υποστήριξη για διαδικτυακό ραδιόφωνο και ροών ήχου. Έχει απίστευτα ευέλικτες " "δυνατότητες επεξεργασίας και αναζήτησης μεταδεδομένων ετικετών μουσικής." #: ../data/quodlibet.desktop.in.h:1 msgid "Music Player" msgstr "Αναπαραγωγή Μουσικής" #: ../quodlibet/browsers/albums/main.py:168 #: ../quodlibet/browsers/covergrid/main.py:54 msgid "_Title" msgstr "_Τίτλος" #: ../quodlibet/browsers/albums/main.py:169 #: ../quodlibet/browsers/covergrid/main.py:55 ../quodlibet/qltk/prefs.py:49 msgid "_Artist" msgstr "_Καλλιτέχνης" #: ../quodlibet/browsers/albums/main.py:170 #: ../quodlibet/browsers/covergrid/main.py:56 ../quodlibet/qltk/prefs.py:54 msgid "_Date" msgstr "_Ημερομηνία" #: ../quodlibet/browsers/albums/main.py:171 #: ../quodlibet/browsers/covergrid/main.py:57 ../quodlibet/qltk/prefs.py:53 msgid "_Genre" msgstr "_Είδος μουσικής" #: ../quodlibet/browsers/albums/main.py:172 #: ../quodlibet/browsers/covergrid/main.py:58 ../quodlibet/qltk/prefs.py:58 #: ../quodlibet/qltk/ratingsmenu.py:39 msgid "_Rating" msgstr "_Βαθμολογία" #: ../quodlibet/browsers/albums/main.py:178 #: ../quodlibet/browsers/covergrid/main.py:64 msgid "Sort _by…" msgstr "Τα_ξινόμηση κατά…" #: ../quodlibet/browsers/albums/main.py:199 #: ../quodlibet/browsers/covergrid/main.py:85 #: ../quodlibet/browsers/paned/prefs.py:166 #: ../quodlibet/browsers/playlists/main.py:629 #: ../quodlibet/qltk/exfalsowindow.py:109 ../quodlibet/qltk/pluginwin.py:341 #: ../quodlibet/qltk/quodlibetwindow.py:1016 msgid "_Preferences" msgstr "_Προτιμήσεις" #: ../quodlibet/browsers/albums/main.py:361 msgid "Album List" msgstr "Λίστα Άλμπουμ" #: ../quodlibet/browsers/albums/main.py:362 msgid "_Album List" msgstr "Λίστα Ά_λμπουμ" #: ../quodlibet/browsers/albums/main.py:472 #: ../quodlibet/browsers/covergrid/main.py:279 #: ../quodlibet/browsers/covergrid/main.py:488 msgid "All Albums" msgstr "Όλα τα Άλμπουμ" #: ../quodlibet/browsers/albums/main.py:473 #: ../quodlibet/browsers/covergrid/main.py:280 #: ../quodlibet/browsers/covergrid/main.py:489 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d άλμπουμ" msgstr[1] "%d άλμπουμς" #: ../quodlibet/browsers/albums/main.py:650 #: ../quodlibet/browsers/covergrid/main.py:467 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:381 ../quodlibet/util/collection.py:245 #, 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:379 ../quodlibet/util/collection.py:249 #, 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:120 msgid "Options" msgstr "Επιλογές" #: ../quodlibet/browsers/albums/prefs.py:74 #: ../quodlibet/browsers/covergrid/prefs.py:123 msgid "Album Display" msgstr "Προβολή Άλμπουμ" #: ../quodlibet/browsers/albums/prefs.py:78 #: ../quodlibet/browsers/covergrid/prefs.py:127 #: ../quodlibet/browsers/media.py:39 #: ../quodlibet/browsers/playlists/prefs.py:56 #: ../quodlibet/ext/songsmenu/albumart.py:326 #: ../quodlibet/ext/songsmenu/duplicates.py:350 #: ../quodlibet/ext/songsmenu/filterall.py:48 #: ../quodlibet/qltk/bookmarks.py:101 ../quodlibet/qltk/cbes.py:93 #: ../quodlibet/qltk/data_editors.py:99 ../quodlibet/qltk/data_editors.py:324 #: ../quodlibet/qltk/exfalsowindow.py:297 ../quodlibet/qltk/pluginwin.py:79 #: ../quodlibet/qltk/pluginwin.py:427 ../quodlibet/qltk/prefs.py:707 #: ../quodlibet/qltk/textedit.py:164 ../quodlibet/update.py:148 msgid "_Close" msgstr "_Κλείσιμο" #: ../quodlibet/browsers/audiofeeds.py:55 #: ../quodlibet/browsers/audiofeeds.py:67 #: ../quodlibet/browsers/audiofeeds.py:69 #: ../quodlibet/browsers/audiofeeds.py:159 #: ../quodlibet/browsers/paned/models.py:86 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:46 #: ../quodlibet/formats/_audio.py:495 ../quodlibet/order/__init__.py:27 #: ../quodlibet/qltk/information.py:240 ../quodlibet/qltk/information.py:247 #: ../quodlibet/qltk/information.py:273 ../quodlibet/qltk/wlw.py:70 msgid "Unknown" msgstr "Άγνωστο" #: ../quodlibet/browsers/audiofeeds.py:246 msgid "New Feed" msgstr "Νέα Ροή" #: ../quodlibet/browsers/audiofeeds.py:247 msgid "Enter the location of an audio feed:" msgstr "Εισήγαγε την τοποθεσία μιας ροής ήχου" #: ../quodlibet/browsers/audiofeeds.py:248 #: ../quodlibet/browsers/collection/prefs.py:90 #: ../quodlibet/browsers/iradio.py:341 ../quodlibet/browsers/paned/prefs.py:78 #: ../quodlibet/browsers/playlists/menu.py:96 #: ../quodlibet/browsers/playlists/util.py:52 ../quodlibet/qltk/bookmarks.py:62 #: ../quodlibet/qltk/cbes.py:55 ../quodlibet/qltk/data_editors.py:311 #: ../quodlibet/qltk/edittags.py:288 ../quodlibet/qltk/edittags.py:488 #: ../quodlibet/qltk/quodlibetwindow.py:1354 ../quodlibet/qltk/scanbox.py:61 msgid "_Add" msgstr "_Προσθήκη" #: ../quodlibet/browsers/audiofeeds.py:265 msgid "Audio Feeds" msgstr "Ροές Ήχου" #: ../quodlibet/browsers/audiofeeds.py:266 msgid "_Audio Feeds" msgstr "_Ροές Ήχου" #: ../quodlibet/browsers/audiofeeds.py:345 #: ../quodlibet/browsers/audiofeeds.py:350 msgid "_Download…" msgstr "_Λήψη" #: ../quodlibet/browsers/audiofeeds.py:359 msgid "Download Files" msgstr "Κατέβασμα Αρχείων" #. Save button #: ../quodlibet/browsers/audiofeeds.py:359 #: ../quodlibet/browsers/audiofeeds.py:371 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:81 #: ../quodlibet/ext/songsmenu/albumart.py:322 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:355 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:278 #: ../quodlibet/ext/songsmenu/html.py:76 #: ../quodlibet/ext/songsmenu/lastfmsync.py:216 #: ../quodlibet/ext/songsmenu/playlist.py:51 #: ../quodlibet/ext/songsmenu/replaygain.py:365 #: ../quodlibet/ext/songsmenu/tapbpm.py:182 ../quodlibet/qltk/_editutils.py:39 #: ../quodlibet/qltk/lyrics.py:38 ../quodlibet/qltk/msg.py:52 #: ../quodlibet/qltk/renamefiles.py:168 ../quodlibet/qltk/tracknumbers.py:113 msgid "_Save" msgstr "_Αποθήκευση" #: ../quodlibet/browsers/audiofeeds.py:371 msgid "Download File" msgstr "Κατέβασμα Αρχείου" #: ../quodlibet/browsers/audiofeeds.py:394 #: ../quodlibet/browsers/playlists/main.py:213 #: ../quodlibet/qltk/data_editors.py:96 msgid "_New" msgstr "_Νέο" #: ../quodlibet/browsers/audiofeeds.py:454 #: ../quodlibet/browsers/audiofeeds.py:513 msgid "Unable to add feed" msgstr "Αδυναμία προσθήκης ροής" #: ../quodlibet/browsers/audiofeeds.py:455 #: ../quodlibet/browsers/audiofeeds.py:514 #, python-format msgid "" "%s could not be added. The server may be down, or the location may not be an " "audio feed." msgstr "" "Η ροή <b>%s</b> δεν ήταν δυνατό να προστεθεί. Ίσως ο διακομιστής να είναι " "εκτός λειτουργίας, ή η τοποθεσία δεν είναι ροή ήχου." #. refresh button #: ../quodlibet/browsers/audiofeeds.py:462 ../quodlibet/browsers/media.py:217 #: ../quodlibet/browsers/media.py:386 ../quodlibet/qltk/filesel.py:259 #: ../quodlibet/qltk/pluginwin.py:413 msgid "_Refresh" msgstr "Α_νανέωση" #: ../quodlibet/browsers/audiofeeds.py:463 #: ../quodlibet/browsers/playlists/main.py:457 #: ../quodlibet/browsers/playlists/util.py:43 ../quodlibet/qltk/delete.py:143 #: ../quodlibet/qltk/filesel.py:256 ../quodlibet/qltk/lyrics.py:39 #: ../quodlibet/qltk/maskedbox.py:28 ../quodlibet/qltk/songsmenu.py:392 msgid "_Delete" msgstr "_Διαγραφή Αρχείων" #: ../quodlibet/browsers/audiofeeds.py:530 msgid "" "The current audio backend does not support URLs, Audio Feeds browser " "disabled." msgstr "" "Το τρέχων ηχητικό σύστημα δεν υποστηρίζει απομακρυσμένες διευθύνσεις ο " "περιηγητής Ροών Ήχου απενεργοποιήθηκε" #: ../quodlibet/browsers/_base.py:147 ../quodlibet/browsers/_base.py:150 msgid "Library Browser" msgstr "Περιηγητής Μουσικοθήκης" #: ../quodlibet/browsers/_base.py:274 ../quodlibet/ext/songsmenu/refresh.py:30 #: ../quodlibet/qltk/exfalsowindow.py:241 ../quodlibet/qltk/information.py:542 #: ../quodlibet/qltk/maskedbox.py:68 ../quodlibet/util/collection.py:527 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d τραγούδι" msgstr[1] "%d τραγούδια" #: ../quodlibet/browsers/_base.py:402 ../quodlibet/browsers/_base.py:407 #: ../quodlibet/qltk/tagsfrompath.py:194 ../quodlibet/qltk/textedit.py:141 #: ../quodlibet/util/__init__.py:622 msgid "Invalid pattern" msgstr "Μη έγκυρη αναζήτηση" #: ../quodlibet/browsers/collection/main.py:78 msgid "Album Collection" msgstr "Συλλογή Άλμπουμ" #: ../quodlibet/browsers/collection/main.py:79 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:66 #: ../quodlibet/browsers/paned/prefs.py:51 msgid "_Custom" msgstr "_Προσαρμοσμένο" #. Remove button #: ../quodlibet/browsers/collection/prefs.py:94 #: ../quodlibet/browsers/paned/prefs.py:82 #: ../quodlibet/browsers/playlists/menu.py:97 #: ../quodlibet/ext/playlist/remove_duplicates.py:60 #: ../quodlibet/qltk/bookmarks.py:97 ../quodlibet/qltk/bookmarks.py:127 #: ../quodlibet/qltk/cbes.py:82 ../quodlibet/qltk/cbes.py:89 #: ../quodlibet/qltk/data_editors.py:81 ../quodlibet/qltk/data_editors.py:94 #: ../quodlibet/qltk/data_editors.py:301 ../quodlibet/qltk/data_editors.py:314 #: ../quodlibet/qltk/data_editors.py:322 ../quodlibet/qltk/edittags.py:494 #: ../quodlibet/qltk/edittags.py:634 ../quodlibet/qltk/maskedbox.py:48 #: ../quodlibet/qltk/maskedbox.py:88 ../quodlibet/qltk/queue.py:350 #: ../quodlibet/qltk/scanbox.py:36 ../quodlibet/qltk/scanbox.py:63 msgid "_Remove" msgstr "_Αφαίρεση" #: ../quodlibet/browsers/collection/prefs.py:122 #: ../quodlibet/ext/songsmenu/filterall.py:34 #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:92 #: ../quodlibet/qltk/edittags.py:431 msgid "Tag" msgstr "Ετικέτα" #: ../quodlibet/browsers/collection/prefs.py:128 msgid "Merge" msgstr "Συγχώνευση" #: ../quodlibet/browsers/collection/prefs.py:188 msgid "Album Collection Preferences" msgstr "Προτιμήσεις Συλλογής Άλμπουμ" #: ../quodlibet/browsers/collection/prefs.py:195 #: ../quodlibet/browsers/paned/prefs.py:209 #: ../quodlibet/ext/songsmenu/editplaycount.py:45 #: ../quodlibet/ext/songsmenu/exact_rating.py:38 #: ../quodlibet/player/gstbe/prefs.py:40 ../quodlibet/qltk/prefs.py:127 #: ../quodlibet/qltk/textedit.py:65 msgid "_Apply" msgstr "_Εφαρμογή" #: ../quodlibet/browsers/collection/prefs.py:198 #: ../quodlibet/browsers/paned/prefs.py:213 #: ../quodlibet/browsers/playlists/menu.py:95 #: ../quodlibet/browsers/playlists/util.py:42 #: ../quodlibet/errorreport/ui.py:108 #: ../quodlibet/ext/playlist/export_to_folder.py:37 #: ../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:44 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:281 #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:88 #: ../quodlibet/ext/songsmenu/importexport.py:35 #: ../quodlibet/ext/songsmenu/lastfmsync.py:215 #: ../quodlibet/ext/songsmenu/playlist.py:50 #: ../quodlibet/ext/songsmenu/replaygain.py:364 #: ../quodlibet/ext/songsmenu/tapbpm.py:181 ../quodlibet/plugins/playlist.py:39 #: ../quodlibet/qltk/chooser.py:184 ../quodlibet/qltk/chooser.py:205 #: ../quodlibet/qltk/chooser.py:229 ../quodlibet/qltk/chooser.py:253 #: ../quodlibet/qltk/delete.py:90 ../quodlibet/qltk/delete.py:133 #: ../quodlibet/qltk/edittags.py:287 ../quodlibet/qltk/_editutils.py:38 #: ../quodlibet/qltk/getstring.py:28 ../quodlibet/qltk/maskedbox.py:27 #: ../quodlibet/qltk/msg.py:54 ../quodlibet/qltk/msg.py:93 #: ../quodlibet/qltk/ratingsmenu.py:33 ../quodlibet/qltk/songsmenu.py:45 #: ../quodlibet/qltk/songsmenu.py:73 ../quodlibet/update.py:94 msgid "_Cancel" msgstr "_Ακύρωση" #: ../quodlibet/browsers/covergrid/main.py:125 #, fuzzy msgid "Cover Grid" msgstr "Μέγεθος _Εξώφυλλου:" #: ../quodlibet/browsers/covergrid/main.py:126 #, 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:71 #, fuzzy msgid "Show \"All Albums\" Item" msgstr "Όλα τα Άλμπουμ" #: ../quodlibet/browsers/covergrid/prefs.py:78 msgid "Vertical Split" msgstr "" #: ../quodlibet/browsers/covergrid/prefs.py:110 #: ../quodlibet/browsers/covergrid/prefs.py:111 #, fuzzy msgid "Cover Magnification" msgstr "_Εμφάνιση ειδοποίησης" #: ../quodlibet/browsers/filesystem.py:40 msgid "File System" msgstr "Σύστημα Αρχείων" #: ../quodlibet/browsers/filesystem.py:41 msgid "_File System" msgstr "_Σύστημα Αρχείων" #: ../quodlibet/browsers/filesystem.py:113 ../quodlibet/browsers/media.py:491 #: ../quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "Αδυναμία αντιγραφής τραγουδιών" #: ../quodlibet/browsers/filesystem.py:114 ../quodlibet/qltk/songlist.py:268 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "" "Τα επιλεγμένα τραγούδια δεν μπορούν να αντιγραφούν σε άλλες λίστες ή στην " "ουρά αναπαραγωγής." #: ../quodlibet/browsers/filesystem.py:189 msgid "_Add to Library" msgstr "_Προσθήκη στην Μουσικοθήκη" #: ../quodlibet/browsers/iradio.py:178 msgid "Unsupported file type" msgstr "Μη υποστηριζόμενος τύπος αρχείου" #: ../quodlibet/browsers/iradio.py:179 #, 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:219 ../quodlibet/browsers/iradio.py:232 #: ../quodlibet/browsers/iradio.py:810 msgid "Unable to add station" msgstr "Δεν μπορεί να προστεθεί ο σταθμός" #: ../quodlibet/browsers/iradio.py:243 ../quodlibet/browsers/iradio.py:471 msgid "Internet Radio" msgstr "Διαδικτυακό Ραδιόφωνο" #: ../quodlibet/browsers/iradio.py:243 msgid "Downloading station list" msgstr "Κατέβασμα λίστας σταθμών" #: ../quodlibet/browsers/iradio.py:339 msgid "New Station" msgstr "Νέος Σταθμός" #: ../quodlibet/browsers/iradio.py:340 msgid "Enter the location of an Internet radio station:" msgstr "Εισήγαγε την τοποθεσία ενός διαδικτυακού ραδιοφωνικού σταθμού" #: ../quodlibet/browsers/iradio.py:358 msgid "Electronic" msgstr "Ηλεκτρονική" #: ../quodlibet/browsers/iradio.py:361 msgid "Hip Hop / Rap" msgstr "" #: ../quodlibet/browsers/iradio.py:362 msgid "Oldies" msgstr "" #: ../quodlibet/browsers/iradio.py:363 msgid "R&B" msgstr "" #: ../quodlibet/browsers/iradio.py:364 msgid "Japanese" msgstr "Ιαπωνική" #: ../quodlibet/browsers/iradio.py:365 msgid "Indian" msgstr "Ινδική" #: ../quodlibet/browsers/iradio.py:367 msgid "Religious" msgstr "Θρησκευτική" #: ../quodlibet/browsers/iradio.py:369 msgid "Charts" msgstr "" #: ../quodlibet/browsers/iradio.py:370 msgid "Turkish" msgstr "Τουρκική" #: ../quodlibet/browsers/iradio.py:371 msgid "Reggae / Dancehall" msgstr "" #: ../quodlibet/browsers/iradio.py:372 msgid "Latin" msgstr "" #: ../quodlibet/browsers/iradio.py:373 msgid "College Radio" msgstr "Κολεγιακό Ραδιόφωνο" #: ../quodlibet/browsers/iradio.py:374 msgid "Talk / News" msgstr "Ομιλία / Νέα" #: ../quodlibet/browsers/iradio.py:375 msgid "Ambient" msgstr "" #: ../quodlibet/browsers/iradio.py:376 msgid "Jazz" msgstr "" #: ../quodlibet/browsers/iradio.py:377 ../quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "Κλασική" #: ../quodlibet/browsers/iradio.py:378 ../quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "Ποπ" #: ../quodlibet/browsers/iradio.py:379 msgid "Alternative" msgstr "Εναλακτική" #: ../quodlibet/browsers/iradio.py:380 msgid "Metal" msgstr "" #: ../quodlibet/browsers/iradio.py:381 msgid "Country" msgstr "" #: ../quodlibet/browsers/iradio.py:382 msgid "News" msgstr "Νέα" #: ../quodlibet/browsers/iradio.py:383 msgid "Schlager" msgstr "" #: ../quodlibet/browsers/iradio.py:384 msgid "Funk" msgstr "" #: ../quodlibet/browsers/iradio.py:385 msgid "Indie" msgstr "" #: ../quodlibet/browsers/iradio.py:386 msgid "Blues" msgstr "" #: ../quodlibet/browsers/iradio.py:387 msgid "Soul" msgstr "" #: ../quodlibet/browsers/iradio.py:388 msgid "Lounge" msgstr "" #: ../quodlibet/browsers/iradio.py:389 msgid "Punk" msgstr "" #: ../quodlibet/browsers/iradio.py:390 msgid "Reggaeton" msgstr "" #: ../quodlibet/browsers/iradio.py:392 msgid "Slavic" msgstr "Σλαβική" #: ../quodlibet/browsers/iradio.py:394 msgid "Greek" msgstr "Ελληνική" #: ../quodlibet/browsers/iradio.py:395 msgid "Gothic" msgstr "" #: ../quodlibet/browsers/iradio.py:396 ../quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "Ροκ" #: ../quodlibet/browsers/iradio.py:449 msgid "Would you like to load a list of popular radio stations?" msgstr "Θα θέλατε να φορτωθεί μια λίστα δημοφιλών σταθμών;" #: ../quodlibet/browsers/iradio.py:455 msgid "_Load Stations" msgstr "_Φόρτωση Σταθμών" #: ../quodlibet/browsers/iradio.py:472 msgid "_Internet Radio" msgstr "Διαδικτυακό Ραδιό_φωνο" #: ../quodlibet/browsers/iradio.py:538 msgid "_New Station…" msgstr "_Νέος Σταθμός…" #: ../quodlibet/browsers/iradio.py:541 msgid "_Update Stations" msgstr "_Ανανέωση Σταθμών" #: ../quodlibet/browsers/iradio.py:568 msgid "All Stations" msgstr "Όλοι οι Σταθμοί" #. TODO: support for ~#rating=!None etc (#1940) #: ../quodlibet/browsers/iradio.py:572 #: ../quodlibet/browsers/soundcloud/main.py:64 msgid "Favorites" msgstr "Αγαπημένα" #: ../quodlibet/browsers/iradio.py:580 msgid "No Category" msgstr "Χωρίς Κατηγορία" #: ../quodlibet/browsers/iradio.py:802 msgid "No stations found" msgstr "Δεν βρέθηκαν σταθμοί" #: ../quodlibet/browsers/iradio.py:803 #, python-format msgid "No Internet radio stations were found at %s." msgstr "Δεν βρέθηκε σταθμός ραδιοφώνου στο %s." #: ../quodlibet/browsers/iradio.py:811 msgid "All stations listed are already in your library." msgstr "Όλοι οι σταθμοί που επεστράφησαν ανήκουν ήδη στην μουσικοθήκη" #: ../quodlibet/browsers/iradio.py:828 msgid "Add to Favorites" msgstr "Προσθήκη στα Αγαπημένα" #: ../quodlibet/browsers/iradio.py:832 msgid "Remove from Favorites" msgstr "Αφαίρεση από τα Αγαπημένα" #: ../quodlibet/browsers/iradio.py:932 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "%(count)d σταθμός" msgstr[1] "%(count)d σταθμοί" #: ../quodlibet/browsers/media.py:36 msgid "Device Properties" msgstr "Ιδιότητες Συσκευής" #: ../quodlibet/browsers/media.py:52 msgid "Device:" msgstr "Συσκευή:" #: ../quodlibet/browsers/media.py:54 msgid "Not mounted" msgstr "Μη προσαρτημένο" #: ../quodlibet/browsers/media.py:55 msgid "Mount point:" msgstr "Σημείο Προσάρτησης:" #: ../quodlibet/browsers/media.py:61 ../quodlibet/qltk/cbes.py:40 msgid "_Name:" msgstr "Ό_νομα:" #: ../quodlibet/browsers/media.py:135 msgid "Media Devices" msgstr "Συσκευές Μέσων" #: ../quodlibet/browsers/media.py:136 msgid "_Media Devices" msgstr "_Συσκευές Μέσων" #. eject button #: ../quodlibet/browsers/media.py:224 ../quodlibet/browsers/media.py:378 msgid "_Eject" msgstr "_Εξαγωγή" #: ../quodlibet/browsers/media.py:360 msgid "_Properties" msgstr "_Ιδιότητες" #: ../quodlibet/browsers/media.py:365 #: ../quodlibet/browsers/playlists/main.py:464 msgid "_Rename" msgstr "_Μετονομασία" #: ../quodlibet/browsers/media.py:461 #, python-format msgid "%(used-size)s used, %(free-size)s available" msgstr "%(used-size)s σε χρήση, %(free-size)s διαθέσιμο" #: ../quodlibet/browsers/media.py:479 #, python-format msgid "%s is not connected." msgstr "%s δεν είναι συνδεδεμένο." #: ../quodlibet/browsers/media.py:499 #, python-format msgid "Copying %(song)s" msgstr "Αντιγραφή %(song)s" #: ../quodlibet/browsers/media.py:513 ../quodlibet/browsers/media.py:529 msgid "Unable to copy song" msgstr "Αδυναμία αντιγραφής τραγουδιού" #: ../quodlibet/browsers/media.py:514 msgid "There is not enough free space for this song." msgstr "Δεν υπάρχει αρκετός ελεύθερος χώρος γι' αυτό το τραγούδι" #: ../quodlibet/browsers/media.py:526 #, python-format msgid "%s could not be copied." msgstr "Το %s δεν μπόρεσε να αντιγραφεί." #: ../quodlibet/browsers/media.py:545 msgid "Unable to delete songs" msgstr "Αδυναμία διαγραφής τραγουδιών" #: ../quodlibet/browsers/media.py:557 #, python-format msgid "Deleting %(song)s" msgstr "Διαγραφή %(song)s" #: ../quodlibet/browsers/media.py:575 #, python-format msgid "%s could not be deleted." msgstr "Δεν ήταν δυνατό να διαγραφεί το %s." #: ../quodlibet/browsers/media.py:579 msgid "Unable to delete song" msgstr "Αδυναμία διαγραφής τραγουδιού" #: ../quodlibet/browsers/media.py:594 #, python-format msgid "Ejecting %s failed." msgstr "Η εξαγωγή του %s απέτυχε." #: ../quodlibet/browsers/media.py:597 msgid "Unable to eject device" msgstr "Αδυναμία εξαγωγής συσκευής" #: ../quodlibet/browsers/media.py:603 msgid "No device backend, Media Devices browser disabled." msgstr "" "Χωρίς υποστήριξη συσκευών, ο περιηγητής Συσκευών Μέσων απενεργοποιήθηκε." #: ../quodlibet/browsers/paned/main.py:40 ../quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "Περιηγητής με Στήλες" #: ../quodlibet/browsers/paned/main.py:41 msgid "_Paned Browser" msgstr "Περιηγητής με _Στήλες" #: ../quodlibet/browsers/paned/main.py:90 msgid "Select _All" msgstr "Επιλογή Όλ_ων" #: ../quodlibet/browsers/paned/models.py:104 ../quodlibet/qltk/pluginwin.py:122 #: ../quodlibet/qltk/pluginwin.py:164 msgid "All" msgstr "Όλα" #: ../quodlibet/browsers/paned/prefs.py:67 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "<tt>%s</tt>" msgstr "" #: ../quodlibet/browsers/paned/prefs.py:162 msgid "_Wide Mode" msgstr "Λειτουργία _Πλατιάς προβολής" #: ../quodlibet/browsers/paned/prefs.py:197 msgid "Paned Browser Preferences" msgstr "Προτιμήσεις Περιηγητή με Στήλες" #: ../quodlibet/browsers/paned/prefs.py:204 msgid "Equal pane width" msgstr "" #: ../quodlibet/browsers/playlists/main.py:48 #: ../quodlibet/browsers/playlists/main.py:575 #: ../quodlibet/qltk/pluginwin.py:168 msgid "Playlists" msgstr "Λίστες Αναπαραγωγής" #: ../quodlibet/browsers/playlists/main.py:49 msgid "_Playlists" msgstr "_Λίστες Αναπαραγωγής" #: ../quodlibet/browsers/playlists/main.py:152 msgid "_Remove from Playlist" msgstr "Αφαίρεση από την Λίστα" #: ../quodlibet/browsers/playlists/main.py:215 #: ../quodlibet/browsers/playlists/main.py:576 msgid "_Import" msgstr "_Εισαγωγή" #: ../quodlibet/browsers/playlists/main.py:391 #: ../quodlibet/browsers/playlists/util.py:50 #: ../quodlibet/util/collection.py:570 msgid "New Playlist" msgstr "Νέα Λίστα Αναπαραγωγής" #: ../quodlibet/browsers/playlists/main.py:413 msgid "Unable to import playlist" msgstr "Αδυναμία εισαγωγής λίστας αναπαραγωγής" #: ../quodlibet/browsers/playlists/main.py:414 msgid "Quod Libet can only import playlists in the M3U and PLS formats." msgstr "Ο Quod Libet μπορεί να εισάγει λίστες τύπου M3U και PLS μόνο." #: ../quodlibet/browsers/playlists/main.py:565 msgid "Unable to rename playlist" msgstr "Αδυναμία μετονομασίας λίστας αναπαραγωγής" #: ../quodlibet/browsers/playlists/main.py:576 msgid "Import Playlist" msgstr "Εισαγωγή Λίστας Αναπαραγωγής" #: ../quodlibet/browsers/playlists/menu.py:25 msgid "_New Playlist…" msgstr "_Νέα Λίστα Αναπαραγωγής…" #: ../quodlibet/browsers/playlists/menu.py:86 #, 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:90 #, 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 #, 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:33 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "Θέλετε σίγουρα να διαγραφεί η λίστα αναπαραγωγής '%s';" #: ../quodlibet/browsers/playlists/util.py:35 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" "Οι πληροφορίες που αφορούν την επιλεγμένη λίστα αναπαραγωγής θα διαγραφούν " "χωρίς δυνατότητα ανάκτησης" #: ../quodlibet/browsers/playlists/util.py:51 msgid "Enter a name for the new playlist:" msgstr "Εισάγετε όνομα για την νέα λίστα" #: ../quodlibet/browsers/playlists/util.py:102 #, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" "Εισαγωγή λίστας αναπαραγωγής.\n" "\n" "%(current)d/%(total)d τραγούδια προστέθηκαν." #: ../quodlibet/browsers/search.py:33 msgid "_Limit Results" msgstr "_Περιορισμός Αποτελεσμάτων" #: ../quodlibet/browsers/search.py:48 msgid "Search Library" msgstr "Αναζήτηση στην Μουσικοθήκη" #: ../quodlibet/browsers/search.py:49 msgid "_Search Library" msgstr "_Αναζήτηση στην Μουσικοθήκη" #: ../quodlibet/browsers/soundcloud/main.py:38 #, fuzzy msgid "Soundcloud Browser" msgstr "Περιηγητής με Στήλες" #: ../quodlibet/browsers/soundcloud/main.py:39 msgid "Sound_cloud" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:59 #: ../quodlibet/qltk/searchbar.py:73 msgid "Search" msgstr "Αναζήτηση" #: ../quodlibet/browsers/soundcloud/main.py:136 #, python-format msgid "Go to %s" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:380 #, fuzzy msgid "Connected" msgstr "Σύνδεση" #: ../quodlibet/browsers/soundcloud/main.py:381 #, python-format msgid "Quod Libet is now connected, <b>%s</b>!" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:393 #, python-format msgid "Log out of %s" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:395 msgid "Enter code…" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:396 #, python-format msgid "Log in to %s" msgstr "" #: ../quodlibet/browsers/soundcloud/util.py:86 msgid "Soundcloud authorisation" msgstr "" #: ../quodlibet/browsers/soundcloud/util.py:87 msgid "Enter Soundcloud auth code:" msgstr "" #: ../quodlibet/cli.py:50 msgid "Quod Libet is not running (add '--run' to start it)" msgstr "Ο Quod Libet δεν εκτελείται (προσθέστε '--run' για να τον ξεκινήσετε)" #: ../quodlibet/cli.py:85 msgid "a music library and player" msgstr "Μουσικοθήκη και αναπαραγωγέας" #: ../quodlibet/cli.py:86 msgid "[option]" msgstr "[επιλογή]" #: ../quodlibet/cli.py:88 msgid "Print the playing song and exit" msgstr "Εμφάνιση του αναπαραγόμενου τραγουδιού και έξοδος" #: ../quodlibet/cli.py:89 msgid "Begin playing immediately" msgstr "Έναρξη αναπαραγωγής άμεσα" #: ../quodlibet/cli.py:90 msgid "Don't show any windows on start" msgstr "" #: ../quodlibet/cli.py:93 msgid "Jump to next song" msgstr "Μεταπήδηση στο επόμενο τραγούδι" #: ../quodlibet/cli.py:95 msgid "Jump to previous song or restart if near the beginning" msgstr "" "Μεταπήδηση στην αρχή του τραγουδιού ή στο προηγούμενο αν είναι ήδη κοντά " "στην αρχή" #: ../quodlibet/cli.py:96 msgid "Jump to previous song" msgstr "Μεταπήδηση στο προηγούμενο τραγούδι" #: ../quodlibet/cli.py:97 msgid "Start playback" msgstr "Έναρξη αναπαραγωγής" #: ../quodlibet/cli.py:98 msgid "Pause playback" msgstr "Παύση αναπαραγωγής" #: ../quodlibet/cli.py:99 msgid "Toggle play/pause mode" msgstr "Εναλλαγή αναπαραγωγής/παύσης" #: ../quodlibet/cli.py:100 msgid "Stop playback" msgstr "Σταμάτημα αναπαραγωγής" #: ../quodlibet/cli.py:101 msgid "Turn up volume" msgstr "Αύξηση της έντασης αναπαραγωγής" #: ../quodlibet/cli.py:102 msgid "Turn down volume" msgstr "Μείωση της έντασης αναπαραγωγής" #: ../quodlibet/cli.py:103 msgid "Print player status" msgstr "Εμφάνιση της κατάστασης του αναπαραγωγέα" #: ../quodlibet/cli.py:104 msgid "Hide main window" msgstr "Απόκρυψη του κυρίου παραθύρου" #: ../quodlibet/cli.py:105 msgid "Show main window" msgstr "Εμφάνιση του κυρίου παραθύρου" #: ../quodlibet/cli.py:106 msgid "Toggle main window visibility" msgstr "Εναλλαγή ορατότητας κυρίου παραθύρου" #: ../quodlibet/cli.py:107 msgid "Focus the running player" msgstr "Εστίαση του εκτελούμενου αναπαραγωγέα" #: ../quodlibet/cli.py:108 msgid "Remove active browser filters" msgstr "Αφαίρεση ενεργών φίλτρων περιηγητή" #: ../quodlibet/cli.py:109 msgid "Refresh and rescan library" msgstr "Ανανέωση και σάρωση ξανά της μουσικοθήκης" #: ../quodlibet/cli.py:110 msgid "List available browsers" msgstr "Προβολή διαθέσιμων περιηγητών" #: ../quodlibet/cli.py:111 msgid "Print the current playlist" msgstr "Εμφάνιση της τρέχουσας λίστας αναπαραγωγής" #: ../quodlibet/cli.py:112 msgid "Print the contents of the queue" msgstr "Εμφάνιση των περιεχομένων της ουράς αναπαραγωγής" #: ../quodlibet/cli.py:113 msgid "Print the active text query" msgstr "Εμφάνιση της ενεργής αναζήτησης" #: ../quodlibet/cli.py:114 msgid "Start without plugins" msgstr "Εκκίνηση χωρίς πρόσθετα" #: ../quodlibet/cli.py:115 msgid "Start Quod Libet if it isn't running" msgstr "Εκκινήστε τον Quod Libet αν δεν εκτελείται" #: ../quodlibet/cli.py:116 msgid "Exit Quod Libet" msgstr "Έξοδος από τον Quod Libet" #: ../quodlibet/cli.py:121 msgid "Seek within the playing song" msgstr "Αναζήτηση στο αναπαραγόμενο τραγούδι" #: ../quodlibet/cli.py:121 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][ΩΩ:]ΛΛ:ΔΔ" #: ../quodlibet/cli.py:122 #, fuzzy msgid "Set or toggle shuffle mode" msgstr "Εναλλαγή αναπαραγωγής/παύσης" #: ../quodlibet/cli.py:123 msgid "Turn repeat off, on, or toggle it" msgstr "Ενεργοποίηση, απενεργοποίηση ή εναλλαγή της επανάληψης" #: ../quodlibet/cli.py:124 msgid "Set the volume" msgstr "Καθορισμός έντασης" #: ../quodlibet/cli.py:125 msgid "Search your audio library" msgstr "Αναζήτηση στην μουσικοθήκη" #: ../quodlibet/cli.py:125 ../quodlibet/cli.py:137 ../quodlibet/cli.py:141 #: ../quodlibet/cli.py:143 msgid "query" msgstr "ερώτημα" #: ../quodlibet/cli.py:126 msgid "Play a file" msgstr "Αναπαραγωγή αρχείου" #: ../quodlibet/cli.py:126 ../quodlibet/cli.py:137 ../quodlibet/cli.py:143 msgctxt "command" msgid "filename" msgstr "όνομα αρχείου" #: ../quodlibet/cli.py:127 msgid "Rate the playing song" msgstr "Βαθμολόγηση αναπαραγόμενου τραγουδιού" #: ../quodlibet/cli.py:128 msgid "Set the current browser" msgstr "Καθορισμός τρέχοντος περιηγητή" #: ../quodlibet/cli.py:129 #, fuzzy msgid "Stop after the playing song" msgstr "Βαθμολόγηση αναπαραγόμενου τραγουδιού" #: ../quodlibet/cli.py:130 msgid "Open a new browser" msgstr "Άνοιγμα νέου περιηγητή" #: ../quodlibet/cli.py:131 msgid "Show or hide the queue" msgstr "Εμφάνιση ή απόκρυψη της ουράς αναπαραγωγής" #: ../quodlibet/cli.py:133 #, fuzzy msgid "Show or hide the main song list (deprecated)" msgstr "Εμφάνιση ή απόκρυψη της κύριας λίστας τραγουδιών" #: ../quodlibet/cli.py:134 msgid "Filter on a random value" msgstr "Φιλτρο βάσει τυχαίας τιμής" #: ../quodlibet/cli.py:134 msgctxt "command" msgid "tag" msgstr "ετικέτα" #: ../quodlibet/cli.py:135 msgid "Filter on a tag value" msgstr "Φίλτρο βάσει ετικέτας" #: ../quodlibet/cli.py:135 msgid "tag=value" msgstr "ετικέτα=τιμή" #: ../quodlibet/cli.py:136 msgid "Enqueue a file or query" msgstr "Προσθήκη ενός αρχείου ή ενός ερωτήματος στην ουρά" #: ../quodlibet/cli.py:138 msgid "Enqueue comma-separated files" msgstr "Προσθήκη στην ουρά αρχείων διαχωρισμένων με κόμματα" #: ../quodlibet/cli.py:139 ../quodlibet/util/tags.py:147 msgid "filename" msgstr "όνομα αρχείου" #: ../quodlibet/cli.py:140 msgid "Print filenames of results of query to stdout" msgstr "" "Εμφάνιση ονομάτων αρχείων ή αποτελεσμάτων ερωτήματος στην κανονική έξοδο" #: ../quodlibet/cli.py:142 msgid "Unqueue a file or query" msgstr "Αφαίρεση αρχείου ή ερωτήματος από την ουρά αναπαραγωγής" #: ../quodlibet/cli.py:203 #, python-format msgid "Invalid argument for '%s'." msgstr "Μη έγκυρο όρισμα για το '%s'." #: ../quodlibet/cli.py:204 ../quodlibet/util/__init__.py:190 #, python-format msgid "Try %s --help." msgstr "Δοκιμάστε το %s --help." #: ../quodlibet/devices/_base.py:65 msgid "Unknown Device" msgstr "Άγνωστη Συσκευή" #: ../quodlibet/devices/__init__.py:32 #, python-format msgid "Could not import %s, which is needed for device support." msgstr "Δεν μπόρεσε να εισαχθεί το %s, που χρειάζεται για υποστήριξη συσκευών." #: ../quodlibet/devices/__init__.py:153 #, python-format msgid "%r is not a supported device." msgstr "Το %r δεν είναι υποστηριζόμενη συσκευή." #: ../quodlibet/devices/__init__.py:245 ../quodlibet/devices/__init__.py:251 #, python-format msgid "Could not find '%s'." msgstr "Δεν βρέθηκε το %s." #: ../quodlibet/devices/__init__.py:450 msgid "Initializing device backend." msgstr "Αρχικοποίηση υποστήριξης συσκευών" #: ../quodlibet/devices/__init__.py:451 #, python-format msgid "Trying '%s'" msgstr "Δοκιμή '%s'" #: ../quodlibet/devices/__init__.py:461 msgid "Couldn't connect to a device backend." msgstr "Δεν ήταν δυνατή η σύνδεση σε κάποιο σύστημα υποστήριξης συσκευών." #: ../quodlibet/devices/__init__.py:463 msgid "Device backend initialized." msgstr "Αρχικοποιήθηκε η υποστήριξη συσκευών." #: ../quodlibet/devices/storage.py:57 msgid "_Filename pattern:" msgstr "_Πρότυπο ονόματος αρχείου:" #: ../quodlibet/devices/storage.py:61 msgid "Copy _album covers" msgstr "Αντιγραφή εξώφυλλων ά_λμπουμ" #: ../quodlibet/devices/storage.py:65 msgid "_Remove unused covers and directories" msgstr "_Αφαίρεση αχρείαστων εξώφυλλων και φακέλων" #: ../quodlibet/errorreport/ui.py:60 #, fuzzy msgid "An Error Occurred" msgstr "Προκλήθηκε Σφάλμα" #: ../quodlibet/errorreport/ui.py:62 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:72 msgid "File Bug Report" msgstr "" #: ../quodlibet/errorreport/ui.py:74 ../quodlibet/errorreport/ui.py:90 msgid "Submit Error Report" msgstr "" #: ../quodlibet/errorreport/ui.py:75 #, fuzzy msgid "Quit Program" msgstr "_Πρόγραμμα:" #: ../quodlibet/errorreport/ui.py:76 #, fuzzy msgid "Ignore Error" msgstr "Αγνόηση Όλων των Σ_φαλμάτων" #: ../quodlibet/errorreport/ui.py:80 #, fuzzy msgid "Error details:" msgstr "Λεπτομέρειες Σφάλματος" #: ../quodlibet/errorreport/ui.py:92 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:100 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "" #: ../quodlibet/errorreport/ui.py:109 msgid "_Send" msgstr "" #: ../quodlibet/errorreport/ui.py:115 #, fuzzy msgid "Short description…" msgstr "περιγραφή" #: ../quodlibet/errorreport/ui.py:118 msgid "Data to be sent:" msgstr "" #: ../quodlibet/exfalso.py:34 msgid "an audio tag editor" msgstr "ένας επεξεργαστής ετικετών μουσικής" #: ../quodlibet/exfalso.py:34 ../quodlibet/util/tags.py:148 msgid "directory" msgstr "κατάλογος" #: ../quodlibet/ext/covers/artwork_url.py:19 #, fuzzy msgid "Artwork URL Cover Source" msgstr "Πηγή Εξωφύλλου Last.fm" #: ../quodlibet/ext/covers/artwork_url.py:20 msgid "" "Downloads covers linked to by the artwork_url tag.This works with the " "Soundcloud browser." msgstr "" #: ../quodlibet/ext/covers/discogs.py:25 #, fuzzy msgid "Discogs Cover Source" msgstr "Πηγή Εξωφύλλου Last.fm" #: ../quodlibet/ext/covers/discogs.py:26 #, fuzzy msgid "Downloads covers from Discogs." msgstr "Λήψη εξώφυλλων άλμπουμ από διάφορες ιστοσελίδες." #: ../quodlibet/ext/covers/lastfm.py:22 msgid "Last.fm Cover Source" msgstr "Πηγή Εξωφύλλου Last.fm" #: ../quodlibet/ext/covers/lastfm.py:23 msgid "Downloads covers from Last.fm's cover art archive." msgstr "Λήψη εικόνας από το αρχείο εξώφυλλων του Last.fm." #: ../quodlibet/ext/covers/musicbrainz.py:19 msgid "MusicBrainz Cover Source" msgstr "Πηγή Εξωφύλλου MusicBrainz" #: ../quodlibet/ext/covers/musicbrainz.py:20 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:25 msgid "Kana/Kanji Simple Inverter" msgstr "Απλός μετατροπέας Kana/Kanji" #: ../quodlibet/ext/editing/kakasi.py:26 msgid "Converts kana/kanji to romaji before renaming." msgstr "" "Μετατροπή των γραμμάτων kana/kanji σε λατινικούς χαρακτήρες (romaji) πριν " "την μετονομασία." #: ../quodlibet/ext/editing/kakasi.py:35 msgid "Romanize _Japanese text" msgstr "Μετατροπή _Ιαπωνικού κειμένου σε λατινικούς χαρακτήρες" #: ../quodlibet/ext/editing/kakasi.py:63 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:19 msgid "" "Allows arbitrary regex substitutions (s///) 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:69 msgid "Advanced Preferences" msgstr "Προχωρημένες Προτιμήσεις" #: ../quodlibet/ext/events/advanced_preferences.py:70 #, fuzzy msgid "Allow editing of advanced config settings." msgstr "Επιτρέψτε την αλλαγή ρυθμίσεων για προχωρημένους." #: ../quodlibet/ext/events/advanced_preferences.py:162 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:153 msgid "Top of screen" msgstr "Κορυφή της οθόνης" #: ../quodlibet/ext/events/animosd/prefs.py:154 msgid "Middle of screen" msgstr "Μέση της οθόνης" #: ../quodlibet/ext/events/animosd/prefs.py:155 msgid "Bottom of screen" msgstr "Κάτω μέρος της οθόνης" #: ../quodlibet/ext/events/animosd/prefs.py:158 msgid "_Position:" msgstr "_Θέση:" #: ../quodlibet/ext/events/animosd/prefs.py:171 msgid "_Cover size:" msgstr "Μέγεθος _Εξώφυλλου:" #: ../quodlibet/ext/events/animosd/prefs.py:177 #: ../quodlibet/ext/events/lyricswindow.py:334 ../quodlibet/qltk/prefs.py:266 msgid "Display" msgstr "Προβολή" #: ../quodlibet/ext/events/animosd/prefs.py:190 msgid "_Font:" msgstr "_Γραμματοσειρά:" #: ../quodlibet/ext/events/animosd/prefs.py:195 msgid "Left" msgstr "Αριστερά" #: ../quodlibet/ext/events/animosd/prefs.py:196 msgid "Center" msgstr "Κέντρο" #: ../quodlibet/ext/events/animosd/prefs.py:197 msgid "Right" msgstr "Δεξιά" #: ../quodlibet/ext/events/animosd/prefs.py:200 msgid "_Align text:" msgstr "_Στοίχιση κειμένου:" #: ../quodlibet/ext/events/animosd/prefs.py:206 msgid "Text" msgstr "Κείμενο" #: ../quodlibet/ext/events/animosd/prefs.py:217 msgid "_Text:" msgstr "_Κείμενο:" #: ../quodlibet/ext/events/animosd/prefs.py:227 msgid "_Fill:" msgstr "_Φόντο:" #: ../quodlibet/ext/events/animosd/prefs.py:232 #: ../quodlibet/ext/events/synchronizedlyrics.py:63 msgid "Colors" msgstr "Χρώματα" #: ../quodlibet/ext/events/animosd/prefs.py:240 msgid "_Shadows" msgstr "_Σκιές" #: ../quodlibet/ext/events/animosd/prefs.py:241 msgid "_Outline" msgstr "_Περίγραμμα" #: ../quodlibet/ext/events/animosd/prefs.py:242 msgid "Rou_nded Corners" msgstr "Στρογγυλεμένες _Γωνίες" #: ../quodlibet/ext/events/animosd/prefs.py:258 msgid "_Delay:" msgstr "Κα_θυστέρηση:" #: ../quodlibet/ext/events/animosd/prefs.py:264 #: ../quodlibet/qltk/pluginwin.py:172 msgid "Effects" msgstr "Εφέ" #: ../quodlibet/ext/events/animosd/prefs.py:270 msgid "Ed_it Display Pattern…" msgstr "_Επεξεργασία Πρότυπου Εμφάνισης…" #: ../quodlibet/ext/events/animosd/prefs.py:274 #: ../quodlibet/ext/events/trayicon/prefs.py:78 msgid "Preview" msgstr "Προεπισκόπηση" #: ../quodlibet/ext/events/auto_library_update.py:136 msgid "Automatic Library Update" msgstr "Αυτόματη Ανανέωση Μουσικοθήκης" #: ../quodlibet/ext/events/auto_library_update.py:137 #, python-format msgid "Keeps your library up to date with inotify. Requires %s." msgstr "" "Διατηρεί τη μουσικοθήκη σας ενημερωμένη με χρήση inotify. Χρειάζεται το %s." #: ../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 by Brian Nelson." msgstr "" "Αυτόματη βαθμολόγιση των τραγουδιών καθώς αναπαράγωνται ή προσπερνούνται. Με " "τη χρήση του 'επιταχυνόμενου' αλγόριθμου του Brian Nelson από το vux." #: ../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/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:97 msgid "Equalizer" msgstr "Αντισταθμιστής" #: ../quodlibet/ext/events/equalizer.py:98 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:132 msgid "The current backend does not support equalization." msgstr "Το τρέχων ηχητικό σύστημα δεν υποστηρίζει αντιστάθμιση." #: ../quodlibet/ext/events/equalizer.py:138 #, python-format msgid "%.1f kHz" msgstr "" #: ../quodlibet/ext/events/equalizer.py:139 #: ../quodlibet/ext/gstreamer/crossfeed.py:93 #: ../quodlibet/ext/gstreamer/karaoke.py:95 #, python-format msgid "%d Hz" msgstr "" #: ../quodlibet/ext/events/equalizer.py:173 #: ../quodlibet/ext/gstreamer/crossfeed.py:112 #, python-format msgid "%.1f dB" msgstr "" #: ../quodlibet/ext/events/equalizer.py:192 #: ../quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Custom" msgstr "Προσαρμοσμένο" #: ../quodlibet/ext/events/equalizer.py:199 msgid "_Clear" msgstr "_Καθαρισμός" #. Translators: statuses relating to Instant Messenger apps #: ../quodlibet/ext/events/gajim_status.py:27 msgid "online" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:28 msgid "offline" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:29 msgid "chat" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:30 msgid "away" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:31 msgid "xa" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:32 msgid "invisible" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:37 msgid "Gajim Status Message" msgstr "Μήνυμα Κατάστασης Gajim" #: ../quodlibet/ext/events/gajim_status.py:38 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:45 #: ../quodlibet/ext/events/telepathy_status.py:69 msgid "paused" 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:160 #, fuzzy msgid "Add '[paused]'" msgstr "παυμένο" #: ../quodlibet/ext/events/gajim_status.py:163 msgid "If checked, '[paused]' will be added to status message on pause" msgstr "" "Αν τσεκαριστεί κατά την παύση θα προστεθεί το '[paused]' στο μήνυμα " "κατάστασης" #: ../quodlibet/ext/events/gajim_status.py:187 #, fuzzy msgid "Statuses for which message will be changed" msgstr "Καταστάσεις για τις οποίες θα αλλαχθεί το μήνυμα κατάστασης" #: ../quodlibet/ext/events/headphonemon.py:156 msgid "Pause on Headphone Unplug" msgstr "" #: ../quodlibet/ext/events/headphonemon.py:157 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" #: ../quodlibet/ext/events/inhibit.py:41 msgid "Inhibit Screensaver" msgstr "Αναστολή Προστασίας Οθόνης" #: ../quodlibet/ext/events/inhibit.py:42 msgid "Prevents the GNOME screensaver from activating while a song is playing." msgstr "Απενεργοποίηση της προστασίας οθόνης του GNOME κατά την αναπαραγωγή." #: ../quodlibet/ext/events/inhibit.py:51 msgid "Music is playing" msgstr "Αναπαράγεται μουσική" #: ../quodlibet/ext/events/iradiolog.py:16 msgid "Internet Radio Log" msgstr "Καταγραφή Διαδικτυακού Ραδιοφώνου" #: ../quodlibet/ext/events/iradiolog.py:17 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:29 msgid "JEP-118" msgstr "" #: ../quodlibet/ext/events/jep118.py:30 msgid "Outputs a Jabber User Tunes file to ~/.quodlibet/jabber." 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 msgid "A restart is required for any changes to take effect" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:199 msgid "No active song" msgstr "Δεν υπάρχει ενεργό τραγούδι" #: ../quodlibet/ext/events/lyricswindow.py:215 msgid "No lyrics found" msgstr "Δεν βρέθηκαν στίχοι" #: ../quodlibet/ext/events/lyricswindow.py:227 msgid "Lyrics:" msgstr "Στίχοι:" #: ../quodlibet/ext/events/lyricswindow.py:284 #, fuzzy msgid "_Zoom level:" msgstr "Επίπε_δο:" #: ../quodlibet/ext/events/lyricswindow.py:302 msgid "URL:" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:307 #, fuzzy msgid "Revert to default" msgstr "Επαναφορά στο προκαθορισμένο πρότυπο" #: ../quodlibet/ext/events/lyricswindow.py:322 msgid "Search via above URL if the lyrics couldn't be found in LyricsWikia." msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:339 #, fuzzy msgid "Alternate search" msgstr "Καθαρισμός αναζήτησης" #: ../quodlibet/ext/events/lyricswindow.py:347 msgid "Lyrics Window" msgstr "Παράθυρο Στίχων" #: ../quodlibet/ext/events/lyricswindow.py:348 msgid "Shows a window containing lyrics of the playing song." msgstr "Εμφανίζει ένα παράθυρο με στίχους του αναπαραγώμενου τραγουδιού." #: ../quodlibet/ext/events/mediaserver.py:38 msgid "UPnP AV Media Server" msgstr "Διακομιστής πολυμέσων UPnP AV Media Server" #: ../quodlibet/ext/events/mediaserver.py:39 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/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:39 msgid "" "Allows control of Quod Libet using the MPRIS 1.0/2.0 D-Bus Interface " "Specification." msgstr "Έλεγχος του Quod Libet με χρήση της διεπαφής D-Bus MPRIS 1.0/2.0." #: ../quodlibet/ext/events/mpris/__init__.py:45 #: ../quodlibet/ext/events/trayicon/prefs.py:30 msgid "Hide main window on close" msgstr "Απόκρυψη του κυρίου παραθύρου στο κλείσιμο" #: ../quodlibet/ext/events/mpris/__init__.py:48 #: ../quodlibet/ext/events/themeswitcher.py:84 #: ../quodlibet/ext/gstreamer/compressor.py:99 #: ../quodlibet/ext/gstreamer/crossfeed.py:136 #: ../quodlibet/ext/gstreamer/karaoke.py:99 #: ../quodlibet/ext/gstreamer/pitch.py:83 ../quodlibet/qltk/prefs.py:688 msgid "Preferences" msgstr "Προτιμήσεις" #: ../quodlibet/ext/events/mqtt.py:50 #, fuzzy, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "" "Μήνυμα κατάστασης όταν κάποιο τραγούδι είναι παυμένο. Δέχεται πρότυπα QL π." "χ. %s" #: ../quodlibet/ext/events/mqtt.py:56 msgid "MQTT Publisher" msgstr "" #: ../quodlibet/ext/events/mqtt.py:57 msgid "Publishes status messages to an MQTT topic." msgstr "" #: ../quodlibet/ext/events/mqtt.py:122 msgid "Broker hostname" msgstr "" #: ../quodlibet/ext/events/mqtt.py:122 msgid "broker hostname / IP" msgstr "" #: ../quodlibet/ext/events/mqtt.py:124 msgid "Broker port" msgstr "" #: ../quodlibet/ext/events/mqtt.py:124 msgid "broker port" msgstr "" #: ../quodlibet/ext/events/mqtt.py:126 msgid "Topic" msgstr "" #: ../quodlibet/ext/events/mqtt.py:128 #, fuzzy msgid "Playing Pattern" msgstr "Πρότυπα Διαδρομών" #: ../quodlibet/ext/events/mqtt.py:130 #, fuzzy msgid "Status text when a song is started." msgstr "" "Μήνυμα κατάστασης όταν αναπαράγεται κάποιο τραγούδι. Δέχεται πρότυπα QL π.χ. " "%s" #: ../quodlibet/ext/events/mqtt.py:132 #, fuzzy msgid "Paused Pattern" msgstr "Πρότυπα Καταστάσεων" #: ../quodlibet/ext/events/mqtt.py:134 msgid "Text when a song is paused." msgstr "" #: ../quodlibet/ext/events/mqtt.py:136 #, fuzzy msgid "No-song Text" msgstr "Χωρίς τρέχων τραγούδι:" #: ../quodlibet/ext/events/mqtt.py:138 #, fuzzy msgid "Plain text for when there is no current song" msgstr "Απλό κείμενο για την κατάσταση για όταν δεν υπάρχει τρέχων τραγούδι" #: ../quodlibet/ext/events/mqtt.py:149 #, fuzzy msgid "MQTT Configuration" msgstr "Ρύθμιση Εξόδου" #: ../quodlibet/ext/events/mqtt.py:153 #, fuzzy msgid "Status Text" msgstr "Κατάσταση" #: ../quodlibet/ext/events/mqtt.py:185 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "" #: ../quodlibet/ext/events/mqtt.py:189 #, fuzzy, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s" msgstr "Δεν ήταν δυνατή η σύνδεση στο %s" #: ../quodlibet/ext/events/mqtt.py:192 #, fuzzy msgid "Connection error" msgstr "Σφάλμα σύνδεσης" #: ../quodlibet/ext/events/notify.py:80 msgid "Notification text" msgstr "Κείμενο ειδοποίησης" #: ../quodlibet/ext/events/notify.py:88 msgid "_Title:" msgstr "_Τίτλος:" #: ../quodlibet/ext/events/notify.py:99 ../quodlibet/ext/events/notify.py:128 msgid "Revert to default pattern" msgstr "Επαναφορά στο προκαθορισμένο πρότυπο" #: ../quodlibet/ext/events/notify.py:118 msgid "_Body:" msgstr "_Σώμα:" #: ../quodlibet/ext/events/notify.py:138 msgid "_Show notification" msgstr "_Εμφάνιση ειδοποίησης" #: ../quodlibet/ext/events/notify.py:156 msgid "Show notifications" msgstr "Εμφάνιση ειδοποιήσεων" #: ../quodlibet/ext/events/notify.py:162 msgid "Only on <i>_manual</i> song changes" msgstr "Μόνο σε <i>_χειροκίνητες</i> αλλαγές τραγουδιών" #: ../quodlibet/ext/events/notify.py:170 msgid "Only on <i>_automatic</i> song changes" msgstr "Μόνο σε <i>_αυτόματες</i> αλλαγές τραγουδιών" #: ../quodlibet/ext/events/notify.py:178 msgid "On <i>a_ll</i> song changes" msgstr "Σε <i>Ό_λες</i> τις αλλαγές τραγουδιών" #: ../quodlibet/ext/events/notify.py:196 msgid "Only when the main window is not _focused" msgstr "Μόνο όταν το κύριο παράθυρο δεν είναι _εστιασμένο" #: ../quodlibet/ext/events/notify.py:204 msgid "Show \"_Next\" button" msgstr "" #: ../quodlibet/ext/events/notify.py:236 msgid "Connection Error" msgstr "Σφάλμα σύνδεσης" #: ../quodlibet/ext/events/notify.py:237 ../quodlibet/ext/events/notify.py:391 #: ../quodlibet/ext/events/notify.py:433 msgid "Couldn't connect to notification daemon." msgstr "Δεν ήταν δυνατή η σύνδεση με τον δαίμονα ειδοποιήσεων." #: ../quodlibet/ext/events/notify.py:251 msgid "Song Notifications" msgstr "Ειδοποιήσεις Τραγουδιών" #: ../quodlibet/ext/events/notify.py:252 msgid "Displays a notification when the song changes." msgstr "Εμφανίζει ειδοποίηση στην αλλαγή τραγουδιού." #: ../quodlibet/ext/events/notify.py:415 ../quodlibet/qltk/unity.py:65 msgid "Next" msgstr "Επόμενο" #: ../quodlibet/ext/events/qlscrobbler.py:178 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" "Παρακαλώ ανοίξτε το παράθυρο προσθέτων και ρυθμίστε το QLScrobbler. " "Διαφορετικά τα τραγούδια δεν θα υποβάλλονται." #: ../quodlibet/ext/events/qlscrobbler.py:254 #, python-format msgid "Could not contact service '%s'." msgstr "Δεν ήταν δυνατή η σύνδεση στην υπηρεσία '%s'." #: ../quodlibet/ext/events/qlscrobbler.py:260 msgid "Authentication failed: invalid URL." msgstr "Η πιστοποίηση απέτυχε: μη έγκυρο URL." #: ../quodlibet/ext/events/qlscrobbler.py:277 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "Η πιστοποίηση απέτυχε: Μη έγκυρο όνομα χρήστη '%s' ή λάθος κωδικός." #: ../quodlibet/ext/events/qlscrobbler.py:282 msgid "Client is banned. Contact the author." msgstr "Ο πελάτης έχει απαγορευτεί. Ειδοποιήστε τον συγγραφέα." #: ../quodlibet/ext/events/qlscrobbler.py:286 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" "Λάθος ώρα συστήματος. Οι υποβολές μπορεί να αποτυγχάνουν μέχρι να διορθωθεί." #: ../quodlibet/ext/events/qlscrobbler.py:351 msgid "AudioScrobbler Submission" msgstr "Υποβολή AudioScrobbler" #: ../quodlibet/ext/events/qlscrobbler.py:352 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" "Πελάτης Audioscrobbler για το Last.fm, Libre.fm και άλλες υπηρεσίες " "Audioscrobbler." #: ../quodlibet/ext/events/qlscrobbler.py:450 msgid "Authentication successful." msgstr "Επιτυχημένη πιστοποίηση" #: ../quodlibet/ext/events/qlscrobbler.py:462 msgid "_Service:" msgstr "_Υπηρεσία:" #: ../quodlibet/ext/events/qlscrobbler.py:462 msgid "_URL:" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:462 msgid "User_name:" msgstr "Όνομα _χρήστη:" #: ../quodlibet/ext/events/qlscrobbler.py:463 msgid "_Password:" msgstr "_Κωδικός:" #. Translators: Other service #: ../quodlibet/ext/events/qlscrobbler.py:479 msgid "Other…" msgstr "Άλλο…" #. verify data #: ../quodlibet/ext/events/qlscrobbler.py:517 msgid "_Verify account data" msgstr "_Επαλήθευση δεδομένων λογαριασμού" #: ../quodlibet/ext/events/qlscrobbler.py:522 #: ../quodlibet/ext/songsmenu/lastfmsync.py:304 msgid "Account" msgstr "Λογαριασμός" #: ../quodlibet/ext/events/qlscrobbler.py:530 msgid "_Artist pattern:" msgstr "Πρότυπο _Καλλιτέχνη:" #: ../quodlibet/ext/events/qlscrobbler.py:530 msgid "_Title pattern:" msgstr "_Πρότυπο Τίτλου:" #: ../quodlibet/ext/events/qlscrobbler.py:531 msgid "Exclude _filter:" msgstr "_Φίλτρο εξαιρέσεων:" #: ../quodlibet/ext/events/qlscrobbler.py:549 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" "Το πρότυπο που θα χρησιμοποιηθεί για την υποβολή του ονόματος καλλιτέχνη. " "Αφήστε το κενό για τη χρήση προκαθορισμένου." #: ../quodlibet/ext/events/qlscrobbler.py:559 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" "Το πρότυπο που θα χρησιμοποιηθεί για την υποβολή του τίτλου. Αφήστε το κενό " "για τη χρήση προκαθορισμένου." #: ../quodlibet/ext/events/qlscrobbler.py:568 msgid "Songs matching this filter will not be submitted" msgstr "Τα τραγούδια που ταιριάζουν με αυτό το φίλτρο δεν θα υποβάλλονται" #: ../quodlibet/ext/events/qlscrobbler.py:576 msgid "_Offline mode (don't submit anything)" msgstr "Λειτουργία Εκτός _Σύνδεσης (να μην υποβληθεί τίποτα)" #: ../quodlibet/ext/events/qlscrobbler.py:580 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:27 msgid "Random Album Playback" msgstr "Αναπαραγωγή Τυχαίου Άλμπουμ" #: ../quodlibet/ext/events/randomalbum.py:28 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:38 msgid "Rated higher" msgstr "Πιο υψηλά βαθμολογημένο" #: ../quodlibet/ext/events/randomalbum.py:39 msgid "Played more often" msgstr "Έχει αναπαραχθεί συχνά" #: ../quodlibet/ext/events/randomalbum.py:40 msgid "Skipped more often" msgstr "Έχει παραληφθεί συχνά" #: ../quodlibet/ext/events/randomalbum.py:41 msgid "Played more recently" msgstr "Έχει αναπαραχθεί πρόσφατα" #: ../quodlibet/ext/events/randomalbum.py:42 msgid "Started more recently" msgstr "Έχει ξεκινήσει να αναπαράγεται πρόσφατα" #: ../quodlibet/ext/events/randomalbum.py:43 msgid "Added more recently" msgstr "Έχει προστεθεί πρόσφατα" #: ../quodlibet/ext/events/randomalbum.py:44 msgid "Longer albums" msgstr "Μεγαλύτερα σε διάρκεια άλμπουμ" #: ../quodlibet/ext/events/randomalbum.py:83 msgid "seconds before starting next album" msgstr "δευτερόλεπτα πριν την εκκίνηση του επόμενου άλμπουμ" #: ../quodlibet/ext/events/randomalbum.py:87 msgid "Weights" msgstr "Βαρύτητες" #: ../quodlibet/ext/events/randomalbum.py:89 msgid "Play some albums more than others" msgstr "Να προτιμούνται κάποια άλμπουμ περισσότερο" #: ../quodlibet/ext/events/randomalbum.py:103 msgid "avoid" msgstr "απέφυγε" #: ../quodlibet/ext/events/randomalbum.py:114 msgid "prefer" msgstr "προτίμησε" #: ../quodlibet/ext/events/randomalbum.py:201 msgid "Random Album" msgstr "Τυχαίο Άλμπουμ" #: ../quodlibet/ext/events/randomalbum.py:202 #, python-format msgid "Waiting to start %s" msgstr "Ξεκινά το %s" #: ../quodlibet/ext/events/rbimport.py:114 msgid "Import Failed" msgstr "Η Εισαγωγή Απέτυχε" #: ../quodlibet/ext/events/rbimport.py:119 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "Επιτυχής εισαγωγή βαθμολογιών και στατιστικών για %d τραγούδια" #: ../quodlibet/ext/events/rbimport.py:127 msgid "Rhythmbox Import" msgstr "Εισαγωγή από τον Rhythmbox" #: ../quodlibet/ext/events/rbimport.py:128 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "Εισάγει βαθμολογίες και στατιστικά τραγουδιών από το Rhythmbox." #: ../quodlibet/ext/events/rbimport.py:132 msgid "Start Import" msgstr "Ξεκίνα την εισαγωγή" #: ../quodlibet/ext/events/screensaver.py:25 msgid "Screensaver Pause" msgstr "Παύση με την Προστασία Οθόνης" #: ../quodlibet/ext/events/screensaver.py:26 msgid "Pauses playback while the GNOME screensaver is active." msgstr "Παύει τη μουσική όταν ενεργοποιηθεί η προστασία οθόνης του GNOME." #: ../quodlibet/ext/events/searchprovider.py:73 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "" "Δεν έχει εγκατασταθεί ο πάροχος αναζήτησης του Quod Libet για το GNOME Shell." #: ../quodlibet/ext/events/searchprovider.py:79 msgid "GNOME Search Provider" msgstr "Πάροχος Αναζήτησης GNOME" #: ../quodlibet/ext/events/searchprovider.py:80 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/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "Συγχρονισμός με το Squeezebox" #: ../quodlibet/ext/events/squeezebox_sync.py:29 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:57 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "Σφάλμα στην εύρεση του διακομιστή Squeezebox" #: ../quodlibet/ext/events/squeezebox_sync.py:58 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "Σφάλμα στην εύρεση του %s. Παρακαλώ ελέγξτε τις ρυθμίσεις" #: ../quodlibet/ext/events/synchronizedlyrics.py:34 #, fuzzy msgid "Synchronized Lyrics" msgstr "Προβολή Στίχων" #: ../quodlibet/ext/events/synchronizedlyrics.py:35 msgid "Shows synchronized lyrics from .lrc file with same name as the track." msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:66 #, fuzzy msgid "Text:" msgstr "_Κείμενο:" #: ../quodlibet/ext/events/synchronizedlyrics.py:76 msgid "Background:" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:87 #, fuzzy msgid "Font" msgstr "_Γραμματοσειρά:" #: ../quodlibet/ext/events/synchronizedlyrics.py:90 msgid "Size (px):" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:62 msgid "Telepathy Status Messages" msgstr "Μηνύματα Κατάστασης Telepathy" #: ../quodlibet/ext/events/telepathy_status.py:63 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:122 msgid "Playing:" msgstr "Αναπαράγεται:" #: ../quodlibet/ext/events/telepathy_status.py:123 #, 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:139 msgid "Paused:" msgstr "Παυμένο:" #: ../quodlibet/ext/events/telepathy_status.py:140 #, 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:156 msgid "Plain text for status when there is no current song" msgstr "Απλό κείμενο για την κατάσταση για όταν δεν υπάρχει τρέχων τραγούδι" #: ../quodlibet/ext/events/telepathy_status.py:157 msgid "No song:" msgstr "Χωρίς τρέχων τραγούδι:" #. Frame #: ../quodlibet/ext/events/telepathy_status.py:164 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/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:77 #: ../quodlibet/ext/events/trayicon/prefs.py:98 #: ../quodlibet/ext/events/trayicon/systemtray.py:177 #: ../quodlibet/qltk/info.py:47 msgid "Not playing" msgstr "Δεν αναπαράγεται" #: ../quodlibet/ext/events/trayicon/__init__.py:53 msgid "Tray Icon" msgstr "Εικονίδιο Περιοχής Συστήματος" #: ../quodlibet/ext/events/trayicon/__init__.py:54 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:183 #: ../quodlibet/qltk/quodlibetwindow.py:1046 #: ../quodlibet/qltk/quodlibetwindow.py:1238 msgid "_Play" msgstr "_Αναπαραγωγή" #: ../quodlibet/ext/events/trayicon/menu.py:63 #: ../quodlibet/qltk/quodlibetwindow.py:185 #: ../quodlibet/qltk/quodlibetwindow.py:1240 ../quodlibet/qltk/wlw.py:51 msgid "P_ause" msgstr "_Παύση" #: ../quodlibet/ext/events/trayicon/menu.py:68 #: ../quodlibet/qltk/quodlibetwindow.py:190 #: ../quodlibet/qltk/quodlibetwindow.py:1041 msgid "Pre_vious" msgstr "Προη_γούμενο" #: ../quodlibet/ext/events/trayicon/menu.py:71 #: ../quodlibet/qltk/quodlibetwindow.py:194 #: ../quodlibet/qltk/quodlibetwindow.py:1051 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:1012 msgid "Open _Browser" msgstr "Άνοιγμα _Περιηγητή" #: ../quodlibet/ext/events/trayicon/menu.py:103 #: ../quodlibet/qltk/quodlibetwindow.py:1031 ../quodlibet/qltk/songsmenu.py:411 msgid "Edit _Tags" msgstr "Επε_ξεργασία Ετικετών" #: ../quodlibet/ext/events/trayicon/menu.py:112 #: ../quodlibet/qltk/quodlibetwindow.py:975 ../quodlibet/qltk/songsmenu.py:424 msgid "_Information" msgstr "Π_ληροφορίες" #: ../quodlibet/ext/events/trayicon/menu.py:114 #: ../quodlibet/qltk/songsmenu.py:340 msgid "Play_lists" msgstr "_Λίστες Αναπαραγωγής" #: ../quodlibet/ext/events/trayicon/menu.py:132 #: ../quodlibet/qltk/quodlibetwindow.py:1026 msgid "_Quit" msgstr "Έ_ξοδος" #: ../quodlibet/ext/events/trayicon/prefs.py:32 ../quodlibet/qltk/prefs.py:69 msgid "Behavior" msgstr "Συμπεριφορά" #: ../quodlibet/ext/events/trayicon/prefs.py:42 #, fuzzy msgid "Scroll wheel adjusts volume" msgstr "" "Ο τροχός του ποντικιού αυξομειώνει την ένταση ήχου\n" "Ο τροχός με πατημένο το Shift αλλάζει τραγούδια" #: ../quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel changes song" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll _Wheel" msgstr "_Τροχός Ποντικιού" #: ../quodlibet/ext/events/trayicon/prefs.py:84 msgid "Tooltip Display" msgstr "Προβολή Συμβουλής" #: ../quodlibet/ext/events/viewlyrics.py:23 msgid "View Lyrics" msgstr "Προβολή Στίχων" #: ../quodlibet/ext/events/viewlyrics.py:24 #, fuzzy msgid "Automatically displays lyrics beneath the song list in the main window." msgstr "Προβολή στίχων κάτω από την λίστα τραγουδιών" #: ../quodlibet/ext/events/viewlyrics.py:29 msgid "_Lyrics" 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:406 #, fuzzy msgid "Waveform Seek Bar" msgstr "Εναλακτική" #: ../quodlibet/ext/events/waveformseekbar.py:410 msgid "A seekbar in the shape of the waveform of the current song." msgstr "" #: ../quodlibet/ext/events/waveformseekbar.py:443 msgid "Override foreground color:" msgstr "" #: ../quodlibet/ext/events/write_cover.py:32 msgid "Picture Saver" msgstr "Αποθηκευτής Εικόνων" #: ../quodlibet/ext/events/write_cover.py:33 msgid "Saves the cover image of the current song to a file." msgstr "Η εικόνα εξωφύλλου του τρέχοντος τραγουδιού αποθηκεύεται σε αρχείο." #: ../quodlibet/ext/events/write_cover.py:66 msgid "File:" msgstr "Αρχείο:" #: ../quodlibet/ext/gstreamer/compressor.py:20 msgid "_Threshold:" msgstr "_Κατώφλι:" #: ../quodlibet/ext/gstreamer/compressor.py:21 msgid "Threshold until the filter is activated" msgstr "Κατώφλι για την ενεργοποίηση του φίλτρου" #: ../quodlibet/ext/gstreamer/compressor.py:22 msgid "R_atio:" msgstr "_Αναλογία" #: ../quodlibet/ext/gstreamer/compressor.py:22 msgid "Compression ratio" msgstr "Αναλογία συμπίεσης" #: ../quodlibet/ext/gstreamer/compressor.py:74 #: ../quodlibet/ext/gstreamer/karaoke.py:91 #, python-format msgid "%d %%" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:105 msgid "Audio Compressor" msgstr "Συμπιεστής Ήχου" #: ../quodlibet/ext/gstreamer/compressor.py:106 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" "Αλλαγή του πλάτους κύματος όλων των δειγμάτων πάνω από κάποιο συγκεκριμένο " "κατώφλι με καθορισμένη αναλογία." #: ../quodlibet/ext/gstreamer/crossfeed.py:19 msgid "_Preset:" msgstr "_Προκαθορισμένο:" #: ../quodlibet/ext/gstreamer/crossfeed.py:19 msgid "Filter preset" msgstr "Προκαθορισμένο φίλτρο" #: ../quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Frequency cut:" msgstr "_Συχνότητα αποκοπής:" #: ../quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Low-pass filter cut frequency" msgstr "Συχνότητα αποκοπής φίλτρου χαμηλής συχνότητας" #: ../quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed _level:" msgstr "Επίπεδο _εισόδου:" #: ../quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed level" msgstr "Επίπεδο εισόδου" #: ../quodlibet/ext/gstreamer/crossfeed.py:25 msgid "Default" msgstr "Προεπιλογή" #: ../quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "Πλησιέστερο σε τοποθέτηση εικονικών ηχείων (30°, 3 μέτρα)" #: ../quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Chu Moy" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "Πλησίον του διατροφοδοτητή του Chu Moy (δημοφιλές)" #: ../quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Jan Meier" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "Πλησίον στους ενισχυτές CORDA του Jan Meier (μικρή αλλαγή)" #: ../quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Custom settings" msgstr "Προσαρμοσμένες ρυθμίσεις" #: ../quodlibet/ext/gstreamer/crossfeed.py:152 msgid "Crossfeed" msgstr "Διατροφοδότηση" #: ../quodlibet/ext/gstreamer/crossfeed.py:153 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:20 msgid "Filter _band:" msgstr "_Ζώνη φίλτρου:" #: ../quodlibet/ext/gstreamer/karaoke.py:21 msgid "The Frequency band of the filter" msgstr "Η ζώνη συχνοτήτων του φίλτρου" #: ../quodlibet/ext/gstreamer/karaoke.py:22 msgid "Filter _width:" msgstr "_Εύρος φίλτρου:" #: ../quodlibet/ext/gstreamer/karaoke.py:23 msgid "The Frequency width of the filter" msgstr "Το εύρος συχνοτήτων του φίλτρου" #: ../quodlibet/ext/gstreamer/karaoke.py:24 msgid "_Level:" msgstr "Επίπε_δο:" #: ../quodlibet/ext/gstreamer/karaoke.py:24 msgid "Level of the effect" msgstr "Η στάθμη επίδρασης" #: ../quodlibet/ext/gstreamer/karaoke.py:105 msgid "Karaoke" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:106 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:20 msgid "R_ate:" msgstr "_Ποσοστό:" #: ../quodlibet/ext/gstreamer/pitch.py:21 msgid "_Tempo:" msgstr "_Τέμπο:" #: ../quodlibet/ext/gstreamer/pitch.py:22 msgid "_Pitch:" msgstr "Τό_νος:" #: ../quodlibet/ext/gstreamer/pitch.py:89 msgid "Audio Pitch / Speed" msgstr "Τόνος / Ταχύτητα Ήχου" #: ../quodlibet/ext/gstreamer/pitch.py:90 msgid "Controls the pitch of an audio stream." msgstr "Έλεγχος του ηχητικού τόνου." #: ../quodlibet/ext/playlist/export_to_folder.py:29 #: ../quodlibet/ext/playlist/export_to_folder.py:97 #: ../quodlibet/ext/playlist/export_to_folder.py:138 #, fuzzy msgid "Export Playlist to Folder" msgstr "Εξαγωγή της λίστας αναπαραγωγής στο Squeezebox" #: ../quodlibet/ext/playlist/export_to_folder.py:38 #, fuzzy msgid "_Export" msgstr "_Εισαγωγή" #: ../quodlibet/ext/playlist/export_to_folder.py:43 #, fuzzy msgid "Destination folder:" msgstr "Δεν βρέθηκαν σταθμοί" #: ../quodlibet/ext/playlist/export_to_folder.py:58 #, 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:156 #, fuzzy msgid "Default filename pattern:" msgstr "_Πρότυπο ονόματος αρχείου:" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:23 #, fuzzy msgid "Export to Squeezebox" msgstr "Εξαγωγή στο Squeezebox…" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:25 #, fuzzy 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 "" "Εξαγωγή λίστας αναπαραγωγής στο Logitech Squeezebox, αρκεί να χρησιμοποιούν " "την ίδια δομή καταλόγων. Χρησιμοποιεί τις ρυθμίσεις του προσθέτου Squeezebox " "Sync." #: ../quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Export playlist to Squeezebox" msgstr "Εξαγωγή της λίστας αναπαραγωγής στο Squeezebox" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:80 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 "" "Playback follows your selection, or the next song in the list once exhausted." msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:22 #, fuzzy msgid "Playcount Equalizer" msgstr "Αντισταθμιστής" #: ../quodlibet/ext/playorder/playcounteq.py:23 msgid "Shuffle, preferring songs with fewer total plays." msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:25 #, fuzzy msgid "Prefer less played" msgstr "τελευταία αναπαραγωγή" #: ../quodlibet/ext/playorder/queue.py:19 msgid "Queue Only" msgstr "Μόνο Ουρά" #: ../quodlibet/ext/playorder/queue.py:21 #, fuzzy msgid "" "Limits playing of songs to the queue. Select this play order in the main " "window, then double-clicking any song will enqueue it instead of playing." msgstr "" "Αναπαραγωγή μόνο τραγουδιών από την ουρά. Διπλό κλικ σε τραγούδι για να το " "προσθέσετε στην ουρά αναπαραγωγής." #: ../quodlibet/ext/playorder/reverse.py:14 msgid "Reverse" msgstr "Αντίστροφα" #: ../quodlibet/ext/playorder/reverse.py:16 msgid "Reverses the play order of songs." msgstr "Αντιστρέφει τη σειρά αναπαραγωγής." #: ../quodlibet/ext/playorder/skip_songs.py:25 #, fuzzy msgid "Skip Songs" msgstr "Μετρητής Παραλείψεων" #: ../quodlibet/ext/playorder/skip_songs.py:27 msgid "" "Playback skips over songs with a rating equal or below a given threshold." msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:30 msgid "Repeat Each Track" msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:32 msgid "Shuffle songs, but repeat every track a set number of times." msgstr "" "Τυχαία σειρά, αλλά κάθε τραγούδι επαναλαμβάνεται έναν προκαθορισμένο αριθμό " "φορών." #: ../quodlibet/ext/playorder/track_repeat.py:51 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. Syntax is '@(if: " "condition, then, else)'." msgstr "" #: ../quodlibet/ext/query/pythonexpression.py:14 #, fuzzy msgid "Python Query" msgstr "Κονσόλα Python" #: ../quodlibet/ext/query/pythonexpression.py:15 msgid "" "Use Python expressions in queries. Syntax is '@(python: expression)'. The " "variable 's' is the song being matched." msgstr "" #: ../quodlibet/ext/query/savedsearch.py:19 #, fuzzy msgid "Include Saved Search" msgstr "Αποθηκευμένες Αναζητήσεις" #: ../quodlibet/ext/query/savedsearch.py:20 msgid "" "Include the results of a saved search as part of another query. Syntax is " "'@(saved: search name)'." 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:116 msgid "Port:" msgstr "Θύρα:" #: ../quodlibet/ext/_shared/squeezebox/base.py:121 msgid "Username:" msgstr "Όνομα Χρήστη:" #: ../quodlibet/ext/_shared/squeezebox/base.py:126 msgid "Password:" msgstr "Κωδικός:" #: ../quodlibet/ext/_shared/squeezebox/base.py:130 msgid "Library directory the server connects to" msgstr "Κατάλογος μουσικοθήκης στον οποίο συνδέεται ο διακομιστής" #: ../quodlibet/ext/_shared/squeezebox/base.py:132 msgid "Library path:" msgstr "Τοποθεσία μουσικοθήκης:" #. Add verify button #: ../quodlibet/ext/_shared/squeezebox/base.py:141 msgid "_Verify settings" msgstr "_Επαλήθευση ρυθμίσεων" #. Server settings Frame #: ../quodlibet/ext/_shared/squeezebox/base.py:147 msgid "Squeezebox Server" msgstr "Διακομιστής Squeezebox" #: ../quodlibet/ext/_shared/squeezebox/base.py:150 msgid "Debug" msgstr "Αποσφαλμάτωση" #: ../quodlibet/ext/_shared/squeezebox/server.py:26 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "Διακομιστής Squeezebox στο {hostname}:{port}" #: ../quodlibet/ext/_shared/squeezebox/server.py:28 msgid "unidentified Squeezebox server" msgstr "άγνωστος διακομιστής Squeezebox" #: ../quodlibet/ext/_shared/squeezebox/server.py:37 #, 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:20 #: ../quodlibet/ext/songsmenu/importexport.py:34 #: ../quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "_Εντάξει" #: ../quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" "Βρέθηκε ο διακομιστής Squeezebox.\n" "Παρακαλώ επιλέξτε τον αναπαραγωγέα" #: ../quodlibet/ext/songsmenu/albumart.py:329 msgid "Fit image to _window" msgstr "Προσαρμογή _μεγέθους εικόνας στο μέγεθος παραθύρου" #. Both labels #: ../quodlibet/ext/songsmenu/albumart.py:338 msgid "_Program:" msgstr "_Πρόγραμμα:" #: ../quodlibet/ext/songsmenu/albumart.py:343 msgid "_Edit image after saving" msgstr "_Επεξεργασία της εικόνας μετά την αποθήκευση" #: ../quodlibet/ext/songsmenu/albumart.py:345 msgid "File_name:" msgstr "Όνομα _αρχείου" #: ../quodlibet/ext/songsmenu/albumart.py:457 msgid "Saving failed" msgstr "Η αποθήκευση απέτυχε" #: ../quodlibet/ext/songsmenu/albumart.py:458 #, python-format msgid "Unable to save \"%s\"." msgstr "Αδυναμία αποθήκευσης \"%s\"." #: ../quodlibet/ext/songsmenu/albumart.py:556 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "[albumart] Σφάλμα HTTP: %s" #: ../quodlibet/ext/songsmenu/albumart.py:613 msgid "Album Art Downloader" msgstr "Λήψη Εξώφυλλων Άλμπουμ" #: ../quodlibet/ext/songsmenu/albumart.py:666 #, python-format msgid "from %(source)s" msgstr "από %(source)s" #: ../quodlibet/ext/songsmenu/albumart.py:669 #, python-format msgid "Resolution: %s" msgstr "Ανάλυση: %s" #: ../quodlibet/ext/songsmenu/albumart.py:672 #, python-format msgid "Size: %s" msgstr "Μέγεθος: %s" #: ../quodlibet/ext/songsmenu/albumart.py:690 msgid "_Search" msgstr "_Αναζήτηση" #: ../quodlibet/ext/songsmenu/albumart.py:741 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:451 msgid "Searching…" msgstr "Αναζήτηση…" #: ../quodlibet/ext/songsmenu/albumart.py:804 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "Τελείωσε" #: ../quodlibet/ext/songsmenu/albumart.py:922 msgid "Download Album Art" msgstr "Λήψη Εξώφυλλων Άλμπουμ" #: ../quodlibet/ext/songsmenu/albumart.py:923 msgid "Downloads album covers from various websites." msgstr "Λήψη εξώφυλλων άλμπουμ από διάφορες ιστοσελίδες." #: ../quodlibet/ext/songsmenu/albumart.py:936 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 #: ../quodlibet/qltk/downloader.py:52 msgid "Filename" msgstr "Όνομα Αρχείου" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:130 #, fuzzy msgid "Disc" msgstr "_Δίσκος" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:131 #: ../quodlibet/ext/songsmenu/replaygain.py:404 #: ../quodlibet/qltk/tracknumbers.py:92 msgid "Track" msgstr "Κομμάτι" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:132 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:447 msgid "Please enter a query." msgstr "Παρακαλώ εισάγεται ένα ερώτημα." #: ../quodlibet/ext/songsmenu/brainz/widgets.py:465 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:496 msgid "Error encountered. Please retry." msgstr "Παρουσιάστηκε σφάλμα. Παρακαλώ δοκιμάστε ξανά." #: ../quodlibet/ext/songsmenu/brainz/widgets.py:472 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:488 msgid "Loading result…" msgstr "Φόρτωση αποτελέσματος…" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:475 msgid "No results found." msgstr "Δεν βρέθηκαν αποτελέσματα." #: ../quodlibet/ext/songsmenu/browsefolders.py:159 msgid "Browse Folders" msgstr "Άνοιγμα Φακέλου" #: ../quodlibet/ext/songsmenu/browsefolders.py:160 msgid "Opens the songs' folders in a file manager." msgstr "Άνοιγμα του φακέλου του τραγουδιού με τον διαχειριστή αρχείων." #: ../quodlibet/ext/songsmenu/browsefolders.py:172 msgid "Unable to open folders" msgstr "Αδυναμία ανοίγματος φακέλων" #: ../quodlibet/ext/songsmenu/browsefolders.py:173 msgid "No program available to open folders." msgstr "Δεν υπάρχει διαθέσιμη εφαρμογή για το άνοιγμα φακέλων." #: ../quodlibet/ext/songsmenu/console.py:40 msgid "Python Console" msgstr "Κονσόλα Python" #: ../quodlibet/ext/songsmenu/console.py:41 msgid "Interactive Python console." msgstr "Διαδραστική κονσόλα Python" #: ../quodlibet/ext/songsmenu/console.py:72 msgid "You can access the following objects by default:" msgstr "Έχετε πρόσβαση στα ακόλουθα αντικείμενα από προεπιλογή:" #: ../quodlibet/ext/songsmenu/console.py:82 msgid "Your current working directory is:" 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:55 msgid "pattern" msgstr "πρότυπο" #: ../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:91 msgid "Input value" msgstr "Εισαγωγή τιμής" #: ../quodlibet/ext/songsmenu/custom_commands.py:92 #, python-format msgid "Value for %s?" msgstr "Τιμή του %s;" #: ../quodlibet/ext/songsmenu/custom_commands.py:136 msgid "Custom Commands" msgstr "Προσαρμοσμένες Εντολές" #: ../quodlibet/ext/songsmenu/custom_commands.py:137 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" "Εκτελεί προσαρμοσμένες εντολές (σε δέσμες αν χρειάζεται) σε τραγούδια " "χρησιμοποιώντας τις τιμές ετικετών τους" #: ../quodlibet/ext/songsmenu/custom_commands.py:188 #: ../quodlibet/ext/songsmenu/custom_commands.py:198 #: ../quodlibet/ext/songsmenu/custom_commands.py:252 msgid "Edit Custom Commands" msgstr "Επεξεργασία Προσαρμοσμένων Εντολών" #: ../quodlibet/ext/songsmenu/custom_commands.py:199 #, fuzzy msgid "" "Supports QL patterns\n" "eg <tt><~artist~title></tt>" msgstr "" "Υποστηρίζει πρότυπα QL\n" "π.χ. <tt><~artist~title></tt>" #: ../quodlibet/ext/songsmenu/custom_commands.py:283 #, python-format msgid "Unable to run custom command %s" msgstr "Αδυναμία εκτέλεσης προσαρμοσμένης εντολής %s" #: ../quodlibet/ext/songsmenu/duplicates.py:290 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "%d ομάδα διπλότυπων" msgstr[1] "%d ομάδες διπλότυπων" #: ../quodlibet/ext/songsmenu/duplicates.py:343 msgid "Collapse / Expand all" msgstr "Σύμπτυξη / Ανάπτυξη όλων" #: ../quodlibet/ext/songsmenu/duplicates.py:347 #, python-format msgid "Duplicate key expression is '%s'" msgstr "Το πρότυπο για το κλειδί διπλοτύπων είναι '%s'" #: ../quodlibet/ext/songsmenu/duplicates.py:363 msgid "Duplicates Browser" msgstr "Αναζήτηση Διπλότυπων" #: ../quodlibet/ext/songsmenu/duplicates.py:364 msgid "Finds and displays similarly tagged versions of songs." msgstr "Εύρεση παρόμοιων εκδόσεων τραγουδιών." #: ../quodlibet/ext/songsmenu/duplicates.py:407 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:409 msgid "_Group duplicates by:" msgstr "_Ομαδοποίηση διπλοτύπων με βάση:" #: ../quodlibet/ext/songsmenu/duplicates.py:414 msgid "Duplicate Key" msgstr "Κλειδί Διπλοτύπων" #: ../quodlibet/ext/songsmenu/duplicates.py:419 msgid "Remove _Whitespace" msgstr "Διαγραφή _Κενών" #: ../quodlibet/ext/songsmenu/duplicates.py:420 msgid "Remove _Diacritics" msgstr "Διαγραφή _Διακριτικών Σημείων" #: ../quodlibet/ext/songsmenu/duplicates.py:421 msgid "Remove _Punctuation" msgstr "Διαγραφή _Στίξης" #: ../quodlibet/ext/songsmenu/duplicates.py:422 msgid "Case _Insensitive" msgstr "Αγνόησε διαφορές πεζών/Κεφαλαίων" #: ../quodlibet/ext/songsmenu/duplicates.py:430 msgid "Matching options" msgstr "Επιλογές ταιριάσματος" #. Create a dialog. #: ../quodlibet/ext/songsmenu/editplaycount.py:19 #: ../quodlibet/ext/songsmenu/editplaycount.py:41 msgid "Edit Playcount" msgstr "Επεξεργασία Μετρητή Αναπαραγωγών" #: ../quodlibet/ext/songsmenu/editplaycount.py:20 msgid "" "Edit a song's ~#playcount and ~#skipcount.\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's ~#playcount to 0, the ~#lastplayed and ~#laststarted " "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:68 msgid "Play Count" msgstr "Μετρητής Αναπαραγωγών" #: ../quodlibet/ext/songsmenu/editplaycount.py:69 msgid "Skip Count" msgstr "Μετρητής Παραλείψεων" #: ../quodlibet/ext/songsmenu/embedded.py:24 msgid "Edit Embedded Images" msgstr "Επεξεργασία Ενσωματωμένων Εικόνων" #: ../quodlibet/ext/songsmenu/embedded.py:25 msgid "Removes or replaces embedded images." msgstr "Διαγραφή ή αντικατάσταση των ενσωματωμένων εικόνων." #: ../quodlibet/ext/songsmenu/embedded.py:78 #, fuzzy msgid "_Remove all Images" msgstr "_Διαγραφή όλων των εικόνων" #: ../quodlibet/ext/songsmenu/embedded.py:82 #, fuzzy msgid "_Embed Current 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:41 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 #: ../quodlibet/qltk/downloader.py:67 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 "Αποθήκευση" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" 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:49 msgid "Generating fingerprints:" msgstr "Παραγωγή αποτυπωμάτων:" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:63 msgid "_Details" msgstr "_Λεπτομέρειες" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:85 msgid "_Submit" msgstr "_Υποβολή" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:115 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:118 msgid "Fingerprints:" msgstr "Αποτυπώματα:" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Songs with MBIDs:" msgstr "Τραγούδια με MBID:" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with sufficient tags:" msgstr "Τραγούδια με επαρκείς ετικέτες:" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs to submit:" msgstr "Τραγούδια για υποβολή:" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:162 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "Τέλος. %(to-send)d/%(all)d τραγούδια για υποβολή." #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:178 msgid "Submitting fingerprints:" msgstr "Υποβάλλονται Αποτυπώματα:" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:186 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/id3tlen.py:21 msgid "Fix MP3 Duration" msgstr "Διόρθωση της διάρκειας του MP3" #: ../quodlibet/ext/songsmenu/id3tlen.py:22 msgid "" "Removes TLEN frames from ID3 tags which can be the cause for invalid song " "durations." msgstr "" "Αφαιρεί από τις ID3 ετικέτες τις καταχωρήσεις TLEN, που ίσως δημιουργούν " "λανθασμένες διάρκειες τραγουδιών." #: ../quodlibet/ext/songsmenu/ifp.py:20 msgid "Send to iFP" msgstr "Αποστολή στο iFP" #: ../quodlibet/ext/songsmenu/ifp.py:21 msgid "Uploads songs to an iRiver iFP device." msgstr "Μεταφόρτωση τραγουδιών σε συσκευή iRiver iFP." #: ../quodlibet/ext/songsmenu/importexport.py:51 msgid "Export Metadata" msgstr "Εξαγωγή Μεταδεδομένων" #: ../quodlibet/ext/songsmenu/importexport.py:52 msgid "Exports metadata of selected songs as a .tags file." msgstr "Εξαγωγή μεταδεδομένων των επιλεγμένων τραγουδιών σε ένα αρχείο .tags." #: ../quodlibet/ext/songsmenu/importexport.py:92 msgid "Import Metadata" msgstr "Εισαγωγή Μεταδεδομένων" #: ../quodlibet/ext/songsmenu/importexport.py:93 msgid "Imports metadata for selected songs from a .tags file." msgstr "" "Εισαγωγή μεταδεδομένων για τα επιλεγμένα τραγούδια από ένα αρχείο .tags." #: ../quodlibet/ext/songsmenu/k3b.py:23 msgid "Burn CD" msgstr "Κάψιμο CD" #: ../quodlibet/ext/songsmenu/k3b.py:24 msgid "Burns CDs with K3b, Brasero or xfburn." msgstr "Δημιουργία CD με το K3b το Brasero ή το xfburn." #: ../quodlibet/ext/songsmenu/lastfmsync.py:96 msgid "Updating chart list." msgstr "Ενημέρωση λίστας chart." #. No charts to fetch, no update scheduled. #: ../quodlibet/ext/songsmenu/lastfmsync.py:114 msgid "Already up-to-date." msgstr "Ήδη ενημερωμένο." #: ../quodlibet/ext/songsmenu/lastfmsync.py:121 #, python-format msgid "Fetching chart for week of %s." msgstr "Λήψη chart εβδομάδας %s." #: ../quodlibet/ext/songsmenu/lastfmsync.py:143 msgid "Sync complete." msgstr "Ο συγχρονισμός ολοκληρώθηκε." #: ../quodlibet/ext/songsmenu/lastfmsync.py:149 msgid "Error during sync" msgstr "Σφάλμα κατά τον συγχρονισμό" #: ../quodlibet/ext/songsmenu/lastfmsync.py:214 #: ../quodlibet/ext/songsmenu/lastfmsync.py:244 msgid "Last.fm Sync" msgstr "Συγχρονισμός last.fm" #: ../quodlibet/ext/songsmenu/lastfmsync.py:245 msgid "Updates your library's statistics from your Last.fm profile." msgstr "" "Ενημερώστε τα στατιστικά της μουσικοθήκης σας από το προφίλ σας στο Last.fm." #: ../quodlibet/ext/songsmenu/lastfmsync.py:293 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 "" "Μετατροπή ονομάτων άλμπουμ και καλλιτέχνη σε ετικέτες ταξινόμησης, συχνά " "αστόχως." #. Create a dialog. #: ../quodlibet/ext/songsmenu/migratemetadata.py:29 #: ../quodlibet/ext/songsmenu/migratemetadata.py:38 #, fuzzy msgid "Migrate Metadata" msgstr "Εξαγωγή Μεταδεδομένων" #: ../quodlibet/ext/songsmenu/migratemetadata.py:32 msgid "Copies the quodlibet-specific metadata between songs." msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:45 msgid "_Copy" msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:47 msgid "_Paste" msgstr "" #. Create the tag table. #: ../quodlibet/ext/songsmenu/migratemetadata.py:57 #, fuzzy msgid "Information to copy/paste" msgstr "Πληροφορίες" #. Create the indexing box. #: ../quodlibet/ext/songsmenu/migratemetadata.py:79 msgid "Map tracks by disc and track number" msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:80 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 "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:96 #, python-format msgid "There is %d stored track." msgid_plural "There are %d stored tracks." msgstr[0] "" msgstr[1] "" #: ../quodlibet/ext/songsmenu/playlist.py:31 #, fuzzy msgid "Export as Playlist" msgstr "Εισαγωγή Λίστας Αναπαραγωγής" #: ../quodlibet/ext/songsmenu/playlist.py:32 msgid "Exports songs to an M3U or PLS playlist." msgstr "Εξαγωγή τραγουδιών σε λίστα M3U ή PLS." #: ../quodlibet/ext/songsmenu/playlist.py:77 msgid "Use relative paths" msgstr "Χρήση σχετικών διαδρομών" #: ../quodlibet/ext/songsmenu/playlist.py:77 msgid "Use absolute paths" msgstr "Χρήση απόλυτων διαδρομών" #: ../quodlibet/ext/songsmenu/playlist.py:132 msgid "Unable to export playlist" msgstr "Αδυναμία εξαγωγής λίστας αναπαραγωγής" #: ../quodlibet/ext/songsmenu/playlist.py:133 #, python-format msgid "Writing to <b>%s</b> 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:362 msgid "ReplayGain Analyzer" msgstr "Αναλυτής ReplayGain" #: ../quodlibet/ext/songsmenu/replaygain.py:418 msgid "Progress" msgstr "Πρόοδος" #: ../quodlibet/ext/songsmenu/replaygain.py:433 msgid "Gain" msgstr "Ενίσχυση" #: ../quodlibet/ext/songsmenu/replaygain.py:448 msgid "Peak" msgstr "Κορυφή" #: ../quodlibet/ext/songsmenu/replaygain.py:463 #, fuzzy, python-format msgid "There is <b>%(to-process)s</b> album to update (of %(all)s)" msgid_plural "There are <b>%(to-process)s</b> 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:578 msgid "Replay Gain" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:579 msgid "" "Analyzes and updates ReplayGain information, using GStreamer. Results are " "grouped by album." msgstr "Ανάλυση ReplayGain με το GStreamer, με ομαδοποίηση κατά άλμπουμ." #: ../quodlibet/ext/songsmenu/replaygain.py:617 msgid "always" msgstr "πάντα" #: ../quodlibet/ext/songsmenu/replaygain.py:618 msgid "if <b>any</b> RG tags are missing" msgstr "αν λείπουν <b>οποιεσδήποτε</b> ετικέτες RG" #: ../quodlibet/ext/songsmenu/replaygain.py:620 msgid "if <b>album</b> RG tags are missing" msgstr "Αν λείπουν οι ετικέτες RG του <b>άλμπουμ</b>" #: ../quodlibet/ext/songsmenu/replaygain.py:637 msgid "_Process albums:" msgstr "_Επεξεργασία άλμπουμ:" #. Server settings Frame #: ../quodlibet/ext/songsmenu/replaygain.py:649 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 "Διαχωρισμός αριθμού δίσκου." #. TRANSLATORS: BPM mean "beats per minute" #: ../quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "" #: ../quodlibet/ext/songsmenu/tapbpm.py:32 #: ../quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" 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:172 #: ../quodlibet/ext/songsmenu/tapbpm.py:179 msgid "Tap BPM" msgstr "" #: ../quodlibet/ext/songsmenu/tapbpm.py:173 #, fuzzy msgid "Tap BPM for the selected song." msgstr "Αδυναμία διαγραφής τραγουδιών" #: ../quodlibet/ext/songsmenu/website_search.py:35 msgid "Website Search" msgstr "Αναζήτηση σε Ιστοσελίδα" #: ../quodlibet/ext/songsmenu/website_search.py:36 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern-example)s." msgstr "" "Αναζητεί σε ιστοσελίδα επιλογής σας χρησιμοποιώντας ετικέτες τραγουδιών.\n" "Υποστηρίζει πρότυπα π.χ. %(pattern-example)s" #: ../quodlibet/ext/songsmenu/website_search.py:78 msgid "Search URL patterns" msgstr "Πρότυπα URL αναζήτησης" #: ../quodlibet/ext/songsmenu/website_search.py:88 msgid "Edit search URLs" msgstr "Επεξεργασία των URL αναζήτησης" #. Add link to editor #: ../quodlibet/ext/songsmenu/website_search.py:114 #, fuzzy msgid "Configure Searches…" msgstr "Επεξεργασία αναζητήσεων…" #: ../quodlibet/ext/songsmenu/wikipedia.py:46 #, python-format msgid "Search at %(website)s" msgstr "Αναζήτηση σε %(website)s" #: ../quodlibet/ext/songsmenu/wikipedia.py:63 msgid "Search Artist in Wikipedia" msgstr "Αναζήτηση του καλλιτέχνη στη Βικιπαίδεια" #: ../quodlibet/ext/songsmenu/wikipedia.py:64 msgid "" "Opens a browser window with Wikipedia article on the playing song artist." msgstr "" "Ανοίγει ένα παράθυρο περιηγητή με το άρθρο της Βικιπαίδειας για τον " "καλλιτέχνη του τρέχοντος τραγουδιού." #: ../quodlibet/ext/songsmenu/wikipedia.py:71 msgid "Search Album in Wikipedia" msgstr "Αναζήτηση του άλμπουμ στη Βικιπαίδεια" #: ../quodlibet/ext/songsmenu/wikipedia.py:72 msgid "" "Opens a browser window with Wikipedia article on the playing song album." msgstr "" "Ανοίγει ένα παράθυρο περιηγητή με το άρθρο της Βικιπαίδειας για το τρέχον " "άλμπουμ" #. then (try to) load all new files #: ../quodlibet/library/libraries.py:650 ../quodlibet/library/libraries.py:660 #: ../quodlibet/library/libraries.py:726 ../quodlibet/library/libraries.py:745 #: ../quodlibet/qltk/information.py:268 ../quodlibet/qltk/prefs.py:639 #: ../quodlibet/util/library.py:124 msgid "Library" msgstr "Μουσικοθήκη" #: ../quodlibet/library/libraries.py:650 msgid "Checking mount points" msgstr "Έλεγχος σημείων προσάρτησης" #: ../quodlibet/library/libraries.py:660 msgid "Scanning library" msgstr "Σάρωση της μουσικοθήκης" #: ../quodlibet/library/libraries.py:725 #, python-format msgid "Scanning %s" msgstr "Σάρωση του %s" #: ../quodlibet/library/libraries.py:745 #, fuzzy msgid "Loading files" msgstr "Η αποθήκευση απέτυχε" #: ../quodlibet/operon/base.py:70 #, python-format msgid "Failed to load file: %r" msgstr "Αποτυχία ανοίγματος αρχείου: %r" #: ../quodlibet/operon/commands.py:37 msgid "List tags" msgstr "Εμφάνιση ετικετών" #: ../quodlibet/operon/commands.py:42 ../quodlibet/operon/commands.py:81 #: ../quodlibet/operon/commands.py:461 msgid "Print terse output" msgstr "Εμφάνιση ωμής εξόδου" #: ../quodlibet/operon/commands.py:44 ../quodlibet/operon/commands.py:83 #: ../quodlibet/operon/commands.py:463 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "Στήλες και η σειρά που θα εμφανιστούν στην ωμή έξοδο (%s)" #: ../quodlibet/operon/commands.py:47 ../quodlibet/operon/commands.py:86 msgid "Also list programmatic tags" msgstr "Εμφάνιση _προγραμματικών ετικετών" #: ../quodlibet/operon/commands.py:51 ../quodlibet/operon/commands.py:129 #: ../quodlibet/operon/commands.py:220 ../quodlibet/operon/commands.py:293 #: ../quodlibet/operon/commands.py:336 ../quodlibet/operon/commands.py:340 #: ../quodlibet/operon/commands.py:391 ../quodlibet/operon/commands.py:394 #: ../quodlibet/operon/commands.py:433 ../quodlibet/operon/commands.py:468 #: ../quodlibet/operon/commands.py:508 ../quodlibet/operon/commands.py:543 #: ../quodlibet/operon/commands.py:585 msgid "Not enough arguments" msgstr "Μη αρκετός αριθμός ορισμάτων" #: ../quodlibet/operon/commands.py:53 ../quodlibet/operon/commands.py:90 #: ../quodlibet/operon/commands.py:131 ../quodlibet/operon/commands.py:222 #: ../quodlibet/operon/commands.py:470 msgid "Too many arguments" msgstr "Υπερβολικός αριθμός ορισμάτων" #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:92 #: ../quodlibet/operon/commands.py:475 ../quodlibet/qltk/data_editors.py:363 msgid "Description" msgstr "Περιγραφή" #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:475 #: ../quodlibet/qltk/edittags.py:454 msgid "Value" msgstr "Τιμή" #: ../quodlibet/operon/commands.py:76 msgid "List all common tags" msgstr "Εμφάνιση όλων των κοινών ετικετών" #: ../quodlibet/operon/commands.py:118 msgid "Copy tags from one file to another" msgstr "Αντιγραφή ετικετών από ένα αρχείο σε άλλο" #: ../quodlibet/operon/commands.py:123 ../quodlibet/operon/commands.py:164 #: ../quodlibet/operon/commands.py:289 ../quodlibet/operon/commands.py:324 #: ../quodlibet/operon/commands.py:384 msgid "Show changes, don't apply them" msgstr "Δείξε τις αλλαγές χωρίς να τις εφαρμόσεις" #: ../quodlibet/operon/commands.py:125 msgid "Skip tags that can't be written" msgstr "Παράλειψη ετικετών που δεν μπορούν να γραφούν" #: ../quodlibet/operon/commands.py:145 #, python-format msgid "Can't copy tag %r to file: %r" 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:304 ../quodlibet/operon/commands.py:444 #: ../quodlibet/operon/commands.py:676 #, python-format msgid "Can not set %r" msgstr "Αδύνατος ο ορισμός του %r" #: ../quodlibet/operon/commands.py:319 msgid "Remove tags" msgstr "Διαγραφή ετικετών" #: ../quodlibet/operon/commands.py:326 ../quodlibet/operon/commands.py:386 msgid "Value is a regular expression" msgstr "Η τιμή είναι κανονική παράσταση" #: ../quodlibet/operon/commands.py:328 msgid "Remove all tags" msgstr "Διαγραφή όλων των ετικετών" #: ../quodlibet/operon/commands.py:332 msgid "Can't combine '--all' with '--regexp'" msgstr "Αδύνατος ο συνδυασμός του '--all' με το '--regexp'" #: ../quodlibet/operon/commands.py:366 #, python-format msgid "Can't remove %r from %r" msgstr "Αδύνατη η αφαίρεση του %r από το %r" #: ../quodlibet/operon/commands.py:379 msgid "Remove a tag value" msgstr "Διαγραφή της τιμής ετικέτας" #: ../quodlibet/operon/commands.py:428 msgid "Add a tag value" msgstr "Προσθήκη τιμής σε ετικέτα" #: ../quodlibet/operon/commands.py:456 msgid "List file information" msgstr "Προβολή πληροφοριών αρχείου" #: ../quodlibet/operon/commands.py:502 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" "Καθορισμός της εικόνας ως κύριας ενσωματωμένης εικόνας και αφαίρεση των " "υπολοίπων ενσωματωμένων εικόνων." #: ../quodlibet/operon/commands.py:515 #, python-format msgid "Failed to load image file: %r" msgstr "Αποτυχία ανοίγματος αρχείου εικόνας: %r" #: ../quodlibet/operon/commands.py:522 ../quodlibet/operon/commands.py:551 #, 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:538 msgid "Remove all embedded images" msgstr "Διαγραφή όλων των ενσωματωμένων εικόνων" #: ../quodlibet/operon/commands.py:568 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "Εξαγωγή ενσωματωμένων εικόνων σε %(filepath)s" #: ../quodlibet/operon/commands.py:580 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" "Τοποθεσία αποθήκευσης εικόνων (η προεπιλογή είναι ο κατάλογος εργασίας)" #: ../quodlibet/operon/commands.py:639 msgid "Rename files based on tags" msgstr "Μετονομασία αρχείων βάσει ετικετών" #: ../quodlibet/operon/commands.py:654 msgid "Fill tags based on the file path" msgstr "Συμπλήρωση ετικετών βάσει διαδρομής αρχείου" #: ../quodlibet/operon/commands.py:704 ../quodlibet/qltk/information.py:305 #: ../quodlibet/qltk/properties.py:84 ../quodlibet/qltk/renamefiles.py:176 #: ../quodlibet/qltk/tagsfrompath.py:229 ../quodlibet/qltk/tracknumbers.py:79 msgid "File" msgstr "Αρχείο" #: ../quodlibet/operon/commands.py:712 msgid "Fill tracknumbers for all files" msgstr "Συμπλήρωση αριθμών κομματιού για όλα τα αρχεία" #: ../quodlibet/operon/commands.py:731 msgid "Print tags based on the given pattern" msgstr "Εμφάνιση ετικετών βάσει παρεχόμενου προτύπου" #: ../quodlibet/operon/commands.py:768 msgid "Display help information" msgstr "Προβολή σύντομων πληροφοριών χρήσης" #: ../quodlibet/operon/util.py:40 #, 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:30 msgid "_Unknown" msgstr "Ά_γνωστο" #: ../quodlibet/order/__init__.py:142 msgid "In Order" msgstr "Με τη Σειρά" #: ../quodlibet/order/__init__.py:143 msgid "_In Order" msgstr "Με τη _Σειρά" #: ../quodlibet/order/reorder.py:23 #, fuzzy msgid "Random" msgstr "_Τυχαία" #: ../quodlibet/order/reorder.py:24 ../quodlibet/qltk/queue.py:119 msgid "_Random" msgstr "_Τυχαία" #: ../quodlibet/order/reorder.py:39 ../quodlibet/order/reorder.py:40 msgid "Prefer higher rated" msgstr "" #: ../quodlibet/order/repeat.py:43 ../quodlibet/order/repeat.py:44 msgid "Repeat this track" msgstr "" #: ../quodlibet/order/repeat.py:57 ../quodlibet/order/repeat.py:58 #, fuzzy msgid "Repeat all" msgstr "_Επανάληψη" #: ../quodlibet/order/repeat.py:73 ../quodlibet/order/repeat.py:74 msgid "One Song" msgstr "Ένα Τραγούδι" #: ../quodlibet/player/gstbe/player.py:98 msgid "Stream" msgstr "Ροή" #: ../quodlibet/player/gstbe/player.py:98 msgid "Buffering" msgstr "Buffering" #: ../quodlibet/player/gstbe/player.py:319 msgid "Could not create GStreamer pipeline" msgstr "Αδυναμία δημιουργίας διασωλήνωσης GStreamer" #: ../quodlibet/player/gstbe/player.py:560 msgid "No GStreamer element found to handle media format" msgstr "" "Δεν βρέθηκε στοιχείο GStreamer ικανό να χειριστεί αυτό το είδος αρχείου" #: ../quodlibet/player/gstbe/player.py:561 #, 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:25 msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. In case the pipeline contains a sink, it will be used instead of " "the default one." msgstr "" "Η διασωλήνωση του GStreamer που χρησιμοποιείται για αναπαραγωγή. Αφήστε το " "κενό για χρήση της προεπιλεγμένης τιμής. Αν η διασωλήνωση περιέχει και " "τελική έξοδο θα χρησιμοποιηθεί αντί της προεπιλεγμένης." #: ../quodlibet/player/gstbe/prefs.py:36 msgid "_Output pipeline:" msgstr "_Διασωλήνωση εξόδου:" #: ../quodlibet/player/gstbe/prefs.py:43 #, python-format msgid "%.1f seconds" msgstr "%.1f δευτερόλεπτα" #: ../quodlibet/player/gstbe/prefs.py:57 msgid "_Buffer duration:" msgstr "Διάρκεια _Buffer:" #: ../quodlibet/player/gstbe/prefs.py:66 msgid "Disable _gapless playback" msgstr "Απενεργοποίηση αναπαραγωγής χωρίς κενά (_gapless)" #: ../quodlibet/player/gstbe/prefs.py:70 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions" msgstr "" "Η απενεργοποίηση της αναπαραγωγής χωρίς κενά μερικές φορές αποτρέπει " "προβλήματα αλλαγής τραγουδιών με ορισμένες εκδόσεις του Gstreamer" #: ../quodlibet/player/gstbe/util.py:93 msgid "No GStreamer audio sink found" msgstr "Δεν βρέθηκε έξοδος ήχου GStreamer" #: ../quodlibet/player/gstbe/util.py:112 msgid "Invalid GStreamer output pipeline" msgstr "Μη έγκυρη διασωλήνωση εξόδου GStreamer" #: ../quodlibet/player/xinebe/player.py:90 msgid "Unable to create audio output" msgstr "Αδυναμία δημιουργίας εξόδου ήχου" #: ../quodlibet/player/xinebe/player.py:91 #, 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:62 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" "Δεν βρέθηκε το πρόσθετο '{module}'. Ίσως χρειάζεται να εγκατασταθεί το " "πακέτο." #: ../quodlibet/plugins/__init__.py:71 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "Αδυναμία εύρεσης του στοιχείου '{element}' του GStreamer." #: ../quodlibet/plugins/playlist.py:30 #, 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:41 ../quodlibet/qltk/songsmenu.py:46 #: ../quodlibet/qltk/songsmenu.py:74 msgid "_Run Plugin" msgstr "_Εκτέλεση Πρόσθετου" #: ../quodlibet/qltk/about.py:40 #, python-format msgid "Supported formats: %s" msgstr "Υποστηριζόμενοι τύποι αρχείων: %s" #: ../quodlibet/qltk/about.py:43 #, python-format msgid "Audio device: %s" msgstr "Συσκευή ήχου: %s" #. 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:207 ../quodlibet/qltk/information.py:131 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:48 ../quodlibet/qltk/edittags.py:311 msgid "_Value:" msgstr "_Τιμή" #: ../quodlibet/qltk/cbes.py:262 msgid "Saved Values" msgstr "Αποθηκευμένες Τιμές" #: ../quodlibet/qltk/cbes.py:263 msgid "Edit saved values…" msgstr "Επεξεργασία αποθηκευμένων τιμών…" #: ../quodlibet/qltk/controls.py:111 msgid "Auto_matic" msgstr "Αυτό_ματα" #: ../quodlibet/qltk/controls.py:112 msgid "_Track Mode" msgstr "Λειτουργία _Κομματιού" #: ../quodlibet/qltk/controls.py:113 msgid "_Album Mode" msgstr "Λειτουργία Ά_λμπουμ" #. Translators: player state, no action #: ../quodlibet/qltk/controls.py:122 msgid "_Mute" msgstr "" #: ../quodlibet/qltk/controls.py:128 #, fuzzy msgid "_Replay Gain Mode" msgstr "Αναλυτής ReplayGain" #. Translators: New Command/Entry/Item/... #: ../quodlibet/qltk/data_editors.py:119 #, python-format msgid "New %s" msgstr "Νέο %s" #: ../quodlibet/qltk/data_editors.py:218 msgid "(unknown)" msgstr "(άγνωστο)" #: ../quodlibet/qltk/data_editors.py:355 msgid "Tag expression" msgstr "Πρότυπο ετικέτας" #: ../quodlibet/qltk/data_editors.py:382 msgid "Tag expression e.g. people:real or ~album~year" msgstr "Πρότυπο ετικέτας π.χ. people:real ή ~album~year" #: ../quodlibet/qltk/data_editors.py:383 msgid "Enter new tag" 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/downloader.py:38 msgid "Downloads" msgstr "Λήψεις" #: ../quodlibet/qltk/downloader.py:62 msgid "Size" msgstr "Μέγεθος" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: ../quodlibet/qltk/downloader.py:94 ../quodlibet/qltk/renamefiles.py:265 #: ../quodlibet/qltk/wlw.py:50 msgid "_Stop" msgstr "_Σταμάτα" #: ../quodlibet/qltk/edittags.py:63 ../quodlibet/qltk/edittags.py:74 #, python-format msgid "missing from %d song" msgid_plural "missing from %d songs" msgstr[0] "Λείπει από %d τραγούδι" msgstr[1] "Λείπει από %d τραγούδια" #: ../quodlibet/qltk/edittags.py:67 ../quodlibet/qltk/edittags.py:71 #, python-format msgid "different across %d song" msgid_plural "different across %d songs" msgstr[0] "Διαφορετικό σε %d τραγούδι" msgstr[1] "Διαφορετικό σε %d τραγούδια" #: ../quodlibet/qltk/edittags.py:193 msgid "Split into _Multiple Values" msgstr "_Διαμοιρασμός σε Πολλαπλές Τιμές" #: ../quodlibet/qltk/edittags.py:211 msgid "Split Disc out of _Album" msgstr "Διαχωρισμός του Δίσκου από το Ά_λμπουμ" #: ../quodlibet/qltk/edittags.py:228 msgid "Split _Version out of Title" msgstr "Διαχωρισμός της Έκ_δοσης από τον Τίτλο" #: ../quodlibet/qltk/edittags.py:259 msgid "Split Arranger out of Ar_tist" msgstr "Διαχωρισμός του Διευθετώντα από τον _Καλλιτέχνη" #: ../quodlibet/qltk/edittags.py:264 msgid "Split _Performer out of Artist" msgstr "Διαχωρισμός του _Εκτελεστή από τον Καλλιτέχνη" #: ../quodlibet/qltk/edittags.py:270 msgid "Split _Performer out of Title" msgstr "Διαχωρισμός του _Εκτελεστή από τον Τίτλο" #: ../quodlibet/qltk/edittags.py:276 msgid "Split _Originalartist out of Title" msgstr "Διαχωρισμός του _Αρχικού Καλλιτέχνη από τον Τίτλο" #: ../quodlibet/qltk/edittags.py:283 msgid "Add a Tag" msgstr "Προσθήκη Ετικέτας" #: ../quodlibet/qltk/edittags.py:302 msgid "_Tag:" msgstr "Ε_τικέτα:" #: ../quodlibet/qltk/edittags.py:404 msgid "Edit Tags" msgstr "Επεξεργασία Ετικετών" #: ../quodlibet/qltk/edittags.py:477 msgid "Show _programmatic tags" msgstr "Εμφάνιση _προγραμματικών ετικετών" #: ../quodlibet/qltk/edittags.py:478 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" "Επεξεργασία όλων των ετικετών, συμπεριλαμβανομένων και των αυτόματα " "δημιουργημένων απο λογισμικό όπως π.χ. MusicBrainz ή ετικέτες του Replay Gain" #. Translators: Revert button in the tag editor #: ../quodlibet/qltk/edittags.py:508 msgctxt "edittags" msgid "_Revert" msgstr "Επαναφο_ρά" #. Translators: Save button in the tag editor #: ../quodlibet/qltk/edittags.py:513 msgctxt "edittags" msgid "_Save" msgstr "_Αποθήκευση" #: ../quodlibet/qltk/edittags.py:659 msgid "Unable to add tag" msgstr "Αδυναμία προσθήκης ετικέτας" #: ../quodlibet/qltk/edittags.py:660 #, python-format msgid "Unable to add <b>%s</b>" msgstr "Αδυναμία προσθήκης <b>%s></b>" #: ../quodlibet/qltk/edittags.py:662 #, python-format msgid "" "The files currently selected do not support multiple values for <b>%s</b>." msgstr "Τα επιλεγμένα αρχεία δεν υποστηρίζουν πολλαπλές τιμές <b>%s</b>." #. Can't add the new tag. #: ../quodlibet/qltk/edittags.py:689 ../quodlibet/qltk/edittags.py:856 #: ../quodlibet/qltk/tagsfrompath.py:212 ../quodlibet/util/__init__.py:554 #: ../quodlibet/util/tags.py:231 msgid "Invalid tag" msgstr "Μη έγκυρη ετικέτα" #: ../quodlibet/qltk/edittags.py:690 ../quodlibet/qltk/edittags.py:857 #: ../quodlibet/qltk/tagsfrompath.py:213 #, python-format msgid "" "Invalid tag <b>%s</b>\n" "\n" "The files currently selected do not support editing this tag." msgstr "" "Μη έγκυρη ετικέτα <b>%s</b>\n" "\n" "Τα επιλεγμένα αρχεία δεν υποστηρίζουν επεξεργασία αυτής της ετικέτας." #: ../quodlibet/qltk/edittags.py:828 ../quodlibet/qltk/edittags.py:868 msgid "Invalid value" msgstr "Μη έγκυρη τιμή" #: ../quodlibet/qltk/edittags.py:829 ../quodlibet/qltk/edittags.py:869 #, python-format msgid "" "Invalid value: <b>%(value)s</b>\n" "\n" "%(error)s" msgstr "" "Μη έγκυρη τιμή: <b>%(value)s</b>\n" "\n" "%(error)s" #: ../quodlibet/qltk/_editutils.py:28 msgid "Tag may not be accurate" msgstr "Η ετικέτα ίσως να μην είναι ακριβής" #: ../quodlibet/qltk/_editutils.py:31 #, 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:47 msgid "Unable to save song" msgstr "Αδυναμία αποθήκευσης τραγουδιού" #: ../quodlibet/qltk/_editutils.py:50 #, 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:142 msgid "_More options…" msgstr "_Περισσότερες επιλογές…" #: ../quodlibet/qltk/entry.py:80 msgid "_Undo" msgstr "_Αναίρεση" #: ../quodlibet/qltk/entry.py:82 msgid "_Redo" msgstr "_Ξανακάνε" #: ../quodlibet/qltk/exfalsowindow.py:95 #: ../quodlibet/qltk/quodlibetwindow.py:1066 msgid "_About" msgstr "Σ_χετικά" #: ../quodlibet/qltk/exfalsowindow.py:99 #: ../quodlibet/qltk/quodlibetwindow.py:1088 msgid "_Check for Updates…" msgstr "" #: ../quodlibet/qltk/exfalsowindow.py:105 #: ../quodlibet/qltk/quodlibetwindow.py:1021 ../quodlibet/qltk/songsmenu.py:304 msgid "_Plugins" msgstr "_Πρόσθετα" #: ../quodlibet/qltk/exfalsowindow.py:267 #, 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:279 msgid "Ex Falso Preferences" msgstr "Προτιμήσεις του Ex Falso" #: ../quodlibet/qltk/exfalsowindow.py:289 ../quodlibet/qltk/prefs.py:598 msgid "Split _on:" msgstr "Διαχωρισμός _στο:" #: ../quodlibet/qltk/exfalsowindow.py:295 ../quodlibet/qltk/prefs.py:613 msgid "Tag Editing" msgstr "Επεξεργασία ετικετών" #: ../quodlibet/qltk/filesel.py:210 msgid "Folders" msgstr "Φάκελοι" #: ../quodlibet/qltk/filesel.py:253 msgid "_New Folder…" msgstr "_Νέος Φάκελος…" #: ../quodlibet/qltk/filesel.py:262 #, fuzzy msgid "_Select all Sub-Folders" msgstr "_Επιλογή όλων των Υποφακέλων" #: ../quodlibet/qltk/filesel.py:374 msgid "New Folder" msgstr "Νέος Φάκελος" #: ../quodlibet/qltk/filesel.py:374 msgid "Enter a name for the new folder:" msgstr "Εισάγετε όνομα για τον νέο φάκελο:" #: ../quodlibet/qltk/filesel.py:387 msgid "Unable to create folder" msgstr "Αδυναμία δημιουργίας φακέλου" #: ../quodlibet/qltk/filesel.py:404 msgid "Unable to delete folder" msgstr "Αδυναμία διαγραφής φακέλου" #: ../quodlibet/qltk/filesel.py:519 ../quodlibet/qltk/pluginwin.py:167 msgid "Songs" msgstr "Τραγούδια" #. Translators: As in "by Artist Name" #: ../quodlibet/qltk/info.py:42 #, python-format msgid "by %s" msgstr "από %s" #: ../quodlibet/qltk/info.py:43 ../quodlibet/qltk/information.py:167 #: ../quodlibet/qltk/information.py:448 #, python-format msgid "Disc %s" msgstr "Δίσκος %s" #: ../quodlibet/qltk/info.py:44 ../quodlibet/qltk/information.py:172 #, python-format msgid "Track %s" msgstr "Κομμάτι %s" #: ../quodlibet/qltk/info.py:108 msgid "_Edit Display…" msgstr "_Επεξεργασία Εμφάνισης…" #: ../quodlibet/qltk/information.py:105 msgid "No songs are selected." msgstr "Δεν υπάρχουν επιλεγμένα τραγούδια." #: ../quodlibet/qltk/information.py:106 msgid "No Songs" msgstr "Κανένα Τραγούδι" #: ../quodlibet/qltk/information.py:121 ../quodlibet/qltk/information.py:338 #: ../quodlibet/qltk/information.py:471 ../quodlibet/qltk/information.py:531 msgid "Information" msgstr "Πληροφορίες" #: ../quodlibet/qltk/information.py:126 msgid "Lyrics" msgstr "Στίχοι" #: ../quodlibet/qltk/information.py:184 ../quodlibet/qltk/information.py:396 #, python-format msgid "Produced by %s" msgstr "Παραγωγή από %s" #: ../quodlibet/qltk/information.py:199 ../quodlibet/util/tags.py:76 msgid "artist" msgstr "καλλιτέχνης" #: ../quodlibet/qltk/information.py:200 ../quodlibet/qltk/information.py:561 #: ../quodlibet/util/tags.py:76 msgid "artists" msgstr "καλλιτέχνες" #. for backwards compat #: ../quodlibet/qltk/information.py:221 ../quodlibet/util/tags.py:86 #: ../quodlibet/util/tags.py:114 msgid "performers" msgstr "εκτελεστές" #: ../quodlibet/qltk/information.py:235 ../quodlibet/qltk/information.py:248 #: ../quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "Ποτέ" #: ../quodlibet/qltk/information.py:236 #, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "%(n)d φορά" msgstr[1] "%(n)d φορές" #: ../quodlibet/qltk/information.py:254 ../quodlibet/util/tags.py:139 msgid "added" msgstr "προστέθηκε" #: ../quodlibet/qltk/information.py:255 ../quodlibet/util/tags.py:140 msgid "last played" msgstr "τελευταία αναπαραγωγή" #: ../quodlibet/qltk/information.py:256 ../quodlibet/util/tags.py:150 msgid "plays" msgstr "αναπαραγωγές" #: ../quodlibet/qltk/information.py:257 ../quodlibet/util/tags.py:151 msgid "skips" msgstr "παραλήψεις" #: ../quodlibet/qltk/information.py:258 ../quodlibet/util/tags.py:156 msgid "rating" msgstr "βαθμολογία" #: ../quodlibet/qltk/information.py:287 msgid "path" msgstr "" #: ../quodlibet/qltk/information.py:288 ../quodlibet/util/tags.py:154 msgid "length" msgstr "διάρκεια" #: ../quodlibet/qltk/information.py:289 msgid "format" msgstr "μορφή" #: ../quodlibet/qltk/information.py:290 ../quodlibet/util/tags.py:163 msgid "codec" msgstr "" #: ../quodlibet/qltk/information.py:291 ../quodlibet/util/tags.py:164 #, fuzzy msgid "encoding" msgstr "Αύξουσα" #: ../quodlibet/qltk/information.py:292 ../quodlibet/util/tags.py:160 msgid "bitrate" msgstr "bitrate" #: ../quodlibet/qltk/information.py:293 ../quodlibet/util/tags.py:161 msgid "file size" msgstr "μέγεθος αρχείου" #: ../quodlibet/qltk/information.py:294 ../quodlibet/util/tags.py:149 msgid "modified" msgstr "τροποποίηση" #: ../quodlibet/qltk/information.py:331 msgid "Additional" msgstr "" #: ../quodlibet/qltk/information.py:383 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d επιλεγμένο" msgstr[1] "%d επιλεγμένα" #: ../quodlibet/qltk/information.py:458 msgid "Track unavailable" msgstr "Μη διαθέσιμο κομμάτι" #: ../quodlibet/qltk/information.py:464 msgid "Track List" msgstr "Λίστα Κομματιών" #: ../quodlibet/qltk/information.py:505 ../quodlibet/qltk/information.py:578 #, 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:508 msgid "Selected Discography" msgstr "Επιλεγμένη Δισκογραφία" #: ../quodlibet/qltk/information.py:558 #, 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:586 ../quodlibet/util/tags.py:74 msgid "albums" msgstr "άλμπουμ" #: ../quodlibet/qltk/information.py:599 msgid "Total length:" msgstr "Συνολική διάρκεια:" #: ../quodlibet/qltk/information.py:603 msgid "Total size:" msgstr "Συνολικό μέγεθος:" #: ../quodlibet/qltk/information.py:606 msgid "Files" msgstr "Αρχεία" #: ../quodlibet/qltk/lyrics.py:37 msgid "_Download" msgstr "_Λήψη" #: ../quodlibet/qltk/lyrics.py:40 msgid "_Edit" msgstr "_Επεξεργασία…" #. buffer.set_text(_("No lyrics found.\n\nYou can click the " #. "Download button to have Quod Libet search " #. "for lyrics online. You can also enter them " #. "yourself and click save.")) #: ../quodlibet/qltk/lyrics.py:73 ../quodlibet/qltk/lyrics.py:109 msgid "No lyrics found for this song." msgstr "Δεν βρέθηκαν στίχοι γι' αυτό το τραγούδι." #: ../quodlibet/qltk/lyrics.py:82 msgid "Searching for lyrics…" 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/msg.py:41 msgid "Discard tag changes?" msgstr "Απόρριψη αλλαγών στις ετικέτες;" #: ../quodlibet/qltk/msg.py:42 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "" "Ετικέτες έχουν αλλαχθεί αλλά δεν έχουν αποθηκευθεί. Αποθήκευση αυτών των " "αρχείων ή επαναφορά και απόρριψη των αλλαγών;" #: ../quodlibet/qltk/msg.py:55 ../quodlibet/qltk/prefs.py:595 #: ../quodlibet/qltk/textedit.py:64 ../quodlibet/qltk/tracknumbers.py:117 msgid "_Revert" msgstr "Επανέφε_ρε" #: ../quodlibet/qltk/msg.py:86 msgid "File exists" msgstr "Το αρχείο υπάρχει" #: ../quodlibet/qltk/msg.py:88 #, python-format msgid "Replace %(file-name)s?" msgstr "Αντικατάσταση του %(file-name)s;" #: ../quodlibet/qltk/msg.py:94 msgid "_Replace File" msgstr "Αντικατάσταση Α_ρχείου" #: ../quodlibet/qltk/notif.py:182 msgid "Active tasks" msgstr "Ενεργές διεργασίες" #: ../quodlibet/qltk/notif.py:188 #, python-format msgid "%d tasks running" msgstr "%d διεργασίες εκτελούνται" #: ../quodlibet/qltk/playorder.py:254 #, fuzzy msgid "Toggle shuffle mode" msgstr "Εναλλαγή αναπαραγωγής/παύσης" #: ../quodlibet/qltk/playorder.py:270 #, fuzzy msgid "Toggle repeat mode" msgstr "Εναλλαγή αναπαραγωγής/παύσης" #: ../quodlibet/qltk/pluginwin.py:44 msgid "Plugin Errors" msgstr "Σφάλματα Πρόσθετων" #: ../quodlibet/qltk/pluginwin.py:124 msgid "Enabled" msgstr "Ενεργοποιημένα" #: ../quodlibet/qltk/pluginwin.py:125 msgid "Disabled" msgstr "Απενεργοποιημένα" #: ../quodlibet/qltk/pluginwin.py:131 msgid "No category" msgstr "Χωρίς κατηγορία" #: ../quodlibet/qltk/pluginwin.py:169 msgid "Events" msgstr "" #: ../quodlibet/qltk/pluginwin.py:170 #, fuzzy msgid "Play Order" msgstr "_Σειρά Αναπαραγωγής" #: ../quodlibet/qltk/pluginwin.py:171 #, fuzzy msgid "Editing" msgstr "Επεξεργασία ετικετών" #: ../quodlibet/qltk/pluginwin.py:173 #, fuzzy msgid "Covers" msgstr "Μέγεθος _Εξώφυλλου:" #: ../quodlibet/qltk/pluginwin.py:309 msgid "No plugins found." msgstr "Δεν βρέθηκαν πρόσθετα." #: ../quodlibet/qltk/pluginwin.py:358 msgid "Plugins" msgstr "Πρόσθετα" #: ../quodlibet/qltk/pluginwin.py:402 msgid "Show _Errors" msgstr "Εμφάνιση _Λαθών" #: ../quodlibet/qltk/prefs.py:45 msgid "_Disc" msgstr "_Δίσκος" #: ../quodlibet/qltk/prefs.py:46 msgid "_Track" msgstr "_Κομμάτι" #: ../quodlibet/qltk/prefs.py:47 msgid "Grou_ping" msgstr "Ομα_δοποίηση" #: ../quodlibet/qltk/prefs.py:50 msgid "Al_bum" msgstr "Ά_λμπουμ" #: ../quodlibet/qltk/prefs.py:55 msgid "_Filename" msgstr "Ό_νομα Αρχείου" #: ../quodlibet/qltk/prefs.py:57 msgid "_Length" msgstr "_Διάρκεια" #: ../quodlibet/qltk/prefs.py:64 msgid "_Jump to playing song automatically" msgstr "Α_υτόματη μεταπήδηση στο αναπαραγώμενο τραγούδι" #: ../quodlibet/qltk/prefs.py:66 msgid "When the playing song changes, scroll to it in the song list" msgstr "" "Όταν το αναπαραγώμενο τραγούδι αλλάζει, μετάβαση σε αυτό στην λίστα " "τραγουδιών" #: ../quodlibet/qltk/prefs.py:82 msgid "_Others:" msgstr "Ά_λλα:" #: ../quodlibet/qltk/prefs.py:88 msgid "_Edit…" msgstr "_Επεξεργασία…" #: ../quodlibet/qltk/prefs.py:91 msgid "Add or remove additional column headers" msgstr "Προσθαφαίρεση κεφαλίδων στηλών" #: ../quodlibet/qltk/prefs.py:101 msgid "Visible Columns" msgstr "Ορατές Στήλες" #: ../quodlibet/qltk/prefs.py:104 msgid "Title includes _version" msgstr "Ο Τίτλος να περιλαμβάνει την έκ_δοση" #: ../quodlibet/qltk/prefs.py:106 msgid "Artist includes all _people" msgstr "Το πεδίο Καλλιτέχνης συμπεριλαμβάνει τα ονόματα όλων των συντελεστών" #: ../quodlibet/qltk/prefs.py:108 msgid "Album includes _disc subtitle" msgstr "Το Άλμπουμ περιλαμβάνει τον υπότιτλο του _δίσκου" #: ../quodlibet/qltk/prefs.py:110 msgid "Filename includes _folder" msgstr "Το Όνομα Αρχείου συμπεριλαμβάνει και τον _φάκελο" #: ../quodlibet/qltk/prefs.py:123 msgid "Column Preferences" msgstr "Προτιμήσεις Στηλών" #: ../quodlibet/qltk/prefs.py:129 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "" "Εφαρμογή τρεχόντων ρυθμίσεων στην λίστα τραγουδιών, προσθέτοντας νέες στήλες " "στο τέλος" #: ../quodlibet/qltk/prefs.py:142 ../quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Λίστα Τραγουδιών" #: ../quodlibet/qltk/prefs.py:222 msgid "Edit Columns" msgstr "Επεξεργασία Στηλών" #: ../quodlibet/qltk/prefs.py:259 msgid "Duration totals" msgstr "" #: ../quodlibet/qltk/prefs.py:271 msgid "_Global filter:" msgstr "Κα_θολικό φίλτρο:" #: ../quodlibet/qltk/prefs.py:277 msgid "Apply this query in addition to all others" msgstr "Εφαρμογή αυτού του ερωτήματος επιπροσθέτως από όλα τα άλλα" #. Translators: The heading of the preference group, no action #: ../quodlibet/qltk/prefs.py:283 msgctxt "heading" msgid "Search" msgstr "Αναζήτηση" #: ../quodlibet/qltk/prefs.py:287 ../quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Περιηγητές" #: ../quodlibet/qltk/prefs.py:293 msgid "Confirm _multiple ratings" msgstr "Επιβεβαίωση πο_λλαπλών βαθμολογήσεων" #: ../quodlibet/qltk/prefs.py:295 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "" "Ζήτησε επιβεβαίωση πριν αλλάξεις τις βαθμολογίες πολλαπλών τραγουδιών " "μονομιάς" #: ../quodlibet/qltk/prefs.py:298 msgid "Enable _one-click ratings" msgstr "Ενεργοποίηση βαθμολόγησης με έ_να κλικ" #: ../quodlibet/qltk/prefs.py:300 msgid "Enable rating by clicking on the rating column in the song list" msgstr "" "Επέτρεψε τη βαθμολόγηση κάνοντας κλικ στην στήλη βαθμολογίας της λίστας " "τραγουδιών" #: ../quodlibet/qltk/prefs.py:306 ../quodlibet/qltk/prefs.py:616 msgid "Ratings" msgstr "Βαθμολογίες" #. Filename choice algorithm config #: ../quodlibet/qltk/prefs.py:312 msgid "Prefer _embedded art" msgstr "Προτίμηση _ενσωματωμένων εικόνων" #: ../quodlibet/qltk/prefs.py:314 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" "Χρήση εξώφυλλων ενσωματωμένων στο αρχείο ήχου (όταν είναι διαθέσιμο) αντί " "από άλλες πηγές" #: ../quodlibet/qltk/prefs.py:319 msgid "_Fixed image filename:" msgstr "Ε_ξαναγκασμός ονόματος αρχείου εικόνας:" #: ../quodlibet/qltk/prefs.py:321 msgid "The single image filename to use if selected" msgstr "Το όνομα αρχείου εικόνας που θα χρησιμοποιηθεί υποχρεωτικά" #: ../quodlibet/qltk/prefs.py:327 msgid "The album art image file to use when forced" msgstr "Το όνομα αρχείου εικόνας που θα χρησιμοποιηθεί υποχρεωτικά" #: ../quodlibet/qltk/prefs.py:336 msgid "Album Art" msgstr "Εξώφυλλα Άλμπουμ" #: ../quodlibet/qltk/prefs.py:357 msgid "Playback" msgstr "Αναπαραγωγή" #: ../quodlibet/qltk/prefs.py:362 msgid "Output Configuration" msgstr "Ρύθμιση Εξόδου" #: ../quodlibet/qltk/prefs.py:373 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" "Αν δεν είναι διαθέσιμες πληροφορίες Replay Gain για ένα τραγούδι, κλιμάκωσε " "την ένταση του ήχου κατά αυτή την τιμή" #: ../quodlibet/qltk/prefs.py:376 msgid "_Fall-back gain (dB):" msgstr "Εναλλακτική τιμή gain (dB):" #: ../quodlibet/qltk/prefs.py:387 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "" "Κλιμάκωσε την ένταση για όλα τα τραγούδια κατά αυτή την τιμή, αρκεί να μην " "υπάρξει αποκοπή" #: ../quodlibet/qltk/prefs.py:390 msgid "_Pre-amp gain (dB):" msgstr "Gain _προενίσχυσης (dB):" #: ../quodlibet/qltk/prefs.py:395 msgid "_Enable Replay Gain volume adjustment" msgstr "_Ρύθμιση της έντασης ήχου από το Replay Gain" #: ../quodlibet/qltk/prefs.py:420 msgid "Replay Gain Volume Adjustment" msgstr "Ρύθμισης Έντασης Replay Gain" #: ../quodlibet/qltk/prefs.py:450 msgid "_Default rating:" msgstr "_Προεπιλεγμένη βαθμολογία:" #: ../quodlibet/qltk/prefs.py:493 msgid "Rating _scale:" msgstr "_Βαθμολογική κλίμακα:" #: ../quodlibet/qltk/prefs.py:542 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:547 msgid "_Bayesian averaging amount:" msgstr "_Μπαγεσιανός παράγοντας μέσου όρου:" #: ../quodlibet/qltk/prefs.py:556 msgid "Save ratings and play _counts" msgstr "Αποθήκευση βαθμολογιών και _μετρητών αναπαραγωγών" #: ../quodlibet/qltk/prefs.py:560 msgid "_Email:" msgstr "Διεύθυνση ηλεκτρονικού _ταχυδρομείου:" #: ../quodlibet/qltk/prefs.py:562 msgid "Ratings and play counts will be set for this email address" msgstr "" "Οι βαθμολογίες και οι μετρητές αναπαραγωγών θα καθοριστούν γι' αυτή την " "διεύθυνση" #: ../quodlibet/qltk/prefs.py:577 msgid "Auto-save tag changes" msgstr "Αυτόματη αποθήκευση αλλαγών στις ετικέτες" #: ../quodlibet/qltk/prefs.py:579 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "" "Αποθήκευση αλλαγών στις ετικέτες χωρίς επιβεβαίωση όταν γίνεται επεξεργασία " "πολλαπλών αρχείων" #: ../quodlibet/qltk/prefs.py:587 #, 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:610 msgid "Tags" msgstr "Ετικέτες" #: ../quodlibet/qltk/prefs.py:631 msgid "Updating for new ratings" msgstr "Ανανέωση για τις νέες βαθμολογίες" #: ../quodlibet/qltk/prefs.py:641 #, fuzzy msgid "Scan library _on start" msgstr "_Ανανέωση της μουσικοθήκης κατά την εκκίνηση" #: ../quodlibet/qltk/prefs.py:651 ../quodlibet/qltk/quodlibetwindow.py:1100 #, fuzzy msgid "_Scan Library" msgstr "_Αναζήτηση στην Μουσικοθήκη" #: ../quodlibet/qltk/prefs.py:653 ../quodlibet/qltk/quodlibetwindow.py:1162 msgid "Check for changes in your library" msgstr "Έλεγχος για αλλαγές στην μουσικοθήκη σας" #: ../quodlibet/qltk/prefs.py:658 #, fuzzy msgid "Re_build Library" msgstr "_Επαναφόρτωση Μουσικοθήκης" #: ../quodlibet/qltk/prefs.py:661 msgid "Reload all songs in your library. This can take a long time." msgstr "" "Επαναφόρτωση όλων των τραγουδιών της μουσικοθήκης σας. Πιθανό να χρειαστεί " "αρκετό χρόνο." #: ../quodlibet/qltk/prefs.py:671 msgid "Scan Directories" msgstr "Σάρωση Καταλόγων" #: ../quodlibet/qltk/prefs.py:677 msgid "Hidden Songs" msgstr "Κρυμμένα Τραγούδια" #: ../quodlibet/qltk/properties.py:158 ../quodlibet/util/collection.py:398 #, 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:162 ../quodlibet/qltk/properties.py:164 msgid "Properties" msgstr "Ιδιότητες" #: ../quodlibet/qltk/queue.py:101 msgid "_Queue" msgstr "_Ουρά Αναπαραγωγής" #: ../quodlibet/qltk/queue.py:126 msgid "Stop Once Empty" msgstr "" #: ../quodlibet/qltk/queue.py:130 #, fuzzy msgid "_Clear Queue" msgstr "_Καθαρισμός" #: ../quodlibet/qltk/queue.py:242 #, 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:198 msgid "_Browse Library" msgstr "_Περιήγηση στην Μουσικοθήκη" #: ../quodlibet/qltk/quodlibetwindow.py:395 #, fuzzy msgid "Toggle queue visibility" msgstr "Εναλλαγή ορατότητας κυρίου παραθύρου" #: ../quodlibet/qltk/quodlibetwindow.py:516 msgid "Playback Error" msgstr "Σφάλμα Αναπαραγωγής" #: ../quodlibet/qltk/quodlibetwindow.py:524 msgid "Set up library directories?" msgstr "Να οριστούν οι κατάλογοι της μουσικοθήκης;" #: ../quodlibet/qltk/quodlibetwindow.py:525 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "Δεν έχετε ορίσει την μουσικοθήκη σας. Θα θέλατε να το κάνετε τώρα;" #: ../quodlibet/qltk/quodlibetwindow.py:531 msgid "_Not Now" msgstr "_Αργότερα" #: ../quodlibet/qltk/quodlibetwindow.py:532 msgid "_Set Up" msgstr "_Ρύθμιση" #: ../quodlibet/qltk/quodlibetwindow.py:956 msgid "Unable to add songs" msgstr "Αδυναμία προσθήκης τραγουδιών" #: ../quodlibet/qltk/quodlibetwindow.py:957 #: ../quodlibet/qltk/quodlibetwindow.py:1364 #, python-format msgid "%s uses an unsupported protocol." msgstr "Το πρωτόκολλο του %s δεν υποστηρίζεται." #: ../quodlibet/qltk/quodlibetwindow.py:980 msgid "_Jump to Playing Song" msgstr "_Μεταπήδηση στο Αναπαραγώμενο Τραγούδι" #: ../quodlibet/qltk/quodlibetwindow.py:986 #, fuzzy msgid "_File" msgstr "Αρχείο" #: ../quodlibet/qltk/quodlibetwindow.py:987 #, fuzzy msgid "_Song" msgstr "Τραγούδια" #: ../quodlibet/qltk/quodlibetwindow.py:988 msgid "_View" msgstr "_Προβολή" #: ../quodlibet/qltk/quodlibetwindow.py:989 #, fuzzy msgid "_Browse" msgstr "Περιηγητές" #: ../quodlibet/qltk/quodlibetwindow.py:990 msgid "_Control" msgstr "Έ_λεγχος" #: ../quodlibet/qltk/quodlibetwindow.py:991 msgid "_Help" msgstr "_Βοήθεια" #: ../quodlibet/qltk/quodlibetwindow.py:997 msgid "_Add a Folder…" msgstr "Προσθήκη _Φακέλου…" #: ../quodlibet/qltk/quodlibetwindow.py:1002 msgid "_Add a File…" msgstr "Προσθήκη _Αρχείου…" #: ../quodlibet/qltk/quodlibetwindow.py:1007 msgid "_Add a Location…" msgstr "Προσθήκη _Τοποθεσίας" #: ../quodlibet/qltk/quodlibetwindow.py:1036 msgid "Edit Bookmarks…" msgstr "Επεξεργασία Σελιδοδεικτών…" #: ../quodlibet/qltk/quodlibetwindow.py:1056 msgid "Stop After This Song" msgstr "Σταμάτησε μετά από αυτό το τραγούδι" #: ../quodlibet/qltk/quodlibetwindow.py:1062 msgid "_Keyboard Shortcuts" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:1071 msgid "Online Help" msgstr "Βοήθεια στο Διαδίκτυο" #: ../quodlibet/qltk/quodlibetwindow.py:1080 msgid "Search Help" msgstr "Αναζήτηση στη Βοήθεια" #: ../quodlibet/qltk/quodlibetwindow.py:1352 msgid "Add a Location" msgstr "Προσθήκη Τοποθεσίας" #: ../quodlibet/qltk/quodlibetwindow.py:1353 msgid "Enter the location of an audio file:" msgstr "Εισάγετε την τοποθεσία ενός αρχείου ήχου:" #: ../quodlibet/qltk/quodlibetwindow.py:1358 #: ../quodlibet/qltk/quodlibetwindow.py:1363 msgid "Unable to add location" msgstr "Αδυναμία προσθήκης τοποθεσίας" #: ../quodlibet/qltk/quodlibetwindow.py:1359 #, python-format msgid "%s is not a valid location." msgstr "Το %s δεν είναι έγκυρη τοποθεσία." #: ../quodlibet/qltk/quodlibetwindow.py:1372 #: ../quodlibet/qltk/quodlibetwindow.py:1381 msgid "Add Music" msgstr "Προσθήκη Μουσικής" #: ../quodlibet/qltk/quodlibetwindow.py:1372 ../quodlibet/qltk/scanbox.py:99 #, fuzzy msgid "_Add Folders" msgstr "Προσθήκη _Φακέλου…" #: ../quodlibet/qltk/quodlibetwindow.py:1379 #, fuzzy msgid "Music Files" msgstr "Αναπαραγωγή Μουσικής" #: ../quodlibet/qltk/quodlibetwindow.py:1381 #, fuzzy msgid "_Add Files" msgstr "Προσθήκη _Αρχείου…" #: ../quodlibet/qltk/ratingsmenu.py:24 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "Σίγουρα θέλετε να αλλάξετε βαθμολογία και στα %d τραγούδια;" #: ../quodlibet/qltk/ratingsmenu.py:26 msgid "The saved ratings will be removed" msgstr "Οι αποθηκευμένες βαθμολογίες θα διαγραφούν" #: ../quodlibet/qltk/ratingsmenu.py:27 #, python-format msgid "The rating of all selected songs will be changed to '%s'" msgstr "Η βαθμολογία όλων των επιλεγμένων τραγουδιών θα αλλαχθεί σε '%s'" #: ../quodlibet/qltk/ratingsmenu.py:57 ../quodlibet/qltk/ratingsmenu.py:111 msgid "_Remove Rating" msgstr "_Διαγραφή Βαθμολογίας" #: ../quodlibet/qltk/ratingsmenu.py:98 msgid "Change _Rating" msgstr "Αλλαγή _Βαθμολογίας" #: ../quodlibet/qltk/renamefiles.py:46 msgid "Replace spaces with _underscores" msgstr "Αντικατάσταση κενών με _κάτω παύλες" #: ../quodlibet/qltk/renamefiles.py:56 msgid "Strip _Windows-incompatible characters" msgstr "Αφαίρεση χαρακτήρων μη συμβατών με τα _Windows" #: ../quodlibet/qltk/renamefiles.py:74 msgid "Strip _diacritical marks" msgstr "Αφαίρεση _διακριτικών συμβόλων" #: ../quodlibet/qltk/renamefiles.py:85 msgid "Strip non-_ASCII characters" msgstr "Αφαίρεση μη-_ASCII χαρακτήρων" #: ../quodlibet/qltk/renamefiles.py:95 msgid "Use only _lowercase characters" msgstr "Χρήση μόνο πε_ζών γραμμάτων" #: ../quodlibet/qltk/renamefiles.py:123 msgid "Rename Files" msgstr "Μετονομασία Αρχείων" #: ../quodlibet/qltk/renamefiles.py:139 ../quodlibet/qltk/tagsfrompath.py:116 msgid "Path Patterns" msgstr "Πρότυπα Διαδρομών" #: ../quodlibet/qltk/renamefiles.py:140 ../quodlibet/qltk/tagsfrompath.py:117 msgid "Edit saved patterns…" msgstr "Επεξεργασία αποθηκευμένων προτύπων…" #: ../quodlibet/qltk/renamefiles.py:143 ../quodlibet/qltk/tagsfrompath.py:120 #: ../quodlibet/qltk/tracknumbers.py:58 msgid "_Preview" msgstr "_Προεπισκόπηση" #: ../quodlibet/qltk/renamefiles.py:190 msgid "New Name" msgstr "Νέο Όνομα" #: ../quodlibet/qltk/renamefiles.py:255 msgid "Unable to rename file" msgstr "Αδυναμία μετονομασίας αρχείου" #: ../quodlibet/qltk/renamefiles.py:256 #, python-format msgid "" "Renaming <b>%(old-name)s</b> to <b>%(new-name)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." msgstr "" "Η μετονομασία του <b>%(old-name)s</b> σε <b>%(new-name)s</b> απέτυχε. " "Πιθανότατα το αρχείο προορισμού υπάρχει ήδη, ή δεν έχετε δικαιώματα " "δημιουργίας νέου αρχείου ή διαγραφής του παλιού." #: ../quodlibet/qltk/renamefiles.py:264 msgid "Ignore _All Errors" msgstr "Αγνόηση Όλων των Σ_φαλμάτων" #: ../quodlibet/qltk/renamefiles.py:267 msgid "_Continue" msgstr "Συνέ_χεια" #: ../quodlibet/qltk/renamefiles.py:296 msgid "Path is not absolute" msgstr "Η διαδρομή αρχείου δεν είναι απόλυτη" #: ../quodlibet/qltk/renamefiles.py:297 #, python-format msgid "" "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 ~/." msgstr "" "Το πρότυπο\n" "\t<b>%s</b>\n" "περιέχει το / μα δεν ξεκινά από τη βάση του συστήματος αρχείων. Για να " "αποφύγετε λάθος ονομασμένους φακέλους, ξεκινήστε το πρότυπό σας με / ή ~/." #: ../quodlibet/qltk/scanbox.py:47 msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "" "Τραγούδια από τους εμφανιζόμενους φακέλους θα προστεθούν στην μουσικοθήκη " "σας μετά από ανανέωση" #: ../quodlibet/qltk/scanbox.py:99 msgid "Select Directories" msgstr "Επιλεγμένοι Κατάλογοι" #: ../quodlibet/qltk/searchbar.py:52 msgid "Saved Searches" msgstr "Αποθηκευμένες Αναζητήσεις" #: ../quodlibet/qltk/searchbar.py:53 msgid "Edit saved searches…" msgstr "Επεξεργασία αποθηκευμένων αναζητήσεων…" #: ../quodlibet/qltk/searchbar.py:74 msgid "Search your library, using free text or QL queries" msgstr "" "Αναζήτηση στην μουσικοθήκη σας, με χρήση ελεύθερου κειμένου ή ερωτημάτων QL" #: ../quodlibet/qltk/searchbar.py:129 msgid "Search after _typing" msgstr "Αναζήτηση με την _πληκτρολόγηση" #: ../quodlibet/qltk/searchbar.py:132 msgid "Show search results after the user stops typing" msgstr "" "Εμφάνισε τα αποτελέσματα αναζήτησης αφού ο χρήστης σταματήσει την " "πληκτρολόγηση" #: ../quodlibet/qltk/searchbar.py:187 msgid "_Limit:" msgstr "Ό_ριο:" #: ../quodlibet/qltk/searchbar.py:200 msgid "_Weight" 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 ../quodlibet/qltk/shortcuts.py:41 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: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:377 #, python-format msgid "_Filter on %s" msgstr "_Φίλτρο στο %s" #: ../quodlibet/qltk/songlist.py:1094 msgid "All _Headers" msgstr "Όλες οι Κε_φαλίδες" #: ../quodlibet/qltk/songlist.py:1095 msgid "_Track Headers" msgstr "Κεφαλίδες _Κομματιών" #: ../quodlibet/qltk/songlist.py:1096 msgid "_Album Headers" msgstr "Κεφαλίδες Ά_λμπουμ" #: ../quodlibet/qltk/songlist.py:1097 msgid "_People Headers" msgstr "Κεφαλίδες _Συντελεστών" #: ../quodlibet/qltk/songlist.py:1098 msgid "_Date Headers" msgstr "Κεφαλίδες _Ημερομηνιών" #: ../quodlibet/qltk/songlist.py:1099 msgid "_File Headers" msgstr "Κεφαλίδες Αρ_χείων" #: ../quodlibet/qltk/songlist.py:1100 msgid "_Production Headers" msgstr "Κεφαλίδες Παρα_γωγής" #: ../quodlibet/qltk/songlist.py:1115 msgid "_Customize Headers…" msgstr "Προσαρμογή _Κεφαλίδων…" #: ../quodlibet/qltk/songlist.py:1120 msgid "_Expand Column" msgstr "_Επέκταση Στήλης" #: ../quodlibet/qltk/songsmenu.py:36 #, 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:64 #, 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:149 #, fuzzy msgid "Configure Plugins…" msgstr "Επεξεργασία αναζητήσεων…" #: ../quodlibet/qltk/songsmenu.py:345 msgid "Add to _Queue" msgstr "Προσθήκη στην _Ουρά" #: ../quodlibet/qltk/songsmenu.py:368 msgid "_Copy to Device" msgstr "Αντιγραφή στην _Συσκευή" #: ../quodlibet/qltk/songsmenu.py:379 #, fuzzy msgid "_Remove from Library" 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:101 msgid "Tags From Path" msgstr "Ετικέτες από την Διαδρομή Αρχείου" #: ../quodlibet/qltk/tagsfrompath.py:138 msgid "Tags replace existing ones" msgstr "Οι ετικέτες αντικαθιστούν τις ήδη υπάρχουσες" #: ../quodlibet/qltk/tagsfrompath.py:139 msgid "Tags are added to existing ones" msgstr "Οι ετικέτες προστίθενται στις ήδη υπάρχουσες" #. Save button #: ../quodlibet/qltk/tagsfrompath.py:153 msgid "Save" msgstr "Αποθήκευση" #: ../quodlibet/qltk/tagsfrompath.py:195 #, python-format msgid "" "The pattern\n" "\t<b>%s</b>\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" "Το πρότυπο\n" "\t<b>%s</b>\n" "δεν είναι έγκυρο. Πιθανότατα περιέχει την ίδια ετικέτα δύο φορές ή έχει μη " "ισορροπημένες γωνιακές αγκύλες (< / >)." #: ../quodlibet/qltk/tagsfrompath.py:216 msgid "Invalid tags" msgstr "Μη έγκυρες ετικέτες" #: ../quodlibet/qltk/tagsfrompath.py:217 #, 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" "Τα επιλεγμένα αρχεία δεν υποστηρίζουν την επεξεργασία αυτών των ετικετών." #: ../quodlibet/qltk/textedit.py:142 #, 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:158 msgid "Edit Display" msgstr "Επεξεργασία Προβολής" #: ../quodlibet/qltk/tracknumbers.py:39 msgid "Track Numbers" msgstr "Αριθμοί Κομματιών" #: ../quodlibet/qltk/tracknumbers.py:42 msgid "Start fro_m:" msgstr "Αρ_χή από:" #: ../quodlibet/qltk/tracknumbers.py:51 msgid "_Total tracks:" msgstr "Συνολικός αριθμός κομματιών:" #: ../quodlibet/qltk/unity.py:52 msgid "Play/Pause" msgstr "Αναπαραγωγή/Παύση" #: ../quodlibet/qltk/unity.py:75 msgid "Previous" msgstr "Προηγούμενο" #: ../quodlibet/qltk/views.py:923 #, 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:89 #, fuzzy msgid "Checking for Updates" msgstr "Έλεγχος σημείων προσάρτησης" #: ../quodlibet/update.py:124 #, fuzzy msgid "Connection failed" msgstr "Σύνδεση" #: ../quodlibet/update.py:133 #, python-format msgid "You are already using the newest version %(version)s" msgstr "" #: ../quodlibet/update.py:136 #, 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:420 msgid "Playlists must have a name" msgstr "" #: ../quodlibet/util/collection.py:603 #, python-format msgid "A playlist named %s already exists." msgstr "Υπάρχει ήδη λίστα αναπαραγωγής με το όνομα %s." #: ../quodlibet/util/cover/built_in.py:26 #, fuzzy msgid "Embedded album covers" msgstr "Επαναφόρτωση ε_ξώφυλλου του άλμπουμ" #: ../quodlibet/util/cover/built_in.py:27 msgid "Uses covers embedded into audio files." msgstr "Χρήση ενσωματωμένων εξώφυλλων άλμπουμ." #: ../quodlibet/util/cover/built_in.py:49 msgid "Filesystem cover" msgstr "Εξώφυλλο άλμπουμ από το σύστημα αρχείων" #: ../quodlibet/util/cover/built_in.py:50 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "Χρήση εικόνων που βρίσκονται στον κατάλογο μαζί με το τραγούδι" #: ../quodlibet/util/__init__.py:93 msgid "Display brief usage information" msgstr "Προβολή σύντομων πληροφοριών χρήσης" #: ../quodlibet/util/__init__.py:95 msgid "Display version and copyright" msgstr "Προβολή έκδοσης και πνευματικών δικαιωμάτων" #: ../quodlibet/util/__init__.py:135 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "Χρήση: %(program)s %(usage)s" #: ../quodlibet/util/__init__.py:137 msgid "[options]" msgstr "[επιλογές]" #: ../quodlibet/util/__init__.py:182 #, python-format msgid "Option %r not recognized." msgstr "Η επιλογή %r δεν αναγνωρίστηκε" #: ../quodlibet/util/__init__.py:185 #, python-format msgid "Option %r requires an argument." msgstr "Η επιλογή %r χρειάζεται ένα όρισμα" #: ../quodlibet/util/__init__.py:188 #, python-format msgid "%r is not a unique prefix." msgstr "Το %r δεν είναι μοναδικά ταυτοποιήσιμο πρόθεμα" #: ../quodlibet/util/__init__.py:364 #, python-format msgid "%d kbps" msgstr "%d kbps" #: ../quodlibet/util/__init__.py:419 #, fuzzy, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%d δευτερόλεπτο" msgstr[1] "%d δευτερόλεπτα" #: ../quodlibet/util/__init__.py:432 msgid "No time information" msgstr "Χωρίς πληροφορίες χρόνου" #: ../quodlibet/util/__init__.py:435 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d δευτερόλεπτο" msgstr[1] "%d δευτερόλεπτα" #: ../quodlibet/util/__init__.py:436 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d λεπτό" msgstr[1] "%d λεπτά" #: ../quodlibet/util/__init__.py:437 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d ώρα" msgstr[1] "%d ώρες" #: ../quodlibet/util/__init__.py:438 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d ημέρα" msgstr[1] "%d ημέρες" #: ../quodlibet/util/__init__.py:439 #, 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:563 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 msgid "Unable to edit song" msgstr "Αδυναμία επεξεργασίας τραγουδιού" #: ../quodlibet/util/songwrapper.py:113 #, python-format msgid "" "Saving <b>%s</b> 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:34 #: ../quodlibet/util/string/__init__.py:44 msgid "[Invalid Encoding]" msgstr "[Μη έγκυρη Κωδικοποίηση]" #: ../quodlibet/util/tags.py:74 msgid "album" msgstr "άλμπουμ" #: ../quodlibet/util/tags.py:75 msgid "arranger" msgstr "διευθετών" #: ../quodlibet/util/tags.py:75 msgid "arrangers" msgstr "διευθετώντες" #: ../quodlibet/util/tags.py:75 msgid "arrangement" msgstr "διευθέτηση" #: ../quodlibet/util/tags.py:77 msgid "author" msgstr "συγγραφέας" #: ../quodlibet/util/tags.py:77 msgid "authors" msgstr "συγγραφείς" #: ../quodlibet/util/tags.py:78 msgid "composer" msgstr "συνθέτης" #: ../quodlibet/util/tags.py:78 msgid "composers" msgstr "συνθέτες" #: ../quodlibet/util/tags.py:78 msgid "composition" msgstr "σύνθεση" #. Translators: conducting as in conducting a musical performance #: ../quodlibet/util/tags.py:80 msgid "conductor" msgstr "διευθυντής ορχήστρας" #: ../quodlibet/util/tags.py:80 msgid "conductors" msgstr "διευθυντές ορχήστρας" #: ../quodlibet/util/tags.py:80 msgid "conducting" msgstr "διεύθυνση ορχήστρας" #: ../quodlibet/util/tags.py:81 msgid "contact" msgstr "σύνδεσμος" #: ../quodlibet/util/tags.py:82 msgid "copyright" msgstr "πνευματική ιδιοκτησία" #: ../quodlibet/util/tags.py:83 msgid "date" msgstr "ημερομηνία" #: ../quodlibet/util/tags.py:84 msgid "description" msgstr "περιγραφή" #: ../quodlibet/util/tags.py:85 msgid "genre" msgstr "είδος" #: ../quodlibet/util/tags.py:85 msgid "genres" msgstr "είδη" #: ../quodlibet/util/tags.py:86 msgid "performer" msgstr "εκτελεστής" #: ../quodlibet/util/tags.py:87 msgid "grouping" msgstr "ομαδοποίηση" #: ../quodlibet/util/tags.py:88 msgid "language" msgstr "γλώσσα" #: ../quodlibet/util/tags.py:89 msgid "license" msgstr "άδεια" #: ../quodlibet/util/tags.py:90 msgid "location" msgstr "τοποθεσία" #: ../quodlibet/util/tags.py:91 msgid "lyricist" msgstr "στιχουργός" #: ../quodlibet/util/tags.py:91 msgid "lyricists" msgstr "στιχουργοί" #: ../quodlibet/util/tags.py:91 #, fuzzy msgid "lyrics" msgstr "στιχουργός" #. Translators: Also e.g. "record label", "publisher" #: ../quodlibet/util/tags.py:93 msgid "organization" msgstr "οργάνωση" #: ../quodlibet/util/tags.py:94 msgid "title" msgstr "τίτλος" #: ../quodlibet/util/tags.py:95 msgid "version" msgstr "έκδοση" #: ../quodlibet/util/tags.py:96 msgid "website" msgstr "ιστοσελίδα" #: ../quodlibet/util/tags.py:98 msgid "album artist" msgstr "καλλιτέχνης άλμπουμ" #: ../quodlibet/util/tags.py:99 msgid "BPM" msgstr "ρυθμός (BPM - διακροτήματα ανά λεπτό)" #. Translators: This used to be called "part". #: ../quodlibet/util/tags.py:102 ../quodlibet/util/tags.py:103 msgid "disc subtitle" msgstr "υπότιτλος δίσκου" #: ../quodlibet/util/tags.py:104 ../quodlibet/util/tags.py:141 msgid "disc" msgstr "δίσκος" #: ../quodlibet/util/tags.py:105 ../quodlibet/util/tags.py:143 msgid "track" msgstr "κομμάτι" #: ../quodlibet/util/tags.py:106 msgid "label ID" msgstr "δισκογραφική ταυτότητα" #: ../quodlibet/util/tags.py:107 msgid "original release date" msgstr "ημερομηνία αρχικής κυκλοφορίας" #: ../quodlibet/util/tags.py:108 msgid "original album" msgstr "αρχικό άλμπουμ" #: ../quodlibet/util/tags.py:109 msgid "original artist" msgstr "αρχικός καλλιτέχνης" #: ../quodlibet/util/tags.py:110 msgid "recording date" msgstr "ημερομηνία ηχογράφησης" #: ../quodlibet/util/tags.py:111 msgid "release country" 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:120 msgid "MusicBrainz recording ID" msgstr "Ταυτότητα ηχογράφησης MusicBrainz" #: ../quodlibet/util/tags.py:121 msgid "MusicBrainz release track ID" msgstr "Ταυτότητα κυκλοφορίας κομματιού MusicBrainz" #: ../quodlibet/util/tags.py:122 msgid "MusicBrainz release ID" msgstr "Ταυτότητα κυκλοφορίας MusicBrainz" #: ../quodlibet/util/tags.py:123 msgid "MusicBrainz artist ID" msgstr "Ταυτότητα καλλιτέχνη MusicBrainz" #: ../quodlibet/util/tags.py:124 msgid "MusicBrainz release artist ID" msgstr "Ταυτότητα καλλιτέχνη κυκλοφορίας MusicBrainz" #: ../quodlibet/util/tags.py:125 msgid "MusicBrainz TRM ID" msgstr "Ταυτότητα TRM MusicBrainz" #: ../quodlibet/util/tags.py:126 msgid "MusicIP PUID" msgstr "Ταυτότητα PUID MusicBrainz" #: ../quodlibet/util/tags.py:127 msgid "MusicBrainz album status" msgstr "Κατάσταση κυκλοφορίας άλμπουμ MusicBrainz" #: ../quodlibet/util/tags.py:128 msgid "MusicBrainz album type" msgstr "Τύπος άλμπουμ MusicBrainz" #: ../quodlibet/util/tags.py:129 #, fuzzy msgid "MusicBrainz release group ID" msgstr "Ταυτότητα κυκλοφορίας MusicBrainz" #. Translators: "gain" means a volume adjustment, not "to acquire". #: ../quodlibet/util/tags.py:132 msgid "track gain" msgstr "ενίσχυση κομματιού" #: ../quodlibet/util/tags.py:133 msgid "track peak" msgstr "ηχητική κορυφή κομματιού" #. Translators: "gain" means a volume adjustment, not "to acquire". #: ../quodlibet/util/tags.py:135 msgid "album gain" msgstr "ενίσχυση άλμπουμ" #: ../quodlibet/util/tags.py:136 msgid "album peak" msgstr "ηχητική κορυφή άλμπουμ" #: ../quodlibet/util/tags.py:137 msgid "reference loudness" msgstr "ηχητική ένταση αναφοράς" #: ../quodlibet/util/tags.py:142 msgid "discs" msgstr "δίσκοι" #: ../quodlibet/util/tags.py:144 msgid "tracks" msgstr "κομμάτια" #: ../quodlibet/util/tags.py:145 msgid "last started" msgstr "τελευταία εκκίνηση αναπαραγωγής" #: ../quodlibet/util/tags.py:146 msgid "full name" msgstr "πλήρες όνομα" #: ../quodlibet/util/tags.py:153 msgid "mount point" msgstr "σημείο προσάρτησης" #: ../quodlibet/util/tags.py:155 msgid "people" msgstr "συντελεστές" #: ../quodlibet/util/tags.py:157 msgid "year" msgstr "έτος" #: ../quodlibet/util/tags.py:158 msgid "original release year" msgstr "έτος αρχικής κυκλοφορίας" #: ../quodlibet/util/tags.py:159 msgid "bookmark" msgstr "σελιδοδείκτης" #: ../quodlibet/util/tags.py:162 msgid "file format" msgstr "τύπος αρχείου" #: ../quodlibet/util/tags.py:165 msgid "playlists" msgstr "λίστες αναπαραγωγής" #: ../quodlibet/util/tags.py:166 #, fuzzy msgid "channel count" msgstr "Λογαριασμός" #. Translators: e.g. "artist (sort)" #: ../quodlibet/util/tags.py:256 msgid "sort" msgstr "ταξινόμηση" #. Translators: e.g. "performer (roles)" #: ../quodlibet/util/tags.py:264 msgid "roles" 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 "Remove all songs from the queue" #~ msgstr "Αφαίρεση όλων των τραγουδιών από τη ουρά" #~ msgid "Watch this folder for new songs" #~ 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 "_Create Database" #~ msgstr "_Δημιουργία βάσης δεδομένων" #~ msgid "_Volume Gain (dB):" #~ msgstr "_Αύξηση Ήχου (dB):" #~ msgid "Combine tags with _multiple values" #~ msgstr "Συνδύασε ετικέτες με _πολλαπλές τιμές" #~ msgid "Model:" #~ msgstr "Μοντέλο:" #~ msgid "Capacity:" #~ msgstr "Χωρητικότητα:" #~ msgid "Firmware:" #~ msgstr "Έκδοση Υλικολογισμικού:" #~ msgid "Removing orphaned iPod track" #~ msgstr "Removing orphaned iPod track" #~ 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 "Unable to open input files" #~ 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 "General" #~ 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9511857 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/po/en_CA.po�������������������������������������������������������������������������0000644�0001750�0001750�00000553637�00000000000�014444� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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: 2017-05-17 18:58+0200\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" #: ../data/exfalso.appdata.xml.in.h:1 ../data/exfalso.desktop.in.h:2 msgid "Edit tags in your audio files" msgstr "Edit tags in your audio files" #: ../data/exfalso.appdata.xml.in.h:2 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/exfalso.appdata.xml.in.h:3 ../data/quodlibet.appdata.xml.in.h:3 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/exfalso.desktop.in.h:1 msgid "Audio tag editor" msgstr "Audio tag editor" #: ../data/quodlibet.appdata.xml.in.h:1 ../data/quodlibet.desktop.in.h:2 msgid "Listen to, browse, or edit your audio collection" msgstr "Listen to, browse, or edit your audio collection" #: ../data/quodlibet.appdata.xml.in.h:2 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 "" #: ../data/quodlibet.desktop.in.h:1 msgid "Music Player" msgstr "Music Player" #: ../quodlibet/browsers/albums/main.py:168 #: ../quodlibet/browsers/covergrid/main.py:54 #, fuzzy msgid "_Title" msgstr "Title" #: ../quodlibet/browsers/albums/main.py:169 #: ../quodlibet/browsers/covergrid/main.py:55 ../quodlibet/qltk/prefs.py:49 msgid "_Artist" msgstr "_Artist" #: ../quodlibet/browsers/albums/main.py:170 #: ../quodlibet/browsers/covergrid/main.py:56 ../quodlibet/qltk/prefs.py:54 msgid "_Date" msgstr "_Date" #: ../quodlibet/browsers/albums/main.py:171 #: ../quodlibet/browsers/covergrid/main.py:57 ../quodlibet/qltk/prefs.py:53 #, fuzzy msgid "_Genre" msgstr "_Genre" #: ../quodlibet/browsers/albums/main.py:172 #: ../quodlibet/browsers/covergrid/main.py:58 ../quodlibet/qltk/prefs.py:58 #: ../quodlibet/qltk/ratingsmenu.py:39 msgid "_Rating" msgstr "_Rating" #: ../quodlibet/browsers/albums/main.py:178 #: ../quodlibet/browsers/covergrid/main.py:64 #, fuzzy msgid "Sort _by…" msgstr "Sort by date" #: ../quodlibet/browsers/albums/main.py:199 #: ../quodlibet/browsers/covergrid/main.py:85 #: ../quodlibet/browsers/paned/prefs.py:166 #: ../quodlibet/browsers/playlists/main.py:629 #: ../quodlibet/qltk/exfalsowindow.py:109 ../quodlibet/qltk/pluginwin.py:341 #: ../quodlibet/qltk/quodlibetwindow.py:1016 #, fuzzy msgid "_Preferences" msgstr "Preferences" #: ../quodlibet/browsers/albums/main.py:361 msgid "Album List" msgstr "Album List" #: ../quodlibet/browsers/albums/main.py:362 msgid "_Album List" msgstr "_Album List" #: ../quodlibet/browsers/albums/main.py:472 #: ../quodlibet/browsers/covergrid/main.py:279 #: ../quodlibet/browsers/covergrid/main.py:488 msgid "All Albums" msgstr "All Albums" #: ../quodlibet/browsers/albums/main.py:473 #: ../quodlibet/browsers/covergrid/main.py:280 #: ../quodlibet/browsers/covergrid/main.py:489 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d album" msgstr[1] "%d albums" #: ../quodlibet/browsers/albums/main.py:650 #: ../quodlibet/browsers/covergrid/main.py:467 #, 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:381 ../quodlibet/util/collection.py:245 #, 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:379 ../quodlibet/util/collection.py:249 #, 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:120 #, fuzzy msgid "Options" msgstr "[options]" #: ../quodlibet/browsers/albums/prefs.py:74 #: ../quodlibet/browsers/covergrid/prefs.py:123 msgid "Album Display" msgstr "Album Display" #: ../quodlibet/browsers/albums/prefs.py:78 #: ../quodlibet/browsers/covergrid/prefs.py:127 #: ../quodlibet/browsers/media.py:39 #: ../quodlibet/browsers/playlists/prefs.py:56 #: ../quodlibet/ext/songsmenu/albumart.py:326 #: ../quodlibet/ext/songsmenu/duplicates.py:350 #: ../quodlibet/ext/songsmenu/filterall.py:48 #: ../quodlibet/qltk/bookmarks.py:101 ../quodlibet/qltk/cbes.py:93 #: ../quodlibet/qltk/data_editors.py:99 ../quodlibet/qltk/data_editors.py:324 #: ../quodlibet/qltk/exfalsowindow.py:297 ../quodlibet/qltk/pluginwin.py:79 #: ../quodlibet/qltk/pluginwin.py:427 ../quodlibet/qltk/prefs.py:707 #: ../quodlibet/qltk/textedit.py:164 ../quodlibet/update.py:148 msgid "_Close" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:55 #: ../quodlibet/browsers/audiofeeds.py:67 #: ../quodlibet/browsers/audiofeeds.py:69 #: ../quodlibet/browsers/audiofeeds.py:159 #: ../quodlibet/browsers/paned/models.py:86 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:46 #: ../quodlibet/formats/_audio.py:495 ../quodlibet/order/__init__.py:27 #: ../quodlibet/qltk/information.py:240 ../quodlibet/qltk/information.py:247 #: ../quodlibet/qltk/information.py:273 ../quodlibet/qltk/wlw.py:70 msgid "Unknown" msgstr "Unknown" #: ../quodlibet/browsers/audiofeeds.py:246 msgid "New Feed" msgstr "New Feed" #: ../quodlibet/browsers/audiofeeds.py:247 msgid "Enter the location of an audio feed:" msgstr "Enter the location of an audio feed:" #: ../quodlibet/browsers/audiofeeds.py:248 #: ../quodlibet/browsers/collection/prefs.py:90 #: ../quodlibet/browsers/iradio.py:341 ../quodlibet/browsers/paned/prefs.py:78 #: ../quodlibet/browsers/playlists/menu.py:96 #: ../quodlibet/browsers/playlists/util.py:52 ../quodlibet/qltk/bookmarks.py:62 #: ../quodlibet/qltk/cbes.py:55 ../quodlibet/qltk/data_editors.py:311 #: ../quodlibet/qltk/edittags.py:288 ../quodlibet/qltk/edittags.py:488 #: ../quodlibet/qltk/quodlibetwindow.py:1354 ../quodlibet/qltk/scanbox.py:61 msgid "_Add" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:265 msgid "Audio Feeds" msgstr "Audio Feeds" #: ../quodlibet/browsers/audiofeeds.py:266 msgid "_Audio Feeds" msgstr "_Audio Feeds" #: ../quodlibet/browsers/audiofeeds.py:345 #: ../quodlibet/browsers/audiofeeds.py:350 #, fuzzy msgid "_Download…" msgstr "_Download" #: ../quodlibet/browsers/audiofeeds.py:359 msgid "Download Files" msgstr "Download Files" #. Save button #: ../quodlibet/browsers/audiofeeds.py:359 #: ../quodlibet/browsers/audiofeeds.py:371 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:81 #: ../quodlibet/ext/songsmenu/albumart.py:322 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:355 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:278 #: ../quodlibet/ext/songsmenu/html.py:76 #: ../quodlibet/ext/songsmenu/lastfmsync.py:216 #: ../quodlibet/ext/songsmenu/playlist.py:51 #: ../quodlibet/ext/songsmenu/replaygain.py:365 #: ../quodlibet/ext/songsmenu/tapbpm.py:182 ../quodlibet/qltk/_editutils.py:39 #: ../quodlibet/qltk/lyrics.py:38 ../quodlibet/qltk/msg.py:52 #: ../quodlibet/qltk/renamefiles.py:168 ../quodlibet/qltk/tracknumbers.py:113 msgid "_Save" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:371 msgid "Download File" msgstr "Download File" #: ../quodlibet/browsers/audiofeeds.py:394 #: ../quodlibet/browsers/playlists/main.py:213 #: ../quodlibet/qltk/data_editors.py:96 msgid "_New" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:454 #: ../quodlibet/browsers/audiofeeds.py:513 msgid "Unable to add feed" msgstr "Unable to add feed" #: ../quodlibet/browsers/audiofeeds.py:455 #: ../quodlibet/browsers/audiofeeds.py:514 #, fuzzy, python-format msgid "" "%s could not be added. The server may be down, or the location may not be an " "audio feed." msgstr "" "<b>%s</b> could not be added. The server may be down, or the location may " "not be an audio feed." #. refresh button #: ../quodlibet/browsers/audiofeeds.py:462 ../quodlibet/browsers/media.py:217 #: ../quodlibet/browsers/media.py:386 ../quodlibet/qltk/filesel.py:259 #: ../quodlibet/qltk/pluginwin.py:413 #, fuzzy msgid "_Refresh" msgstr "Re_fresh Library" #: ../quodlibet/browsers/audiofeeds.py:463 #: ../quodlibet/browsers/playlists/main.py:457 #: ../quodlibet/browsers/playlists/util.py:43 ../quodlibet/qltk/delete.py:143 #: ../quodlibet/qltk/filesel.py:256 ../quodlibet/qltk/lyrics.py:39 #: ../quodlibet/qltk/maskedbox.py:28 ../quodlibet/qltk/songsmenu.py:392 #, fuzzy msgid "_Delete" msgstr "Delete Files" #: ../quodlibet/browsers/audiofeeds.py:530 msgid "" "The current audio backend does not support URLs, Audio Feeds browser " "disabled." msgstr "" #: ../quodlibet/browsers/_base.py:147 ../quodlibet/browsers/_base.py:150 msgid "Library Browser" msgstr "Library Browser" #: ../quodlibet/browsers/_base.py:274 ../quodlibet/ext/songsmenu/refresh.py:30 #: ../quodlibet/qltk/exfalsowindow.py:241 ../quodlibet/qltk/information.py:542 #: ../quodlibet/qltk/maskedbox.py:68 ../quodlibet/util/collection.py:527 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d song" msgstr[1] "%d songs" #: ../quodlibet/browsers/_base.py:402 ../quodlibet/browsers/_base.py:407 #: ../quodlibet/qltk/tagsfrompath.py:194 ../quodlibet/qltk/textedit.py:141 #: ../quodlibet/util/__init__.py:622 msgid "Invalid pattern" msgstr "Invalid pattern" #: ../quodlibet/browsers/collection/main.py:78 msgid "Album Collection" msgstr "" #: ../quodlibet/browsers/collection/main.py:79 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:66 #: ../quodlibet/browsers/paned/prefs.py:51 msgid "_Custom" msgstr "_Custom" #. Remove button #: ../quodlibet/browsers/collection/prefs.py:94 #: ../quodlibet/browsers/paned/prefs.py:82 #: ../quodlibet/browsers/playlists/menu.py:97 #: ../quodlibet/ext/playlist/remove_duplicates.py:60 #: ../quodlibet/qltk/bookmarks.py:97 ../quodlibet/qltk/bookmarks.py:127 #: ../quodlibet/qltk/cbes.py:82 ../quodlibet/qltk/cbes.py:89 #: ../quodlibet/qltk/data_editors.py:81 ../quodlibet/qltk/data_editors.py:94 #: ../quodlibet/qltk/data_editors.py:301 ../quodlibet/qltk/data_editors.py:314 #: ../quodlibet/qltk/data_editors.py:322 ../quodlibet/qltk/edittags.py:494 #: ../quodlibet/qltk/edittags.py:634 ../quodlibet/qltk/maskedbox.py:48 #: ../quodlibet/qltk/maskedbox.py:88 ../quodlibet/qltk/queue.py:350 #: ../quodlibet/qltk/scanbox.py:36 ../quodlibet/qltk/scanbox.py:63 #, fuzzy msgid "_Remove" msgstr "_Remove Station" #: ../quodlibet/browsers/collection/prefs.py:122 #: ../quodlibet/ext/songsmenu/filterall.py:34 #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:92 #: ../quodlibet/qltk/edittags.py:431 msgid "Tag" msgstr "Tag" #: ../quodlibet/browsers/collection/prefs.py:128 msgid "Merge" msgstr "" #: ../quodlibet/browsers/collection/prefs.py:188 #, fuzzy msgid "Album Collection Preferences" msgstr "Album List Preferences" #: ../quodlibet/browsers/collection/prefs.py:195 #: ../quodlibet/browsers/paned/prefs.py:209 #: ../quodlibet/ext/songsmenu/editplaycount.py:45 #: ../quodlibet/ext/songsmenu/exact_rating.py:38 #: ../quodlibet/player/gstbe/prefs.py:40 ../quodlibet/qltk/prefs.py:127 #: ../quodlibet/qltk/textedit.py:65 msgid "_Apply" msgstr "" #: ../quodlibet/browsers/collection/prefs.py:198 #: ../quodlibet/browsers/paned/prefs.py:213 #: ../quodlibet/browsers/playlists/menu.py:95 #: ../quodlibet/browsers/playlists/util.py:42 #: ../quodlibet/errorreport/ui.py:108 #: ../quodlibet/ext/playlist/export_to_folder.py:37 #: ../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:44 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:281 #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:88 #: ../quodlibet/ext/songsmenu/importexport.py:35 #: ../quodlibet/ext/songsmenu/lastfmsync.py:215 #: ../quodlibet/ext/songsmenu/playlist.py:50 #: ../quodlibet/ext/songsmenu/replaygain.py:364 #: ../quodlibet/ext/songsmenu/tapbpm.py:181 ../quodlibet/plugins/playlist.py:39 #: ../quodlibet/qltk/chooser.py:184 ../quodlibet/qltk/chooser.py:205 #: ../quodlibet/qltk/chooser.py:229 ../quodlibet/qltk/chooser.py:253 #: ../quodlibet/qltk/delete.py:90 ../quodlibet/qltk/delete.py:133 #: ../quodlibet/qltk/edittags.py:287 ../quodlibet/qltk/_editutils.py:38 #: ../quodlibet/qltk/getstring.py:28 ../quodlibet/qltk/maskedbox.py:27 #: ../quodlibet/qltk/msg.py:54 ../quodlibet/qltk/msg.py:93 #: ../quodlibet/qltk/ratingsmenu.py:33 ../quodlibet/qltk/songsmenu.py:45 #: ../quodlibet/qltk/songsmenu.py:73 ../quodlibet/update.py:94 msgid "_Cancel" msgstr "" #: ../quodlibet/browsers/covergrid/main.py:125 #, fuzzy msgid "Cover Grid" msgstr "Total size:" #: ../quodlibet/browsers/covergrid/main.py:126 #, 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:71 #, fuzzy msgid "Show \"All Albums\" Item" msgstr "All Albums" #: ../quodlibet/browsers/covergrid/prefs.py:78 msgid "Vertical Split" msgstr "" #: ../quodlibet/browsers/covergrid/prefs.py:110 #: ../quodlibet/browsers/covergrid/prefs.py:111 #, fuzzy msgid "Cover Magnification" msgstr "No new stations" #: ../quodlibet/browsers/filesystem.py:40 msgid "File System" msgstr "File System" #: ../quodlibet/browsers/filesystem.py:41 msgid "_File System" msgstr "_File System" #: ../quodlibet/browsers/filesystem.py:113 ../quodlibet/browsers/media.py:491 #: ../quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "Unable to copy songs" #: ../quodlibet/browsers/filesystem.py:114 ../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:189 msgid "_Add to Library" msgstr "_Add to Library" #: ../quodlibet/browsers/iradio.py:178 msgid "Unsupported file type" msgstr "Unsupported file type" #: ../quodlibet/browsers/iradio.py:179 #, 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:219 ../quodlibet/browsers/iradio.py:232 #: ../quodlibet/browsers/iradio.py:810 msgid "Unable to add station" msgstr "Unable to add station" #: ../quodlibet/browsers/iradio.py:243 ../quodlibet/browsers/iradio.py:471 msgid "Internet Radio" msgstr "Internet Radio" #: ../quodlibet/browsers/iradio.py:243 #, fuzzy msgid "Downloading station list" msgstr "Download Files" #: ../quodlibet/browsers/iradio.py:339 msgid "New Station" msgstr "New Station" #: ../quodlibet/browsers/iradio.py:340 msgid "Enter the location of an Internet radio station:" msgstr "Enter the location of an Internet radio station:" #: ../quodlibet/browsers/iradio.py:358 msgid "Electronic" msgstr "" #: ../quodlibet/browsers/iradio.py:361 msgid "Hip Hop / Rap" msgstr "" #: ../quodlibet/browsers/iradio.py:362 msgid "Oldies" msgstr "" #: ../quodlibet/browsers/iradio.py:363 msgid "R&B" msgstr "" #: ../quodlibet/browsers/iradio.py:364 msgid "Japanese" msgstr "" #: ../quodlibet/browsers/iradio.py:365 msgid "Indian" msgstr "" #: ../quodlibet/browsers/iradio.py:367 msgid "Religious" msgstr "" #: ../quodlibet/browsers/iradio.py:369 msgid "Charts" msgstr "" #: ../quodlibet/browsers/iradio.py:370 msgid "Turkish" msgstr "" #: ../quodlibet/browsers/iradio.py:371 msgid "Reggae / Dancehall" msgstr "" #: ../quodlibet/browsers/iradio.py:372 #, fuzzy msgid "Latin" msgstr "rating" #: ../quodlibet/browsers/iradio.py:373 msgid "College Radio" msgstr "" #: ../quodlibet/browsers/iradio.py:374 msgid "Talk / News" msgstr "" #: ../quodlibet/browsers/iradio.py:375 msgid "Ambient" msgstr "" #: ../quodlibet/browsers/iradio.py:376 msgid "Jazz" msgstr "" #: ../quodlibet/browsers/iradio.py:377 ../quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "" #: ../quodlibet/browsers/iradio.py:378 ../quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "" #: ../quodlibet/browsers/iradio.py:379 msgid "Alternative" msgstr "" #: ../quodlibet/browsers/iradio.py:380 msgid "Metal" msgstr "" #: ../quodlibet/browsers/iradio.py:381 msgid "Country" msgstr "" #: ../quodlibet/browsers/iradio.py:382 msgid "News" msgstr "" #: ../quodlibet/browsers/iradio.py:383 msgid "Schlager" msgstr "" #: ../quodlibet/browsers/iradio.py:384 msgid "Funk" msgstr "" #: ../quodlibet/browsers/iradio.py:385 msgid "Indie" msgstr "" #: ../quodlibet/browsers/iradio.py:386 msgid "Blues" msgstr "" #: ../quodlibet/browsers/iradio.py:387 msgid "Soul" msgstr "" #: ../quodlibet/browsers/iradio.py:388 msgid "Lounge" msgstr "" #: ../quodlibet/browsers/iradio.py:389 msgid "Punk" msgstr "" #: ../quodlibet/browsers/iradio.py:390 msgid "Reggaeton" msgstr "" #: ../quodlibet/browsers/iradio.py:392 msgid "Slavic" msgstr "" #: ../quodlibet/browsers/iradio.py:394 msgid "Greek" msgstr "" #: ../quodlibet/browsers/iradio.py:395 msgid "Gothic" msgstr "" #: ../quodlibet/browsers/iradio.py:396 ../quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "" #: ../quodlibet/browsers/iradio.py:449 msgid "Would you like to load a list of popular radio stations?" msgstr "" #: ../quodlibet/browsers/iradio.py:455 #, fuzzy msgid "_Load Stations" msgstr "_New Station" #: ../quodlibet/browsers/iradio.py:472 msgid "_Internet Radio" msgstr "_Internet Radio" #: ../quodlibet/browsers/iradio.py:538 #, fuzzy msgid "_New Station…" msgstr "New Station" #: ../quodlibet/browsers/iradio.py:541 #, fuzzy msgid "_Update Stations" msgstr "_New Station" #: ../quodlibet/browsers/iradio.py:568 #, fuzzy msgid "All Stations" msgstr "New Station" #. TODO: support for ~#rating=!None etc (#1940) #: ../quodlibet/browsers/iradio.py:572 #: ../quodlibet/browsers/soundcloud/main.py:64 msgid "Favorites" msgstr "" #: ../quodlibet/browsers/iradio.py:580 msgid "No Category" msgstr "" #: ../quodlibet/browsers/iradio.py:802 msgid "No stations found" msgstr "No stations found" #: ../quodlibet/browsers/iradio.py:803 #, python-format msgid "No Internet radio stations were found at %s." msgstr "No Internet radio stations were found at %s." #: ../quodlibet/browsers/iradio.py:811 msgid "All stations listed are already in your library." msgstr "All stations listed are already in your library." #: ../quodlibet/browsers/iradio.py:828 #, fuzzy msgid "Add to Favorites" msgstr "_Add to Playlist" #: ../quodlibet/browsers/iradio.py:832 #, fuzzy msgid "Remove from Favorites" msgstr "_Remove from Playlist" #: ../quodlibet/browsers/iradio.py:932 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "%(count)d station" msgstr[1] "%(count)d stations" #: ../quodlibet/browsers/media.py:36 msgid "Device Properties" msgstr "Device Properties" #: ../quodlibet/browsers/media.py:52 msgid "Device:" msgstr "Device:" #: ../quodlibet/browsers/media.py:54 msgid "Not mounted" msgstr "Not mounted" #: ../quodlibet/browsers/media.py:55 #, fuzzy msgid "Mount point:" msgstr "Mount Point:" #: ../quodlibet/browsers/media.py:61 ../quodlibet/qltk/cbes.py:40 msgid "_Name:" msgstr "_Name:" #: ../quodlibet/browsers/media.py:135 msgid "Media Devices" msgstr "Media Devices" #: ../quodlibet/browsers/media.py:136 msgid "_Media Devices" msgstr "_Media Devices" #. eject button #: ../quodlibet/browsers/media.py:224 ../quodlibet/browsers/media.py:378 msgid "_Eject" msgstr "_Eject" #: ../quodlibet/browsers/media.py:360 #, fuzzy msgid "_Properties" msgstr "Properties" #: ../quodlibet/browsers/media.py:365 #: ../quodlibet/browsers/playlists/main.py:464 msgid "_Rename" msgstr "_Rename" #: ../quodlibet/browsers/media.py:461 #, fuzzy, python-format msgid "%(used-size)s used, %(free-size)s available" msgstr "<b>%s</b> used, <b>%s</b> available" #: ../quodlibet/browsers/media.py:479 #, fuzzy, python-format msgid "%s is not connected." msgstr "<b>%s</b> is not connected." #: ../quodlibet/browsers/media.py:499 #, fuzzy, python-format msgid "Copying %(song)s" msgstr "Copying <b>%s</b>" #: ../quodlibet/browsers/media.py:513 ../quodlibet/browsers/media.py:529 msgid "Unable to copy song" msgstr "Unable to copy song" #: ../quodlibet/browsers/media.py:514 msgid "There is not enough free space for this song." msgstr "There is not enough free space for this song." #: ../quodlibet/browsers/media.py:526 #, fuzzy, python-format msgid "%s could not be copied." msgstr "<b>%s</b> could not be copied." #: ../quodlibet/browsers/media.py:545 msgid "Unable to delete songs" msgstr "Unable to delete songs" #: ../quodlibet/browsers/media.py:557 #, fuzzy, python-format msgid "Deleting %(song)s" msgstr "Deleting <b>%s</b>" #: ../quodlibet/browsers/media.py:575 #, fuzzy, python-format msgid "%s could not be deleted." msgstr "<b>%s</b> could not be deleted." #: ../quodlibet/browsers/media.py:579 msgid "Unable to delete song" msgstr "Unable to delete song" #: ../quodlibet/browsers/media.py:594 #, fuzzy, python-format msgid "Ejecting %s failed." msgstr "Ejecting <b>%s</b> failed." #: ../quodlibet/browsers/media.py:597 msgid "Unable to eject device" msgstr "Unable to eject device" #: ../quodlibet/browsers/media.py:603 msgid "No device backend, Media Devices browser disabled." msgstr "" #: ../quodlibet/browsers/paned/main.py:40 ../quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "Paned Browser" #: ../quodlibet/browsers/paned/main.py:41 msgid "_Paned Browser" msgstr "_Paned Browser" #: ../quodlibet/browsers/paned/main.py:90 msgid "Select _All" msgstr "Select _All" #: ../quodlibet/browsers/paned/models.py:104 ../quodlibet/qltk/pluginwin.py:122 #: ../quodlibet/qltk/pluginwin.py:164 msgid "All" msgstr "All" #: ../quodlibet/browsers/paned/prefs.py:67 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "<tt>%s</tt>" msgstr "" #: ../quodlibet/browsers/paned/prefs.py:162 msgid "_Wide Mode" msgstr "" #: ../quodlibet/browsers/paned/prefs.py:197 msgid "Paned Browser Preferences" msgstr "Paned Browser Preferences" #: ../quodlibet/browsers/paned/prefs.py:204 msgid "Equal pane width" msgstr "" #: ../quodlibet/browsers/playlists/main.py:48 #: ../quodlibet/browsers/playlists/main.py:575 #: ../quodlibet/qltk/pluginwin.py:168 msgid "Playlists" msgstr "Playlists" #: ../quodlibet/browsers/playlists/main.py:49 msgid "_Playlists" msgstr "_Playlists" #: ../quodlibet/browsers/playlists/main.py:152 msgid "_Remove from Playlist" msgstr "_Remove from Playlist" #: ../quodlibet/browsers/playlists/main.py:215 #: ../quodlibet/browsers/playlists/main.py:576 msgid "_Import" msgstr "_Import" #: ../quodlibet/browsers/playlists/main.py:391 #: ../quodlibet/browsers/playlists/util.py:50 #: ../quodlibet/util/collection.py:570 msgid "New Playlist" msgstr "New Playlist" #: ../quodlibet/browsers/playlists/main.py:413 msgid "Unable to import playlist" msgstr "Unable to import playlist" #: ../quodlibet/browsers/playlists/main.py:414 msgid "Quod Libet can only import playlists in the M3U and PLS formats." msgstr "Quod Libet can only import playlists in the M3U and PLS formats." #: ../quodlibet/browsers/playlists/main.py:565 msgid "Unable to rename playlist" msgstr "Unable to rename playlist" #: ../quodlibet/browsers/playlists/main.py:576 msgid "Import Playlist" msgstr "Import Playlist" #: ../quodlibet/browsers/playlists/menu.py:25 #, fuzzy msgid "_New Playlist…" msgstr "_New Playlist" #: ../quodlibet/browsers/playlists/menu.py:86 #, 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:90 #, 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:33 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "" #: ../quodlibet/browsers/playlists/util.py:35 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" #: ../quodlibet/browsers/playlists/util.py:51 #, fuzzy msgid "Enter a name for the new playlist:" msgstr "Enter a name for the new folder:" #: ../quodlibet/browsers/playlists/util.py:102 #, 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/search.py:33 msgid "_Limit Results" msgstr "_Limit Results" #: ../quodlibet/browsers/search.py:48 msgid "Search Library" msgstr "Search Library" #: ../quodlibet/browsers/search.py:49 msgid "_Search Library" msgstr "_Search Library" #: ../quodlibet/browsers/soundcloud/main.py:38 #, fuzzy msgid "Soundcloud Browser" msgstr "Paned Browser" #: ../quodlibet/browsers/soundcloud/main.py:39 msgid "Sound_cloud" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:59 #: ../quodlibet/qltk/searchbar.py:73 msgid "Search" msgstr "Search" #: ../quodlibet/browsers/soundcloud/main.py:136 #, python-format msgid "Go to %s" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:380 #, fuzzy msgid "Connected" msgstr "location" #: ../quodlibet/browsers/soundcloud/main.py:381 #, python-format msgid "Quod Libet is now connected, <b>%s</b>!" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:393 #, python-format msgid "Log out of %s" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:395 msgid "Enter code…" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:396 #, python-format msgid "Log in to %s" msgstr "" #: ../quodlibet/browsers/soundcloud/util.py:86 msgid "Soundcloud authorisation" msgstr "" #: ../quodlibet/browsers/soundcloud/util.py:87 msgid "Enter Soundcloud auth code:" msgstr "" #: ../quodlibet/cli.py:50 #, fuzzy msgid "Quod Libet is not running (add '--run' to start it)" msgstr "Quod Libet is not running." #: ../quodlibet/cli.py:85 msgid "a music library and player" msgstr "a music library and player" #: ../quodlibet/cli.py:86 #, fuzzy msgid "[option]" msgstr "[options]" #: ../quodlibet/cli.py:88 msgid "Print the playing song and exit" msgstr "Print the playing song and exit" #: ../quodlibet/cli.py:89 msgid "Begin playing immediately" msgstr "Begin playing immediately" #: ../quodlibet/cli.py:90 msgid "Don't show any windows on start" msgstr "" #: ../quodlibet/cli.py:93 msgid "Jump to next song" msgstr "Jump to next song" #: ../quodlibet/cli.py:95 msgid "Jump to previous song or restart if near the beginning" msgstr "" #: ../quodlibet/cli.py:96 msgid "Jump to previous song" msgstr "Jump to previous song" #: ../quodlibet/cli.py:97 msgid "Start playback" msgstr "Start playback" #: ../quodlibet/cli.py:98 msgid "Pause playback" msgstr "Pause playback" #: ../quodlibet/cli.py:99 msgid "Toggle play/pause mode" msgstr "Toggle play/pause mode" #: ../quodlibet/cli.py:100 #, fuzzy msgid "Stop playback" msgstr "Start playback" #: ../quodlibet/cli.py:101 msgid "Turn up volume" msgstr "Turn up volume" #: ../quodlibet/cli.py:102 msgid "Turn down volume" msgstr "Turn down volume" #: ../quodlibet/cli.py:103 msgid "Print player status" msgstr "Print player status" #: ../quodlibet/cli.py:104 msgid "Hide main window" msgstr "Hide main window" #: ../quodlibet/cli.py:105 msgid "Show main window" msgstr "Show main window" #: ../quodlibet/cli.py:106 msgid "Toggle main window visibility" msgstr "Toggle main window visibility" #: ../quodlibet/cli.py:107 msgid "Focus the running player" msgstr "Focus the running player" #: ../quodlibet/cli.py:108 msgid "Remove active browser filters" msgstr "Remove active browser filters" #: ../quodlibet/cli.py:109 #, fuzzy msgid "Refresh and rescan library" msgstr "Re_fresh Library" #: ../quodlibet/cli.py:110 #, fuzzy msgid "List available browsers" msgstr "Disable Browser" #: ../quodlibet/cli.py:111 msgid "Print the current playlist" msgstr "Print the current playlist" #: ../quodlibet/cli.py:112 msgid "Print the contents of the queue" msgstr "Print the contents of the queue" #: ../quodlibet/cli.py:113 #, fuzzy msgid "Print the active text query" msgstr "Print the contents of the queue" #: ../quodlibet/cli.py:114 msgid "Start without plugins" msgstr "" #: ../quodlibet/cli.py:115 #, fuzzy msgid "Start Quod Libet if it isn't running" msgstr "Quod Libet is not running." #: ../quodlibet/cli.py:116 msgid "Exit Quod Libet" msgstr "Exit Quod Libet" #: ../quodlibet/cli.py:121 msgid "Seek within the playing song" msgstr "Seek within the playing song" #: ../quodlibet/cli.py:121 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: ../quodlibet/cli.py:122 #, fuzzy msgid "Set or toggle shuffle mode" msgstr "Toggle play/pause mode" #: ../quodlibet/cli.py:123 msgid "Turn repeat off, on, or toggle it" msgstr "Turn repeat off, on, or toggle it" #: ../quodlibet/cli.py:124 msgid "Set the volume" msgstr "Set the volume" #: ../quodlibet/cli.py:125 msgid "Search your audio library" msgstr "Search your audio library" #: ../quodlibet/cli.py:125 ../quodlibet/cli.py:137 ../quodlibet/cli.py:141 #: ../quodlibet/cli.py:143 msgid "query" msgstr "query" #: ../quodlibet/cli.py:126 msgid "Play a file" msgstr "Play a file" #: ../quodlibet/cli.py:126 ../quodlibet/cli.py:137 ../quodlibet/cli.py:143 #, fuzzy msgctxt "command" msgid "filename" msgstr "filename" #: ../quodlibet/cli.py:127 msgid "Rate the playing song" msgstr "Rate the playing song" #: ../quodlibet/cli.py:128 msgid "Set the current browser" msgstr "Set the current browser" #: ../quodlibet/cli.py:129 #, fuzzy msgid "Stop after the playing song" msgstr "Rate the playing song" #: ../quodlibet/cli.py:130 msgid "Open a new browser" msgstr "Open a new browser" #: ../quodlibet/cli.py:131 msgid "Show or hide the queue" msgstr "Show or hide the queue" #: ../quodlibet/cli.py:133 #, fuzzy msgid "Show or hide the main song list (deprecated)" msgstr "Show or hide the main song list" #: ../quodlibet/cli.py:134 msgid "Filter on a random value" msgstr "Filter on a random value" #: ../quodlibet/cli.py:134 #, fuzzy msgctxt "command" msgid "tag" msgstr "tag" #: ../quodlibet/cli.py:135 msgid "Filter on a tag value" msgstr "Filter on a tag value" #: ../quodlibet/cli.py:135 msgid "tag=value" msgstr "tag=value" #: ../quodlibet/cli.py:136 msgid "Enqueue a file or query" msgstr "Enqueue a file or query" #: ../quodlibet/cli.py:138 msgid "Enqueue comma-separated files" msgstr "" #: ../quodlibet/cli.py:139 ../quodlibet/util/tags.py:147 msgid "filename" msgstr "filename" #: ../quodlibet/cli.py:140 msgid "Print filenames of results of query to stdout" msgstr "" #: ../quodlibet/cli.py:142 msgid "Unqueue a file or query" msgstr "Unqueue a file or query" #: ../quodlibet/cli.py:203 #, fuzzy, python-format msgid "Invalid argument for '%s'." msgstr "E: Invalid argument for '%s'." #: ../quodlibet/cli.py:204 ../quodlibet/util/__init__.py:190 #, fuzzy, python-format msgid "Try %s --help." msgstr "E: Try %s --help." #: ../quodlibet/devices/_base.py:65 msgid "Unknown Device" msgstr "Unknown Device" #: ../quodlibet/devices/__init__.py:32 #, python-format msgid "Could not import %s, which is needed for device support." msgstr "" #: ../quodlibet/devices/__init__.py:153 #, fuzzy, python-format msgid "%r is not a supported device." msgstr "E: '%s' is not a unique prefix." #: ../quodlibet/devices/__init__.py:245 ../quodlibet/devices/__init__.py:251 #, fuzzy, python-format msgid "Could not find '%s'." msgstr "Could not play %s." #: ../quodlibet/devices/__init__.py:450 #, fuzzy msgid "Initializing device backend." msgstr "Invalid tag name" #: ../quodlibet/devices/__init__.py:451 #, python-format msgid "Trying '%s'" msgstr "" #: ../quodlibet/devices/__init__.py:461 msgid "Couldn't connect to a device backend." msgstr "" #: ../quodlibet/devices/__init__.py:463 msgid "Device backend initialized." msgstr "" #: ../quodlibet/devices/storage.py:57 #, fuzzy msgid "_Filename pattern:" msgstr "_Filename Pattern:" #: ../quodlibet/devices/storage.py:61 msgid "Copy _album covers" msgstr "Copy _album covers" #: ../quodlibet/devices/storage.py:65 msgid "_Remove unused covers and directories" msgstr "_Remove unused covers and directories" #: ../quodlibet/errorreport/ui.py:60 msgid "An Error Occurred" msgstr "" #: ../quodlibet/errorreport/ui.py:62 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:72 msgid "File Bug Report" msgstr "" #: ../quodlibet/errorreport/ui.py:74 ../quodlibet/errorreport/ui.py:90 msgid "Submit Error Report" msgstr "" #: ../quodlibet/errorreport/ui.py:75 msgid "Quit Program" msgstr "" #: ../quodlibet/errorreport/ui.py:76 #, fuzzy msgid "Ignore Error" msgstr "Show _Errors" #: ../quodlibet/errorreport/ui.py:80 msgid "Error details:" msgstr "" #: ../quodlibet/errorreport/ui.py:92 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:100 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "" #: ../quodlibet/errorreport/ui.py:109 msgid "_Send" msgstr "" #: ../quodlibet/errorreport/ui.py:115 #, fuzzy msgid "Short description…" msgstr "description" #: ../quodlibet/errorreport/ui.py:118 msgid "Data to be sent:" msgstr "" #: ../quodlibet/exfalso.py:34 msgid "an audio tag editor" msgstr "an audio tag editor" #: ../quodlibet/exfalso.py:34 ../quodlibet/util/tags.py:148 msgid "directory" msgstr "directory" #: ../quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "" #: ../quodlibet/ext/covers/artwork_url.py:20 msgid "" "Downloads covers linked to by the artwork_url tag.This works with the " "Soundcloud browser." msgstr "" #: ../quodlibet/ext/covers/discogs.py:25 #, fuzzy msgid "Discogs Cover Source" msgstr "MusicBrainz track ID" #: ../quodlibet/ext/covers/discogs.py:26 msgid "Downloads covers from Discogs." msgstr "" #: ../quodlibet/ext/covers/lastfm.py:22 msgid "Last.fm Cover Source" msgstr "" #: ../quodlibet/ext/covers/lastfm.py:23 msgid "Downloads covers from Last.fm's cover art archive." msgstr "" #: ../quodlibet/ext/covers/musicbrainz.py:19 #, fuzzy msgid "MusicBrainz Cover Source" msgstr "MusicBrainz track ID" #: ../quodlibet/ext/covers/musicbrainz.py:20 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:25 msgid "Kana/Kanji Simple Inverter" msgstr "" #: ../quodlibet/ext/editing/kakasi.py:26 msgid "Converts kana/kanji to romaji before renaming." msgstr "" #: ../quodlibet/ext/editing/kakasi.py:35 msgid "Romanize _Japanese text" msgstr "" #: ../quodlibet/ext/editing/kakasi.py:63 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:19 msgid "" "Allows arbitrary regex substitutions (s///) 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:69 #, fuzzy msgid "Advanced Preferences" msgstr "Paned Browser Preferences" #: ../quodlibet/ext/events/advanced_preferences.py:70 msgid "Allow editing of advanced config settings." msgstr "" #: ../quodlibet/ext/events/advanced_preferences.py:162 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:153 msgid "Top of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:154 msgid "Middle of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:155 msgid "Bottom of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:158 msgid "_Position:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:171 #, fuzzy msgid "_Cover size:" msgstr "Total size:" #: ../quodlibet/ext/events/animosd/prefs.py:177 #: ../quodlibet/ext/events/lyricswindow.py:334 ../quodlibet/qltk/prefs.py:266 #, fuzzy msgid "Display" msgstr "Edit Display" #: ../quodlibet/ext/events/animosd/prefs.py:190 msgid "_Font:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:195 msgid "Left" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:196 msgid "Center" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:197 #, fuzzy msgid "Right" msgstr "_Weighted" #: ../quodlibet/ext/events/animosd/prefs.py:200 msgid "_Align text:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:206 msgid "Text" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:217 msgid "_Text:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:227 msgid "_Fill:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:232 #: ../quodlibet/ext/events/synchronizedlyrics.py:63 msgid "Colors" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:240 msgid "_Shadows" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:241 msgid "_Outline" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:242 msgid "Rou_nded Corners" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:258 msgid "_Delay:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:264 #: ../quodlibet/qltk/pluginwin.py:172 msgid "Effects" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:270 #, fuzzy msgid "Ed_it Display Pattern…" msgstr "Edit Display" #: ../quodlibet/ext/events/animosd/prefs.py:274 #: ../quodlibet/ext/events/trayicon/prefs.py:78 #, fuzzy msgid "Preview" msgstr "_Preview" #: ../quodlibet/ext/events/auto_library_update.py:136 msgid "Automatic Library Update" msgstr "" #: ../quodlibet/ext/events/auto_library_update.py:137 #, python-format msgid "Keeps your library up to date with inotify. Requires %s." 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 by Brian Nelson." 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/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:97 msgid "Equalizer" msgstr "" #: ../quodlibet/ext/events/equalizer.py:98 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:132 msgid "The current backend does not support equalization." msgstr "" #: ../quodlibet/ext/events/equalizer.py:138 #, python-format msgid "%.1f kHz" msgstr "" #: ../quodlibet/ext/events/equalizer.py:139 #: ../quodlibet/ext/gstreamer/crossfeed.py:93 #: ../quodlibet/ext/gstreamer/karaoke.py:95 #, python-format msgid "%d Hz" msgstr "" #: ../quodlibet/ext/events/equalizer.py:173 #: ../quodlibet/ext/gstreamer/crossfeed.py:112 #, fuzzy, python-format msgid "%.1f dB" msgstr "1 second" #: ../quodlibet/ext/events/equalizer.py:192 #: ../quodlibet/ext/gstreamer/crossfeed.py:31 #, fuzzy msgid "Custom" msgstr "_Custom" #: ../quodlibet/ext/events/equalizer.py:199 #, fuzzy msgid "_Clear" msgstr "_Clear Errors" #. Translators: statuses relating to Instant Messenger apps #: ../quodlibet/ext/events/gajim_status.py:27 msgid "online" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:28 msgid "offline" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:29 msgid "chat" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:30 msgid "away" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:31 msgid "xa" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:32 msgid "invisible" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:37 msgid "Gajim Status Message" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:38 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:45 #: ../quodlibet/ext/events/telepathy_status.py:69 msgid "paused" 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:160 msgid "Add '[paused]'" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:163 msgid "If checked, '[paused]' will be added to status message on pause." msgstr "" #: ../quodlibet/ext/events/gajim_status.py:187 msgid "Statuses for which message will be changed" msgstr "" #: ../quodlibet/ext/events/headphonemon.py:156 msgid "Pause on Headphone Unplug" msgstr "" #: ../quodlibet/ext/events/headphonemon.py:157 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" #: ../quodlibet/ext/events/inhibit.py:41 msgid "Inhibit Screensaver" msgstr "" #: ../quodlibet/ext/events/inhibit.py:42 msgid "Prevents the GNOME screensaver from activating while a song is playing." msgstr "" #: ../quodlibet/ext/events/inhibit.py:51 #, fuzzy msgid "Music is playing" msgstr "Music Player" #: ../quodlibet/ext/events/iradiolog.py:16 #, fuzzy msgid "Internet Radio Log" msgstr "Internet Radio" #: ../quodlibet/ext/events/iradiolog.py:17 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" #: ../quodlibet/ext/events/jep118.py:29 msgid "JEP-118" msgstr "" #: ../quodlibet/ext/events/jep118.py:30 msgid "Outputs a Jabber User Tunes file to ~/.quodlibet/jabber." 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 msgid "A restart is required for any changes to take effect" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:199 #, fuzzy msgid "No active song" msgstr "Unable to save song" #: ../quodlibet/ext/events/lyricswindow.py:215 #, fuzzy msgid "No lyrics found" msgstr "No plugins found." #: ../quodlibet/ext/events/lyricswindow.py:227 #, fuzzy msgid "Lyrics:" msgstr "Lyrics" #: ../quodlibet/ext/events/lyricswindow.py:284 msgid "_Zoom level:" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:302 msgid "URL:" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:307 msgid "Revert to default" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:322 msgid "Search via above URL if the lyrics couldn't be found in LyricsWikia." msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:339 #, fuzzy msgid "Alternate search" msgstr "Clear search" #: ../quodlibet/ext/events/lyricswindow.py:347 #, fuzzy msgid "Lyrics Window" msgstr "Lyrics" #: ../quodlibet/ext/events/lyricswindow.py:348 #, fuzzy msgid "Shows a window containing lyrics of the playing song." msgstr "View and edit tags in the playing song" #: ../quodlibet/ext/events/mediaserver.py:38 msgid "UPnP AV Media Server" msgstr "" #: ../quodlibet/ext/events/mediaserver.py:39 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." 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:39 msgid "" "Allows control of Quod Libet using the MPRIS 1.0/2.0 D-Bus Interface " "Specification." msgstr "" #: ../quodlibet/ext/events/mpris/__init__.py:45 #: ../quodlibet/ext/events/trayicon/prefs.py:30 #, fuzzy msgid "Hide main window on close" msgstr "Hide main window" #: ../quodlibet/ext/events/mpris/__init__.py:48 #: ../quodlibet/ext/events/themeswitcher.py:84 #: ../quodlibet/ext/gstreamer/compressor.py:99 #: ../quodlibet/ext/gstreamer/crossfeed.py:136 #: ../quodlibet/ext/gstreamer/karaoke.py:99 #: ../quodlibet/ext/gstreamer/pitch.py:83 ../quodlibet/qltk/prefs.py:688 #, fuzzy msgid "Preferences" msgstr "Preferences" #: ../quodlibet/ext/events/mqtt.py:50 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/mqtt.py:56 msgid "MQTT Publisher" msgstr "" #: ../quodlibet/ext/events/mqtt.py:57 msgid "Publishes status messages to an MQTT topic." msgstr "" #: ../quodlibet/ext/events/mqtt.py:122 msgid "Broker hostname" msgstr "" #: ../quodlibet/ext/events/mqtt.py:122 msgid "broker hostname / IP" msgstr "" #: ../quodlibet/ext/events/mqtt.py:124 msgid "Broker port" msgstr "" #: ../quodlibet/ext/events/mqtt.py:124 msgid "broker port" msgstr "" #: ../quodlibet/ext/events/mqtt.py:126 msgid "Topic" msgstr "" #: ../quodlibet/ext/events/mqtt.py:128 #, fuzzy msgid "Playing Pattern" msgstr "Invalid Pattern" #: ../quodlibet/ext/events/mqtt.py:130 msgid "Status text when a song is started." msgstr "" #: ../quodlibet/ext/events/mqtt.py:132 #, fuzzy msgid "Paused Pattern" msgstr "Invalid Pattern" #: ../quodlibet/ext/events/mqtt.py:134 msgid "Text when a song is paused." msgstr "" #: ../quodlibet/ext/events/mqtt.py:136 #, fuzzy msgid "No-song Text" msgstr "%d song" #: ../quodlibet/ext/events/mqtt.py:138 #, fuzzy msgid "Plain text for when there is no current song" msgstr "Pause/resume the current song" #: ../quodlibet/ext/events/mqtt.py:149 #, fuzzy msgid "MQTT Configuration" msgstr "Information" #: ../quodlibet/ext/events/mqtt.py:153 #, fuzzy msgid "Status Text" msgstr "Invalid Pattern" #: ../quodlibet/ext/events/mqtt.py:185 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "" #: ../quodlibet/ext/events/mqtt.py:189 #, fuzzy, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s" msgstr "Could not play %s." #: ../quodlibet/ext/events/mqtt.py:192 #, fuzzy msgid "Connection error" msgstr "location" #: ../quodlibet/ext/events/notify.py:80 msgid "Notification text" msgstr "" #: ../quodlibet/ext/events/notify.py:88 #, fuzzy msgid "_Title:" msgstr "Title" #: ../quodlibet/ext/events/notify.py:99 ../quodlibet/ext/events/notify.py:128 msgid "Revert to default pattern" msgstr "" #: ../quodlibet/ext/events/notify.py:118 msgid "_Body:" msgstr "" #: ../quodlibet/ext/events/notify.py:138 msgid "_Show notification" msgstr "" #: ../quodlibet/ext/events/notify.py:156 #, fuzzy msgid "Show notifications" msgstr "No new stations" #: ../quodlibet/ext/events/notify.py:162 msgid "Only on <i>_manual</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:170 msgid "Only on <i>_automatic</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:178 msgid "On <i>a_ll</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:196 msgid "Only when the main window is not _focused" msgstr "" #: ../quodlibet/ext/events/notify.py:204 msgid "Show \"_Next\" button" msgstr "" #: ../quodlibet/ext/events/notify.py:236 msgid "Connection Error" msgstr "" #: ../quodlibet/ext/events/notify.py:237 ../quodlibet/ext/events/notify.py:391 #: ../quodlibet/ext/events/notify.py:433 msgid "Couldn't connect to notification daemon." msgstr "" #: ../quodlibet/ext/events/notify.py:251 #, fuzzy msgid "Song Notifications" msgstr "No new stations" #: ../quodlibet/ext/events/notify.py:252 msgid "Displays a notification when the song changes." msgstr "" #: ../quodlibet/ext/events/notify.py:415 ../quodlibet/qltk/unity.py:65 #, fuzzy msgid "Next" msgstr "_Next" #: ../quodlibet/ext/events/qlscrobbler.py:178 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:254 #, python-format msgid "Could not contact service '%s'." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:260 msgid "Authentication failed: invalid URL." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:277 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:282 msgid "Client is banned. Contact the author." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:286 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:351 msgid "AudioScrobbler Submission" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:352 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:450 msgid "Authentication successful." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:462 #, fuzzy msgid "_Service:" msgstr "Device:" #: ../quodlibet/ext/events/qlscrobbler.py:462 msgid "_URL:" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:462 #, fuzzy msgid "User_name:" msgstr "_Name:" #: ../quodlibet/ext/events/qlscrobbler.py:463 msgid "_Password:" msgstr "" #. Translators: Other service #: ../quodlibet/ext/events/qlscrobbler.py:479 #, fuzzy msgid "Other…" msgstr "_Others: " #. verify data #: ../quodlibet/ext/events/qlscrobbler.py:517 msgid "_Verify account data" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:522 #: ../quodlibet/ext/songsmenu/lastfmsync.py:304 msgid "Account" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:530 #, fuzzy msgid "_Artist pattern:" msgstr "_Artist" #: ../quodlibet/ext/events/qlscrobbler.py:530 #, fuzzy msgid "_Title pattern:" msgstr "_Filename Pattern:" #: ../quodlibet/ext/events/qlscrobbler.py:531 msgid "Exclude _filter:" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:549 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:559 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:568 msgid "Songs matching this filter will not be submitted." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:576 msgid "_Offline mode (don't submit anything)" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:580 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:27 #, fuzzy msgid "Random Album Playback" msgstr "Random Al_bum" #: ../quodlibet/ext/events/randomalbum.py:28 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:38 msgid "Rated higher" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:39 msgid "Played more often" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:40 msgid "Skipped more often" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:41 msgid "Played more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:42 msgid "Started more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:43 msgid "Added more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:44 #, fuzzy msgid "Longer albums" msgstr "albums" #: ../quodlibet/ext/events/randomalbum.py:83 msgid "seconds before starting next album" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:87 #, fuzzy msgid "Weights" msgstr "_Weighted" #: ../quodlibet/ext/events/randomalbum.py:89 msgid "Play some albums more than others" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:103 msgid "avoid" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:114 msgid "prefer" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:201 #, fuzzy msgid "Random Album" msgstr "Random Al_bum" #: ../quodlibet/ext/events/randomalbum.py:202 #, python-format msgid "Waiting to start %s" msgstr "" #: ../quodlibet/ext/events/rbimport.py:114 #, fuzzy msgid "Import Failed" msgstr "Import Playlist" #: ../quodlibet/ext/events/rbimport.py:119 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "" #: ../quodlibet/ext/events/rbimport.py:127 msgid "Rhythmbox Import" msgstr "" #: ../quodlibet/ext/events/rbimport.py:128 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "" #: ../quodlibet/ext/events/rbimport.py:132 #, fuzzy msgid "Start Import" msgstr "_Import" #: ../quodlibet/ext/events/screensaver.py:25 msgid "Screensaver Pause" msgstr "" #: ../quodlibet/ext/events/screensaver.py:26 msgid "Pauses playback while the GNOME screensaver is active." msgstr "" #: ../quodlibet/ext/events/searchprovider.py:73 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "" #: ../quodlibet/ext/events/searchprovider.py:79 msgid "GNOME Search Provider" msgstr "" #: ../quodlibet/ext/events/searchprovider.py:80 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/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:29 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:57 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:58 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:34 #, fuzzy msgid "Synchronized Lyrics" msgstr "Lyrics" #: ../quodlibet/ext/events/synchronizedlyrics.py:35 msgid "Shows synchronized lyrics from .lrc file with same name as the track." msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:66 msgid "Text:" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:76 msgid "Background:" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:87 msgid "Font" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:90 msgid "Size (px):" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:62 msgid "Telepathy Status Messages" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:63 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:122 #, fuzzy msgid "Playing:" msgstr "Play _song" #: ../quodlibet/ext/events/telepathy_status.py:123 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:139 msgid "Paused:" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:140 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:156 #, fuzzy msgid "Plain text for status when there is no current song" msgstr "Pause/resume the current song" #: ../quodlibet/ext/events/telepathy_status.py:157 #, fuzzy msgid "No song:" msgstr "%d song" #. Frame #: ../quodlibet/ext/events/telepathy_status.py:164 #, 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/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:77 #: ../quodlibet/ext/events/trayicon/prefs.py:98 #: ../quodlibet/ext/events/trayicon/systemtray.py:177 #: ../quodlibet/qltk/info.py:47 msgid "Not playing" msgstr "Not playing" #: ../quodlibet/ext/events/trayicon/__init__.py:53 #, fuzzy msgid "Tray Icon" msgstr "Tray Icon Preferences" #: ../quodlibet/ext/events/trayicon/__init__.py:54 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:183 #: ../quodlibet/qltk/quodlibetwindow.py:1046 #: ../quodlibet/qltk/quodlibetwindow.py:1238 #, fuzzy msgid "_Play" msgstr "Player" #: ../quodlibet/ext/events/trayicon/menu.py:63 #: ../quodlibet/qltk/quodlibetwindow.py:185 #: ../quodlibet/qltk/quodlibetwindow.py:1240 ../quodlibet/qltk/wlw.py:51 #, fuzzy msgid "P_ause" msgstr "_Pause" #: ../quodlibet/ext/events/trayicon/menu.py:68 #: ../quodlibet/qltk/quodlibetwindow.py:190 #: ../quodlibet/qltk/quodlibetwindow.py:1041 #, fuzzy msgid "Pre_vious" msgstr "Pre_vious" #: ../quodlibet/ext/events/trayicon/menu.py:71 #: ../quodlibet/qltk/quodlibetwindow.py:194 #: ../quodlibet/qltk/quodlibetwindow.py:1051 #, 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:1012 #, fuzzy msgid "Open _Browser" msgstr "Open a new browser" #: ../quodlibet/ext/events/trayicon/menu.py:103 #: ../quodlibet/qltk/quodlibetwindow.py:1031 ../quodlibet/qltk/songsmenu.py:411 msgid "Edit _Tags" msgstr "Edit _Tags" #: ../quodlibet/ext/events/trayicon/menu.py:112 #: ../quodlibet/qltk/quodlibetwindow.py:975 ../quodlibet/qltk/songsmenu.py:424 msgid "_Information" msgstr "_Information" #: ../quodlibet/ext/events/trayicon/menu.py:114 #: ../quodlibet/qltk/songsmenu.py:340 #, fuzzy msgid "Play_lists" msgstr "Playlists" #: ../quodlibet/ext/events/trayicon/menu.py:132 #: ../quodlibet/qltk/quodlibetwindow.py:1026 msgid "_Quit" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:32 ../quodlibet/qltk/prefs.py:69 msgid "Behavior" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:42 #, fuzzy msgid "Scroll wheel adjusts volume" msgstr "" "Scroll wheel adjusts volume\n" "Shift and scroll wheel changes song" #: ../quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel changes song" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll _Wheel" msgstr "Scroll _Wheel" #: ../quodlibet/ext/events/trayicon/prefs.py:84 msgid "Tooltip Display" msgstr "Tooltip Display" #: ../quodlibet/ext/events/viewlyrics.py:23 #, fuzzy msgid "View Lyrics" msgstr "Lyrics" #: ../quodlibet/ext/events/viewlyrics.py:24 msgid "Automatically displays lyrics beneath the song list in the main window." msgstr "" #: ../quodlibet/ext/events/viewlyrics.py:29 #, fuzzy msgid "_Lyrics" msgstr "Lyrics" #: ../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:406 msgid "Waveform Seek Bar" msgstr "" #: ../quodlibet/ext/events/waveformseekbar.py:410 msgid "A seekbar in the shape of the waveform of the current song." msgstr "" #: ../quodlibet/ext/events/waveformseekbar.py:443 msgid "Override foreground color:" msgstr "" #: ../quodlibet/ext/events/write_cover.py:32 msgid "Picture Saver" msgstr "" #: ../quodlibet/ext/events/write_cover.py:33 msgid "Saves the cover image of the current song to a file." msgstr "" #: ../quodlibet/ext/events/write_cover.py:66 #, fuzzy msgid "File:" msgstr "Files" #: ../quodlibet/ext/gstreamer/compressor.py:20 msgid "_Threshold:" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:21 msgid "Threshold until the filter is activated" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:22 msgid "R_atio:" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:22 msgid "Compression ratio" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:74 #: ../quodlibet/ext/gstreamer/karaoke.py:91 #, python-format msgid "%d %%" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:105 msgid "Audio Compressor" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:106 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:19 #, fuzzy msgid "_Preset:" msgstr "_Preview" #: ../quodlibet/ext/gstreamer/crossfeed.py:19 #, fuzzy msgid "Filter preset" msgstr "Filter on _Artist" #: ../quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Frequency cut:" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Low-pass filter cut frequency" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed _level:" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed level" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:25 #, fuzzy msgid "Default" msgstr "Set Rating" #: ../quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Chu Moy" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Jan Meier" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:31 #, fuzzy msgid "Custom settings" msgstr "_Custom" #: ../quodlibet/ext/gstreamer/crossfeed.py:152 msgid "Crossfeed" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:153 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:20 #, fuzzy msgid "Filter _band:" msgstr "Filter on _Genre" #: ../quodlibet/ext/gstreamer/karaoke.py:21 msgid "The Frequency band of the filter" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:22 #, fuzzy msgid "Filter _width:" msgstr "Filter on _Artist" #: ../quodlibet/ext/gstreamer/karaoke.py:23 msgid "The Frequency width of the filter" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:24 msgid "_Level:" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:24 msgid "Level of the effect" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:105 msgid "Karaoke" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:106 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:20 msgid "R_ate:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:21 msgid "_Tempo:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:22 msgid "_Pitch:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:89 #, fuzzy msgid "Audio Pitch / Speed" msgstr "Audio Feeds" #: ../quodlibet/ext/gstreamer/pitch.py:90 #, fuzzy msgid "Controls the pitch of an audio stream." msgstr "Enter the location of an audio feed:" #: ../quodlibet/ext/playlist/export_to_folder.py:29 #: ../quodlibet/ext/playlist/export_to_folder.py:97 #: ../quodlibet/ext/playlist/export_to_folder.py:138 #, fuzzy msgid "Export Playlist to Folder" msgstr "Import Playlist" #: ../quodlibet/ext/playlist/export_to_folder.py:38 #, fuzzy msgid "_Export" msgstr "_Import" #: ../quodlibet/ext/playlist/export_to_folder.py:43 #, fuzzy msgid "Destination folder:" msgstr "No stations found" #: ../quodlibet/ext/playlist/export_to_folder.py:58 #, 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:156 #, fuzzy msgid "Default filename pattern:" msgstr "_Filename Pattern:" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:23 msgid "Export to Squeezebox" msgstr "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:25 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 "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Export playlist to Squeezebox" msgstr "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:80 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 "" "Playback follows your selection, or the next song in the list once exhausted." msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:22 msgid "Playcount Equalizer" msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:23 msgid "Shuffle, preferring songs with fewer total plays." msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:25 #, fuzzy msgid "Prefer less played" msgstr "last played" #: ../quodlibet/ext/playorder/queue.py:19 #, fuzzy msgid "Queue Only" msgstr "_Queue" #: ../quodlibet/ext/playorder/queue.py:21 msgid "" "Limits playing of songs to the queue. Select this play order in the main " "window, then double-clicking any song will enqueue it instead of playing." msgstr "" #: ../quodlibet/ext/playorder/reverse.py:14 #, fuzzy msgid "Reverse" msgstr "Never" #: ../quodlibet/ext/playorder/reverse.py:16 msgid "Reverses the play order of songs." msgstr "" #: ../quodlibet/ext/playorder/skip_songs.py:25 #, fuzzy msgid "Skip Songs" msgstr "skip count" #: ../quodlibet/ext/playorder/skip_songs.py:27 msgid "" "Playback skips over songs with a rating equal or below a given threshold." msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:30 msgid "Repeat Each Track" msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:32 msgid "Shuffle songs, but repeat every track a set number of times." msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:51 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. Syntax is '@(if: " "condition, then, else)'." msgstr "" #: ../quodlibet/ext/query/pythonexpression.py:14 msgid "Python Query" msgstr "" #: ../quodlibet/ext/query/pythonexpression.py:15 msgid "" "Use Python expressions in queries. Syntax is '@(python: expression)'. The " "variable 's' is the song being matched." msgstr "" #: ../quodlibet/ext/query/savedsearch.py:19 #, fuzzy msgid "Include Saved Search" msgstr "Saved Values" #: ../quodlibet/ext/query/savedsearch.py:20 msgid "" "Include the results of a saved search as part of another query. Syntax is " "'@(saved: search name)'." 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:116 msgid "Port:" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:121 #, fuzzy msgid "Username:" msgstr "_Rename" #: ../quodlibet/ext/_shared/squeezebox/base.py:126 msgid "Password:" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:130 msgid "Library directory the server connects to." msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:132 #, fuzzy msgid "Library path:" msgstr "Library" #. Add verify button #: ../quodlibet/ext/_shared/squeezebox/base.py:141 msgid "_Verify settings" msgstr "" #. Server settings Frame #: ../quodlibet/ext/_shared/squeezebox/base.py:147 msgid "Squeezebox Server" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:150 msgid "Debug" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:26 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:28 msgid "unidentified Squeezebox server" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:37 #, 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:20 #: ../quodlibet/ext/songsmenu/importexport.py:34 #: ../quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:329 #, fuzzy msgid "Fit image to _window" msgstr "Hide main window" #. Both labels #: ../quodlibet/ext/songsmenu/albumart.py:338 msgid "_Program:" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:343 msgid "_Edit image after saving" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:345 #, fuzzy msgid "File_name:" msgstr "Filename" #: ../quodlibet/ext/songsmenu/albumart.py:457 msgid "Saving failed" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:458 #, fuzzy, python-format msgid "Unable to save \"%s\"." msgstr "Unable to save song" #: ../quodlibet/ext/songsmenu/albumart.py:556 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:613 #, fuzzy msgid "Album Art Downloader" msgstr "Album List" #: ../quodlibet/ext/songsmenu/albumart.py:666 #, python-format msgid "from %(source)s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:669 #, python-format msgid "Resolution: %s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:672 #, fuzzy, python-format msgid "Size: %s" msgstr "Size" #: ../quodlibet/ext/songsmenu/albumart.py:690 #, fuzzy msgid "_Search" msgstr "_Search:" #: ../quodlibet/ext/songsmenu/albumart.py:741 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:451 #, fuzzy msgid "Searching…" msgstr "Search" #: ../quodlibet/ext/songsmenu/albumart.py:804 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:922 #, fuzzy msgid "Download Album Art" msgstr "Album List" #: ../quodlibet/ext/songsmenu/albumart.py:923 msgid "Downloads album covers from various websites." msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:936 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 #: ../quodlibet/qltk/downloader.py:52 msgid "Filename" msgstr "Filename" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:130 #, fuzzy msgid "Disc" msgstr "_Disc" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:131 #: ../quodlibet/ext/songsmenu/replaygain.py:404 #: ../quodlibet/qltk/tracknumbers.py:92 msgid "Track" msgstr "Track" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:132 #, 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:447 msgid "Please enter a query." msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:465 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:496 msgid "Error encountered. Please retry." msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:472 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:488 msgid "Loading result…" msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:475 #, fuzzy msgid "No results found." msgstr "No plugins found." #: ../quodlibet/ext/songsmenu/browsefolders.py:159 #, fuzzy msgid "Browse Folders" msgstr "Browsers" #: ../quodlibet/ext/songsmenu/browsefolders.py:160 msgid "Opens the songs' folders in a file manager." msgstr "" #: ../quodlibet/ext/songsmenu/browsefolders.py:172 #, fuzzy msgid "Unable to open folders" msgstr "Unable to create folder" #: ../quodlibet/ext/songsmenu/browsefolders.py:173 msgid "No program available to open folders." msgstr "" #: ../quodlibet/ext/songsmenu/console.py:40 msgid "Python Console" msgstr "" #: ../quodlibet/ext/songsmenu/console.py:41 msgid "Interactive Python console." msgstr "" #: ../quodlibet/ext/songsmenu/console.py:72 msgid "You can access the following objects by default:" msgstr "" #: ../quodlibet/ext/songsmenu/console.py:82 msgid "Your current working directory is:" 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:55 msgid "pattern" msgstr "pattern" #: ../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:91 #, fuzzy msgid "Input value" msgstr "Invalid value" #: ../quodlibet/ext/songsmenu/custom_commands.py:92 #, python-format msgid "Value for %s?" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:136 #, fuzzy msgid "Custom Commands" msgstr "_Custom" #: ../quodlibet/ext/songsmenu/custom_commands.py:137 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:188 #: ../quodlibet/ext/songsmenu/custom_commands.py:198 #: ../quodlibet/ext/songsmenu/custom_commands.py:252 msgid "Edit Custom Commands" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:199 msgid "" "Supports QL patterns\n" "eg <tt><~artist~title></tt>" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:283 #, fuzzy, python-format msgid "Unable to run custom command %s" msgstr "Unable to copy songs" #: ../quodlibet/ext/songsmenu/duplicates.py:290 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "" msgstr[1] "" #: ../quodlibet/ext/songsmenu/duplicates.py:343 msgid "Collapse / Expand all" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:347 #, python-format msgid "Duplicate key expression is '%s'" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:363 #, fuzzy msgid "Duplicates Browser" msgstr "Disable Browser" #: ../quodlibet/ext/songsmenu/duplicates.py:364 msgid "Finds and displays similarly tagged versions of songs." msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:407 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:409 msgid "_Group duplicates by:" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:414 #, fuzzy msgid "Duplicate Key" msgstr "Remove selected tag" #: ../quodlibet/ext/songsmenu/duplicates.py:419 #, fuzzy msgid "Remove _Whitespace" msgstr "Remove selected tag" #: ../quodlibet/ext/songsmenu/duplicates.py:420 #, fuzzy msgid "Remove _Diacritics" msgstr "Remove selected tag" #: ../quodlibet/ext/songsmenu/duplicates.py:421 #, fuzzy msgid "Remove _Punctuation" msgstr "_Remove Station" #: ../quodlibet/ext/songsmenu/duplicates.py:422 msgid "Case _Insensitive" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:430 msgid "Matching options" msgstr "" #. Create a dialog. #: ../quodlibet/ext/songsmenu/editplaycount.py:19 #: ../quodlibet/ext/songsmenu/editplaycount.py:41 #, fuzzy msgid "Edit Playcount" msgstr "Edit Display" #: ../quodlibet/ext/songsmenu/editplaycount.py:20 msgid "" "Edit a song's ~#playcount and ~#skipcount.\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's ~#playcount to 0, the ~#lastplayed and ~#laststarted " "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:68 msgid "Play Count" msgstr "" #: ../quodlibet/ext/songsmenu/editplaycount.py:69 #, fuzzy msgid "Skip Count" msgstr "skip count" #: ../quodlibet/ext/songsmenu/embedded.py:24 #, fuzzy msgid "Edit Embedded Images" msgstr "Remove selected tag" #: ../quodlibet/ext/songsmenu/embedded.py:25 #, fuzzy msgid "Removes or replaces embedded images." msgstr "Remove selected tag" #: ../quodlibet/ext/songsmenu/embedded.py:78 #, fuzzy msgid "_Remove all Images" msgstr "Remove selected tag" #: ../quodlibet/ext/songsmenu/embedded.py:82 #, fuzzy msgid "_Embed Current Image" msgstr "Remove selected tag" #: ../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:41 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 #: ../quodlibet/qltk/downloader.py:67 #, 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" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" 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 "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:49 msgid "Generating fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:63 msgid "_Details" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:85 msgid "_Submit" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:115 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:118 msgid "Fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Songs with MBIDs:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with sufficient tags:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs to submit:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:162 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:178 msgid "Submitting fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:186 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/id3tlen.py:21 msgid "Fix MP3 Duration" msgstr "" #: ../quodlibet/ext/songsmenu/id3tlen.py:22 msgid "" "Removes TLEN frames from ID3 tags which can be the cause for invalid song " "durations." msgstr "" #: ../quodlibet/ext/songsmenu/ifp.py:20 msgid "Send to iFP" msgstr "" #: ../quodlibet/ext/songsmenu/ifp.py:21 msgid "Uploads songs to an iRiver iFP device." msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:51 msgid "Export Metadata" msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:52 msgid "Exports metadata of selected songs as a .tags file." msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:92 #, fuzzy msgid "Import Metadata" msgstr "Import Playlist" #: ../quodlibet/ext/songsmenu/importexport.py:93 msgid "Imports metadata for selected songs from a .tags file." msgstr "" #: ../quodlibet/ext/songsmenu/k3b.py:23 msgid "Burn CD" msgstr "" #: ../quodlibet/ext/songsmenu/k3b.py:24 msgid "Burns CDs with K3b, Brasero or xfburn." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:96 msgid "Updating chart list." msgstr "" #. No charts to fetch, no update scheduled. #: ../quodlibet/ext/songsmenu/lastfmsync.py:114 msgid "Already up-to-date." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:121 #, python-format msgid "Fetching chart for week of %s." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:143 msgid "Sync complete." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:149 msgid "Error during sync" msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:214 #: ../quodlibet/ext/songsmenu/lastfmsync.py:244 msgid "Last.fm Sync" msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:245 msgid "Updates your library's statistics from your Last.fm profile." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:293 #, 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 "" #. Create a dialog. #: ../quodlibet/ext/songsmenu/migratemetadata.py:29 #: ../quodlibet/ext/songsmenu/migratemetadata.py:38 #, fuzzy msgid "Migrate Metadata" msgstr "Import Playlist" #: ../quodlibet/ext/songsmenu/migratemetadata.py:32 msgid "Copies the quodlibet-specific metadata between songs." msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:45 msgid "_Copy" msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:47 msgid "_Paste" msgstr "" #. Create the tag table. #: ../quodlibet/ext/songsmenu/migratemetadata.py:57 #, fuzzy msgid "Information to copy/paste" msgstr "Information" #. Create the indexing box. #: ../quodlibet/ext/songsmenu/migratemetadata.py:79 msgid "Map tracks by disc and track number" msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:80 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 "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:96 #, python-format msgid "There is %d stored track." msgid_plural "There are %d stored tracks." msgstr[0] "" msgstr[1] "" #: ../quodlibet/ext/songsmenu/playlist.py:31 #, fuzzy msgid "Export as Playlist" msgstr "Import Playlist" #: ../quodlibet/ext/songsmenu/playlist.py:32 msgid "Exports songs to an M3U or PLS playlist." msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:77 msgid "Use relative paths" msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:77 msgid "Use absolute paths" msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:132 #, fuzzy msgid "Unable to export playlist" msgstr "Unable to import playlist" #: ../quodlibet/ext/songsmenu/playlist.py:133 #, fuzzy, python-format msgid "Writing to <b>%s</b> 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:362 msgid "ReplayGain Analyzer" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:418 msgid "Progress" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:433 msgid "Gain" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:448 msgid "Peak" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:463 #, python-format msgid "There is <b>%(to-process)s</b> album to update (of %(all)s)" msgid_plural "There are <b>%(to-process)s</b> albums to update (of %(all)s)" msgstr[0] "" msgstr[1] "" #: ../quodlibet/ext/songsmenu/replaygain.py:578 msgid "Replay Gain" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:579 msgid "" "Analyzes and updates ReplayGain information, using GStreamer. Results are " "grouped by album." msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:617 msgid "always" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:618 msgid "if <b>any</b> RG tags are missing" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:620 msgid "if <b>album</b> RG tags are missing" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:637 msgid "_Process albums:" msgstr "" #. Server settings Frame #: ../quodlibet/ext/songsmenu/replaygain.py:649 #, 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 "" #. TRANSLATORS: BPM mean "beats per minute" #: ../quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "" #: ../quodlibet/ext/songsmenu/tapbpm.py:32 #: ../quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" 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:172 #: ../quodlibet/ext/songsmenu/tapbpm.py:179 msgid "Tap BPM" msgstr "" #: ../quodlibet/ext/songsmenu/tapbpm.py:173 #, fuzzy msgid "Tap BPM for the selected song." msgstr "Unable to delete songs" #: ../quodlibet/ext/songsmenu/website_search.py:35 #, fuzzy msgid "Website Search" msgstr "Search" #: ../quodlibet/ext/songsmenu/website_search.py:36 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern-example)s." msgstr "" #: ../quodlibet/ext/songsmenu/website_search.py:78 #, fuzzy msgid "Search URL patterns" msgstr "Invalid Pattern" #: ../quodlibet/ext/songsmenu/website_search.py:88 #, fuzzy msgid "Edit search URLs" msgstr "Edit saved values..." #. Add link to editor #: ../quodlibet/ext/songsmenu/website_search.py:114 #, fuzzy msgid "Configure Searches…" msgstr "Colour _search terms" #: ../quodlibet/ext/songsmenu/wikipedia.py:46 #, python-format msgid "Search at %(website)s" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:63 msgid "Search Artist in Wikipedia" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:64 msgid "" "Opens a browser window with Wikipedia article on the playing song artist." msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:71 msgid "Search Album in Wikipedia" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:72 msgid "" "Opens a browser window with Wikipedia article on the playing song album." msgstr "" #. then (try to) load all new files #: ../quodlibet/library/libraries.py:650 ../quodlibet/library/libraries.py:660 #: ../quodlibet/library/libraries.py:726 ../quodlibet/library/libraries.py:745 #: ../quodlibet/qltk/information.py:268 ../quodlibet/qltk/prefs.py:639 #: ../quodlibet/util/library.py:124 msgid "Library" msgstr "Library" #: ../quodlibet/library/libraries.py:650 msgid "Checking mount points" msgstr "Checking mount points" #: ../quodlibet/library/libraries.py:660 msgid "Scanning library" msgstr "Scanning library" #: ../quodlibet/library/libraries.py:725 #, python-format msgid "Scanning %s" msgstr "Scanning %s" #: ../quodlibet/library/libraries.py:745 msgid "Loading files" msgstr "" #: ../quodlibet/operon/base.py:70 #, python-format msgid "Failed to load file: %r" msgstr "" #: ../quodlibet/operon/commands.py:37 msgid "List tags" msgstr "" #: ../quodlibet/operon/commands.py:42 ../quodlibet/operon/commands.py:81 #: ../quodlibet/operon/commands.py:461 msgid "Print terse output" msgstr "" #: ../quodlibet/operon/commands.py:44 ../quodlibet/operon/commands.py:83 #: ../quodlibet/operon/commands.py:463 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "" #: ../quodlibet/operon/commands.py:47 ../quodlibet/operon/commands.py:86 #, fuzzy msgid "Also list programmatic tags" msgstr "Show _programmatic tags" #: ../quodlibet/operon/commands.py:51 ../quodlibet/operon/commands.py:129 #: ../quodlibet/operon/commands.py:220 ../quodlibet/operon/commands.py:293 #: ../quodlibet/operon/commands.py:336 ../quodlibet/operon/commands.py:340 #: ../quodlibet/operon/commands.py:391 ../quodlibet/operon/commands.py:394 #: ../quodlibet/operon/commands.py:433 ../quodlibet/operon/commands.py:468 #: ../quodlibet/operon/commands.py:508 ../quodlibet/operon/commands.py:543 #: ../quodlibet/operon/commands.py:585 msgid "Not enough arguments" msgstr "" #: ../quodlibet/operon/commands.py:53 ../quodlibet/operon/commands.py:90 #: ../quodlibet/operon/commands.py:131 ../quodlibet/operon/commands.py:222 #: ../quodlibet/operon/commands.py:470 msgid "Too many arguments" msgstr "" #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:92 #: ../quodlibet/operon/commands.py:475 ../quodlibet/qltk/data_editors.py:363 #, fuzzy msgid "Description" msgstr "Description" #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:475 #: ../quodlibet/qltk/edittags.py:454 msgid "Value" msgstr "Value" #: ../quodlibet/operon/commands.py:76 msgid "List all common tags" msgstr "" #: ../quodlibet/operon/commands.py:118 msgid "Copy tags from one file to another" msgstr "" #: ../quodlibet/operon/commands.py:123 ../quodlibet/operon/commands.py:164 #: ../quodlibet/operon/commands.py:289 ../quodlibet/operon/commands.py:324 #: ../quodlibet/operon/commands.py:384 msgid "Show changes, don't apply them" msgstr "" #: ../quodlibet/operon/commands.py:125 msgid "Skip tags that can't be written" msgstr "" #: ../quodlibet/operon/commands.py:145 #, python-format msgid "Can't copy tag %r to file: %r" 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:304 ../quodlibet/operon/commands.py:444 #: ../quodlibet/operon/commands.py:676 #, python-format msgid "Can not set %r" msgstr "" #: ../quodlibet/operon/commands.py:319 #, fuzzy msgid "Remove tags" msgstr "_Remove Station" #: ../quodlibet/operon/commands.py:326 ../quodlibet/operon/commands.py:386 msgid "Value is a regular expression" msgstr "" #: ../quodlibet/operon/commands.py:328 #, fuzzy msgid "Remove all tags" msgstr "Remove selected tag" #: ../quodlibet/operon/commands.py:332 msgid "Can't combine '--all' with '--regexp'" msgstr "" #: ../quodlibet/operon/commands.py:366 #, python-format msgid "Can't remove %r from %r" msgstr "" #: ../quodlibet/operon/commands.py:379 #, fuzzy msgid "Remove a tag value" msgstr "Filter on a tag value" #: ../quodlibet/operon/commands.py:428 #, fuzzy msgid "Add a tag value" msgstr "Filter on a tag value" #: ../quodlibet/operon/commands.py:456 #, fuzzy msgid "List file information" msgstr "No time information" #: ../quodlibet/operon/commands.py:502 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" #: ../quodlibet/operon/commands.py:515 #, fuzzy, python-format msgid "Failed to load image file: %r" msgstr "Unable to rename file" #: ../quodlibet/operon/commands.py:522 ../quodlibet/operon/commands.py:551 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" #: ../quodlibet/operon/commands.py:538 #, fuzzy msgid "Remove all embedded images" msgstr "Remove selected tag" #: ../quodlibet/operon/commands.py:568 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "" #: ../quodlibet/operon/commands.py:580 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" #: ../quodlibet/operon/commands.py:639 msgid "Rename files based on tags" msgstr "" #: ../quodlibet/operon/commands.py:654 msgid "Fill tags based on the file path" msgstr "" #: ../quodlibet/operon/commands.py:704 ../quodlibet/qltk/information.py:305 #: ../quodlibet/qltk/properties.py:84 ../quodlibet/qltk/renamefiles.py:176 #: ../quodlibet/qltk/tagsfrompath.py:229 ../quodlibet/qltk/tracknumbers.py:79 msgid "File" msgstr "File" #: ../quodlibet/operon/commands.py:712 msgid "Fill tracknumbers for all files" msgstr "" #: ../quodlibet/operon/commands.py:731 msgid "Print tags based on the given pattern" msgstr "" #: ../quodlibet/operon/commands.py:768 #, fuzzy msgid "Display help information" msgstr "Display brief usage information" #: ../quodlibet/operon/util.py:40 #, 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:30 #, fuzzy msgid "_Unknown" msgstr "Unknown" #: ../quodlibet/order/__init__.py:142 msgid "In Order" msgstr "In Order" #: ../quodlibet/order/__init__.py:143 msgid "_In Order" msgstr "_In Order" #: ../quodlibet/order/reorder.py:23 #, fuzzy msgid "Random" msgstr "_Random" #: ../quodlibet/order/reorder.py:24 ../quodlibet/qltk/queue.py:119 msgid "_Random" msgstr "_Random" #: ../quodlibet/order/reorder.py:39 ../quodlibet/order/reorder.py:40 msgid "Prefer higher rated" msgstr "" #: ../quodlibet/order/repeat.py:43 ../quodlibet/order/repeat.py:44 msgid "Repeat this track" msgstr "" #: ../quodlibet/order/repeat.py:57 ../quodlibet/order/repeat.py:58 #, fuzzy msgid "Repeat all" msgstr "_Repeat" #: ../quodlibet/order/repeat.py:73 ../quodlibet/order/repeat.py:74 msgid "One Song" msgstr "One Song" #: ../quodlibet/player/gstbe/player.py:98 msgid "Stream" msgstr "" #: ../quodlibet/player/gstbe/player.py:98 msgid "Buffering" msgstr "" #: ../quodlibet/player/gstbe/player.py:319 msgid "Could not create GStreamer pipeline" msgstr "" #: ../quodlibet/player/gstbe/player.py:560 msgid "No GStreamer element found to handle media format" msgstr "" #: ../quodlibet/player/gstbe/player.py:561 #, 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:25 msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. In case the pipeline contains a sink, it will be used instead of " "the default one." msgstr "" #: ../quodlibet/player/gstbe/prefs.py:36 msgid "_Output pipeline:" msgstr "" #: ../quodlibet/player/gstbe/prefs.py:43 #, fuzzy, python-format msgid "%.1f seconds" msgstr "1 second" #: ../quodlibet/player/gstbe/prefs.py:57 msgid "_Buffer duration:" msgstr "" #: ../quodlibet/player/gstbe/prefs.py:66 msgid "Disable _gapless playback" msgstr "" #: ../quodlibet/player/gstbe/prefs.py:70 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions." msgstr "" #: ../quodlibet/player/gstbe/util.py:93 #, fuzzy msgid "No GStreamer audio sink found" msgstr "No audio device found" #: ../quodlibet/player/gstbe/util.py:112 msgid "Invalid GStreamer output pipeline" msgstr "" #: ../quodlibet/player/xinebe/player.py:90 #, fuzzy msgid "Unable to create audio output" msgstr "Unable to create folder" #: ../quodlibet/player/xinebe/player.py:91 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "" #: ../quodlibet/plugins/__init__.py:62 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" #: ../quodlibet/plugins/__init__.py:71 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "" #: ../quodlibet/plugins/playlist.py:30 #, 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:41 ../quodlibet/qltk/songsmenu.py:46 #: ../quodlibet/qltk/songsmenu.py:74 #, fuzzy msgid "_Run Plugin" msgstr "_Plugins" #: ../quodlibet/qltk/about.py:40 #, python-format msgid "Supported formats: %s" msgstr "Supported formats: %s" #: ../quodlibet/qltk/about.py:43 #, python-format msgid "Audio device: %s" msgstr "Audio device: %s" #. 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:207 ../quodlibet/qltk/information.py:131 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:48 ../quodlibet/qltk/edittags.py:311 msgid "_Value:" msgstr "_Value:" #: ../quodlibet/qltk/cbes.py:262 msgid "Saved Values" msgstr "Saved Values" #: ../quodlibet/qltk/cbes.py:263 #, fuzzy msgid "Edit saved values…" msgstr "Edit saved values..." #: ../quodlibet/qltk/controls.py:111 msgid "Auto_matic" msgstr "" #: ../quodlibet/qltk/controls.py:112 #, fuzzy msgid "_Track Mode" msgstr "_Track Headers" #: ../quodlibet/qltk/controls.py:113 #, fuzzy msgid "_Album Mode" msgstr "_Album Headers" #. Translators: player state, no action #: ../quodlibet/qltk/controls.py:122 msgid "_Mute" msgstr "" #: ../quodlibet/qltk/controls.py:128 #, fuzzy msgid "_Replay Gain Mode" msgstr "_Replay Gain volume adjustment" #. Translators: New Command/Entry/Item/... #: ../quodlibet/qltk/data_editors.py:119 #, python-format msgid "New %s" msgstr "" #: ../quodlibet/qltk/data_editors.py:218 #, fuzzy msgid "(unknown)" msgstr "Unknown" #: ../quodlibet/qltk/data_editors.py:355 msgid "Tag expression" msgstr "" #: ../quodlibet/qltk/data_editors.py:382 msgid "Tag expression e.g. people:real or ~album~year." msgstr "" #: ../quodlibet/qltk/data_editors.py:383 #, fuzzy msgid "Enter new tag" msgstr "Filter on a tag value" #: ../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/downloader.py:38 msgid "Downloads" msgstr "Downloads" #: ../quodlibet/qltk/downloader.py:62 msgid "Size" msgstr "Size" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: ../quodlibet/qltk/downloader.py:94 ../quodlibet/qltk/renamefiles.py:265 #: ../quodlibet/qltk/wlw.py:50 msgid "_Stop" msgstr "" #: ../quodlibet/qltk/edittags.py:63 ../quodlibet/qltk/edittags.py:74 #, 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:67 ../quodlibet/qltk/edittags.py:71 #, 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:193 msgid "Split into _Multiple Values" msgstr "Split into _Multiple Values" #: ../quodlibet/qltk/edittags.py:211 msgid "Split Disc out of _Album" msgstr "Split Disc out of _Album" #: ../quodlibet/qltk/edittags.py:228 msgid "Split _Version out of Title" msgstr "Split _Version out of Title" #: ../quodlibet/qltk/edittags.py:259 msgid "Split Arranger out of Ar_tist" msgstr "Split Arranger out of Ar_tist" #: ../quodlibet/qltk/edittags.py:264 msgid "Split _Performer out of Artist" msgstr "Split _Performer out of Artist" #: ../quodlibet/qltk/edittags.py:270 #, fuzzy msgid "Split _Performer out of Title" msgstr "Split _Performer out of Artist" #: ../quodlibet/qltk/edittags.py:276 #, fuzzy msgid "Split _Originalartist out of Title" msgstr "Split _Version out of Title" #: ../quodlibet/qltk/edittags.py:283 msgid "Add a Tag" msgstr "Add a Tag" #: ../quodlibet/qltk/edittags.py:302 msgid "_Tag:" msgstr "_Tag:" #: ../quodlibet/qltk/edittags.py:404 msgid "Edit Tags" msgstr "Edit Tags" #: ../quodlibet/qltk/edittags.py:477 msgid "Show _programmatic tags" msgstr "Show _programmatic tags" #: ../quodlibet/qltk/edittags.py:478 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" #. Translators: Revert button in the tag editor #: ../quodlibet/qltk/edittags.py:508 #, fuzzy msgctxt "edittags" msgid "_Revert" msgstr "Never" #. Translators: Save button in the tag editor #: ../quodlibet/qltk/edittags.py:513 msgctxt "edittags" msgid "_Save" msgstr "" #: ../quodlibet/qltk/edittags.py:659 msgid "Unable to add tag" msgstr "Unable to add tag" #: ../quodlibet/qltk/edittags.py:660 #, fuzzy, python-format msgid "Unable to add <b>%s</b>" msgstr "Unable to add song" #: ../quodlibet/qltk/edittags.py:662 #, fuzzy, python-format msgid "" "The files currently selected do not support multiple values for <b>%s</b>." 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:689 ../quodlibet/qltk/edittags.py:856 #: ../quodlibet/qltk/tagsfrompath.py:212 ../quodlibet/util/__init__.py:554 #: ../quodlibet/util/tags.py:231 msgid "Invalid tag" msgstr "Invalid tag" #: ../quodlibet/qltk/edittags.py:690 ../quodlibet/qltk/edittags.py:857 #: ../quodlibet/qltk/tagsfrompath.py:213 #, python-format msgid "" "Invalid tag <b>%s</b>\n" "\n" "The files currently selected do not support editing this tag." msgstr "" "Invalid tag <b>%s</b>\n" "\n" "The files currently selected do not support editing this tag." #: ../quodlibet/qltk/edittags.py:828 ../quodlibet/qltk/edittags.py:868 msgid "Invalid value" msgstr "Invalid value" #: ../quodlibet/qltk/edittags.py:829 ../quodlibet/qltk/edittags.py:869 #, python-format msgid "" "Invalid value: <b>%(value)s</b>\n" "\n" "%(error)s" msgstr "" "Invalid value: <b>%(value)s</b>\n" "\n" "%(error)s" #: ../quodlibet/qltk/_editutils.py:28 msgid "Tag may not be accurate" msgstr "Tag may not be accurate" #: ../quodlibet/qltk/_editutils.py:31 #, 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:47 msgid "Unable to save song" msgstr "Unable to save song" #: ../quodlibet/qltk/_editutils.py:50 #, 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:142 #, 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:95 #: ../quodlibet/qltk/quodlibetwindow.py:1066 msgid "_About" msgstr "_About" #: ../quodlibet/qltk/exfalsowindow.py:99 #: ../quodlibet/qltk/quodlibetwindow.py:1088 msgid "_Check for Updates…" msgstr "" #: ../quodlibet/qltk/exfalsowindow.py:105 #: ../quodlibet/qltk/quodlibetwindow.py:1021 ../quodlibet/qltk/songsmenu.py:304 msgid "_Plugins" msgstr "_Plugins" #: ../quodlibet/qltk/exfalsowindow.py:267 #, 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:279 msgid "Ex Falso Preferences" msgstr "Ex Falso Preferences" #: ../quodlibet/qltk/exfalsowindow.py:289 ../quodlibet/qltk/prefs.py:598 msgid "Split _on:" msgstr "Split _on:" #: ../quodlibet/qltk/exfalsowindow.py:295 ../quodlibet/qltk/prefs.py:613 msgid "Tag Editing" msgstr "Tag Editing" #: ../quodlibet/qltk/filesel.py:210 msgid "Folders" msgstr "Folders" #: ../quodlibet/qltk/filesel.py:253 #, fuzzy msgid "_New Folder…" msgstr "New Folder" #: ../quodlibet/qltk/filesel.py:262 #, fuzzy msgid "_Select all Sub-Folders" msgstr "_Select All Subfolders" #: ../quodlibet/qltk/filesel.py:374 msgid "New Folder" msgstr "New Folder" #: ../quodlibet/qltk/filesel.py:374 msgid "Enter a name for the new folder:" msgstr "Enter a name for the new folder:" #: ../quodlibet/qltk/filesel.py:387 msgid "Unable to create folder" msgstr "Unable to create folder" #: ../quodlibet/qltk/filesel.py:404 msgid "Unable to delete folder" msgstr "Unable to delete folder" #: ../quodlibet/qltk/filesel.py:519 ../quodlibet/qltk/pluginwin.py:167 msgid "Songs" msgstr "Songs" #. Translators: As in "by Artist Name" #: ../quodlibet/qltk/info.py:42 #, python-format msgid "by %s" msgstr "by %s" #: ../quodlibet/qltk/info.py:43 ../quodlibet/qltk/information.py:167 #: ../quodlibet/qltk/information.py:448 #, python-format msgid "Disc %s" msgstr "Disc %s" #: ../quodlibet/qltk/info.py:44 ../quodlibet/qltk/information.py:172 #, python-format msgid "Track %s" msgstr "Track %s" #: ../quodlibet/qltk/info.py:108 #, fuzzy msgid "_Edit Display…" msgstr "Edit Display" #: ../quodlibet/qltk/information.py:105 msgid "No songs are selected." msgstr "No songs are selected." #: ../quodlibet/qltk/information.py:106 msgid "No Songs" msgstr "No Songs" #: ../quodlibet/qltk/information.py:121 ../quodlibet/qltk/information.py:338 #: ../quodlibet/qltk/information.py:471 ../quodlibet/qltk/information.py:531 msgid "Information" msgstr "Information" #: ../quodlibet/qltk/information.py:126 msgid "Lyrics" msgstr "Lyrics" #: ../quodlibet/qltk/information.py:184 ../quodlibet/qltk/information.py:396 #, python-format msgid "Produced by %s" msgstr "Produced by %s" #: ../quodlibet/qltk/information.py:199 ../quodlibet/util/tags.py:76 msgid "artist" msgstr "artist" #: ../quodlibet/qltk/information.py:200 ../quodlibet/qltk/information.py:561 #: ../quodlibet/util/tags.py:76 msgid "artists" msgstr "artists" #. for backwards compat #: ../quodlibet/qltk/information.py:221 ../quodlibet/util/tags.py:86 #: ../quodlibet/util/tags.py:114 msgid "performers" msgstr "performers" #: ../quodlibet/qltk/information.py:235 ../quodlibet/qltk/information.py:248 #: ../quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "Never" #: ../quodlibet/qltk/information.py:236 #, fuzzy, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "%d time" msgstr[1] "%d times" #: ../quodlibet/qltk/information.py:254 ../quodlibet/util/tags.py:139 msgid "added" msgstr "added" #: ../quodlibet/qltk/information.py:255 ../quodlibet/util/tags.py:140 msgid "last played" msgstr "last played" #: ../quodlibet/qltk/information.py:256 ../quodlibet/util/tags.py:150 msgid "plays" msgstr "plays" #: ../quodlibet/qltk/information.py:257 ../quodlibet/util/tags.py:151 msgid "skips" msgstr "skips" #: ../quodlibet/qltk/information.py:258 ../quodlibet/util/tags.py:156 msgid "rating" msgstr "rating" #: ../quodlibet/qltk/information.py:287 msgid "path" msgstr "" #: ../quodlibet/qltk/information.py:288 ../quodlibet/util/tags.py:154 msgid "length" msgstr "length" #: ../quodlibet/qltk/information.py:289 #, fuzzy msgid "format" msgstr "Information" #: ../quodlibet/qltk/information.py:290 ../quodlibet/util/tags.py:163 msgid "codec" msgstr "" #: ../quodlibet/qltk/information.py:291 ../quodlibet/util/tags.py:164 #, fuzzy msgid "encoding" msgstr "[Invalid Encoding]" #: ../quodlibet/qltk/information.py:292 ../quodlibet/util/tags.py:160 msgid "bitrate" msgstr "bitrate" #: ../quodlibet/qltk/information.py:293 ../quodlibet/util/tags.py:161 msgid "file size" msgstr "file size" #: ../quodlibet/qltk/information.py:294 ../quodlibet/util/tags.py:149 msgid "modified" msgstr "modified" #: ../quodlibet/qltk/information.py:331 msgid "Additional" msgstr "" #: ../quodlibet/qltk/information.py:383 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d selected" msgstr[1] "%d selected" #: ../quodlibet/qltk/information.py:458 msgid "Track unavailable" msgstr "Track unavailable" #: ../quodlibet/qltk/information.py:464 msgid "Track List" msgstr "Track List" #: ../quodlibet/qltk/information.py:505 ../quodlibet/qltk/information.py:578 #, 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:508 msgid "Selected Discography" msgstr "Selected Discography" #: ../quodlibet/qltk/information.py:558 #, 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:586 ../quodlibet/util/tags.py:74 msgid "albums" msgstr "albums" #: ../quodlibet/qltk/information.py:599 msgid "Total length:" msgstr "Total length:" #: ../quodlibet/qltk/information.py:603 msgid "Total size:" msgstr "Total size:" #: ../quodlibet/qltk/information.py:606 msgid "Files" msgstr "Files" #: ../quodlibet/qltk/lyrics.py:37 msgid "_Download" msgstr "_Download" #: ../quodlibet/qltk/lyrics.py:40 #, fuzzy msgid "_Edit" msgstr "_Edit Display..." #. buffer.set_text(_("No lyrics found.\n\nYou can click the " #. "Download button to have Quod Libet search " #. "for lyrics online. You can also enter them " #. "yourself and click save.")) #: ../quodlibet/qltk/lyrics.py:73 ../quodlibet/qltk/lyrics.py:109 msgid "No lyrics found for this song." msgstr "No lyrics found for this song." #: ../quodlibet/qltk/lyrics.py:82 #, fuzzy msgid "Searching for lyrics…" msgstr "Searching for lyrics..." #: ../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/msg.py:41 msgid "Discard tag changes?" msgstr "Discard tag changes?" #: ../quodlibet/qltk/msg.py:42 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:55 ../quodlibet/qltk/prefs.py:595 #: ../quodlibet/qltk/textedit.py:64 ../quodlibet/qltk/tracknumbers.py:117 #, fuzzy msgid "_Revert" msgstr "Never" #: ../quodlibet/qltk/msg.py:86 msgid "File exists" msgstr "File exists" #: ../quodlibet/qltk/msg.py:88 #, python-format msgid "Replace %(file-name)s?" msgstr "" #: ../quodlibet/qltk/msg.py:94 #, fuzzy msgid "_Replace File" msgstr "Rename Files" #: ../quodlibet/qltk/notif.py:182 msgid "Active tasks" msgstr "" #: ../quodlibet/qltk/notif.py:188 #, fuzzy, python-format msgid "%d tasks running" msgstr "Quod Libet is running" #: ../quodlibet/qltk/playorder.py:254 #, fuzzy msgid "Toggle shuffle mode" msgstr "Toggle play/pause mode" #: ../quodlibet/qltk/playorder.py:270 #, fuzzy msgid "Toggle repeat mode" msgstr "Toggle play/pause mode" #: ../quodlibet/qltk/pluginwin.py:44 msgid "Plugin Errors" msgstr "Plugin Errors" #: ../quodlibet/qltk/pluginwin.py:124 msgid "Enabled" msgstr "" #: ../quodlibet/qltk/pluginwin.py:125 #, fuzzy msgid "Disabled" msgstr "Disable Browser" #: ../quodlibet/qltk/pluginwin.py:131 msgid "No category" msgstr "" #: ../quodlibet/qltk/pluginwin.py:169 msgid "Events" msgstr "" #: ../quodlibet/qltk/pluginwin.py:170 #, fuzzy msgid "Play Order" msgstr "Play _Order" #: ../quodlibet/qltk/pluginwin.py:171 #, fuzzy msgid "Editing" msgstr "Tag Editing" #: ../quodlibet/qltk/pluginwin.py:173 #, fuzzy msgid "Covers" msgstr "Total size:" #: ../quodlibet/qltk/pluginwin.py:309 msgid "No plugins found." msgstr "No plugins found." #: ../quodlibet/qltk/pluginwin.py:358 #, fuzzy msgid "Plugins" msgstr "_Plugins" #: ../quodlibet/qltk/pluginwin.py:402 msgid "Show _Errors" msgstr "Show _Errors" #: ../quodlibet/qltk/prefs.py:45 msgid "_Disc" msgstr "_Disc" #: ../quodlibet/qltk/prefs.py:46 msgid "_Track" msgstr "_Track" #: ../quodlibet/qltk/prefs.py:47 #, fuzzy msgid "Grou_ping" msgstr "grouping" #: ../quodlibet/qltk/prefs.py:50 msgid "Al_bum" msgstr "Al_bum" #: ../quodlibet/qltk/prefs.py:55 msgid "_Filename" msgstr "_Filename" #: ../quodlibet/qltk/prefs.py:57 msgid "_Length" msgstr "_Length" #: ../quodlibet/qltk/prefs.py:64 msgid "_Jump to playing song automatically" msgstr "_Jump to playing song automatically" #: ../quodlibet/qltk/prefs.py:66 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:82 msgid "_Others:" msgstr "_Others: " #: ../quodlibet/qltk/prefs.py:88 #, fuzzy msgid "_Edit…" msgstr "_Edit Display..." #: ../quodlibet/qltk/prefs.py:91 #, fuzzy msgid "Add or remove additional column headers" msgstr "Set and save column headers" #: ../quodlibet/qltk/prefs.py:101 msgid "Visible Columns" msgstr "Visible Columns" #: ../quodlibet/qltk/prefs.py:104 msgid "Title includes _version" msgstr "Title includes _version" #: ../quodlibet/qltk/prefs.py:106 #, fuzzy msgid "Artist includes all _people" msgstr "Title includes _version" #: ../quodlibet/qltk/prefs.py:108 #, fuzzy msgid "Album includes _disc subtitle" msgstr "Album includes _part" #: ../quodlibet/qltk/prefs.py:110 msgid "Filename includes _folder" msgstr "Filename includes _folder" #: ../quodlibet/qltk/prefs.py:123 #, fuzzy msgid "Column Preferences" msgstr "Preferences" #: ../quodlibet/qltk/prefs.py:129 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "" #: ../quodlibet/qltk/prefs.py:142 ../quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Song List" #: ../quodlibet/qltk/prefs.py:222 #, fuzzy msgid "Edit Columns" msgstr "Visible Columns" #: ../quodlibet/qltk/prefs.py:259 msgid "Duration totals" msgstr "" #: ../quodlibet/qltk/prefs.py:271 msgid "_Global filter:" msgstr "_Global filter:" #: ../quodlibet/qltk/prefs.py:277 msgid "Apply this query in addition to all others" msgstr "" #. Translators: The heading of the preference group, no action #: ../quodlibet/qltk/prefs.py:283 #, fuzzy msgctxt "heading" msgid "Search" msgstr "Search" #: ../quodlibet/qltk/prefs.py:287 ../quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Browsers" #: ../quodlibet/qltk/prefs.py:293 msgid "Confirm _multiple ratings" msgstr "" #: ../quodlibet/qltk/prefs.py:295 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "" #: ../quodlibet/qltk/prefs.py:298 msgid "Enable _one-click ratings" msgstr "" #: ../quodlibet/qltk/prefs.py:300 #, 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:306 ../quodlibet/qltk/prefs.py:616 #, fuzzy msgid "Ratings" msgstr "Rating" #. Filename choice algorithm config #: ../quodlibet/qltk/prefs.py:312 msgid "Prefer _embedded art" msgstr "" #: ../quodlibet/qltk/prefs.py:314 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" #: ../quodlibet/qltk/prefs.py:319 msgid "_Fixed image filename:" msgstr "" #: ../quodlibet/qltk/prefs.py:321 msgid "The single image filename to use if selected" msgstr "" #: ../quodlibet/qltk/prefs.py:327 msgid "The album art image file to use when forced" msgstr "" #: ../quodlibet/qltk/prefs.py:336 #, fuzzy msgid "Album Art" msgstr "Album List" #: ../quodlibet/qltk/prefs.py:357 #, fuzzy msgid "Playback" msgstr "Pause playback" #: ../quodlibet/qltk/prefs.py:362 msgid "Output Configuration" msgstr "" #: ../quodlibet/qltk/prefs.py:373 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" #: ../quodlibet/qltk/prefs.py:376 #, fuzzy msgid "_Fall-back gain (dB):" msgstr "_Volume Gain (dB):" #: ../quodlibet/qltk/prefs.py:387 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "" #: ../quodlibet/qltk/prefs.py:390 #, fuzzy msgid "_Pre-amp gain (dB):" msgstr "_Volume Gain (dB):" #: ../quodlibet/qltk/prefs.py:395 #, fuzzy msgid "_Enable Replay Gain volume adjustment" msgstr "_Replay Gain volume adjustment" #: ../quodlibet/qltk/prefs.py:420 #, fuzzy msgid "Replay Gain Volume Adjustment" msgstr "_Replay Gain volume adjustment" #: ../quodlibet/qltk/prefs.py:450 #, fuzzy msgid "_Default rating:" msgstr "Set Rating" #: ../quodlibet/qltk/prefs.py:493 #, fuzzy msgid "Rating _scale:" msgstr "Rating" #: ../quodlibet/qltk/prefs.py:542 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:547 msgid "_Bayesian averaging amount:" msgstr "" #: ../quodlibet/qltk/prefs.py:556 #, fuzzy msgid "Save ratings and play _counts" msgstr "Save ratings and play counts" #: ../quodlibet/qltk/prefs.py:560 msgid "_Email:" msgstr "_Email:" #: ../quodlibet/qltk/prefs.py:562 msgid "Ratings and play counts will be set for this email address" msgstr "Ratings and play counts will be set for this email address" #: ../quodlibet/qltk/prefs.py:577 #, fuzzy msgid "Auto-save tag changes" msgstr "Discard tag changes?" #: ../quodlibet/qltk/prefs.py:579 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "" #: ../quodlibet/qltk/prefs.py:587 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:610 #, fuzzy msgid "Tags" msgstr "Edit Tags" #: ../quodlibet/qltk/prefs.py:631 #, fuzzy msgid "Updating for new ratings" msgstr "_New Station" #: ../quodlibet/qltk/prefs.py:641 #, fuzzy msgid "Scan library _on start" msgstr "Re_fresh Library" #: ../quodlibet/qltk/prefs.py:651 ../quodlibet/qltk/quodlibetwindow.py:1100 #, fuzzy msgid "_Scan Library" msgstr "_Search Library" #: ../quodlibet/qltk/prefs.py:653 ../quodlibet/qltk/quodlibetwindow.py:1162 msgid "Check for changes in your library" msgstr "Check for changes in your library" #: ../quodlibet/qltk/prefs.py:658 #, fuzzy msgid "Re_build Library" msgstr "Re_load Library" #: ../quodlibet/qltk/prefs.py:661 #, 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:671 #, fuzzy msgid "Scan Directories" msgstr "Scan _Directories" #: ../quodlibet/qltk/prefs.py:677 #, fuzzy msgid "Hidden Songs" msgstr "No Songs" #: ../quodlibet/qltk/properties.py:158 ../quodlibet/util/collection.py:398 #, 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:162 ../quodlibet/qltk/properties.py:164 msgid "Properties" msgstr "Properties" #: ../quodlibet/qltk/queue.py:101 msgid "_Queue" msgstr "_Queue" #: ../quodlibet/qltk/queue.py:126 msgid "Stop Once Empty" msgstr "" #: ../quodlibet/qltk/queue.py:130 #, fuzzy msgid "_Clear Queue" msgstr "_Clear Errors" #: ../quodlibet/qltk/queue.py:242 #, 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:198 msgid "_Browse Library" msgstr "_Browse Library" #: ../quodlibet/qltk/quodlibetwindow.py:395 #, fuzzy msgid "Toggle queue visibility" msgstr "Toggle main window visibility" #: ../quodlibet/qltk/quodlibetwindow.py:516 #, fuzzy msgid "Playback Error" msgstr "Pause playback" #: ../quodlibet/qltk/quodlibetwindow.py:524 #, fuzzy msgid "Set up library directories?" msgstr "Select Directories" #: ../quodlibet/qltk/quodlibetwindow.py:525 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:531 msgid "_Not Now" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:532 msgid "_Set Up" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:956 msgid "Unable to add songs" msgstr "Unable to add songs" #: ../quodlibet/qltk/quodlibetwindow.py:957 #: ../quodlibet/qltk/quodlibetwindow.py:1364 #, fuzzy, python-format msgid "%s uses an unsupported protocol." msgstr "<b>%s</b> uses an unsupported protocol." #: ../quodlibet/qltk/quodlibetwindow.py:980 msgid "_Jump to Playing Song" msgstr "_Jump to Playing Song" #: ../quodlibet/qltk/quodlibetwindow.py:986 #, fuzzy msgid "_File" msgstr "File" #: ../quodlibet/qltk/quodlibetwindow.py:987 #, fuzzy msgid "_Song" msgstr "Songs" #: ../quodlibet/qltk/quodlibetwindow.py:988 msgid "_View" msgstr "_View" #: ../quodlibet/qltk/quodlibetwindow.py:989 #, fuzzy msgid "_Browse" msgstr "Browsers" #: ../quodlibet/qltk/quodlibetwindow.py:990 msgid "_Control" msgstr "_Control" #: ../quodlibet/qltk/quodlibetwindow.py:991 msgid "_Help" msgstr "_Help" #: ../quodlibet/qltk/quodlibetwindow.py:997 #, fuzzy msgid "_Add a Folder…" msgstr "_Add a Folder..." #: ../quodlibet/qltk/quodlibetwindow.py:1002 #, fuzzy msgid "_Add a File…" msgstr "_Add a File..." #: ../quodlibet/qltk/quodlibetwindow.py:1007 #, fuzzy msgid "_Add a Location…" msgstr "Add a Location" #: ../quodlibet/qltk/quodlibetwindow.py:1036 #, fuzzy msgid "Edit Bookmarks…" msgstr "_Edit Bookmarks..." #: ../quodlibet/qltk/quodlibetwindow.py:1056 #, fuzzy msgid "Stop After This Song" msgstr "Stop after this song" #: ../quodlibet/qltk/quodlibetwindow.py:1062 msgid "_Keyboard Shortcuts" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:1071 msgid "Online Help" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:1080 #, fuzzy msgid "Search Help" msgstr "Search" #: ../quodlibet/qltk/quodlibetwindow.py:1352 msgid "Add a Location" msgstr "Add a Location" #: ../quodlibet/qltk/quodlibetwindow.py:1353 msgid "Enter the location of an audio file:" msgstr "Enter the location of an audio file:" #: ../quodlibet/qltk/quodlibetwindow.py:1358 #: ../quodlibet/qltk/quodlibetwindow.py:1363 msgid "Unable to add location" msgstr "Unable to add location" #: ../quodlibet/qltk/quodlibetwindow.py:1359 #, fuzzy, python-format msgid "%s is not a valid location." msgstr "<b>%s</b> is not a valid location." #: ../quodlibet/qltk/quodlibetwindow.py:1372 #: ../quodlibet/qltk/quodlibetwindow.py:1381 msgid "Add Music" msgstr "Add Music" #: ../quodlibet/qltk/quodlibetwindow.py:1372 ../quodlibet/qltk/scanbox.py:99 #, fuzzy msgid "_Add Folders" msgstr "_Add a Folder..." #: ../quodlibet/qltk/quodlibetwindow.py:1379 #, fuzzy msgid "Music Files" msgstr "Music Player" #: ../quodlibet/qltk/quodlibetwindow.py:1381 #, fuzzy msgid "_Add Files" msgstr "_Add a File..." #: ../quodlibet/qltk/ratingsmenu.py:24 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "" #: ../quodlibet/qltk/ratingsmenu.py:26 msgid "The saved ratings will be removed" msgstr "" #: ../quodlibet/qltk/ratingsmenu.py:27 #, python-format msgid "The rating of all selected songs will be changed to '%s'" msgstr "" #: ../quodlibet/qltk/ratingsmenu.py:57 ../quodlibet/qltk/ratingsmenu.py:111 #, fuzzy msgid "_Remove Rating" msgstr "_Remove Station" #: ../quodlibet/qltk/ratingsmenu.py:98 #, fuzzy msgid "Change _Rating" msgstr "_Rating" #: ../quodlibet/qltk/renamefiles.py:46 msgid "Replace spaces with _underscores" msgstr "Replace spaces with _underscores" #: ../quodlibet/qltk/renamefiles.py:56 msgid "Strip _Windows-incompatible characters" msgstr "Strip _Windows-incompatible characters" #: ../quodlibet/qltk/renamefiles.py:74 msgid "Strip _diacritical marks" msgstr "Strip _diacritical marks" #: ../quodlibet/qltk/renamefiles.py:85 msgid "Strip non-_ASCII characters" msgstr "Strip non-_ASCII characters" #: ../quodlibet/qltk/renamefiles.py:95 msgid "Use only _lowercase characters" msgstr "" #: ../quodlibet/qltk/renamefiles.py:123 msgid "Rename Files" msgstr "Rename Files" #: ../quodlibet/qltk/renamefiles.py:139 ../quodlibet/qltk/tagsfrompath.py:116 #, fuzzy msgid "Path Patterns" msgstr "Invalid Pattern" #: ../quodlibet/qltk/renamefiles.py:140 ../quodlibet/qltk/tagsfrompath.py:117 #, fuzzy msgid "Edit saved patterns…" msgstr "Edit saved values..." #: ../quodlibet/qltk/renamefiles.py:143 ../quodlibet/qltk/tagsfrompath.py:120 #: ../quodlibet/qltk/tracknumbers.py:58 msgid "_Preview" msgstr "_Preview" #: ../quodlibet/qltk/renamefiles.py:190 msgid "New Name" msgstr "New Name" #: ../quodlibet/qltk/renamefiles.py:255 msgid "Unable to rename file" msgstr "Unable to rename file" #: ../quodlibet/qltk/renamefiles.py:256 #, fuzzy, python-format msgid "" "Renaming <b>%(old-name)s</b> to <b>%(new-name)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." 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:264 #, fuzzy msgid "Ignore _All Errors" msgstr "Show _Errors" #: ../quodlibet/qltk/renamefiles.py:267 msgid "_Continue" msgstr "_Continue" #: ../quodlibet/qltk/renamefiles.py:296 msgid "Path is not absolute" msgstr "Path is not absolute" #: ../quodlibet/qltk/renamefiles.py:297 #, python-format msgid "" "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 ~/." 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:47 #, 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:99 msgid "Select Directories" msgstr "Select Directories" #: ../quodlibet/qltk/searchbar.py:52 #, fuzzy msgid "Saved Searches" msgstr "Saved Values" #: ../quodlibet/qltk/searchbar.py:53 #, fuzzy msgid "Edit saved searches…" msgstr "Edit saved values..." #: ../quodlibet/qltk/searchbar.py:74 msgid "Search your library, using free text or QL queries" msgstr "" #: ../quodlibet/qltk/searchbar.py:129 #, fuzzy msgid "Search after _typing" msgstr "search-string" #: ../quodlibet/qltk/searchbar.py:132 msgid "Show search results after the user stops typing." msgstr "" #: ../quodlibet/qltk/searchbar.py:187 msgid "_Limit:" msgstr "_Limit:" #: ../quodlibet/qltk/searchbar.py:200 msgid "_Weight" msgstr "_Weighted" #: ../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 ../quodlibet/qltk/shortcuts.py:41 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: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:377 #, python-format msgid "_Filter on %s" msgstr "_Filter on %s" #: ../quodlibet/qltk/songlist.py:1094 #, fuzzy msgid "All _Headers" msgstr "_Album Headers" #: ../quodlibet/qltk/songlist.py:1095 msgid "_Track Headers" msgstr "_Track Headers" #: ../quodlibet/qltk/songlist.py:1096 msgid "_Album Headers" msgstr "_Album Headers" #: ../quodlibet/qltk/songlist.py:1097 msgid "_People Headers" msgstr "_People Headers" #: ../quodlibet/qltk/songlist.py:1098 msgid "_Date Headers" msgstr "_Date Headers" #: ../quodlibet/qltk/songlist.py:1099 msgid "_File Headers" msgstr "_File Headers" #: ../quodlibet/qltk/songlist.py:1100 msgid "_Production Headers" msgstr "_Production Headers" #: ../quodlibet/qltk/songlist.py:1115 #, fuzzy msgid "_Customize Headers…" msgstr "_Customize Headers..." #: ../quodlibet/qltk/songlist.py:1120 msgid "_Expand Column" msgstr "" #: ../quodlibet/qltk/songsmenu.py:36 #, 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:64 #, 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:149 #, fuzzy msgid "Configure Plugins…" msgstr "Colour _search terms" #: ../quodlibet/qltk/songsmenu.py:345 msgid "Add to _Queue" msgstr "Add to _Queue" #: ../quodlibet/qltk/songsmenu.py:368 msgid "_Copy to Device" msgstr "_Copy to Device" #: ../quodlibet/qltk/songsmenu.py:379 #, fuzzy msgid "_Remove from Library" msgstr "_Remove from Library" #: ../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:101 msgid "Tags From Path" msgstr "Tags From Path" #: ../quodlibet/qltk/tagsfrompath.py:138 msgid "Tags replace existing ones" msgstr "Tags replace existing ones" #: ../quodlibet/qltk/tagsfrompath.py:139 msgid "Tags are added to existing ones" msgstr "Tags are added to existing ones" #. Save button #: ../quodlibet/qltk/tagsfrompath.py:153 msgid "Save" msgstr "" #: ../quodlibet/qltk/tagsfrompath.py:195 #, python-format msgid "" "The pattern\n" "\t<b>%s</b>\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/tagsfrompath.py:216 msgid "Invalid tags" msgstr "Invalid tags" #: ../quodlibet/qltk/tagsfrompath.py:217 #, 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." #: ../quodlibet/qltk/textedit.py:142 #, 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:158 msgid "Edit Display" msgstr "Edit Display" #: ../quodlibet/qltk/tracknumbers.py:39 msgid "Track Numbers" msgstr "Track Numbers" #: ../quodlibet/qltk/tracknumbers.py:42 msgid "Start fro_m:" msgstr "Start fro_m:" #: ../quodlibet/qltk/tracknumbers.py:51 msgid "_Total tracks:" msgstr "_Total tracks:" #: ../quodlibet/qltk/unity.py:52 #, fuzzy msgid "Play/Pause" msgstr "_Pause" #: ../quodlibet/qltk/unity.py:75 #, fuzzy msgid "Previous" msgstr "Pre_vious" #: ../quodlibet/qltk/views.py:923 #, 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:89 #, fuzzy msgid "Checking for Updates" msgstr "Checking mount points" #: ../quodlibet/update.py:124 #, fuzzy msgid "Connection failed" msgstr "location" #: ../quodlibet/update.py:133 #, python-format msgid "You are already using the newest version %(version)s" msgstr "" #: ../quodlibet/update.py:136 #, 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:420 msgid "Playlists must have a name" msgstr "" #: ../quodlibet/util/collection.py:603 #, python-format msgid "A playlist named %s already exists." msgstr "A playlist named %s already exists." #: ../quodlibet/util/cover/built_in.py:26 #, fuzzy msgid "Embedded album covers" msgstr "Show album _covers" #: ../quodlibet/util/cover/built_in.py:27 msgid "Uses covers embedded into audio files." msgstr "" #: ../quodlibet/util/cover/built_in.py:49 #, fuzzy msgid "Filesystem cover" msgstr "File System" #: ../quodlibet/util/cover/built_in.py:50 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "" #: ../quodlibet/util/__init__.py:93 msgid "Display brief usage information" msgstr "Display brief usage information" #: ../quodlibet/util/__init__.py:95 msgid "Display version and copyright" msgstr "Display version and copyright" #: ../quodlibet/util/__init__.py:135 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "" #: ../quodlibet/util/__init__.py:137 msgid "[options]" msgstr "[options]" #: ../quodlibet/util/__init__.py:182 #, fuzzy, python-format msgid "Option %r not recognized." msgstr "E: Option '%s' not recognized." #: ../quodlibet/util/__init__.py:185 #, fuzzy, python-format msgid "Option %r requires an argument." msgstr "E: Option '%s' requires an argument." #: ../quodlibet/util/__init__.py:188 #, fuzzy, python-format msgid "%r is not a unique prefix." msgstr "E: '%s' is not a unique prefix." #: ../quodlibet/util/__init__.py:364 #, python-format msgid "%d kbps" msgstr "%d kbps" #: ../quodlibet/util/__init__.py:419 #, fuzzy, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%d second" msgstr[1] "%d seconds" #: ../quodlibet/util/__init__.py:432 msgid "No time information" msgstr "No time information" #: ../quodlibet/util/__init__.py:435 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d second" msgstr[1] "%d seconds" #: ../quodlibet/util/__init__.py:436 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d minute" msgstr[1] "%d minutes" #: ../quodlibet/util/__init__.py:437 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d hour" msgstr[1] "%d hours" #: ../quodlibet/util/__init__.py:438 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d day" msgstr[1] "%d days" #: ../quodlibet/util/__init__.py:439 #, 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:563 #, 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 msgid "Unable to edit song" msgstr "Unable to edit song" #: ../quodlibet/util/songwrapper.py:113 #, python-format msgid "" "Saving <b>%s</b> 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:34 #: ../quodlibet/util/string/__init__.py:44 msgid "[Invalid Encoding]" msgstr "[Invalid Encoding]" #: ../quodlibet/util/tags.py:74 msgid "album" msgstr "album" #: ../quodlibet/util/tags.py:75 msgid "arranger" msgstr "arranger" #: ../quodlibet/util/tags.py:75 msgid "arrangers" msgstr "arrangers" #: ../quodlibet/util/tags.py:75 #, fuzzy msgid "arrangement" msgstr "arranger" #: ../quodlibet/util/tags.py:77 msgid "author" msgstr "author" #: ../quodlibet/util/tags.py:77 msgid "authors" msgstr "authors" #: ../quodlibet/util/tags.py:78 msgid "composer" msgstr "composer" #: ../quodlibet/util/tags.py:78 msgid "composers" msgstr "composers" #: ../quodlibet/util/tags.py:78 #, fuzzy msgid "composition" msgstr "composer" #. Translators: conducting as in conducting a musical performance #: ../quodlibet/util/tags.py:80 msgid "conductor" msgstr "conductor" #: ../quodlibet/util/tags.py:80 msgid "conductors" msgstr "conductors" #: ../quodlibet/util/tags.py:80 #, fuzzy msgid "conducting" msgstr "conductor" #: ../quodlibet/util/tags.py:81 msgid "contact" msgstr "contact" #: ../quodlibet/util/tags.py:82 msgid "copyright" msgstr "copyright" #: ../quodlibet/util/tags.py:83 msgid "date" msgstr "date" #: ../quodlibet/util/tags.py:84 msgid "description" msgstr "description" #: ../quodlibet/util/tags.py:85 msgid "genre" msgstr "genre" #: ../quodlibet/util/tags.py:85 #, fuzzy msgid "genres" msgstr "genre" #: ../quodlibet/util/tags.py:86 msgid "performer" msgstr "performer" #: ../quodlibet/util/tags.py:87 msgid "grouping" msgstr "grouping" #: ../quodlibet/util/tags.py:88 msgid "language" msgstr "language" #: ../quodlibet/util/tags.py:89 msgid "license" msgstr "licence" #: ../quodlibet/util/tags.py:90 msgid "location" msgstr "location" #: ../quodlibet/util/tags.py:91 msgid "lyricist" msgstr "lyricist" #: ../quodlibet/util/tags.py:91 msgid "lyricists" msgstr "lyricists" #: ../quodlibet/util/tags.py:91 #, fuzzy msgid "lyrics" msgstr "lyricist" #. Translators: Also e.g. "record label", "publisher" #: ../quodlibet/util/tags.py:93 msgid "organization" msgstr "organization" #: ../quodlibet/util/tags.py:94 msgid "title" msgstr "title" #: ../quodlibet/util/tags.py:95 msgid "version" msgstr "version" #: ../quodlibet/util/tags.py:96 msgid "website" msgstr "website" #: ../quodlibet/util/tags.py:98 msgid "album artist" msgstr "album artist" #: ../quodlibet/util/tags.py:99 msgid "BPM" msgstr "BPM" #. Translators: This used to be called "part". #: ../quodlibet/util/tags.py:102 ../quodlibet/util/tags.py:103 msgid "disc subtitle" msgstr "" #: ../quodlibet/util/tags.py:104 ../quodlibet/util/tags.py:141 msgid "disc" msgstr "disc" #: ../quodlibet/util/tags.py:105 ../quodlibet/util/tags.py:143 msgid "track" msgstr "track" #: ../quodlibet/util/tags.py:106 msgid "label ID" msgstr "label ID" #: ../quodlibet/util/tags.py:107 msgid "original release date" msgstr "original release date" #: ../quodlibet/util/tags.py:108 msgid "original album" msgstr "original album" #: ../quodlibet/util/tags.py:109 msgid "original artist" msgstr "original artist" #: ../quodlibet/util/tags.py:110 msgid "recording date" msgstr "recording date" #: ../quodlibet/util/tags.py:111 msgid "release country" msgstr "release country" #. 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:120 #, fuzzy msgid "MusicBrainz recording ID" msgstr "MusicBrainz track ID" #: ../quodlibet/util/tags.py:121 #, fuzzy msgid "MusicBrainz release track ID" msgstr "MusicBrainz track ID" #: ../quodlibet/util/tags.py:122 #, fuzzy msgid "MusicBrainz release ID" msgstr "MusicBrainz track ID" #: ../quodlibet/util/tags.py:123 #, fuzzy msgid "MusicBrainz artist ID" msgstr "MusicBrainz artist ID" #: ../quodlibet/util/tags.py:124 #, fuzzy msgid "MusicBrainz release artist ID" msgstr "MusicBrainz track ID" #: ../quodlibet/util/tags.py:125 msgid "MusicBrainz TRM ID" msgstr "MusicBrainz TRM ID" #: ../quodlibet/util/tags.py:126 msgid "MusicIP PUID" msgstr "MusicIP PUID" #: ../quodlibet/util/tags.py:127 msgid "MusicBrainz album status" msgstr "MusicBrainz album status" #: ../quodlibet/util/tags.py:128 msgid "MusicBrainz album type" msgstr "MusicBrainz album type" #: ../quodlibet/util/tags.py:129 #, fuzzy msgid "MusicBrainz release group ID" msgstr "MusicBrainz track ID" #. Translators: "gain" means a volume adjustment, not "to acquire". #: ../quodlibet/util/tags.py:132 msgid "track gain" msgstr "track gain" #: ../quodlibet/util/tags.py:133 msgid "track peak" msgstr "track peak" #. Translators: "gain" means a volume adjustment, not "to acquire". #: ../quodlibet/util/tags.py:135 msgid "album gain" msgstr "album gain" #: ../quodlibet/util/tags.py:136 msgid "album peak" msgstr "album peak" #: ../quodlibet/util/tags.py:137 #, fuzzy msgid "reference loudness" msgstr "Preferences" #: ../quodlibet/util/tags.py:142 msgid "discs" msgstr "discs" #: ../quodlibet/util/tags.py:144 msgid "tracks" msgstr "tracks" #: ../quodlibet/util/tags.py:145 msgid "last started" msgstr "last started" #: ../quodlibet/util/tags.py:146 msgid "full name" msgstr "full name" #: ../quodlibet/util/tags.py:153 msgid "mount point" msgstr "mount point" #: ../quodlibet/util/tags.py:155 msgid "people" msgstr "people" #: ../quodlibet/util/tags.py:157 msgid "year" msgstr "year" #: ../quodlibet/util/tags.py:158 #, fuzzy msgid "original release year" msgstr "original release date" #: ../quodlibet/util/tags.py:159 #, fuzzy msgid "bookmark" msgstr "Bookmarks" #: ../quodlibet/util/tags.py:162 #, fuzzy msgid "file format" msgstr "format" #: ../quodlibet/util/tags.py:165 #, fuzzy msgid "playlists" msgstr "Playlists" #: ../quodlibet/util/tags.py:166 msgid "channel count" msgstr "" #. Translators: e.g. "artist (sort)" #: ../quodlibet/util/tags.py:256 msgid "sort" msgstr "" #. Translators: e.g. "performer (roles)" #: ../quodlibet/util/tags.py:264 msgid "roles" msgstr "" #, fuzzy #~ msgid "browsers" #~ msgstr "Browsers" #~ msgid "Unable to download lyrics." #~ msgstr "Unable to download lyrics." #~ msgid "Remove all songs from the queue" #~ msgstr "Remove all songs from the queue" #~ msgid "Watch this folder for new songs" #~ msgstr "Watch this folder for new songs" #~ 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 "Model:" #~ msgstr "Model:" #~ msgid "Capacity:" #~ msgstr "Capacity:" #~ msgid "Firmware:" #~ msgstr "Firmware:" #, fuzzy #~ msgid "Removing orphaned iPod track" #~ msgstr "W: removing orphaned iPod track" #, 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 "Unable to open input files" #~ msgstr "Unable to open files" #, 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 "_Select" #~ msgstr "_Select" #~ 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 "Choose New Stations" #~ msgstr "Choose New Stations" #~ msgid "Add" #~ msgstr "Add" #, fuzzy #~ msgid "Bitrate" #~ msgstr "bitrate" #~ msgid "_Stations..." #~ msgstr "_Stations..." #, fuzzy #~ msgid "Quod Libet" #~ msgstr "Exit Quod Libet" #~ 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 "Deleting %d/%d." #~ msgstr "Deleting %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 "Tag by Filename" #~ msgstr "Tag by Filename" #~ 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 "Search Bar" #~ msgstr "Search Bar" #~ 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 "Supported formats:" #~ msgstr "Supported formats:" #~ 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9551857 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/po/en_GB.po�������������������������������������������������������������������������0000644�0001750�0001750�00000526655�00000000000�014451� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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: 2020-10-18 16:11+0100\n" "PO-Revision-Date: 2020-10-18 16:04+0100\n" "Last-Translator: Nick Boultbee <nick.boultbee@gmail.com>\n" "Language-Team: Joe Wreschnig <piman@sacredchao.net>\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: Poedit 2.3\n" #: quodlibet/browsers/albums/main.py:222 #: quodlibet/browsers/covergrid/main.py:54 msgid "_Title" msgstr "" #: quodlibet/browsers/albums/main.py:223 #: quodlibet/browsers/covergrid/main.py:55 quodlibet/qltk/prefs.py:49 msgid "_Artist" msgstr "" #: quodlibet/browsers/albums/main.py:224 #: quodlibet/browsers/covergrid/main.py:56 quodlibet/qltk/prefs.py:54 msgid "_Date" msgstr "" #: quodlibet/browsers/albums/main.py:225 msgid "_Date Added" msgstr "" #: quodlibet/browsers/albums/main.py:226 msgid "_Original Date" msgstr "" #: quodlibet/browsers/albums/main.py:227 #: quodlibet/browsers/covergrid/main.py:57 quodlibet/qltk/prefs.py:53 msgid "_Genre" msgstr "" #: quodlibet/browsers/albums/main.py:228 #: quodlibet/browsers/covergrid/main.py:58 quodlibet/qltk/prefs.py:58 #: quodlibet/qltk/ratingsmenu.py:39 msgid "_Rating" msgstr "" #: quodlibet/browsers/albums/main.py:229 msgid "_Playcount" msgstr "" #: quodlibet/browsers/albums/main.py:235 #: quodlibet/browsers/covergrid/main.py:64 msgid "Sort _by…" msgstr "" #: quodlibet/browsers/albums/main.py:256 #: quodlibet/browsers/covergrid/main.py:85 #: quodlibet/browsers/paned/prefs.py:203 #: quodlibet/browsers/playlists/main.py:674 quodlibet/qltk/exfalsowindow.py:108 #: quodlibet/qltk/pluginwin.py:367 quodlibet/qltk/quodlibetwindow.py:906 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:545 #: quodlibet/browsers/covergrid/main.py:285 #: quodlibet/browsers/covergrid/main.py:501 msgid "All Albums" msgstr "" #: quodlibet/browsers/albums/main.py:546 #: quodlibet/browsers/covergrid/main.py:286 #: quodlibet/browsers/covergrid/main.py:502 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "" msgstr[1] "" #: quodlibet/browsers/albums/main.py:727 #: quodlibet/browsers/covergrid/main.py:480 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:385 quodlibet/util/collection.py:262 #, 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:383 quodlibet/util/collection.py:266 #, 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:124 #: quodlibet/ext/songsmenu/cover_download.py:308 msgid "Options" msgstr "" #: quodlibet/browsers/albums/prefs.py:74 #: quodlibet/browsers/covergrid/prefs.py:127 msgid "Album Display" msgstr "" #: quodlibet/browsers/albums/prefs.py:78 #: quodlibet/browsers/covergrid/prefs.py:131 #: quodlibet/browsers/playlists/prefs.py:56 #: quodlibet/ext/songsmenu/albumart.py:330 #: 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:96 #: quodlibet/qltk/data_editors.py:321 quodlibet/qltk/exfalsowindow.py:286 #: quodlibet/qltk/pluginwin.py:100 quodlibet/qltk/pluginwin.py:449 #: quodlibet/qltk/prefs.py:767 quodlibet/qltk/textedit.py:163 #: quodlibet/update.py:149 msgid "_Close" msgstr "" #: quodlibet/browsers/audiofeeds.py:51 quodlibet/browsers/audiofeeds.py:63 #: quodlibet/browsers/audiofeeds.py:65 quodlibet/browsers/audiofeeds.py:152 #: quodlibet/browsers/paned/models.py:88 #: quodlibet/ext/songsmenu/fingerprint/search.py:46 #: quodlibet/formats/_audio.py:501 quodlibet/order/__init__.py:29 #: quodlibet/qltk/information.py:244 quodlibet/qltk/information.py:251 #: quodlibet/qltk/information.py:277 quodlibet/qltk/pluginwin.py:51 #: quodlibet/qltk/wlw.py:69 msgid "Unknown" msgstr "" #: quodlibet/browsers/audiofeeds.py:213 msgid "New Feed" msgstr "" #: quodlibet/browsers/audiofeeds.py:214 msgid "Enter the location of an audio feed:" msgstr "" #: quodlibet/browsers/audiofeeds.py:215 #: quodlibet/browsers/collection/prefs.py:89 quodlibet/browsers/iradio.py:366 #: quodlibet/browsers/paned/prefs.py:120 #: quodlibet/browsers/playlists/menu.py:96 #: quodlibet/browsers/playlists/util.py:52 quodlibet/qltk/bookmarks.py:62 #: quodlibet/qltk/cbes.py:57 quodlibet/qltk/data_editors.py:308 #: quodlibet/qltk/edittags.py:331 quodlibet/qltk/edittags.py:538 #: quodlibet/qltk/quodlibetwindow.py:1276 quodlibet/qltk/scanbox.py:61 msgid "_Add" msgstr "" #: quodlibet/browsers/audiofeeds.py:269 msgid "Audio Feeds" msgstr "" #: quodlibet/browsers/audiofeeds.py:270 msgid "_Audio Feeds" msgstr "" #: quodlibet/browsers/audiofeeds.py:373 quodlibet/qltk/data_editors.py:93 msgid "_New" msgstr "" #: quodlibet/browsers/audiofeeds.py:433 quodlibet/browsers/audiofeeds.py:492 msgid "Unable to add feed" msgstr "" #: quodlibet/browsers/audiofeeds.py:434 quodlibet/browsers/audiofeeds.py:493 #, python-format msgid "" "%s could not be added. The server may be down, or the location may not be an " "audio feed." msgstr "" #: quodlibet/browsers/audiofeeds.py:441 quodlibet/qltk/filesel.py:260 #: quodlibet/qltk/pluginwin.py:432 msgid "_Refresh" msgstr "" #: quodlibet/browsers/audiofeeds.py:442 #: quodlibet/browsers/playlists/main.py:494 #: quodlibet/browsers/playlists/util.py:43 quodlibet/qltk/delete.py:143 #: quodlibet/qltk/filesel.py:257 quodlibet/qltk/lyrics.py:35 #: quodlibet/qltk/maskedbox.py:28 quodlibet/qltk/songsmenu.py:364 msgid "_Delete" msgstr "" #: quodlibet/browsers/audiofeeds.py:509 msgid "" "The current audio backend does not support URLs, Audio Feeds browser " "disabled." msgstr "" #: quodlibet/browsers/_base.py:147 quodlibet/browsers/_base.py:150 msgid "Library Browser" msgstr "" #: quodlibet/browsers/_base.py:274 quodlibet/ext/songsmenu/console.py:45 #: quodlibet/ext/songsmenu/refresh.py:30 quodlibet/qltk/exfalsowindow.py:240 #: quodlibet/qltk/information.py:554 quodlibet/qltk/maskedbox.py:68 #: quodlibet/util/collection.py:540 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "" msgstr[1] "" #: quodlibet/browsers/_base.py:402 quodlibet/browsers/_base.py:407 #: quodlibet/qltk/tagsfrompath.py:193 quodlibet/qltk/textedit.py:140 #: quodlibet/util/__init__.py:575 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 "" #. Remove button #: quodlibet/browsers/collection/prefs.py:93 #: quodlibet/browsers/paned/prefs.py:124 #: quodlibet/browsers/playlists/menu.py:97 #: 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:78 quodlibet/qltk/data_editors.py:91 #: quodlibet/qltk/data_editors.py:298 quodlibet/qltk/data_editors.py:311 #: quodlibet/qltk/data_editors.py:319 quodlibet/qltk/edittags.py:544 #: quodlibet/qltk/edittags.py:732 quodlibet/qltk/maskedbox.py:48 #: quodlibet/qltk/maskedbox.py:88 quodlibet/qltk/queue.py:427 #: quodlibet/qltk/scanbox.py:36 quodlibet/qltk/scanbox.py:63 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:481 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:247 #: quodlibet/ext/songsmenu/editplaycount.py:45 #: quodlibet/ext/songsmenu/exact_rating.py:38 #: quodlibet/player/gstbe/prefs.py:40 quodlibet/qltk/prefs.py:127 #: quodlibet/qltk/textedit.py:64 msgid "_Apply" msgstr "" #: quodlibet/browsers/collection/prefs.py:197 #: quodlibet/browsers/paned/prefs.py:251 #: quodlibet/browsers/playlists/menu.py:95 #: quodlibet/browsers/playlists/util.py:42 quodlibet/errorreport/ui.py:103 #: quodlibet/ext/playlist/export_to_folder.py:38 #: 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:44 #: quodlibet/ext/songsmenu/fingerprint/search.py:281 #: quodlibet/ext/songsmenu/fingerprint/submit.py:90 #: quodlibet/ext/songsmenu/importexport.py:39 #: quodlibet/ext/songsmenu/lastfmsync.py:215 #: quodlibet/ext/songsmenu/playlist.py:50 #: quodlibet/ext/songsmenu/replaygain.py:354 #: 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:330 #: quodlibet/qltk/_editutils.py:41 quodlibet/qltk/getstring.py:28 #: quodlibet/qltk/maskedbox.py:27 quodlibet/qltk/msg.py:54 #: quodlibet/qltk/msg.py:93 quodlibet/qltk/msg.py:111 #: quodlibet/qltk/ratingsmenu.py:33 quodlibet/update.py:95 msgid "_Cancel" msgstr "" #: quodlibet/browsers/covergrid/main.py:126 msgid "Cover Grid" msgstr "" #: quodlibet/browsers/covergrid/main.py:127 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:71 msgid "Show \"All Albums\" Item" msgstr "" #: quodlibet/browsers/covergrid/prefs.py:82 msgid "Wide Mode" msgstr "" #: quodlibet/browsers/covergrid/prefs.py:114 #: quodlibet/browsers/covergrid/prefs.py:115 msgid "Cover Magnification" msgstr "" #: quodlibet/browsers/filesystem.py:39 msgid "File System" msgstr "" #: quodlibet/browsers/filesystem.py:40 msgid "_File System" msgstr "" #: quodlibet/browsers/filesystem.py:124 quodlibet/qltk/songlist.py:258 msgid "Unable to copy songs" msgstr "" #: quodlibet/browsers/filesystem.py:125 quodlibet/qltk/songlist.py:259 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "" #: quodlibet/browsers/filesystem.py:197 msgid "_Add to Library" msgstr "" #: quodlibet/browsers/iradio.py:186 #, 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:222 quodlibet/browsers/iradio.py:263 #: quodlibet/browsers/iradio.py:495 msgid "Internet Radio" msgstr "" #: quodlibet/browsers/iradio.py:222 msgid "Add stations" msgstr "" #: quodlibet/browsers/iradio.py:263 msgid "Downloading station list" msgstr "" #: quodlibet/browsers/iradio.py:364 msgid "New Station" msgstr "" #: quodlibet/browsers/iradio.py:365 msgid "Enter the location of an Internet radio station:" msgstr "" #: quodlibet/browsers/iradio.py:383 msgid "Electronic" msgstr "" #: quodlibet/browsers/iradio.py:386 msgid "Hip Hop / Rap" msgstr "" #: quodlibet/browsers/iradio.py:387 msgid "Oldies" msgstr "" #: quodlibet/browsers/iradio.py:388 msgid "R&B" msgstr "" #: quodlibet/browsers/iradio.py:389 msgid "Japanese" msgstr "" #: quodlibet/browsers/iradio.py:390 msgid "Indian" msgstr "" #: quodlibet/browsers/iradio.py:392 msgid "Religious" msgstr "" #: quodlibet/browsers/iradio.py:394 msgid "Charts" msgstr "" #: quodlibet/browsers/iradio.py:395 msgid "Turkish" msgstr "" #: quodlibet/browsers/iradio.py:396 msgid "Reggae / Dancehall" msgstr "" #: quodlibet/browsers/iradio.py:397 msgid "Latin" msgstr "" #: quodlibet/browsers/iradio.py:398 msgid "College Radio" msgstr "" #: quodlibet/browsers/iradio.py:399 msgid "Talk / News" msgstr "" #: quodlibet/browsers/iradio.py:400 msgid "Ambient" msgstr "" #: quodlibet/browsers/iradio.py:401 msgid "Jazz" msgstr "" #: quodlibet/browsers/iradio.py:402 quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "" #: quodlibet/browsers/iradio.py:403 quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "" #: quodlibet/browsers/iradio.py:404 msgid "Alternative" msgstr "" #: quodlibet/browsers/iradio.py:405 msgid "Metal" msgstr "" #: quodlibet/browsers/iradio.py:406 msgid "Country" msgstr "" #: quodlibet/browsers/iradio.py:407 msgid "News" msgstr "" #: quodlibet/browsers/iradio.py:408 msgid "Schlager" msgstr "" #: quodlibet/browsers/iradio.py:409 msgid "Funk" msgstr "" #: quodlibet/browsers/iradio.py:410 msgid "Indie" msgstr "" #: quodlibet/browsers/iradio.py:411 msgid "Blues" msgstr "" #: quodlibet/browsers/iradio.py:412 msgid "Soul" msgstr "" #: quodlibet/browsers/iradio.py:413 msgid "Lounge" msgstr "" #: quodlibet/browsers/iradio.py:414 msgid "Punk" msgstr "" #: quodlibet/browsers/iradio.py:415 msgid "Reggaeton" msgstr "" #: quodlibet/browsers/iradio.py:417 msgid "Slavic" msgstr "" #: quodlibet/browsers/iradio.py:419 msgid "Greek" msgstr "" #: quodlibet/browsers/iradio.py:420 msgid "Gothic" msgstr "" #: quodlibet/browsers/iradio.py:421 quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "" #: quodlibet/browsers/iradio.py:474 msgid "Would you like to load a list of popular radio stations?" msgstr "" #: quodlibet/browsers/iradio.py:480 msgid "_Load Stations" msgstr "" #: quodlibet/browsers/iradio.py:496 msgid "_Internet Radio" msgstr "" #: quodlibet/browsers/iradio.py:569 msgid "_New Station…" msgstr "" #: quodlibet/browsers/iradio.py:572 msgid "_Update Stations" msgstr "" #: quodlibet/browsers/iradio.py:599 msgid "All Stations" msgstr "" #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:603 quodlibet/browsers/soundcloud/main.py:65 msgid "Favorites" msgstr "Favourites" #: quodlibet/browsers/iradio.py:611 msgid "No Category" msgstr "" #: quodlibet/browsers/iradio.py:834 msgid "No stations found" msgstr "" #: quodlibet/browsers/iradio.py:835 #, python-format msgid "No Internet radio stations were found at %s." msgstr "" #: quodlibet/browsers/iradio.py:848 msgid "Nothing to add" msgstr "" #: quodlibet/browsers/iradio.py:849 msgid "All stations listed are already in your library." msgstr "" #: quodlibet/browsers/iradio.py:870 msgid "Add to Favorites" msgstr "Add to Favourites" #: quodlibet/browsers/iradio.py:874 msgid "Remove from Favorites" msgstr "Remove from Favourites" #: quodlibet/browsers/iradio.py:974 #, 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:106 quodlibet/qltk/pluginwin.py:143 #: quodlibet/qltk/pluginwin.py:185 msgid "All" msgstr "" #: quodlibet/browsers/paned/prefs.py:41 #: quodlibet/ext/songsmenu/cover_download.py:159 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" "<tt>%s</tt>" msgstr "" #: quodlibet/browsers/paned/prefs.py:231 msgid "Paned Browser Preferences" msgstr "" #: quodlibet/browsers/paned/prefs.py:236 msgid "Column layout" msgstr "" #: quodlibet/browsers/paned/prefs.py:240 msgid "Column content" msgstr "" #: quodlibet/browsers/paned/prefs.py:242 msgid "Equal pane width" msgstr "" #: quodlibet/browsers/playlists/main.py:48 #: quodlibet/browsers/playlists/main.py:610 quodlibet/qltk/pluginwin.py:35 msgid "Playlists" msgstr "" #: quodlibet/browsers/playlists/main.py:49 msgid "_Playlists" msgstr "" #: quodlibet/browsers/playlists/main.py:159 msgid "_Remove from Playlist" msgstr "" #: quodlibet/browsers/playlists/main.py:224 msgid "New" msgstr "" #: quodlibet/browsers/playlists/main.py:228 msgid "Import" msgstr "" #: quodlibet/browsers/playlists/main.py:450 msgid "Unable to import playlist" msgstr "" #: quodlibet/browsers/playlists/main.py:451 msgid "Quod Libet can only import playlists in the M3U/M3U8 and PLS formats." msgstr "" #: quodlibet/browsers/playlists/main.py:501 msgid "_Rename" msgstr "" #: quodlibet/browsers/playlists/main.py:599 msgid "Unable to rename playlist" msgstr "" #: quodlibet/browsers/playlists/main.py:611 msgid "Import Playlist" msgstr "" #: quodlibet/browsers/playlists/main.py:611 msgid "_Import" msgstr "" #: quodlibet/browsers/playlists/menu.py:25 msgid "_New Playlist…" msgstr "" #: quodlibet/browsers/playlists/menu.py:86 #, 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:90 #, 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:33 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "" #: quodlibet/browsers/playlists/util.py:35 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" #: quodlibet/browsers/playlists/util.py:50 #: quodlibet/browsers/playlists/util.py:125 quodlibet/util/collection.py:590 msgid "New Playlist" msgstr "" #: quodlibet/browsers/playlists/util.py:51 msgid "Enter a name for the new playlist:" msgstr "" #: quodlibet/browsers/playlists/util.py:89 #, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" #: quodlibet/browsers/tracks.py:32 msgid "_Limit Results" msgstr "" #: quodlibet/browsers/tracks.py:37 msgid "_Allow multiple queries" msgstr "" #: quodlibet/browsers/tracks.py:51 quodlibet/qltk/information.py:468 msgid "Track List" msgstr "" #: quodlibet/browsers/tracks.py:52 msgid "_Track List" msgstr "" #: quodlibet/browsers/soundcloud/main.py:39 msgid "Soundcloud Browser" msgstr "" #: quodlibet/browsers/soundcloud/main.py:40 msgid "Sound_cloud" msgstr "" #: quodlibet/browsers/soundcloud/main.py:60 quodlibet/qltk/searchbar.py:81 msgid "Search" msgstr "" #: quodlibet/browsers/soundcloud/main.py:69 msgid "My tracks" msgstr "" #: quodlibet/browsers/soundcloud/main.py:141 #, python-format msgid "Go to %s" msgstr "" #: quodlibet/browsers/soundcloud/main.py:443 msgid "Connected" msgstr "" #: quodlibet/browsers/soundcloud/main.py:444 #, python-format msgid "Quod Libet is now connected, <b>%s</b>!" msgstr "" #: quodlibet/browsers/soundcloud/main.py:456 #, python-format msgid "Log out of %s" msgstr "" #: quodlibet/browsers/soundcloud/main.py:458 msgid "Enter code…" msgstr "" #: quodlibet/browsers/soundcloud/main.py:459 #, python-format msgid "Log in to %s" msgstr "" #: quodlibet/browsers/soundcloud/util.py:86 msgid "Soundcloud authorisation" msgstr "" #: quodlibet/browsers/soundcloud/util.py:87 msgid "Enter Soundcloud auth code:" msgstr "" #: quodlibet/cli.py:50 msgid "Quod Libet is not running (add '--run' to start it)" msgstr "" #: quodlibet/cli.py:86 msgid "a music library and player" msgstr "" #: quodlibet/cli.py:87 msgid "[option]" msgstr "" #: quodlibet/cli.py:89 msgid "Print the playing song and exit" msgstr "" #: quodlibet/cli.py:90 msgid "Begin playing immediately" msgstr "" #: quodlibet/cli.py:91 msgid "Don't show any windows on start" msgstr "" #: quodlibet/cli.py:94 msgid "Jump to next song" msgstr "" #: quodlibet/cli.py:96 msgid "Jump to previous song or restart if near the beginning" msgstr "" #: quodlibet/cli.py:97 msgid "Jump to previous song" msgstr "" #: quodlibet/cli.py:98 msgid "Start playback" msgstr "" #: quodlibet/cli.py:99 msgid "Pause playback" msgstr "" #: quodlibet/cli.py:100 msgid "Toggle play/pause mode" msgstr "" #: quodlibet/cli.py:101 msgid "Stop playback" msgstr "" #: quodlibet/cli.py:102 msgid "Turn up volume" msgstr "" #: quodlibet/cli.py:103 msgid "Turn down volume" msgstr "" #: quodlibet/cli.py:104 msgid "Increase rating of playing song by one star" msgstr "" #: quodlibet/cli.py:105 msgid "Decrease rating of playing song by one star" msgstr "" #: quodlibet/cli.py:106 msgid "Print player status" msgstr "" #: quodlibet/cli.py:107 msgid "Hide main window" msgstr "" #: quodlibet/cli.py:108 msgid "Show main window" msgstr "" #: quodlibet/cli.py:109 msgid "Toggle main window visibility" msgstr "" #: quodlibet/cli.py:110 msgid "Focus the running player" msgstr "" #: quodlibet/cli.py:111 msgid "Remove active browser filters" msgstr "" #: quodlibet/cli.py:112 msgid "Refresh and rescan library" msgstr "" #: quodlibet/cli.py:113 msgid "List available browsers" msgstr "" #: quodlibet/cli.py:114 msgid "Print the current playlist" msgstr "" #: quodlibet/cli.py:115 msgid "Print the contents of the queue" msgstr "" #: quodlibet/cli.py:116 msgid "Print the active text query" msgstr "" #: quodlibet/cli.py:117 msgid "Start without plugins" msgstr "" #: quodlibet/cli.py:118 msgid "Start Quod Libet if it isn't running" msgstr "" #: quodlibet/cli.py:119 msgid "Exit Quod Libet" msgstr "" #: quodlibet/cli.py:124 msgid "Seek within the playing song" msgstr "" #: quodlibet/cli.py:124 msgid "[+|-][HH:]MM:SS" msgstr "" #: quodlibet/cli.py:125 msgid "Set or toggle shuffle mode" msgstr "" #: quodlibet/cli.py:126 msgid "Set shuffle mode type" msgstr "" #: quodlibet/cli.py:127 msgid "Turn repeat off, on, or toggle it" msgstr "" #: quodlibet/cli.py:128 msgid "Set repeat mode type" msgstr "" #: quodlibet/cli.py:129 msgid "Set the volume" msgstr "" #: quodlibet/cli.py:130 msgid "Search your audio library" msgstr "" #: quodlibet/cli.py:130 quodlibet/cli.py:140 quodlibet/cli.py:144 #: quodlibet/cli.py:146 msgid "query" msgstr "" #: quodlibet/cli.py:131 msgid "Play a file" msgstr "" #: quodlibet/cli.py:131 quodlibet/cli.py:140 quodlibet/cli.py:146 msgctxt "command" msgid "filename" msgstr "" #: quodlibet/cli.py:132 msgid "Set rating of playing song" msgstr "" #: quodlibet/cli.py:133 msgid "Set the current browser" msgstr "" #: quodlibet/cli.py:134 msgid "Stop after the playing song" msgstr "" #: quodlibet/cli.py:135 msgid "Open a new browser" msgstr "" #: quodlibet/cli.py:136 msgid "Show or hide the queue" msgstr "" #: quodlibet/cli.py:137 msgid "Filter on a random value" msgstr "" #: quodlibet/cli.py:137 msgctxt "command" msgid "tag" msgstr "" #: quodlibet/cli.py:138 msgid "Filter on a tag value" msgstr "" #: quodlibet/cli.py:138 msgid "tag=value" msgstr "" #: quodlibet/cli.py:139 msgid "Enqueue a file or query" msgstr "" #: quodlibet/cli.py:141 msgid "Enqueue comma-separated files" msgstr "" #: quodlibet/cli.py:142 quodlibet/util/tags.py:158 msgid "filename" msgstr "" #: quodlibet/cli.py:143 msgid "Print filenames of results of query to stdout" msgstr "" #: quodlibet/cli.py:145 msgid "Unqueue a file or query" msgstr "" #: quodlibet/cli.py:147 msgid "Add a file or directory to the library" msgstr "" #: quodlibet/cli.py:148 quodlibet/util/tags.py:100 msgid "location" msgstr "" #: quodlibet/cli.py:213 #, python-format msgid "Invalid argument for '%s'." msgstr "" #: quodlibet/cli.py:214 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:34 msgid "an audio tag editor" msgstr "" #: quodlibet/exfalso.py:34 quodlibet/util/tags.py:159 msgid "directory" msgstr "" #: quodlibet/exfalso.py:41 msgid "Audio metadata editor" msgstr "" #: quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "" #: quodlibet/ext/covers/artwork_url.py:20 msgid "" "Downloads covers linked to by the artwork_url tag. This works with the " "Soundcloud browser." 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:19 msgid "" "Allows arbitrary regex substitutions (s///) 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:71 msgid "Advanced Preferences" msgstr "" #: quodlibet/ext/events/advanced_preferences.py:72 msgid "Allow editing of advanced config settings." msgstr "" #: quodlibet/ext/events/advanced_preferences.py:190 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/ext/events/weblyrics.py:318 quodlibet/qltk/prefs.py:266 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:66 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:41 msgid "Effects" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:288 msgid "Ed_it Display Pattern…" msgstr "" #: quodlibet/ext/events/animosd/prefs.py:292 #: 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_library_update.py:139 msgid "Automatic Library Update" msgstr "" #: quodlibet/ext/events/auto_library_update.py:140 #, python-format msgid "Keeps your library up to date with inotify. Requires %s." 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 #, 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:570 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:123 #, python-format msgid "Error in %s" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:188 msgid "Ensure play counts are above zero when saving" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:222 msgid "_Update strategy:" msgstr "" #: quodlibet/ext/events/auto_update_tags_in_files.py:236 #: 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/qltk/prefs.py:744 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 by Brian Nelson." msgstr "" #: quodlibet/ext/events/bansheeimport.py:106 msgid "Specified Banshee database is malformed or missing" msgstr "" #: quodlibet/ext/events/bansheeimport.py:111 #: quodlibet/ext/events/rbimport.py:114 msgid "Import Failed" msgstr "" #: quodlibet/ext/events/bansheeimport.py:117 #, 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:126 msgid "Banshee Import" msgstr "" #: quodlibet/ext/events/bansheeimport.py:127 msgid "Imports ratings and song statistics from Banshee." msgstr "" #: quodlibet/ext/events/bansheeimport.py:136 msgid "_Database path:" msgstr "" #: quodlibet/ext/events/bansheeimport.py:164 #: quodlibet/ext/events/rbimport.py:132 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/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/playlist/export_to_squeezebox.py:80 #: quodlibet/ext/songsmenu/albumart.py:326 #: quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/cover_download.py:384 #: quodlibet/ext/songsmenu/fingerprint/search.py:278 #: quodlibet/ext/songsmenu/html.py:75 quodlibet/ext/songsmenu/lastfmsync.py:216 #: quodlibet/ext/songsmenu/playlist.py:51 #: quodlibet/ext/songsmenu/replaygain.py:355 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/_editutils.py:42 #: quodlibet/qltk/lyrics.py:34 quodlibet/qltk/msg.py:52 #: 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:16 msgid "Internet Radio Log" msgstr "" #: quodlibet/ext/events/iradiolog.py:17 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:31 msgid "Outputs a Jabber User Tunes file to ~/.quodlibet/jabber." 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 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:37 msgid "MPRIS D-Bus Support" msgstr "" #: quodlibet/ext/events/mpris/__init__.py:38 msgid "" "Allows control of Quod Libet using the MPRIS 2 D-Bus Interface Specification." msgstr "" #: quodlibet/ext/events/mpris/__init__.py:44 #: quodlibet/ext/events/trayicon/prefs.py:36 msgid "Hide main window on close" msgstr "" #: quodlibet/ext/events/mpris/__init__.py:47 #: quodlibet/ext/events/trayicon/prefs.py:38 quodlibet/qltk/prefs.py:69 msgid "Behavior" msgstr "Behaviour" #: 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" msgstr "" #: quodlibet/ext/events/mqtt.py:138 msgid "broker hostname / IP (defaults to localhost)" msgstr "" #: quodlibet/ext/events/mqtt.py:140 msgid "Broker port" msgstr "" #: quodlibet/ext/events/mqtt.py:140 msgid "broker port (defaults to 1883)" msgstr "" #: quodlibet/ext/events/mqtt.py:142 msgid "Broker username" 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: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:205 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "" #: quodlibet/ext/events/mqtt.py:209 #, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s)" msgstr "" #: quodlibet/ext/events/mqtt.py:212 msgid "Connection error" 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/qlscrobbler.py:176 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:253 #, python-format msgid "Could not contact service '%s'." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:259 msgid "Authentication failed: invalid URL." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:276 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:281 msgid "Client is banned. Contact the author." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:285 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:350 msgid "AudioScrobbler Submission" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:351 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:456 msgid "Authentication successful." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:468 msgid "_Service:" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:468 msgid "_URL:" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:468 msgid "User_name:" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:469 msgid "_Password:" msgstr "" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:485 msgid "Other…" msgstr "" #. verify data #: quodlibet/ext/events/qlscrobbler.py:523 msgid "_Verify account data" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:528 #: quodlibet/ext/songsmenu/lastfmsync.py:309 msgid "Account" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:536 msgid "_Artist pattern:" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:536 msgid "_Title pattern:" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:537 msgid "Exclude _filter:" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:555 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:565 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" #: quodlibet/ext/events/qlscrobbler.py:574 msgid "Songs matching this filter will not be submitted" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:582 msgid "_Offline mode (don't submit anything)" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:586 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:119 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "" #: quodlibet/ext/events/rbimport.py:127 msgid "Rhythmbox Import" msgstr "" #: quodlibet/ext/events/rbimport.py:128 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:73 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "" #: quodlibet/ext/events/searchprovider.py:79 msgid "GNOME Search Provider" msgstr "" #: quodlibet/ext/events/searchprovider.py:80 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" "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:29 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:56 #: quodlibet/ext/playlist/export_to_squeezebox.py:89 msgid "Error finding Squeezebox server" msgstr "" #: quodlibet/ext/events/squeezebox_sync.py:57 #: quodlibet/ext/playlist/export_to_squeezebox.py:90 #, python-format msgid "Error finding %s. Please check settings" msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:34 msgid "Synchronized Lyrics" msgstr "Synchronised Lyrics" #: quodlibet/ext/events/synchronizedlyrics.py:35 msgid "Shows synchronized lyrics from .lrc file with same name as the track." msgstr "Shows synchronised lyrics from .lrc file with same name as the track." #: quodlibet/ext/events/synchronizedlyrics.py:69 msgid "Text:" msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:79 msgid "Background:" msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:90 msgid "Font" msgstr "" #: quodlibet/ext/events/synchronizedlyrics.py:93 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:145 msgid "Paused:" msgstr "" #: quodlibet/ext/events/telepathy_status.py:146 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "" #: quodlibet/ext/events/telepathy_status.py:162 msgid "Plain text for status when there is no current song" msgstr "" #: quodlibet/ext/events/telepathy_status.py:163 msgid "No song:" msgstr "" #. Frame #: quodlibet/ext/events/telepathy_status.py:170 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:91 msgid "Thumb Rating" msgstr "" #: quodlibet/ext/events/thumbrating.py:92 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 '~#score'." 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:47 msgid "Not playing" msgstr "" #: quodlibet/ext/events/trayicon/__init__.py:53 msgid "Tray Icon" msgstr "" #: quodlibet/ext/events/trayicon/__init__.py:54 msgid "Controls Quod Libet from the system tray." msgstr "" #: quodlibet/ext/events/trayicon/menu.py:42 #, python-format msgid "_Show %(application-name)s" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:61 #: quodlibet/qltk/quodlibetwindow.py:183 quodlibet/qltk/quodlibetwindow.py:936 #: quodlibet/qltk/quodlibetwindow.py:1142 msgid "_Play" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:64 #: quodlibet/qltk/quodlibetwindow.py:185 quodlibet/qltk/quodlibetwindow.py:1144 #: quodlibet/qltk/wlw.py:50 msgid "P_ause" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:69 #: quodlibet/qltk/quodlibetwindow.py:190 quodlibet/qltk/quodlibetwindow.py:931 msgid "Pre_vious" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:72 #: quodlibet/qltk/quodlibetwindow.py:194 quodlibet/qltk/quodlibetwindow.py:941 msgid "_Next" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:77 msgid "_Shuffle" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:82 msgid "_Repeat" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:87 msgid "Stop _After This Song" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:93 #: quodlibet/qltk/quodlibetwindow.py:902 msgid "Open _Browser" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:104 #: quodlibet/qltk/quodlibetwindow.py:921 quodlibet/qltk/songsmenu.py:383 msgid "Edit _Tags" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:113 #: quodlibet/qltk/quodlibetwindow.py:864 quodlibet/qltk/songsmenu.py:396 msgid "_Information" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:115 quodlibet/qltk/songsmenu.py:324 msgid "Play_lists" msgstr "" #: quodlibet/ext/events/trayicon/menu.py:133 #: quodlibet/qltk/quodlibetwindow.py:916 msgid "_Quit" 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 quodlibet/ext/events/weblyrics.py:193 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:606 msgid "Waveform Seek Bar" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:610 msgid "A seekbar in the shape of the waveform of the current song." msgstr "" #: quodlibet/ext/events/waveformseekbar.py:679 msgid "Override foreground color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:683 msgid "Override hover color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:687 msgid "Override remaining color:" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:691 msgid "Show current position" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:696 msgid "Show time labels" msgstr "" #: quodlibet/ext/events/waveformseekbar.py:704 msgid "Seek amount when scrolling (milliseconds):" msgstr "" #: quodlibet/ext/events/weblyrics.py:208 msgid "No lyrics found" msgstr "" #: quodlibet/ext/events/weblyrics.py:268 msgid "_Zoom level:" msgstr "" #: quodlibet/ext/events/weblyrics.py:286 msgid "URL:" msgstr "" #: quodlibet/ext/events/weblyrics.py:291 msgid "Revert to default" msgstr "" #: quodlibet/ext/events/weblyrics.py:306 msgid "Search via above URL if the lyrics couldn't be found in LyricsWikia." msgstr "" #: quodlibet/ext/events/weblyrics.py:323 msgid "Alternate search" msgstr "" #: quodlibet/ext/events/weblyrics.py:332 msgid "Web Lyrics" msgstr "" #: quodlibet/ext/events/weblyrics.py:333 msgid "Shows a sidebar containing online lyrics of the playing song." 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 #, 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:147 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:100 msgid "Exports a playlist by copying files to a folder." msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:121 #: quodlibet/ext/songsmenu/playlist.py:132 msgid "Unable to export playlist" msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:122 msgid "Ensure you have write access to the destination." msgstr "" #: quodlibet/ext/playlist/export_to_folder.py:165 msgid "Default filename pattern:" 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. Shares configuration with <a href=" "\"quodlibet:///prefs/plugins/Squeezebox Output\">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:96 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/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/queue.py:18 msgid "Queue Only" msgstr "" #: quodlibet/ext/playorder/queue.py:20 msgid "" "Limits playing of songs to the queue.\n" "Select this play order in the main window, then double-clicking any song " "will enqueue it instead of playing." msgstr "" #: quodlibet/ext/playorder/reverse.py:14 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/shufflebygrouping.py:32 #: quodlibet/ext/playorder/shufflebygrouping.py:94 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. 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:95 msgid "Waiting to start new group…" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:145 msgid "Grouping tag:" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:149 msgid "Tag to group songs by" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:151 msgid "Filter tag:" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:156 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:161 msgid "Delay:" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:167 msgid "Time delay in seconds before starting next group" msgstr "" #: quodlibet/ext/playorder/shufflebygrouping.py:183 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/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:49 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/missing.py:16 msgid "Missing Query" msgstr "" #: quodlibet/ext/query/missing.py:17 msgid "Matches songs without the given tag." msgstr "" #: quodlibet/ext/query/missing.py:32 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/savedsearch.py:19 msgid "Include Saved Search" msgstr "" #: quodlibet/ext/query/savedsearch.py:20 msgid "Include the results of a saved search as part of another query." 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:20 #: quodlibet/ext/songsmenu/importexport.py:38 quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "" #: quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:333 msgid "Fit image to _window" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:339 msgid "See '[plugins] cover_filenames' config entry for image filename strings" msgstr "" #. Both labels #: quodlibet/ext/songsmenu/albumart.py:345 msgid "_Program:" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:350 msgid "_Edit image after saving" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:352 msgid "File_name:" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:468 msgid "Saving failed" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:469 #, python-format msgid "Unable to save \"%s\"." msgstr "" #: quodlibet/ext/songsmenu/albumart.py:567 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:624 msgid "Album Art Downloader" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:677 #, python-format msgid "from %(source)s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:680 #, python-format msgid "Resolution: %s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:683 #, python-format msgid "Size: %s" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:729 msgid "Per engine 'at best' results limit" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:739 msgid "_Search" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:821 #: quodlibet/ext/songsmenu/brainz/widgets.py:451 msgid "Searching…" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:886 #: quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:1008 msgid "Download Album Art" msgstr "" #: quodlibet/ext/songsmenu/albumart.py:1009 msgid "Downloads album covers from various websites." msgstr "" #: quodlibet/ext/songsmenu/albumart.py:1022 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 msgid "Disc" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 #: quodlibet/ext/songsmenu/replaygain.py:394 quodlibet/qltk/tracknumbers.py:91 msgid "Track" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:132 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:447 msgid "Please enter a query." msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:465 #: quodlibet/ext/songsmenu/brainz/widgets.py:496 msgid "Error encountered. Please retry." msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:472 #: quodlibet/ext/songsmenu/brainz/widgets.py:488 msgid "Loading result…" msgstr "" #: quodlibet/ext/songsmenu/brainz/widgets.py:475 msgid "No results found." msgstr "" #: quodlibet/ext/songsmenu/console.py:40 msgid "Python Console" msgstr "" #: quodlibet/ext/songsmenu/console.py:41 msgid "Interactive Python console. Opens a new window." msgstr "" #: quodlibet/ext/songsmenu/console.py:48 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "" #: quodlibet/ext/songsmenu/console.py:55 msgid "Python Console Sidebar" msgstr "" #: quodlibet/ext/songsmenu/console.py:56 msgid "" "Interactive Python console sidebar, that follows the selected songs in the " "main window." msgstr "" #: quodlibet/ext/songsmenu/console.py:75 msgid "You can access the following objects by default:" msgstr "" #: quodlibet/ext/songsmenu/console.py:85 msgid "Your current working directory is:" 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 cover plugins." msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:160 msgid "Classic" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:161 msgid "Large" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:162 msgid "HD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:163 msgid "Full HD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:164 msgid "WQXGA" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:165 msgid "4K UHD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:171 msgid "Cover Art Download" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:231 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:295 #, python-format msgid "" "Nothing found for albums:\n" "<i>%(albums)s</i>.\n" "\n" "Providers used:\n" "<tt>%(providers)s</tt>" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:298 msgid "No covers found" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:320 #, python-brace-format msgid "{size} ✕ {size} px" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:333 msgid "Preview size" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:342 msgid "Save destination" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:373 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:375 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:55 msgid "pattern" 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:91 msgid "Input value" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:92 #, python-format msgid "Value for %s?" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:137 msgid "Custom Commands" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:138 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:197 #: quodlibet/ext/songsmenu/custom_commands.py:207 #: quodlibet/ext/songsmenu/custom_commands.py:259 msgid "Edit Custom Commands" msgstr "" #: quodlibet/ext/songsmenu/custom_commands.py:290 #, 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:41 msgid "Edit Playcount" msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:20 msgid "" "Edit a song's ~#playcount and ~#skipcount.\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's ~#playcount to 0, the ~#lastplayed and ~#laststarted " "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:68 msgid "Play Count" msgstr "" #: quodlibet/ext/songsmenu/editplaycount.py:69 msgid "Skip Count" msgstr "" #: quodlibet/ext/songsmenu/embedded.py:25 msgid "Edit Embedded Images" msgstr "" #: quodlibet/ext/songsmenu/embedded.py:26 msgid "Removes or replaces embedded images." msgstr "" #: quodlibet/ext/songsmenu/embedded.py:80 msgid "_Remove all Images" msgstr "" #: quodlibet/ext/songsmenu/embedded.py:85 msgid "_Embed Current 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/exact_rating.py:54 quodlibet/qltk/ratingsmenu.py:98 msgid "Change _Rating" 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 "" #: quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" 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:65 quodlibet/ext/songsmenu/html.py:75 msgid "Export to HTML" msgstr "" #: quodlibet/ext/songsmenu/html.py:66 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:62 msgid "Error uploading" msgstr "" #: quodlibet/ext/songsmenu/ifp.py:63 #, python-format msgid "" "Unable to upload <b>%s</b>. The device may be out of space, or turned off." msgstr "" #: quodlibet/ext/songsmenu/importexport.py:59 msgid "Export Metadata" msgstr "" #: quodlibet/ext/songsmenu/importexport.py:60 msgid "Exports metadata of selected songs as a .tags file." msgstr "" #: quodlibet/ext/songsmenu/importexport.py:104 msgid "Import Metadata" msgstr "" #: quodlibet/ext/songsmenu/importexport.py:105 msgid "Imports metadata for selected songs from a .tags file." msgstr "" #: quodlibet/ext/songsmenu/k3b.py:23 msgid "Burn CD" msgstr "" #: quodlibet/ext/songsmenu/k3b.py:24 msgid "Burns CDs with K3b, Brasero or xfburn." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:94 msgid "Updating chart list." msgstr "" #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:113 msgid "Already up-to-date." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:121 #, python-format msgid "Fetching chart for week of %s." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:143 msgid "Sync complete." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:149 msgid "Error during sync" msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:214 #: quodlibet/ext/songsmenu/lastfmsync.py:244 msgid "Last.fm Sync" msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:245 msgid "Updates your library's statistics from your Last.fm profile." msgstr "" #: quodlibet/ext/songsmenu/lastfmsync.py:298 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 "" #. Create a dialog. #: quodlibet/ext/songsmenu/migratemetadata.py:37 #: quodlibet/ext/songsmenu/migratemetadata.py:46 msgid "Migrate Metadata" msgstr "" #: quodlibet/ext/songsmenu/migratemetadata.py:40 msgid "Copies the quodlibet-specific metadata between songs." msgstr "" #: quodlibet/ext/songsmenu/migratemetadata.py:53 msgid "_Copy" msgstr "" #: quodlibet/ext/songsmenu/migratemetadata.py:55 msgid "_Paste" msgstr "" #. Create the tag table. #: quodlibet/ext/songsmenu/migratemetadata.py:65 msgid "Information to copy/paste" msgstr "" #. Create the indexing box. #: quodlibet/ext/songsmenu/migratemetadata.py:87 msgid "Map tracks by disc and track number" msgstr "" #: quodlibet/ext/songsmenu/migratemetadata.py:88 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 "" #: quodlibet/ext/songsmenu/migratemetadata.py:104 #, python-format msgid "There is %d stored track." msgid_plural "There are %d stored tracks." msgstr[0] "" msgstr[1] "" #: quodlibet/ext/songsmenu/playlist.py:31 msgid "Export as Playlist" msgstr "" #: quodlibet/ext/songsmenu/playlist.py:32 msgid "Exports songs to an M3U or PLS playlist." msgstr "" #: quodlibet/ext/songsmenu/playlist.py:77 msgid "Use relative paths" msgstr "" #: quodlibet/ext/songsmenu/playlist.py:77 msgid "Use absolute paths" msgstr "" #: quodlibet/ext/songsmenu/playlist.py:133 #, python-format msgid "Writing to <b>%s</b> 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:352 msgid "ReplayGain Analyzer" msgstr "ReplayGain Analyser" #: 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 <b>%(to-process)s</b> album to update (of %(all)s)" msgid_plural "There are <b>%(to-process)s</b> 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:570 msgid "" "Analyzes and updates ReplayGain information, using GStreamer. Results are " "grouped by album." msgstr "" "Analyses and updates Rep\n" "layGain information, using GStreamer. Results are grouped by album." #: quodlibet/ext/songsmenu/replaygain.py:608 msgid "always" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:609 msgid "if <b>any</b> RG tags are missing" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:611 msgid "if <b>album</b> RG tags are missing" msgstr "" #: quodlibet/ext/songsmenu/replaygain.py:628 msgid "_Process albums:" msgstr "" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:640 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:37 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern-example)s." msgstr "" #: quodlibet/ext/songsmenu/website_search.py:81 msgid "Search URL patterns" msgstr "" #: quodlibet/ext/songsmenu/website_search.py:91 msgid "Edit search URLs" msgstr "" #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:117 msgid "Configure Searches…" msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:35 msgid "Search Tag in Wikipedia" msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:36 msgid "" "Opens a browser window with the Wikipedia article on the selected song's " "corresponding tag." msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:56 #, python-format msgid "Search at %(website)s" msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:70 #: quodlibet/ext/songsmenu/wikipedia.py:76 quodlibet/qltk/edittags.py:452 msgid "Edit Tags" msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:111 msgid "Search failed" msgstr "" #: quodlibet/ext/songsmenu/wikipedia.py:112 #, python-format msgid "Tag \"%s\" not found." msgstr "" #. then (try to) load all new files #: quodlibet/library/libraries.py:651 quodlibet/library/libraries.py:661 #: quodlibet/library/libraries.py:727 quodlibet/library/libraries.py:746 #: quodlibet/qltk/information.py:272 quodlibet/qltk/prefs.py:695 #: quodlibet/util/library.py:123 msgid "Library" msgstr "" #: quodlibet/library/libraries.py:651 msgid "Checking mount points" msgstr "" #: quodlibet/library/libraries.py:661 msgid "Scanning library" msgstr "" #: quodlibet/library/libraries.py:726 #, python-format msgid "Scanning %s" msgstr "" #: quodlibet/library/libraries.py:746 msgid "Loading files" msgstr "" #: quodlibet/main.py:50 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:462 msgid "Print terse output" msgstr "" #: quodlibet/operon/commands.py:43 quodlibet/operon/commands.py:82 #: quodlibet/operon/commands.py:464 #, 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:336 quodlibet/operon/commands.py:340 #: quodlibet/operon/commands.py:392 quodlibet/operon/commands.py:395 #: quodlibet/operon/commands.py:434 quodlibet/operon/commands.py:469 #: quodlibet/operon/commands.py:509 quodlibet/operon/commands.py:544 #: quodlibet/operon/commands.py:586 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:471 msgid "Too many arguments" msgstr "" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:91 #: quodlibet/operon/commands.py:476 quodlibet/qltk/data_editors.py:352 msgid "Description" msgstr "" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:476 #: quodlibet/qltk/edittags.py:504 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:324 #: quodlibet/operon/commands.py:385 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:304 quodlibet/operon/commands.py:445 #: quodlibet/operon/commands.py:677 #, python-format msgid "Can not set %r" msgstr "" #: quodlibet/operon/commands.py:319 msgid "Remove tags" msgstr "" #: quodlibet/operon/commands.py:326 quodlibet/operon/commands.py:387 msgid "Value is a regular expression" msgstr "" #: quodlibet/operon/commands.py:328 msgid "Remove all tags" msgstr "" #: quodlibet/operon/commands.py:332 msgid "Can't combine '--all' with '--regexp'" msgstr "" #: quodlibet/operon/commands.py:366 #, python-brace-format msgid "Can't remove {tagname} from {filename}" msgstr "" #: quodlibet/operon/commands.py:380 msgid "Remove a tag value" msgstr "" #: quodlibet/operon/commands.py:429 msgid "Add a tag value" msgstr "" #: quodlibet/operon/commands.py:457 msgid "List file information" msgstr "" #: quodlibet/operon/commands.py:503 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" #: quodlibet/operon/commands.py:516 #, python-format msgid "Failed to load image file: %r" msgstr "" #: quodlibet/operon/commands.py:523 quodlibet/operon/commands.py:552 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" #: quodlibet/operon/commands.py:539 msgid "Remove all embedded images" msgstr "" #: quodlibet/operon/commands.py:569 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "" #: quodlibet/operon/commands.py:581 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" #: quodlibet/operon/commands.py:640 msgid "Rename files based on tags" msgstr "" #: quodlibet/operon/commands.py:655 msgid "Fill tags based on the file path" msgstr "" #: quodlibet/operon/commands.py:705 quodlibet/qltk/information.py:309 #: quodlibet/qltk/properties.py:83 quodlibet/qltk/renamefiles.py:245 #: quodlibet/qltk/tagsfrompath.py:228 quodlibet/qltk/tracknumbers.py:78 msgid "File" msgstr "" #: quodlibet/operon/commands.py:713 msgid "Fill tracknumbers for all files" msgstr "" #: quodlibet/operon/commands.py:732 msgid "Print tags based on the given pattern" msgstr "" #: quodlibet/operon/commands.py:769 msgid "Display help information" msgstr "" #: quodlibet/operon/util.py:43 #, python-format msgid "'%(column-id)s' is not a valid column name (%(all-column-ids)s)." msgstr "" #: quodlibet/order/__init__.py:32 msgid "_Unknown" msgstr "" #: quodlibet/order/__init__.py:144 msgid "In Order" msgstr "" #: quodlibet/order/__init__.py:145 msgid "_In Order" msgstr "" #: quodlibet/order/reorder.py:22 msgid "Random" msgstr "" #: quodlibet/order/reorder.py:23 quodlibet/qltk/queue.py:147 msgid "_Random" msgstr "" #: quodlibet/order/reorder.py:40 quodlibet/order/reorder.py:41 msgid "Prefer higher rated" msgstr "" #: quodlibet/order/repeat.py:43 quodlibet/order/repeat.py:44 msgid "Repeat this track" msgstr "" #: quodlibet/order/repeat.py:57 quodlibet/order/repeat.py:58 msgid "Repeat all" msgstr "" #: quodlibet/order/repeat.py:73 quodlibet/order/repeat.py:74 msgid "One Song" msgstr "" #: quodlibet/player/gstbe/player.py:99 msgid "Stream" msgstr "" #: quodlibet/player/gstbe/player.py:99 msgid "Buffering" msgstr "" #: quodlibet/player/gstbe/player.py:453 msgid "Could not create GStreamer pipeline" msgstr "" #: quodlibet/player/gstbe/player.py:652 msgid "No GStreamer element found to handle media format" msgstr "" #: quodlibet/player/gstbe/player.py:653 #, 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:25 msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. In case the pipeline contains a sink, it will be used instead of " "the default one." msgstr "" #: quodlibet/player/gstbe/prefs.py:36 msgid "_Output pipeline:" msgstr "" #: quodlibet/player/gstbe/prefs.py:43 #, python-format msgid "%.1f seconds" msgstr "" #: quodlibet/player/gstbe/prefs.py:57 msgid "_Buffer duration:" msgstr "" #: quodlibet/player/gstbe/prefs.py:66 msgid "Disable _gapless playback" msgstr "" #: quodlibet/player/gstbe/prefs.py:70 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions" msgstr "" #: quodlibet/player/gstbe/util.py:101 msgid "No GStreamer audio sink found" msgstr "" #: quodlibet/player/gstbe/util.py:120 msgid "Invalid GStreamer output pipeline" msgstr "" #: quodlibet/player/xinebe/player.py:90 msgid "Unable to create audio output" msgstr "" #: quodlibet/player/xinebe/player.py:91 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "" #: quodlibet/plugins/__init__.py:61 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" #: quodlibet/plugins/__init__.py:70 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." 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:55 #: quodlibet/qltk/songsmenu.py:66 msgid "_Run Plugin" msgstr "" #: quodlibet/plugins/query.py:63 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:354 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:116 #, python-format msgid "New %s" msgstr "" #: quodlibet/qltk/data_editors.py:215 msgid "(unknown)" msgstr "" #: quodlibet/qltk/data_editors.py:344 msgid "Tag expression" msgstr "" #: quodlibet/qltk/data_editors.py:371 msgid "Tag expression e.g. people:real or ~album~year" msgstr "" #: quodlibet/qltk/data_editors.py:372 msgid "Enter new tag" 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/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:199 msgid "Split into _Multiple Values" msgstr "" #: quodlibet/qltk/edittags.py:221 msgid "Split Disc out of _Album" msgstr "" #: quodlibet/qltk/edittags.py:245 msgid "Split _Version out of Title" msgstr "" #: quodlibet/qltk/edittags.py:302 msgid "Split Arranger out of Ar_tist" msgstr "" #: quodlibet/qltk/edittags.py:307 msgid "Split _Performer out of Artist" msgstr "" #: quodlibet/qltk/edittags.py:313 msgid "Split _Performer out of Title" msgstr "" #: quodlibet/qltk/edittags.py:319 msgid "Split _Originalartist out of Title" msgstr "" #: quodlibet/qltk/edittags.py:326 msgid "Add a Tag" msgstr "" #: quodlibet/qltk/edittags.py:345 msgid "_Tag:" msgstr "" #: quodlibet/qltk/edittags.py:527 msgid "Show _programmatic tags" msgstr "" #: quodlibet/qltk/edittags.py:528 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:558 msgctxt "edittags" msgid "_Revert" msgstr "" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:563 msgctxt "edittags" msgid "_Save" msgstr "" #: quodlibet/qltk/edittags.py:703 msgid "_Configure" msgstr "" #: quodlibet/qltk/edittags.py:718 msgid "_Split Tag" msgstr "" #: quodlibet/qltk/edittags.py:727 msgid "_Copy Value(s)" msgstr "" #: quodlibet/qltk/edittags.py:758 msgid "Unable to add tag" msgstr "" #: quodlibet/qltk/edittags.py:759 #, python-format msgid "Unable to add <b>%s</b>" msgstr "" #: quodlibet/qltk/edittags.py:761 #, python-format msgid "" "The files currently selected do not support multiple values for <b>%s</b>." msgstr "" #. Can't add the new tag. #: quodlibet/qltk/edittags.py:788 quodlibet/qltk/edittags.py:969 #: quodlibet/qltk/tagsfrompath.py:211 quodlibet/util/__init__.py:507 #: quodlibet/util/tags.py:244 msgid "Invalid tag" msgstr "" #: quodlibet/qltk/edittags.py:789 quodlibet/qltk/edittags.py:970 #: quodlibet/qltk/tagsfrompath.py:212 #, python-format msgid "" "Invalid tag <b>%s</b>\n" "\n" "The files currently selected do not support editing this tag." msgstr "" #: quodlibet/qltk/edittags.py:940 quodlibet/qltk/edittags.py:981 msgid "Invalid value" msgstr "" #: quodlibet/qltk/edittags.py:941 quodlibet/qltk/edittags.py:982 #, python-format msgid "" "Invalid value: <b>%(value)s</b>\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:146 msgid "_More options…" msgstr "" #: quodlibet/qltk/entry.py:78 msgid "_Undo" msgstr "" #: quodlibet/qltk/entry.py:80 msgid "_Redo" msgstr "" #: quodlibet/qltk/exfalsowindow.py:94 quodlibet/qltk/quodlibetwindow.py:956 msgid "_About" msgstr "" #: quodlibet/qltk/exfalsowindow.py:98 quodlibet/qltk/quodlibetwindow.py:978 msgid "_Check for Updates…" msgstr "" #: quodlibet/qltk/exfalsowindow.py:104 quodlibet/qltk/quodlibetwindow.py:911 #: quodlibet/qltk/songsmenu.py:289 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:278 msgid "Ex Falso Preferences" msgstr "" #: quodlibet/qltk/exfalsowindow.py:284 quodlibet/qltk/prefs.py:669 msgid "Tag Editing" 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:386 msgid "Unable to create folder" msgstr "" #: quodlibet/qltk/filesel.py:403 msgid "Unable to delete folder" msgstr "" #: quodlibet/qltk/filesel.py:519 quodlibet/qltk/pluginwin.py:34 msgid "Songs" msgstr "" #. Translators: As in "by Artist Name" #: quodlibet/qltk/info.py:42 #, python-format msgid "by %s" msgstr "" #: quodlibet/qltk/info.py:43 quodlibet/qltk/information.py:171 #: quodlibet/qltk/information.py:452 #, python-format msgid "Disc %s" msgstr "" #: quodlibet/qltk/info.py:44 quodlibet/qltk/information.py:176 #, python-format msgid "Track %s" msgstr "" #: quodlibet/qltk/info.py:98 msgid "Current _Song" msgstr "" #: quodlibet/qltk/info.py:108 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:342 #: quodlibet/qltk/information.py:475 quodlibet/qltk/information.py:543 msgid "Information" msgstr "" #: quodlibet/qltk/information.py:127 msgid "Lyrics" msgstr "" #: quodlibet/qltk/information.py:188 quodlibet/qltk/information.py:400 #, python-format msgid "Produced by %s" msgstr "" #: quodlibet/qltk/information.py:203 quodlibet/util/tags.py:85 msgid "artist" msgstr "" #: quodlibet/qltk/information.py:204 quodlibet/qltk/information.py:573 #: quodlibet/util/tags.py:85 msgid "artists" msgstr "" #. for backwards compat #: quodlibet/qltk/information.py:225 quodlibet/util/tags.py:96 #: quodlibet/util/tags.py:125 msgid "performers" msgstr "" #: quodlibet/qltk/information.py:239 quodlibet/qltk/information.py:252 #: quodlibet/qltk/songlistcolumns.py:273 msgid "Never" msgstr "" #: quodlibet/qltk/information.py:240 #, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/information.py:258 quodlibet/util/tags.py:150 msgid "added" msgstr "" #: quodlibet/qltk/information.py:259 quodlibet/util/tags.py:151 msgid "last played" msgstr "" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:161 msgid "plays" msgstr "" #: quodlibet/qltk/information.py:261 quodlibet/util/tags.py:162 msgid "skips" msgstr "" #: quodlibet/qltk/information.py:262 quodlibet/util/tags.py:167 msgid "rating" msgstr "" #: quodlibet/qltk/information.py:291 msgid "path" msgstr "" #: quodlibet/qltk/information.py:292 quodlibet/util/tags.py:165 msgid "length" msgstr "" #: quodlibet/qltk/information.py:293 msgid "format" msgstr "" #: quodlibet/qltk/information.py:294 quodlibet/util/tags.py:175 msgid "codec" msgstr "" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:176 msgid "encoding" msgstr "" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:172 msgid "bitrate" msgstr "" #: quodlibet/qltk/information.py:297 quodlibet/util/tags.py:173 msgid "file size" msgstr "" #: quodlibet/qltk/information.py:298 quodlibet/util/tags.py:160 msgid "modified" msgstr "" #: quodlibet/qltk/information.py:335 msgid "Additional" msgstr "" #: quodlibet/qltk/information.py:387 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/information.py:462 msgid "Track unavailable" msgstr "" #: quodlibet/qltk/information.py:500 quodlibet/qltk/information.py:590 #, python-format msgid "%d song with no album" msgid_plural "%d songs with no album" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/information.py:503 msgid "Selected Discography" msgstr "" #: quodlibet/qltk/information.py:570 #, python-format msgid "%d song with no artist" msgid_plural "%d songs with no artist" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/information.py:598 quodlibet/util/tags.py:83 msgid "albums" msgstr "" #: quodlibet/qltk/information.py:611 msgid "Total length:" msgstr "" #: quodlibet/qltk/information.py:615 msgid "Total size:" msgstr "" #: quodlibet/qltk/information.py:618 msgid "Files" msgstr "" #: quodlibet/qltk/lyrics.py:36 msgid "_View online" msgstr "" #: quodlibet/qltk/lyrics.py:64 msgid "No lyrics found for this song." msgstr "" #: quodlibet/qltk/lyrics.py:75 msgid "Searching for lyrics…" 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/msg.py:41 msgid "Discard tag changes?" msgstr "" #: quodlibet/qltk/msg.py:42 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "" #: quodlibet/qltk/msg.py:55 quodlibet/qltk/prefs.py:631 #: quodlibet/qltk/prefs.py:638 quodlibet/qltk/textedit.py:63 #: quodlibet/qltk/tracknumbers.py:116 msgid "_Revert" msgstr "" #: quodlibet/qltk/msg.py:104 msgid "File exists" msgstr "" #: quodlibet/qltk/msg.py:106 #, python-format msgid "Replace %(file-name)s?" msgstr "" #: quodlibet/qltk/msg.py:112 msgid "_Replace File" msgstr "" #: quodlibet/qltk/notif.py:182 msgid "Active tasks" msgstr "" #: quodlibet/qltk/notif.py:188 #, python-format msgid "%d tasks running" msgstr "" #: quodlibet/qltk/playorder.py:256 msgid "Toggle shuffle mode" msgstr "" #: quodlibet/qltk/playorder.py:272 msgid "Toggle repeat mode" msgstr "" #: quodlibet/qltk/pluginwin.py:36 msgid "Events" msgstr "" #: quodlibet/qltk/pluginwin.py:37 msgid "Play Order" msgstr "" #: quodlibet/qltk/pluginwin.py:38 msgid "Editing" msgstr "" #: quodlibet/qltk/pluginwin.py:39 msgid "Renaming" msgstr "" #: quodlibet/qltk/pluginwin.py:40 msgid "Querying" msgstr "" #: quodlibet/qltk/pluginwin.py:42 msgid "Covers" msgstr "" #: quodlibet/qltk/pluginwin.py:64 msgid "Plugin Errors" msgstr "" #: quodlibet/qltk/pluginwin.py:145 msgid "Enabled" msgstr "" #: quodlibet/qltk/pluginwin.py:146 msgid "Disabled" msgstr "" #: quodlibet/qltk/pluginwin.py:152 msgid "No category" msgstr "" #: quodlibet/qltk/pluginwin.py:328 msgid "No plugins found." msgstr "" #: quodlibet/qltk/pluginwin.py:384 msgid "Plugins" msgstr "" #: quodlibet/qltk/pluginwin.py:406 msgid "Filter by plugin state / tag" msgstr "" #: quodlibet/qltk/pluginwin.py:412 msgid "Filter by plugin type" msgstr "" #: quodlibet/qltk/pluginwin.py:417 msgid "Filter by plugin name or description" msgstr "" #: quodlibet/qltk/pluginwin.py:420 msgid "Show _Errors" msgstr "" #: quodlibet/qltk/prefs.py:45 msgid "_Disc" msgstr "" #: quodlibet/qltk/prefs.py:46 msgid "_Track" msgstr "" #: quodlibet/qltk/prefs.py:47 msgid "Grou_ping" msgstr "" #: quodlibet/qltk/prefs.py:50 msgid "Al_bum" msgstr "" #: quodlibet/qltk/prefs.py:55 msgid "_Filename" msgstr "" #: quodlibet/qltk/prefs.py:57 msgid "_Length" msgstr "" #: quodlibet/qltk/prefs.py:64 msgid "_Jump to playing song automatically" msgstr "" #: quodlibet/qltk/prefs.py:66 msgid "When the playing song changes, scroll to it in the song list" msgstr "" #: quodlibet/qltk/prefs.py:82 msgid "_Others:" msgstr "" #: quodlibet/qltk/prefs.py:88 msgid "_Edit…" msgstr "" #: quodlibet/qltk/prefs.py:91 msgid "Add or remove additional column headers" msgstr "" #: quodlibet/qltk/prefs.py:101 msgid "Visible Columns" msgstr "" #: quodlibet/qltk/prefs.py:104 msgid "Title includes _version" msgstr "" #: quodlibet/qltk/prefs.py:106 msgid "Artist includes all _people" msgstr "" #: quodlibet/qltk/prefs.py:108 msgid "Album includes _disc subtitle" msgstr "" #: quodlibet/qltk/prefs.py:110 msgid "Filename includes _folder" msgstr "" #: quodlibet/qltk/prefs.py:123 msgid "Column Preferences" msgstr "" #: quodlibet/qltk/prefs.py:129 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "" #: quodlibet/qltk/prefs.py:142 quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "" #: quodlibet/qltk/prefs.py:222 msgid "Edit Columns" msgstr "" #: quodlibet/qltk/prefs.py:259 msgid "Duration totals" msgstr "" #: quodlibet/qltk/prefs.py:271 msgid "_Global filter:" msgstr "" #: quodlibet/qltk/prefs.py:277 msgid "Apply this query in addition to all others" msgstr "" #. Translators: The heading of the preference group, no action #: quodlibet/qltk/prefs.py:283 msgctxt "heading" msgid "Search" msgstr "" #: quodlibet/qltk/prefs.py:287 quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "" #: quodlibet/qltk/prefs.py:293 msgid "Confirm _multiple ratings" msgstr "" #: quodlibet/qltk/prefs.py:295 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "" #: quodlibet/qltk/prefs.py:298 msgid "Enable _one-click ratings" msgstr "" #: quodlibet/qltk/prefs.py:300 msgid "Enable rating by clicking on the rating column in the song list" msgstr "" #: quodlibet/qltk/prefs.py:306 quodlibet/qltk/prefs.py:672 msgid "Ratings" msgstr "" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:312 msgid "Prefer _embedded art" msgstr "" #: quodlibet/qltk/prefs.py:314 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" #: quodlibet/qltk/prefs.py:321 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:325 msgid "_Preferred image filename(s):" msgstr "" #: quodlibet/qltk/prefs.py:340 msgid "Album Art" msgstr "" #: quodlibet/qltk/prefs.py:361 msgid "Playback" msgstr "" #: quodlibet/qltk/prefs.py:366 msgid "Output Configuration" msgstr "" #: quodlibet/qltk/prefs.py:377 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" #: quodlibet/qltk/prefs.py:380 msgid "_Fall-back gain (dB):" msgstr "" #: quodlibet/qltk/prefs.py:391 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "" #: quodlibet/qltk/prefs.py:394 msgid "_Pre-amp gain (dB):" msgstr "" #: quodlibet/qltk/prefs.py:399 msgid "_Enable Replay Gain volume adjustment" msgstr "" #: quodlibet/qltk/prefs.py:424 msgid "Replay Gain Volume Adjustment" msgstr "" #: quodlibet/qltk/prefs.py:431 msgid "_Continue playback on startup" msgstr "" #: quodlibet/qltk/prefs.py:433 msgid "" "If music is playing on shutdown, automatically start playing on next startup" msgstr "" #: quodlibet/qltk/prefs.py:437 msgid "Startup" msgstr "" #: quodlibet/qltk/prefs.py:464 msgid "_Default rating:" msgstr "" #: quodlibet/qltk/prefs.py:507 msgid "Rating _scale:" msgstr "" #: quodlibet/qltk/prefs.py:556 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:561 msgid "_Bayesian averaging amount:" msgstr "" #: quodlibet/qltk/prefs.py:578 msgid "_Email:" msgstr "" #: quodlibet/qltk/prefs.py:580 msgid "Ratings and play counts will be saved in tags for this email address" msgstr "" #: quodlibet/qltk/prefs.py:600 msgid "Auto-save tag changes" msgstr "" #: quodlibet/qltk/prefs.py:602 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "" #: quodlibet/qltk/prefs.py:611 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:621 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:634 msgid "Split _tag on:" msgstr "" #: quodlibet/qltk/prefs.py:641 msgid "Split _subtag on:" msgstr "" #: quodlibet/qltk/prefs.py:666 msgid "Tags" msgstr "" #: quodlibet/qltk/prefs.py:687 msgid "Updating for new ratings" msgstr "" #: quodlibet/qltk/prefs.py:697 msgid "Scan library _on start" msgstr "" #: quodlibet/qltk/prefs.py:707 quodlibet/qltk/quodlibetwindow.py:990 msgid "_Scan Library" msgstr "" #: quodlibet/qltk/prefs.py:709 quodlibet/qltk/quodlibetwindow.py:1052 msgid "Check for changes in your library" msgstr "" #: quodlibet/qltk/prefs.py:714 msgid "Re_build Library" msgstr "" #: quodlibet/qltk/prefs.py:717 msgid "Reload all songs in your library. This can take a long time." msgstr "" #: quodlibet/qltk/prefs.py:727 msgid "Scan Directories" msgstr "" #: quodlibet/qltk/prefs.py:733 msgid "Hidden Songs" msgstr "" #: quodlibet/qltk/properties.py:157 quodlibet/util/collection.py:413 #, 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:104 msgid "_Queue" msgstr "" #: quodlibet/qltk/queue.py:124 msgid "Ephemeral" msgstr "" #: quodlibet/qltk/queue.py:125 msgid "Remove songs from the queue after playing them" msgstr "" #: quodlibet/qltk/queue.py:133 msgid "Persistent" msgstr "" #: quodlibet/qltk/queue.py:134 msgid "Keep songs in the queue after playing them" msgstr "" #: quodlibet/qltk/queue.py:142 msgid "Mode" msgstr "" #: quodlibet/qltk/queue.py:153 msgid "Stop at End" msgstr "" #: quodlibet/qltk/queue.py:157 msgid "_Clear Queue" msgstr "" #: quodlibet/qltk/queue.py:178 msgid "Disable queue - the queue will be ignored when playing" msgstr "" #: quodlibet/qltk/queue.py:290 #, python-format msgid "%(count)d song (%(time)s)" msgid_plural "%(count)d songs (%(time)s)" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/quodlibetwindow.py:198 msgid "_Browse Library" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:348 msgid "Toggle queue visibility" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:376 msgid "Playback Error" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:384 msgid "Set up library directories?" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:385 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:391 msgid "_Not Now" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:392 msgid "_Set Up" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:845 msgid "Unable to add songs" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:846 quodlibet/qltk/quodlibetwindow.py:1286 #, python-format msgid "%s uses an unsupported protocol." msgstr "" #: quodlibet/qltk/quodlibetwindow.py:869 msgid "_Jump to Playing Song" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:876 msgid "_File" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:877 msgid "_Song" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:878 msgid "_View" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:879 msgid "_Browse" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:880 msgid "_Control" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:881 msgid "_Help" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:887 msgid "_Add a Folder…" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:892 msgid "_Add a File…" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:897 msgid "_Add a Location…" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:926 msgid "Edit Bookmarks…" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:946 msgid "Stop After This Song" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:952 msgid "_Keyboard Shortcuts" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:961 msgid "Online Help" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:970 msgid "Search Help" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:1274 msgid "Add a Location" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:1275 msgid "Enter the location of an audio file:" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:1280 #: quodlibet/qltk/quodlibetwindow.py:1285 msgid "Unable to add location" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:1281 #, python-format msgid "%s is not a valid location." msgstr "" #: quodlibet/qltk/quodlibetwindow.py:1294 #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "Add Music" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:1294 quodlibet/qltk/scanbox.py:99 msgid "_Add Folders" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:1301 msgid "Music Files" msgstr "" #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "_Add Files" msgstr "" #: quodlibet/qltk/ratingsmenu.py:24 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "" #: quodlibet/qltk/ratingsmenu.py:26 msgid "The saved ratings will be removed" msgstr "" #: quodlibet/qltk/ratingsmenu.py:27 #, python-format msgid "The rating of all selected songs will be changed to '%s'" msgstr "" #: quodlibet/qltk/ratingsmenu.py:57 quodlibet/qltk/ratingsmenu.py:111 msgid "_Remove 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:167 quodlibet/qltk/tagsfrompath.py:115 msgid "Path Patterns" msgstr "" #: quodlibet/qltk/renamefiles.py:168 quodlibet/qltk/tagsfrompath.py:116 msgid "Edit saved patterns…" 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 <b>%(old-name)s</b> to <b>%(new-name)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." 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<b>%s</b>\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:47 msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "" #: quodlibet/qltk/scanbox.py:99 msgid "Select Directories" msgstr "" #: quodlibet/qltk/searchbar.py:57 msgid "Saved Searches" msgstr "" #: quodlibet/qltk/searchbar.py:58 msgid "Edit saved searches…" msgstr "" #: quodlibet/qltk/searchbar.py:82 msgid "Search your library, using free text or QL queries" msgstr "" #: quodlibet/qltk/searchbar.py:144 msgid "Search after _typing" msgstr "" #: quodlibet/qltk/searchbar.py:147 msgid "Show search results after the user stops typing" msgstr "" #: quodlibet/qltk/searchbar.py:215 msgid "_Limit:" msgstr "" #: quodlibet/qltk/searchbar.py:228 msgid "_Weight" msgstr "" #: quodlibet/qltk/searchbar.py:355 msgid "Add query" msgstr "" #: quodlibet/qltk/searchbar.py:356 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:379 #, python-format msgid "_Filter on %s" msgstr "" #: quodlibet/qltk/songlist.py:1098 msgid "All _Headers" msgstr "" #: quodlibet/qltk/songlist.py:1099 msgid "_Track Headers" msgstr "" #: quodlibet/qltk/songlist.py:1100 msgid "_Album Headers" msgstr "" #: quodlibet/qltk/songlist.py:1101 msgid "_People Headers" msgstr "" #: quodlibet/qltk/songlist.py:1102 msgid "_Date Headers" msgstr "" #: quodlibet/qltk/songlist.py:1103 msgid "_File Headers" msgstr "" #: quodlibet/qltk/songlist.py:1104 msgid "_Production Headers" msgstr "" #: quodlibet/qltk/songlist.py:1119 msgid "_Customize Headers…" msgstr "_Customise Headers…" #: quodlibet/qltk/songlist.py:1124 msgid "_Expand Column" msgstr "" #: quodlibet/qltk/songsmenu.py:40 #, python-format msgid "Remove track: \"%%(title)s\" from library?" msgid_plural "Remove %(count)d tracks from library?" msgstr[0] "" msgstr[1] "" #: quodlibet/qltk/songsmenu.py:46 msgid "Remove from Library" msgstr "" #: quodlibet/qltk/songsmenu.py:51 #, 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:62 #, 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:134 msgid "Configure Plugins…" msgstr "" #: quodlibet/qltk/songsmenu.py:329 msgid "Add to _Queue" msgstr "" #: quodlibet/qltk/songsmenu.py:349 msgid "_Remove from Library…" msgstr "" #: quodlibet/qltk/songsmenu.py:414 msgid "Unable to show files" msgstr "" #: quodlibet/qltk/songsmenu.py:415 msgid "Error showing files, or no program available to show them." msgstr "" #: quodlibet/qltk/songsmenu.py:422 #, python-format msgid "_Show in File Manager" msgid_plural "_Show %(total)d Files in File Manager" msgstr[0] "" msgstr[1] "" #: 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<b>%s</b>\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" #: quodlibet/qltk/tagsfrompath.py:215 msgid "Invalid tags" msgstr "" #: quodlibet/qltk/tagsfrompath.py:216 #, python-format msgid "" "Invalid tags <b>%s</b>\n" "\n" "The files currently selected do not support editing these tags." 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:925 #, python-format msgid "and %d more…" msgstr "" #: quodlibet/qltk/wlw.py:199 msgid "Saving the songs you changed." msgstr "" #: quodlibet/qltk/wlw.py:200 #, python-format msgid "" "%(current)d/%(total)d songs saved\n" "(%(remaining)s remaining)" msgstr "" #: quodlibet/qltk/wlw.py:233 #, 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:435 msgid "Playlists must have a name" msgstr "" #: quodlibet/util/collection.py:624 #, 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:349 #, python-format msgid "%d kbps" msgstr "" #: quodlibet/util/__init__.py:404 #, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "" msgstr[1] "" #: quodlibet/util/__init__.py:417 msgid "No time information" msgstr "" #: quodlibet/util/__init__.py:420 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "" msgstr[1] "" #: quodlibet/util/__init__.py:421 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "" msgstr[1] "" #: quodlibet/util/__init__.py:422 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "" msgstr[1] "" #: quodlibet/util/__init__.py:423 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "" msgstr[1] "" #: quodlibet/util/__init__.py:424 #, 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:516 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:116 msgid "Unable to edit song" msgstr "" #: quodlibet/util/songwrapper.py:117 #, python-format msgid "" "Saving <b>%s</b> 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 "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 "Download Files" #~ msgstr "Download Files" #~ 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" #~ msgid "Media Devices" #~ msgstr "Media Devices" #~ msgid "_Media Devices" #~ msgstr "_Media Devices" #~ msgid "_Eject" #~ msgstr "_Eject" #~ 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." #~ 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" #, fuzzy #~ msgid "browsers" #~ msgstr "Browsers" #~ msgid "Unable to download lyrics." #~ msgstr "Unable to download lyrics." #~ msgid "Watch this folder for new songs" #~ msgstr "Watch this folder for new songs" #~ 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 "_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" #~ 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" #, fuzzy #~ msgid "_Remove rating" #~ msgstr "_Remove Station" #, fuzzy #~ msgid "ql-revert" #~ msgstr "ql-remove" #~ 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 "_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 "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:" #~ 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 "Choose New Stations" #~ msgstr "Choose New Stations" #~ 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 "Tag by Filename" #~ msgstr "Tag by Filename" #~ 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 "" #~ "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 _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 "" #~ "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 "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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9551857 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/po/es.po����������������������������������������������������������������������������0000644�0001750�0001750�00000604275�00000000000�014101� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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: 2017-05-17 18:58+0200\n" "PO-Revision-Date: 2010-02-15 18:25+0100\n" "Last-Translator: Johám-Luís Miguéns Vila <galiza.ceive@gmail.com>\n" "Language-Team: Spanish <LL@li.org>\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" #: ../data/exfalso.appdata.xml.in.h:1 ../data/exfalso.desktop.in.h:2 msgid "Edit tags in your audio files" msgstr "Edita las etiquetas de tus archivos de música" #: ../data/exfalso.appdata.xml.in.h:2 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/exfalso.appdata.xml.in.h:3 ../data/quodlibet.appdata.xml.in.h:3 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/exfalso.desktop.in.h:1 msgid "Audio tag editor" msgstr "Editor de etiquetas de audio" #: ../data/quodlibet.appdata.xml.in.h:1 ../data/quodlibet.desktop.in.h:2 msgid "Listen to, browse, or edit your audio collection" msgstr "Escucha, examina o edita tu colección de música" #: ../data/quodlibet.appdata.xml.in.h:2 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 "" #: ../data/quodlibet.desktop.in.h:1 msgid "Music Player" msgstr "Reproductor de música" #: ../quodlibet/browsers/albums/main.py:168 #: ../quodlibet/browsers/covergrid/main.py:54 #, fuzzy msgid "_Title" msgstr "Título" #: ../quodlibet/browsers/albums/main.py:169 #: ../quodlibet/browsers/covergrid/main.py:55 ../quodlibet/qltk/prefs.py:49 msgid "_Artist" msgstr "_Artista" #: ../quodlibet/browsers/albums/main.py:170 #: ../quodlibet/browsers/covergrid/main.py:56 ../quodlibet/qltk/prefs.py:54 msgid "_Date" msgstr "F_echa" #: ../quodlibet/browsers/albums/main.py:171 #: ../quodlibet/browsers/covergrid/main.py:57 ../quodlibet/qltk/prefs.py:53 #, fuzzy msgid "_Genre" msgstr "Estilo" #: ../quodlibet/browsers/albums/main.py:172 #: ../quodlibet/browsers/covergrid/main.py:58 ../quodlibet/qltk/prefs.py:58 #: ../quodlibet/qltk/ratingsmenu.py:39 msgid "_Rating" msgstr "_Puntuación" #: ../quodlibet/browsers/albums/main.py:178 #: ../quodlibet/browsers/covergrid/main.py:64 #, fuzzy msgid "Sort _by…" msgstr "Ordenar _por:" #: ../quodlibet/browsers/albums/main.py:199 #: ../quodlibet/browsers/covergrid/main.py:85 #: ../quodlibet/browsers/paned/prefs.py:166 #: ../quodlibet/browsers/playlists/main.py:629 #: ../quodlibet/qltk/exfalsowindow.py:109 ../quodlibet/qltk/pluginwin.py:341 #: ../quodlibet/qltk/quodlibetwindow.py:1016 #, fuzzy msgid "_Preferences" msgstr "Preferencias" #: ../quodlibet/browsers/albums/main.py:361 msgid "Album List" msgstr "Lista de álbumes" #: ../quodlibet/browsers/albums/main.py:362 msgid "_Album List" msgstr "Lista de á_lbumes" #: ../quodlibet/browsers/albums/main.py:472 #: ../quodlibet/browsers/covergrid/main.py:279 #: ../quodlibet/browsers/covergrid/main.py:488 msgid "All Albums" msgstr "Todos los álbumes" #: ../quodlibet/browsers/albums/main.py:473 #: ../quodlibet/browsers/covergrid/main.py:280 #: ../quodlibet/browsers/covergrid/main.py:489 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d álbum" msgstr[1] "%d álbumes" #: ../quodlibet/browsers/albums/main.py:650 #: ../quodlibet/browsers/covergrid/main.py:467 #, fuzzy msgid "Reload album _cover" msgid_plural "Reload album _covers" msgstr[0] "Mostrar _carátulas" msgstr[1] "Mostrar _carátulas" #: ../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:381 ../quodlibet/util/collection.py:245 #, 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:379 ../quodlibet/util/collection.py:249 #, 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 los álbumes" #: ../quodlibet/browsers/albums/prefs.py:52 msgid "Album List Preferences" msgstr "Preferencias de la lista de álbumes" #: ../quodlibet/browsers/albums/prefs.py:61 msgid "Show album _covers" msgstr "Mostrar _carátulas" #: ../quodlibet/browsers/albums/prefs.py:67 msgid "Inline _search includes people" msgstr "La _búsqueda incluye los \"componentes\"" #: ../quodlibet/browsers/albums/prefs.py:71 #: ../quodlibet/browsers/covergrid/prefs.py:120 #, fuzzy msgid "Options" msgstr "[opciones]" #: ../quodlibet/browsers/albums/prefs.py:74 #: ../quodlibet/browsers/covergrid/prefs.py:123 msgid "Album Display" msgstr "Vista de álbumes" #: ../quodlibet/browsers/albums/prefs.py:78 #: ../quodlibet/browsers/covergrid/prefs.py:127 #: ../quodlibet/browsers/media.py:39 #: ../quodlibet/browsers/playlists/prefs.py:56 #: ../quodlibet/ext/songsmenu/albumart.py:326 #: ../quodlibet/ext/songsmenu/duplicates.py:350 #: ../quodlibet/ext/songsmenu/filterall.py:48 #: ../quodlibet/qltk/bookmarks.py:101 ../quodlibet/qltk/cbes.py:93 #: ../quodlibet/qltk/data_editors.py:99 ../quodlibet/qltk/data_editors.py:324 #: ../quodlibet/qltk/exfalsowindow.py:297 ../quodlibet/qltk/pluginwin.py:79 #: ../quodlibet/qltk/pluginwin.py:427 ../quodlibet/qltk/prefs.py:707 #: ../quodlibet/qltk/textedit.py:164 ../quodlibet/update.py:148 msgid "_Close" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:55 #: ../quodlibet/browsers/audiofeeds.py:67 #: ../quodlibet/browsers/audiofeeds.py:69 #: ../quodlibet/browsers/audiofeeds.py:159 #: ../quodlibet/browsers/paned/models.py:86 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:46 #: ../quodlibet/formats/_audio.py:495 ../quodlibet/order/__init__.py:27 #: ../quodlibet/qltk/information.py:240 ../quodlibet/qltk/information.py:247 #: ../quodlibet/qltk/information.py:273 ../quodlibet/qltk/wlw.py:70 msgid "Unknown" msgstr "Desconocido" #: ../quodlibet/browsers/audiofeeds.py:246 msgid "New Feed" msgstr "Nueva fuente (feed)" #: ../quodlibet/browsers/audiofeeds.py:247 msgid "Enter the location of an audio feed:" msgstr "Introduce la direcciónde la fuente de audio (feed)" #: ../quodlibet/browsers/audiofeeds.py:248 #: ../quodlibet/browsers/collection/prefs.py:90 #: ../quodlibet/browsers/iradio.py:341 ../quodlibet/browsers/paned/prefs.py:78 #: ../quodlibet/browsers/playlists/menu.py:96 #: ../quodlibet/browsers/playlists/util.py:52 ../quodlibet/qltk/bookmarks.py:62 #: ../quodlibet/qltk/cbes.py:55 ../quodlibet/qltk/data_editors.py:311 #: ../quodlibet/qltk/edittags.py:288 ../quodlibet/qltk/edittags.py:488 #: ../quodlibet/qltk/quodlibetwindow.py:1354 ../quodlibet/qltk/scanbox.py:61 msgid "_Add" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:265 msgid "Audio Feeds" msgstr "Fuentes de audio" #: ../quodlibet/browsers/audiofeeds.py:266 msgid "_Audio Feeds" msgstr "Fuentes de _audio" #: ../quodlibet/browsers/audiofeeds.py:345 #: ../quodlibet/browsers/audiofeeds.py:350 #, fuzzy msgid "_Download…" msgstr "_Descargar" #: ../quodlibet/browsers/audiofeeds.py:359 msgid "Download Files" msgstr "Descargar archivos" #. Save button #: ../quodlibet/browsers/audiofeeds.py:359 #: ../quodlibet/browsers/audiofeeds.py:371 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:81 #: ../quodlibet/ext/songsmenu/albumart.py:322 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:355 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:278 #: ../quodlibet/ext/songsmenu/html.py:76 #: ../quodlibet/ext/songsmenu/lastfmsync.py:216 #: ../quodlibet/ext/songsmenu/playlist.py:51 #: ../quodlibet/ext/songsmenu/replaygain.py:365 #: ../quodlibet/ext/songsmenu/tapbpm.py:182 ../quodlibet/qltk/_editutils.py:39 #: ../quodlibet/qltk/lyrics.py:38 ../quodlibet/qltk/msg.py:52 #: ../quodlibet/qltk/renamefiles.py:168 ../quodlibet/qltk/tracknumbers.py:113 msgid "_Save" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:371 msgid "Download File" msgstr "Descargar archivo" #: ../quodlibet/browsers/audiofeeds.py:394 #: ../quodlibet/browsers/playlists/main.py:213 #: ../quodlibet/qltk/data_editors.py:96 msgid "_New" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:454 #: ../quodlibet/browsers/audiofeeds.py:513 msgid "Unable to add feed" msgstr "No ha sido posible añadir la fuente" #: ../quodlibet/browsers/audiofeeds.py:455 #: ../quodlibet/browsers/audiofeeds.py:514 #, fuzzy, python-format msgid "" "%s could not be added. The server may be down, or the location may not be an " "audio feed." msgstr "" "No se ha podido añadir <b>%s</b>. Es posible que el servidor esté caido, o " "que la dirección no contenga una fuente de audio (feed)." #. refresh button #: ../quodlibet/browsers/audiofeeds.py:462 ../quodlibet/browsers/media.py:217 #: ../quodlibet/browsers/media.py:386 ../quodlibet/qltk/filesel.py:259 #: ../quodlibet/qltk/pluginwin.py:413 #, fuzzy msgid "_Refresh" msgstr "Ac_tualizar la colección" #: ../quodlibet/browsers/audiofeeds.py:463 #: ../quodlibet/browsers/playlists/main.py:457 #: ../quodlibet/browsers/playlists/util.py:43 ../quodlibet/qltk/delete.py:143 #: ../quodlibet/qltk/filesel.py:256 ../quodlibet/qltk/lyrics.py:39 #: ../quodlibet/qltk/maskedbox.py:28 ../quodlibet/qltk/songsmenu.py:392 #, fuzzy msgid "_Delete" msgstr "Eliminar los archivos" #: ../quodlibet/browsers/audiofeeds.py:530 msgid "" "The current audio backend does not support URLs, Audio Feeds browser " "disabled." msgstr "" "La infraestructura de sonido actual no admite URLs. El navegador de fuentes " "(feed) de audio ha sido desactivado." #: ../quodlibet/browsers/_base.py:147 ../quodlibet/browsers/_base.py:150 msgid "Library Browser" msgstr "Navegador de la colección" #: ../quodlibet/browsers/_base.py:274 ../quodlibet/ext/songsmenu/refresh.py:30 #: ../quodlibet/qltk/exfalsowindow.py:241 ../quodlibet/qltk/information.py:542 #: ../quodlibet/qltk/maskedbox.py:68 ../quodlibet/util/collection.py:527 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d canción" msgstr[1] "%d canciones" #: ../quodlibet/browsers/_base.py:402 ../quodlibet/browsers/_base.py:407 #: ../quodlibet/qltk/tagsfrompath.py:194 ../quodlibet/qltk/textedit.py:141 #: ../quodlibet/util/__init__.py:622 msgid "Invalid pattern" msgstr "Patrón inválido" #: ../quodlibet/browsers/collection/main.py:78 msgid "Album Collection" msgstr "Colección de álbumes" #: ../quodlibet/browsers/collection/main.py:79 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 #, fuzzy, python-format msgid "Multiple %s Values" msgstr "Extraer en valores _múltiples" #: ../quodlibet/browsers/collection/prefs.py:66 #: ../quodlibet/browsers/paned/prefs.py:51 msgid "_Custom" msgstr "_Personalizada" #. Remove button #: ../quodlibet/browsers/collection/prefs.py:94 #: ../quodlibet/browsers/paned/prefs.py:82 #: ../quodlibet/browsers/playlists/menu.py:97 #: ../quodlibet/ext/playlist/remove_duplicates.py:60 #: ../quodlibet/qltk/bookmarks.py:97 ../quodlibet/qltk/bookmarks.py:127 #: ../quodlibet/qltk/cbes.py:82 ../quodlibet/qltk/cbes.py:89 #: ../quodlibet/qltk/data_editors.py:81 ../quodlibet/qltk/data_editors.py:94 #: ../quodlibet/qltk/data_editors.py:301 ../quodlibet/qltk/data_editors.py:314 #: ../quodlibet/qltk/data_editors.py:322 ../quodlibet/qltk/edittags.py:494 #: ../quodlibet/qltk/edittags.py:634 ../quodlibet/qltk/maskedbox.py:48 #: ../quodlibet/qltk/maskedbox.py:88 ../quodlibet/qltk/queue.py:350 #: ../quodlibet/qltk/scanbox.py:36 ../quodlibet/qltk/scanbox.py:63 #, fuzzy msgid "_Remove" msgstr "_Eliminar la emisora" #: ../quodlibet/browsers/collection/prefs.py:122 #: ../quodlibet/ext/songsmenu/filterall.py:34 #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:92 #: ../quodlibet/qltk/edittags.py:431 msgid "Tag" msgstr "Etiqueta" #: ../quodlibet/browsers/collection/prefs.py:128 msgid "Merge" msgstr "Unir" #: ../quodlibet/browsers/collection/prefs.py:188 #, fuzzy msgid "Album Collection Preferences" msgstr "Preferencias de la lista de álbumes" #: ../quodlibet/browsers/collection/prefs.py:195 #: ../quodlibet/browsers/paned/prefs.py:209 #: ../quodlibet/ext/songsmenu/editplaycount.py:45 #: ../quodlibet/ext/songsmenu/exact_rating.py:38 #: ../quodlibet/player/gstbe/prefs.py:40 ../quodlibet/qltk/prefs.py:127 #: ../quodlibet/qltk/textedit.py:65 msgid "_Apply" msgstr "" #: ../quodlibet/browsers/collection/prefs.py:198 #: ../quodlibet/browsers/paned/prefs.py:213 #: ../quodlibet/browsers/playlists/menu.py:95 #: ../quodlibet/browsers/playlists/util.py:42 #: ../quodlibet/errorreport/ui.py:108 #: ../quodlibet/ext/playlist/export_to_folder.py:37 #: ../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:44 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:281 #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:88 #: ../quodlibet/ext/songsmenu/importexport.py:35 #: ../quodlibet/ext/songsmenu/lastfmsync.py:215 #: ../quodlibet/ext/songsmenu/playlist.py:50 #: ../quodlibet/ext/songsmenu/replaygain.py:364 #: ../quodlibet/ext/songsmenu/tapbpm.py:181 ../quodlibet/plugins/playlist.py:39 #: ../quodlibet/qltk/chooser.py:184 ../quodlibet/qltk/chooser.py:205 #: ../quodlibet/qltk/chooser.py:229 ../quodlibet/qltk/chooser.py:253 #: ../quodlibet/qltk/delete.py:90 ../quodlibet/qltk/delete.py:133 #: ../quodlibet/qltk/edittags.py:287 ../quodlibet/qltk/_editutils.py:38 #: ../quodlibet/qltk/getstring.py:28 ../quodlibet/qltk/maskedbox.py:27 #: ../quodlibet/qltk/msg.py:54 ../quodlibet/qltk/msg.py:93 #: ../quodlibet/qltk/ratingsmenu.py:33 ../quodlibet/qltk/songsmenu.py:45 #: ../quodlibet/qltk/songsmenu.py:73 ../quodlibet/update.py:94 msgid "_Cancel" msgstr "" #: ../quodlibet/browsers/covergrid/main.py:125 #, fuzzy msgid "Cover Grid" msgstr "Tamaño total:" #: ../quodlibet/browsers/covergrid/main.py:126 #, fuzzy msgid "_Cover Grid" msgstr "Tamaño total:" #: ../quodlibet/browsers/covergrid/prefs.py:54 #, fuzzy msgid "Cover Grid Preferences" msgstr "Preferencias de la vista por paneles" #: ../quodlibet/browsers/covergrid/prefs.py:64 #, fuzzy msgid "Show album _text" msgstr "Mostrar _carátulas" #: ../quodlibet/browsers/covergrid/prefs.py:71 #, fuzzy msgid "Show \"All Albums\" Item" msgstr "Todos los álbumes" #: ../quodlibet/browsers/covergrid/prefs.py:78 msgid "Vertical Split" msgstr "" #: ../quodlibet/browsers/covergrid/prefs.py:110 #: ../quodlibet/browsers/covergrid/prefs.py:111 #, fuzzy msgid "Cover Magnification" msgstr "No existen emisoras nuevas" #: ../quodlibet/browsers/filesystem.py:40 msgid "File System" msgstr "Sistema de archvos" #: ../quodlibet/browsers/filesystem.py:41 msgid "_File System" msgstr "Sistema de _archivos" #: ../quodlibet/browsers/filesystem.py:113 ../quodlibet/browsers/media.py:491 #: ../quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "No ha sido posible copiar las canciones" #: ../quodlibet/browsers/filesystem.py:114 ../quodlibet/qltk/songlist.py:268 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "" "Los archivos seleccionados no pueden ser copiados\n" "a otra lista ni a la cola de reproducción." #: ../quodlibet/browsers/filesystem.py:189 msgid "_Add to Library" msgstr "_Añadir a la colección" #: ../quodlibet/browsers/iradio.py:178 msgid "Unsupported file type" msgstr "Tipo de archivo no admitido" #: ../quodlibet/browsers/iradio.py:179 #, 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 sólo pueden contener la dirección de las mismas, no " "otra lista de emisoras o lista de reproducción. Las siguientes emisoras no " "han podido ser cargadas:\n" "%s" #: ../quodlibet/browsers/iradio.py:219 ../quodlibet/browsers/iradio.py:232 #: ../quodlibet/browsers/iradio.py:810 msgid "Unable to add station" msgstr "No se ha podido añadir la emisora" #: ../quodlibet/browsers/iradio.py:243 ../quodlibet/browsers/iradio.py:471 msgid "Internet Radio" msgstr "Radio por Internet" #: ../quodlibet/browsers/iradio.py:243 #, fuzzy msgid "Downloading station list" msgstr "Descargar archivos" #: ../quodlibet/browsers/iradio.py:339 msgid "New Station" msgstr "Nueva emisora" #: ../quodlibet/browsers/iradio.py:340 msgid "Enter the location of an Internet radio station:" msgstr "Por favor, introduce la dirección de una emisora de radio por Internet" #: ../quodlibet/browsers/iradio.py:358 msgid "Electronic" msgstr "Electrónica" #: ../quodlibet/browsers/iradio.py:361 msgid "Hip Hop / Rap" msgstr "Hip Hop / Rap" #: ../quodlibet/browsers/iradio.py:362 msgid "Oldies" msgstr "Viejos éxitos" #: ../quodlibet/browsers/iradio.py:363 msgid "R&B" msgstr "R&B" #: ../quodlibet/browsers/iradio.py:364 msgid "Japanese" msgstr "Japonesa" #: ../quodlibet/browsers/iradio.py:365 msgid "Indian" msgstr "India" #: ../quodlibet/browsers/iradio.py:367 msgid "Religious" msgstr "Religiosa" #: ../quodlibet/browsers/iradio.py:369 msgid "Charts" msgstr "Éxitos" #: ../quodlibet/browsers/iradio.py:370 msgid "Turkish" msgstr "Turca" #: ../quodlibet/browsers/iradio.py:371 msgid "Reggae / Dancehall" msgstr "Regae / Baile" #: ../quodlibet/browsers/iradio.py:372 #, fuzzy msgid "Latin" msgstr "puntuación" #: ../quodlibet/browsers/iradio.py:373 msgid "College Radio" msgstr "Radio universitaria" #: ../quodlibet/browsers/iradio.py:374 msgid "Talk / News" msgstr "Debate / Noticias" #: ../quodlibet/browsers/iradio.py:375 msgid "Ambient" msgstr "Ambiente" #: ../quodlibet/browsers/iradio.py:376 msgid "Jazz" msgstr "Jazz" #: ../quodlibet/browsers/iradio.py:377 ../quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "Clásica" #: ../quodlibet/browsers/iradio.py:378 ../quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "Pop" #: ../quodlibet/browsers/iradio.py:379 msgid "Alternative" msgstr "Alternativa" #: ../quodlibet/browsers/iradio.py:380 msgid "Metal" msgstr "Metal" #: ../quodlibet/browsers/iradio.py:381 msgid "Country" msgstr "Country" #: ../quodlibet/browsers/iradio.py:382 msgid "News" msgstr "Noticias" #: ../quodlibet/browsers/iradio.py:383 msgid "Schlager" msgstr "Schlager" #: ../quodlibet/browsers/iradio.py:384 msgid "Funk" msgstr "Funk" #: ../quodlibet/browsers/iradio.py:385 msgid "Indie" msgstr "Indie" #: ../quodlibet/browsers/iradio.py:386 msgid "Blues" msgstr "Blues" #: ../quodlibet/browsers/iradio.py:387 msgid "Soul" msgstr "Soul" #: ../quodlibet/browsers/iradio.py:388 msgid "Lounge" msgstr "Lounge" #: ../quodlibet/browsers/iradio.py:389 msgid "Punk" msgstr "Punk" #: ../quodlibet/browsers/iradio.py:390 msgid "Reggaeton" msgstr "Reggaeton" #: ../quodlibet/browsers/iradio.py:392 msgid "Slavic" msgstr "Eslava" #: ../quodlibet/browsers/iradio.py:394 msgid "Greek" msgstr "Griega" #: ../quodlibet/browsers/iradio.py:395 msgid "Gothic" msgstr "Gótica" #: ../quodlibet/browsers/iradio.py:396 ../quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "Rock" #: ../quodlibet/browsers/iradio.py:449 msgid "Would you like to load a list of popular radio stations?" msgstr "" #: ../quodlibet/browsers/iradio.py:455 #, fuzzy msgid "_Load Stations" msgstr "_Nueva emisora" #: ../quodlibet/browsers/iradio.py:472 msgid "_Internet Radio" msgstr "Radio por _Internet" #: ../quodlibet/browsers/iradio.py:538 #, fuzzy msgid "_New Station…" msgstr "Nueva emisora" #: ../quodlibet/browsers/iradio.py:541 #, fuzzy msgid "_Update Stations" msgstr "_Nueva emisora" #: ../quodlibet/browsers/iradio.py:568 #, fuzzy msgid "All Stations" msgstr "Nueva emisora" #. TODO: support for ~#rating=!None etc (#1940) #: ../quodlibet/browsers/iradio.py:572 #: ../quodlibet/browsers/soundcloud/main.py:64 msgid "Favorites" msgstr "Favoritos" #: ../quodlibet/browsers/iradio.py:580 #, fuzzy msgid "No Category" msgstr "Sin categoría" #: ../quodlibet/browsers/iradio.py:802 msgid "No stations found" msgstr "No se han encontrado emisoras" #: ../quodlibet/browsers/iradio.py:803 #, python-format msgid "No Internet radio stations were found at %s." msgstr "No se han encontrado emisoras en %s." #: ../quodlibet/browsers/iradio.py:811 msgid "All stations listed are already in your library." msgstr "Todas las emisoras referidas ya se encuentran en tu colección." #: ../quodlibet/browsers/iradio.py:828 #, fuzzy msgid "Add to Favorites" msgstr "_Añadir a la lista" #: ../quodlibet/browsers/iradio.py:832 #, fuzzy msgid "Remove from Favorites" msgstr "_Eliminar de la lista" #: ../quodlibet/browsers/iradio.py:932 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "%(count)d emisora" msgstr[1] "%(count)d emisoras" #: ../quodlibet/browsers/media.py:36 msgid "Device Properties" msgstr "Propiedades del dispositivo" #: ../quodlibet/browsers/media.py:52 msgid "Device:" msgstr "Dispositivo:" #: ../quodlibet/browsers/media.py:54 msgid "Not mounted" msgstr "No montado" #: ../quodlibet/browsers/media.py:55 #, fuzzy msgid "Mount point:" msgstr "Punto de montaje:" #: ../quodlibet/browsers/media.py:61 ../quodlibet/qltk/cbes.py:40 msgid "_Name:" msgstr "_Nombre" #: ../quodlibet/browsers/media.py:135 msgid "Media Devices" msgstr "Dispositivos externos" #: ../quodlibet/browsers/media.py:136 msgid "_Media Devices" msgstr "Dispositivos _externos" #. eject button #: ../quodlibet/browsers/media.py:224 ../quodlibet/browsers/media.py:378 msgid "_Eject" msgstr "_Expulsar" #: ../quodlibet/browsers/media.py:360 #, fuzzy msgid "_Properties" msgstr "Propiedades" #: ../quodlibet/browsers/media.py:365 #: ../quodlibet/browsers/playlists/main.py:464 msgid "_Rename" msgstr "_Cambiar el nombre" #: ../quodlibet/browsers/media.py:461 #, fuzzy, python-format msgid "%(used-size)s used, %(free-size)s available" msgstr "<b>%s</b> utilizado, <b>%s</b> disponible" #: ../quodlibet/browsers/media.py:479 #, fuzzy, python-format msgid "%s is not connected." msgstr "<b>%s</b> no está conectado." #: ../quodlibet/browsers/media.py:499 #, fuzzy, python-format msgid "Copying %(song)s" msgstr "Copiando <b>%(song)s</b>" #: ../quodlibet/browsers/media.py:513 ../quodlibet/browsers/media.py:529 msgid "Unable to copy song" msgstr "No se ha podido copiar la canción" #: ../quodlibet/browsers/media.py:514 msgid "There is not enough free space for this song." msgstr "No hay espacio libre suficiente para esta canción" #: ../quodlibet/browsers/media.py:526 #, fuzzy, python-format msgid "%s could not be copied." msgstr "No se ha podido copiar <b>%s<b>." #: ../quodlibet/browsers/media.py:545 msgid "Unable to delete songs" msgstr "No se han podido eliminar las canciones" #: ../quodlibet/browsers/media.py:557 #, fuzzy, python-format msgid "Deleting %(song)s" msgstr "Eliminando <b>%(song)s</b>" #: ../quodlibet/browsers/media.py:575 #, fuzzy, python-format msgid "%s could not be deleted." msgstr "No ha podido eliminarse <b>%s</b>.." #: ../quodlibet/browsers/media.py:579 msgid "Unable to delete song" msgstr "No se ha podido eliminar la canción" #: ../quodlibet/browsers/media.py:594 #, fuzzy, python-format msgid "Ejecting %s failed." msgstr "Error al expulsar <b>%s</b>." #: ../quodlibet/browsers/media.py:597 msgid "Unable to eject device" msgstr "No ha sido posible expulsar el dispositivo" #: ../quodlibet/browsers/media.py:603 msgid "No device backend, Media Devices browser disabled." msgstr "" "Sin infraestructura de dispositivos. El navegador de dispositivos ha sido " "desactivado." #: ../quodlibet/browsers/paned/main.py:40 ../quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "Vista en paneles" #: ../quodlibet/browsers/paned/main.py:41 msgid "_Paned Browser" msgstr "_Vista en paneles" #: ../quodlibet/browsers/paned/main.py:90 msgid "Select _All" msgstr "Seleccionar _todo" #: ../quodlibet/browsers/paned/models.py:104 ../quodlibet/qltk/pluginwin.py:122 #: ../quodlibet/qltk/pluginwin.py:164 msgid "All" msgstr "Todo" #: ../quodlibet/browsers/paned/prefs.py:67 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "<tt>%s</tt>" msgstr "" #: ../quodlibet/browsers/paned/prefs.py:162 msgid "_Wide Mode" msgstr "" #: ../quodlibet/browsers/paned/prefs.py:197 msgid "Paned Browser Preferences" msgstr "Preferencias de la vista por paneles" #: ../quodlibet/browsers/paned/prefs.py:204 msgid "Equal pane width" msgstr "" #: ../quodlibet/browsers/playlists/main.py:48 #: ../quodlibet/browsers/playlists/main.py:575 #: ../quodlibet/qltk/pluginwin.py:168 msgid "Playlists" msgstr "Listas" #: ../quodlibet/browsers/playlists/main.py:49 msgid "_Playlists" msgstr "_Listas" #: ../quodlibet/browsers/playlists/main.py:152 msgid "_Remove from Playlist" msgstr "_Eliminar de la lista" #: ../quodlibet/browsers/playlists/main.py:215 #: ../quodlibet/browsers/playlists/main.py:576 msgid "_Import" msgstr "_Importar" #: ../quodlibet/browsers/playlists/main.py:391 #: ../quodlibet/browsers/playlists/util.py:50 #: ../quodlibet/util/collection.py:570 msgid "New Playlist" msgstr "Nueva lista" #: ../quodlibet/browsers/playlists/main.py:413 msgid "Unable to import playlist" msgstr "No ha sido posible importar la lista de reproducción" #: ../quodlibet/browsers/playlists/main.py:414 msgid "Quod Libet can only import playlists in the M3U and PLS formats." msgstr "" "Quod Libet sólo puede importar listas de reproducción en los formatos M3U y " "PLS." #: ../quodlibet/browsers/playlists/main.py:565 msgid "Unable to rename playlist" msgstr "No ha sido posible cambiar el nombre de la lista" #: ../quodlibet/browsers/playlists/main.py:576 msgid "Import Playlist" msgstr "Importar lista" #: ../quodlibet/browsers/playlists/menu.py:25 #, fuzzy msgid "_New Playlist…" msgstr "_Nueva lista" #: ../quodlibet/browsers/playlists/menu.py:86 #, 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á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?" #: ../quodlibet/browsers/playlists/menu.py:90 #, 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 "Nueva lista" #: ../quodlibet/browsers/playlists/prefs.py:47 #, fuzzy msgid "Playlist Browser Preferences" msgstr "Preferencias de la vista por paneles" #: ../quodlibet/browsers/playlists/prefs.py:52 #, fuzzy msgid "Playlist display" msgstr "Listas" #: ../quodlibet/browsers/playlists/util.py:33 #, fuzzy, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "Estás a punto de eliminar la lista <i>%s</i>.\n" #: ../quodlibet/browsers/playlists/util.py:35 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:51 #, fuzzy msgid "Enter a name for the new playlist:" msgstr "Introduce un nombre para la nueva carpeta" #: ../quodlibet/browsers/playlists/util.py:102 #, 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/search.py:33 msgid "_Limit Results" msgstr "_Limitar resultados" #: ../quodlibet/browsers/search.py:48 msgid "Search Library" msgstr "Buscar en la colección" #: ../quodlibet/browsers/search.py:49 msgid "_Search Library" msgstr "_Buscar en la colección" #: ../quodlibet/browsers/soundcloud/main.py:38 #, fuzzy msgid "Soundcloud Browser" msgstr "Vista en paneles" #: ../quodlibet/browsers/soundcloud/main.py:39 msgid "Sound_cloud" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:59 #: ../quodlibet/qltk/searchbar.py:73 msgid "Search" msgstr "Buscar" #: ../quodlibet/browsers/soundcloud/main.py:136 #, python-format msgid "Go to %s" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:380 #, fuzzy msgid "Connected" msgstr "ubicación" #: ../quodlibet/browsers/soundcloud/main.py:381 #, python-format msgid "Quod Libet is now connected, <b>%s</b>!" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:393 #, python-format msgid "Log out of %s" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:395 msgid "Enter code…" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:396 #, python-format msgid "Log in to %s" msgstr "" #: ../quodlibet/browsers/soundcloud/util.py:86 msgid "Soundcloud authorisation" msgstr "" #: ../quodlibet/browsers/soundcloud/util.py:87 msgid "Enter Soundcloud auth code:" msgstr "" #: ../quodlibet/cli.py:50 #, fuzzy msgid "Quod Libet is not running (add '--run' to start it)" msgstr "Quod Libet no está siendo ejecutado" #: ../quodlibet/cli.py:85 msgid "a music library and player" msgstr "un gestor y reproductor de música" #: ../quodlibet/cli.py:86 #, fuzzy msgid "[option]" msgstr "[opciones]" #: ../quodlibet/cli.py:88 msgid "Print the playing song and exit" msgstr "Muestra la canción reproducida y termina" #: ../quodlibet/cli.py:89 msgid "Begin playing immediately" msgstr "Comenzar a reproducir de inmediato" #: ../quodlibet/cli.py:90 msgid "Don't show any windows on start" msgstr "" #: ../quodlibet/cli.py:93 msgid "Jump to next song" msgstr "Saltar hasta la siguiente canción" #: ../quodlibet/cli.py:95 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:96 msgid "Jump to previous song" msgstr "Volver a la canción anterior" #: ../quodlibet/cli.py:97 msgid "Start playback" msgstr "Comenzar la reproducción" #: ../quodlibet/cli.py:98 msgid "Pause playback" msgstr "Parar la reproducción" #: ../quodlibet/cli.py:99 msgid "Toggle play/pause mode" msgstr "Alternar reproducir y parar" #: ../quodlibet/cli.py:100 #, fuzzy msgid "Stop playback" msgstr "Comenzar la reproducción" #: ../quodlibet/cli.py:101 msgid "Turn up volume" msgstr "Subir el volumen" #: ../quodlibet/cli.py:102 msgid "Turn down volume" msgstr "Bajar el volumen" #: ../quodlibet/cli.py:103 msgid "Print player status" msgstr "Mostrar el estado del reproductor" #: ../quodlibet/cli.py:104 msgid "Hide main window" msgstr "Esconder la ventana principal" #: ../quodlibet/cli.py:105 msgid "Show main window" msgstr "Mostrar la ventana principal" #: ../quodlibet/cli.py:106 msgid "Toggle main window visibility" msgstr "Alternar la visibilidad de la ventana principal" #: ../quodlibet/cli.py:107 msgid "Focus the running player" msgstr "Centrarse en el reproductor" #: ../quodlibet/cli.py:108 msgid "Remove active browser filters" msgstr "Eliminar los filtros de navegación activos" #: ../quodlibet/cli.py:109 msgid "Refresh and rescan library" msgstr "Actualizar y analizar de nuevo la colección" #: ../quodlibet/cli.py:110 #, fuzzy msgid "List available browsers" msgstr "Desactivar el navegador" #: ../quodlibet/cli.py:111 msgid "Print the current playlist" msgstr "Mostrar la lista de reproducción" #: ../quodlibet/cli.py:112 msgid "Print the contents of the queue" msgstr "Mostrar las canciones en la cola de reproducción" #: ../quodlibet/cli.py:113 #, fuzzy msgid "Print the active text query" msgstr "Mostrar las canciones en la cola de reproducción" #: ../quodlibet/cli.py:114 msgid "Start without plugins" msgstr "Comenzar sin extensiones" #: ../quodlibet/cli.py:115 #, fuzzy msgid "Start Quod Libet if it isn't running" msgstr "Quod Libet no está siendo ejecutado" #: ../quodlibet/cli.py:116 msgid "Exit Quod Libet" msgstr "Salir de Quod Libet" #: ../quodlibet/cli.py:121 msgid "Seek within the playing song" msgstr "Avanzar en la canción activa" #: ../quodlibet/cli.py:121 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: ../quodlibet/cli.py:122 #, fuzzy msgid "Set or toggle shuffle mode" msgstr "Alternar reproducir y parar" #: ../quodlibet/cli.py:123 msgid "Turn repeat off, on, or toggle it" msgstr "Activar o desactivar el modo repetición" #: ../quodlibet/cli.py:124 msgid "Set the volume" msgstr "Ajustar el volumen" #: ../quodlibet/cli.py:125 msgid "Search your audio library" msgstr "Buscar en la colección" #: ../quodlibet/cli.py:125 ../quodlibet/cli.py:137 ../quodlibet/cli.py:141 #: ../quodlibet/cli.py:143 msgid "query" msgstr "búsqueda" #: ../quodlibet/cli.py:126 msgid "Play a file" msgstr "Reproducir un archivo" #: ../quodlibet/cli.py:126 ../quodlibet/cli.py:137 ../quodlibet/cli.py:143 #, fuzzy msgctxt "command" msgid "filename" msgstr "nombre del archivo" #: ../quodlibet/cli.py:127 msgid "Rate the playing song" msgstr "Puntuar la canción activa" #: ../quodlibet/cli.py:128 msgid "Set the current browser" msgstr "Configurar el navegador actual" #: ../quodlibet/cli.py:129 #, fuzzy msgid "Stop after the playing song" msgstr "Puntuar la canción activa" #: ../quodlibet/cli.py:130 msgid "Open a new browser" msgstr "Abrir un nuevo navegador" #: ../quodlibet/cli.py:131 msgid "Show or hide the queue" msgstr "Mostrar o esconder la cola de reproducción" #: ../quodlibet/cli.py:133 #, fuzzy msgid "Show or hide the main song list (deprecated)" msgstr "Mostrar o esconder la lista principal de canciones" #: ../quodlibet/cli.py:134 msgid "Filter on a random value" msgstr "Filtro en un valor aleatorio" #: ../quodlibet/cli.py:134 #, fuzzy msgctxt "command" msgid "tag" msgstr "etiqueta" #: ../quodlibet/cli.py:135 msgid "Filter on a tag value" msgstr "Filtro en un valor de las etiquetas" #: ../quodlibet/cli.py:135 msgid "tag=value" msgstr "etiqueta=valor" #: ../quodlibet/cli.py:136 msgid "Enqueue a file or query" msgstr "Poner en cola un archivo o búsqueda" #: ../quodlibet/cli.py:138 msgid "Enqueue comma-separated files" msgstr "Añadir nombres de archivo separados por comas a la cola" #: ../quodlibet/cli.py:139 ../quodlibet/util/tags.py:147 msgid "filename" msgstr "nombre del archivo" #: ../quodlibet/cli.py:140 msgid "Print filenames of results of query to stdout" msgstr "" "Mostrar los nombres de archivo de los resultados de la búsqueda en la salida " "estandard" #: ../quodlibet/cli.py:142 msgid "Unqueue a file or query" msgstr "Eliminar de la cola un archivo o búsqueda" #: ../quodlibet/cli.py:203 #, python-format msgid "Invalid argument for '%s'." msgstr "Argumento inválido para '%s'." #: ../quodlibet/cli.py:204 ../quodlibet/util/__init__.py:190 #, python-format msgid "Try %s --help." msgstr "Intenta %s --help" #: ../quodlibet/devices/_base.py:65 msgid "Unknown Device" msgstr "Dispositivo desconocido" #: ../quodlibet/devices/__init__.py:32 #, fuzzy, python-format 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" #: ../quodlibet/devices/__init__.py:153 #, python-format msgid "%r is not a supported device." msgstr "%r no es un dispositivo admitido." #: ../quodlibet/devices/__init__.py:245 ../quodlibet/devices/__init__.py:251 #, fuzzy, python-format msgid "Could not find '%s'." msgstr "%s: no se ha podido encontrar media-player-info" #: ../quodlibet/devices/__init__.py:450 msgid "Initializing device backend." msgstr "Activando la infraestructura de dispositivos." #: ../quodlibet/devices/__init__.py:451 #, python-format msgid "Trying '%s'" msgstr "Intentando '%s'" #: ../quodlibet/devices/__init__.py:461 msgid "Couldn't connect to a device backend." msgstr "No se ha podido conectar a una infraestructura de dispositivos" #: ../quodlibet/devices/__init__.py:463 msgid "Device backend initialized." msgstr "La infraestructura de dispositivos ha sido iniciada." #: ../quodlibet/devices/storage.py:57 #, fuzzy msgid "_Filename pattern:" msgstr "Patrón para el nombre de _archivo:" #: ../quodlibet/devices/storage.py:61 msgid "Copy _album covers" msgstr "Copiar las _carátulas del álbum" #: ../quodlibet/devices/storage.py:65 msgid "_Remove unused covers and directories" msgstr "_Eliminar las portadas de discos y las carpetas sin utilizar" #: ../quodlibet/errorreport/ui.py:60 #, fuzzy msgid "An Error Occurred" msgstr "Ha ocurrido un error" #: ../quodlibet/errorreport/ui.py:62 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:72 msgid "File Bug Report" msgstr "" #: ../quodlibet/errorreport/ui.py:74 ../quodlibet/errorreport/ui.py:90 msgid "Submit Error Report" msgstr "" #: ../quodlibet/errorreport/ui.py:75 msgid "Quit Program" msgstr "" #: ../quodlibet/errorreport/ui.py:76 #, fuzzy msgid "Ignore Error" msgstr "_Ignorar todos los errores" #: ../quodlibet/errorreport/ui.py:80 msgid "Error details:" msgstr "" #: ../quodlibet/errorreport/ui.py:92 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:100 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "" #: ../quodlibet/errorreport/ui.py:109 msgid "_Send" msgstr "" #: ../quodlibet/errorreport/ui.py:115 #, fuzzy msgid "Short description…" msgstr "descripción" #: ../quodlibet/errorreport/ui.py:118 msgid "Data to be sent:" msgstr "" #: ../quodlibet/exfalso.py:34 msgid "an audio tag editor" msgstr "un editor de etiquetas de audio" #: ../quodlibet/exfalso.py:34 ../quodlibet/util/tags.py:148 msgid "directory" msgstr "ruta" #: ../quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "" #: ../quodlibet/ext/covers/artwork_url.py:20 msgid "" "Downloads covers linked to by the artwork_url tag.This works with the " "Soundcloud browser." msgstr "" #: ../quodlibet/ext/covers/discogs.py:25 #, fuzzy msgid "Discogs Cover Source" msgstr "ID MusicBrainz de la pista" #: ../quodlibet/ext/covers/discogs.py:26 msgid "Downloads covers from Discogs." msgstr "" #: ../quodlibet/ext/covers/lastfm.py:22 msgid "Last.fm Cover Source" msgstr "" #: ../quodlibet/ext/covers/lastfm.py:23 msgid "Downloads covers from Last.fm's cover art archive." msgstr "" #: ../quodlibet/ext/covers/musicbrainz.py:19 #, fuzzy msgid "MusicBrainz Cover Source" msgstr "ID MusicBrainz de la pista" #: ../quodlibet/ext/covers/musicbrainz.py:20 msgid "Downloads covers from MusicBrainz's cover art archive." msgstr "" #: ../quodlibet/ext/editing/iconv.py:26 #, fuzzy msgid "Convert Encodings" msgstr "[Codificación 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:25 msgid "Kana/Kanji Simple Inverter" msgstr "" #: ../quodlibet/ext/editing/kakasi.py:26 msgid "Converts kana/kanji to romaji before renaming." msgstr "" #: ../quodlibet/ext/editing/kakasi.py:35 msgid "Romanize _Japanese text" msgstr "" #: ../quodlibet/ext/editing/kakasi.py:63 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:19 msgid "" "Allows arbitrary regex substitutions (s///) 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 audio" #: ../quodlibet/ext/editing/titlecase.py:40 #, fuzzy msgid "Title-_case Value" msgstr "C_on mayúscula inicial los valores resultantes" #: ../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:69 #, fuzzy msgid "Advanced Preferences" msgstr "Preferencias de la vista por paneles" #: ../quodlibet/ext/events/advanced_preferences.py:70 msgid "Allow editing of advanced config settings." msgstr "" #: ../quodlibet/ext/events/advanced_preferences.py:162 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:153 msgid "Top of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:154 msgid "Middle of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:155 msgid "Bottom of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:158 msgid "_Position:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:171 #, fuzzy msgid "_Cover size:" msgstr "Tamaño total:" #: ../quodlibet/ext/events/animosd/prefs.py:177 #: ../quodlibet/ext/events/lyricswindow.py:334 ../quodlibet/qltk/prefs.py:266 #, fuzzy msgid "Display" msgstr "Editar la vista" #: ../quodlibet/ext/events/animosd/prefs.py:190 msgid "_Font:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:195 msgid "Left" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:196 msgid "Center" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:197 #, fuzzy msgid "Right" msgstr "_Importancia" #: ../quodlibet/ext/events/animosd/prefs.py:200 msgid "_Align text:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:206 msgid "Text" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:217 msgid "_Text:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:227 msgid "_Fill:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:232 #: ../quodlibet/ext/events/synchronizedlyrics.py:63 msgid "Colors" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:240 msgid "_Shadows" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:241 #, fuzzy msgid "_Outline" msgstr "_Infraestructura de salida de sonido:" #: ../quodlibet/ext/events/animosd/prefs.py:242 msgid "Rou_nded Corners" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:258 msgid "_Delay:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:264 #: ../quodlibet/qltk/pluginwin.py:172 msgid "Effects" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:270 #, fuzzy msgid "Ed_it Display Pattern…" msgstr "Editar la vista" #: ../quodlibet/ext/events/animosd/prefs.py:274 #: ../quodlibet/ext/events/trayicon/prefs.py:78 #, fuzzy msgid "Preview" msgstr "_Prever" #: ../quodlibet/ext/events/auto_library_update.py:136 msgid "Automatic Library Update" msgstr "" #: ../quodlibet/ext/events/auto_library_update.py:137 #, python-format msgid "Keeps your library up to date with inotify. Requires %s." msgstr "" #: ../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 by Brian Nelson." 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/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:97 msgid "Equalizer" msgstr "" #: ../quodlibet/ext/events/equalizer.py:98 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:132 #, fuzzy msgid "The current backend does not support equalization." msgstr "" "La infraestructura de sonido actual no admite URLs. El navegador de fuentes " "(feed) de audio ha sido desactivado." #: ../quodlibet/ext/events/equalizer.py:138 #, python-format msgid "%.1f kHz" msgstr "" #: ../quodlibet/ext/events/equalizer.py:139 #: ../quodlibet/ext/gstreamer/crossfeed.py:93 #: ../quodlibet/ext/gstreamer/karaoke.py:95 #, python-format msgid "%d Hz" msgstr "" #: ../quodlibet/ext/events/equalizer.py:173 #: ../quodlibet/ext/gstreamer/crossfeed.py:112 #, fuzzy, python-format msgid "%.1f dB" msgstr "%d segundo" #: ../quodlibet/ext/events/equalizer.py:192 #: ../quodlibet/ext/gstreamer/crossfeed.py:31 #, fuzzy msgid "Custom" msgstr "_Personalizada" #: ../quodlibet/ext/events/equalizer.py:199 #, fuzzy msgid "_Clear" msgstr "_Eliminar errores" #. Translators: statuses relating to Instant Messenger apps #: ../quodlibet/ext/events/gajim_status.py:27 msgid "online" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:28 msgid "offline" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:29 msgid "chat" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:30 msgid "away" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:31 msgid "xa" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:32 msgid "invisible" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:37 msgid "Gajim Status Message" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:38 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:45 #: ../quodlibet/ext/events/telepathy_status.py:69 msgid "paused" 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:160 msgid "Add '[paused]'" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:163 msgid "If checked, '[paused]' will be added to status message on pause." msgstr "" #: ../quodlibet/ext/events/gajim_status.py:187 msgid "Statuses for which message will be changed" msgstr "" #: ../quodlibet/ext/events/headphonemon.py:156 msgid "Pause on Headphone Unplug" msgstr "" #: ../quodlibet/ext/events/headphonemon.py:157 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" #: ../quodlibet/ext/events/inhibit.py:41 msgid "Inhibit Screensaver" msgstr "" #: ../quodlibet/ext/events/inhibit.py:42 msgid "Prevents the GNOME screensaver from activating while a song is playing." msgstr "" #: ../quodlibet/ext/events/inhibit.py:51 #, fuzzy msgid "Music is playing" msgstr "Reproductor de música" #: ../quodlibet/ext/events/iradiolog.py:16 #, fuzzy msgid "Internet Radio Log" msgstr "Radio por Internet" #: ../quodlibet/ext/events/iradiolog.py:17 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" #: ../quodlibet/ext/events/jep118.py:29 msgid "JEP-118" msgstr "" #: ../quodlibet/ext/events/jep118.py:30 msgid "Outputs a Jabber User Tunes file to ~/.quodlibet/jabber." msgstr "" #: ../quodlibet/ext/events/language.py:21 #, fuzzy msgid "Change Language" msgstr "_Puntuación" #: ../quodlibet/ext/events/language.py:22 msgid "Change the user interface language." msgstr "" #: ../quodlibet/ext/events/language.py:43 #, fuzzy msgid "System Default" msgstr "Predefinida" #: ../quodlibet/ext/events/language.py:70 msgid "A restart is required for any changes to take effect" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:199 #, fuzzy msgid "No active song" msgstr "No ha sido posible guardar la canción" #: ../quodlibet/ext/events/lyricswindow.py:215 #, fuzzy msgid "No lyrics found" msgstr "No se ha encontrado extensión alguna" #: ../quodlibet/ext/events/lyricswindow.py:227 #, fuzzy msgid "Lyrics:" msgstr "Letra" #: ../quodlibet/ext/events/lyricswindow.py:284 msgid "_Zoom level:" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:302 msgid "URL:" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:307 msgid "Revert to default" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:322 msgid "Search via above URL if the lyrics couldn't be found in LyricsWikia." msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:339 #, fuzzy msgid "Alternate search" msgstr "Borrar la búsqueda" #: ../quodlibet/ext/events/lyricswindow.py:347 #, fuzzy msgid "Lyrics Window" msgstr "Letra" #: ../quodlibet/ext/events/lyricswindow.py:348 #, fuzzy msgid "Shows a window containing lyrics of the playing song." msgstr "Ver y editar las etiquetas de la canción reproducida" #: ../quodlibet/ext/events/mediaserver.py:38 msgid "UPnP AV Media Server" msgstr "" #: ../quodlibet/ext/events/mediaserver.py:39 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." 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 "ubicación" #: ../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:39 msgid "" "Allows control of Quod Libet using the MPRIS 1.0/2.0 D-Bus Interface " "Specification." msgstr "" #: ../quodlibet/ext/events/mpris/__init__.py:45 #: ../quodlibet/ext/events/trayicon/prefs.py:30 #, fuzzy msgid "Hide main window on close" msgstr "Esconder la ventana principal" #: ../quodlibet/ext/events/mpris/__init__.py:48 #: ../quodlibet/ext/events/themeswitcher.py:84 #: ../quodlibet/ext/gstreamer/compressor.py:99 #: ../quodlibet/ext/gstreamer/crossfeed.py:136 #: ../quodlibet/ext/gstreamer/karaoke.py:99 #: ../quodlibet/ext/gstreamer/pitch.py:83 ../quodlibet/qltk/prefs.py:688 #, fuzzy msgid "Preferences" msgstr "Preferencias" #: ../quodlibet/ext/events/mqtt.py:50 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/mqtt.py:56 msgid "MQTT Publisher" msgstr "" #: ../quodlibet/ext/events/mqtt.py:57 msgid "Publishes status messages to an MQTT topic." msgstr "" #: ../quodlibet/ext/events/mqtt.py:122 msgid "Broker hostname" msgstr "" #: ../quodlibet/ext/events/mqtt.py:122 msgid "broker hostname / IP" msgstr "" #: ../quodlibet/ext/events/mqtt.py:124 msgid "Broker port" msgstr "" #: ../quodlibet/ext/events/mqtt.py:124 msgid "broker port" msgstr "" #: ../quodlibet/ext/events/mqtt.py:126 msgid "Topic" msgstr "" #: ../quodlibet/ext/events/mqtt.py:128 #, fuzzy msgid "Playing Pattern" msgstr "patrón" #: ../quodlibet/ext/events/mqtt.py:130 msgid "Status text when a song is started." msgstr "" #: ../quodlibet/ext/events/mqtt.py:132 #, fuzzy msgid "Paused Pattern" msgstr "patrón" #: ../quodlibet/ext/events/mqtt.py:134 msgid "Text when a song is paused." msgstr "" #: ../quodlibet/ext/events/mqtt.py:136 #, fuzzy msgid "No-song Text" msgstr "%d canción" #: ../quodlibet/ext/events/mqtt.py:138 msgid "Plain text for when there is no current song" msgstr "" #: ../quodlibet/ext/events/mqtt.py:149 #, fuzzy msgid "MQTT Configuration" msgstr "Registro" #: ../quodlibet/ext/events/mqtt.py:153 #, fuzzy msgid "Status Text" msgstr "patrón" #: ../quodlibet/ext/events/mqtt.py:185 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "" #: ../quodlibet/ext/events/mqtt.py:189 #, fuzzy, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s" msgstr "No se ha podido conectar a una infraestructura de dispositivos" #: ../quodlibet/ext/events/mqtt.py:192 #, fuzzy msgid "Connection error" msgstr "ubicación" #: ../quodlibet/ext/events/notify.py:80 msgid "Notification text" msgstr "" #: ../quodlibet/ext/events/notify.py:88 #, fuzzy msgid "_Title:" msgstr "Título" #: ../quodlibet/ext/events/notify.py:99 ../quodlibet/ext/events/notify.py:128 msgid "Revert to default pattern" msgstr "" #: ../quodlibet/ext/events/notify.py:118 msgid "_Body:" msgstr "" #: ../quodlibet/ext/events/notify.py:138 msgid "_Show notification" msgstr "" #: ../quodlibet/ext/events/notify.py:156 #, fuzzy msgid "Show notifications" msgstr "No existen emisoras nuevas" #: ../quodlibet/ext/events/notify.py:162 msgid "Only on <i>_manual</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:170 msgid "Only on <i>_automatic</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:178 msgid "On <i>a_ll</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:196 msgid "Only when the main window is not _focused" msgstr "" #: ../quodlibet/ext/events/notify.py:204 msgid "Show \"_Next\" button" msgstr "" #: ../quodlibet/ext/events/notify.py:236 msgid "Connection Error" msgstr "" #: ../quodlibet/ext/events/notify.py:237 ../quodlibet/ext/events/notify.py:391 #: ../quodlibet/ext/events/notify.py:433 #, fuzzy msgid "Couldn't connect to notification daemon." msgstr "No se ha podido conectar a una infraestructura de dispositivos" #: ../quodlibet/ext/events/notify.py:251 #, fuzzy msgid "Song Notifications" msgstr "No existen emisoras nuevas" #: ../quodlibet/ext/events/notify.py:252 msgid "Displays a notification when the song changes." msgstr "" #: ../quodlibet/ext/events/notify.py:415 ../quodlibet/qltk/unity.py:65 msgid "Next" msgstr "Siguiente" #: ../quodlibet/ext/events/qlscrobbler.py:178 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:254 #, fuzzy, python-format msgid "Could not contact service '%s'." msgstr "No se ha podido conectar a una infraestructura de dispositivos" #: ../quodlibet/ext/events/qlscrobbler.py:260 msgid "Authentication failed: invalid URL." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:277 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:282 msgid "Client is banned. Contact the author." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:286 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:351 msgid "AudioScrobbler Submission" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:352 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:450 msgid "Authentication successful." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:462 #, fuzzy msgid "_Service:" msgstr "Dispositivo:" #: ../quodlibet/ext/events/qlscrobbler.py:462 msgid "_URL:" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:462 #, fuzzy msgid "User_name:" msgstr "_Nombre" #: ../quodlibet/ext/events/qlscrobbler.py:463 msgid "_Password:" msgstr "" #. Translators: Other service #: ../quodlibet/ext/events/qlscrobbler.py:479 #, fuzzy msgid "Other…" msgstr "_Otras:" #. verify data #: ../quodlibet/ext/events/qlscrobbler.py:517 msgid "_Verify account data" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:522 #: ../quodlibet/ext/songsmenu/lastfmsync.py:304 msgid "Account" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:530 #, fuzzy msgid "_Artist pattern:" msgstr "_Artista" #: ../quodlibet/ext/events/qlscrobbler.py:530 #, fuzzy msgid "_Title pattern:" msgstr "Patrón para el nombre de _archivo:" #: ../quodlibet/ext/events/qlscrobbler.py:531 msgid "Exclude _filter:" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:549 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:559 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:568 msgid "Songs matching this filter will not be submitted." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:576 msgid "_Offline mode (don't submit anything)" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:580 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:27 #, fuzzy msgid "Random Album Playback" msgstr "Ál_bum aleatorio" #: ../quodlibet/ext/events/randomalbum.py:28 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:38 msgid "Rated higher" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:39 msgid "Played more often" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:40 msgid "Skipped more often" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:41 msgid "Played more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:42 msgid "Started more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:43 msgid "Added more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:44 #, fuzzy msgid "Longer albums" msgstr "álbumes" #: ../quodlibet/ext/events/randomalbum.py:83 msgid "seconds before starting next album" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:87 #, fuzzy msgid "Weights" msgstr "_Importancia" #: ../quodlibet/ext/events/randomalbum.py:89 msgid "Play some albums more than others" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:103 msgid "avoid" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:114 msgid "prefer" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:201 #, fuzzy msgid "Random Album" msgstr "Ál_bum aleatorio" #: ../quodlibet/ext/events/randomalbum.py:202 #, python-format msgid "Waiting to start %s" msgstr "" #: ../quodlibet/ext/events/rbimport.py:114 #, fuzzy msgid "Import Failed" msgstr "Importar lista" #: ../quodlibet/ext/events/rbimport.py:119 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "" #: ../quodlibet/ext/events/rbimport.py:127 msgid "Rhythmbox Import" msgstr "" #: ../quodlibet/ext/events/rbimport.py:128 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "" #: ../quodlibet/ext/events/rbimport.py:132 #, fuzzy msgid "Start Import" msgstr "_Importar" #: ../quodlibet/ext/events/screensaver.py:25 msgid "Screensaver Pause" msgstr "" #: ../quodlibet/ext/events/screensaver.py:26 msgid "Pauses playback while the GNOME screensaver is active." msgstr "" #: ../quodlibet/ext/events/searchprovider.py:73 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "" #: ../quodlibet/ext/events/searchprovider.py:79 msgid "GNOME Search Provider" msgstr "" #: ../quodlibet/ext/events/searchprovider.py:80 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/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:29 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:57 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:58 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:34 #, fuzzy msgid "Synchronized Lyrics" msgstr "Letra" #: ../quodlibet/ext/events/synchronizedlyrics.py:35 msgid "Shows synchronized lyrics from .lrc file with same name as the track." msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:66 msgid "Text:" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:76 msgid "Background:" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:87 msgid "Font" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:90 msgid "Size (px):" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:62 msgid "Telepathy Status Messages" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:63 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:122 #, fuzzy msgid "Playing:" msgstr "Sin reproducción" #: ../quodlibet/ext/events/telepathy_status.py:123 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:139 msgid "Paused:" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:140 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:156 msgid "Plain text for status when there is no current song" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:157 #, fuzzy msgid "No song:" msgstr "%d canción" #. Frame #: ../quodlibet/ext/events/telepathy_status.py:164 #, fuzzy msgid "Status Patterns" msgstr "patrón" #: ../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/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:77 #: ../quodlibet/ext/events/trayicon/prefs.py:98 #: ../quodlibet/ext/events/trayicon/systemtray.py:177 #: ../quodlibet/qltk/info.py:47 msgid "Not playing" msgstr "Sin reproducción" #: ../quodlibet/ext/events/trayicon/__init__.py:53 #, fuzzy msgid "Tray Icon" msgstr "Preferencias del Icono" #: ../quodlibet/ext/events/trayicon/__init__.py:54 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:183 #: ../quodlibet/qltk/quodlibetwindow.py:1046 #: ../quodlibet/qltk/quodlibetwindow.py:1238 #, fuzzy msgid "_Play" msgstr "_Listas" #: ../quodlibet/ext/events/trayicon/menu.py:63 #: ../quodlibet/qltk/quodlibetwindow.py:185 #: ../quodlibet/qltk/quodlibetwindow.py:1240 ../quodlibet/qltk/wlw.py:51 #, fuzzy msgid "P_ause" msgstr "Reproductor" #: ../quodlibet/ext/events/trayicon/menu.py:68 #: ../quodlibet/qltk/quodlibetwindow.py:190 #: ../quodlibet/qltk/quodlibetwindow.py:1041 #, fuzzy msgid "Pre_vious" msgstr "_Prever" #: ../quodlibet/ext/events/trayicon/menu.py:71 #: ../quodlibet/qltk/quodlibetwindow.py:194 #: ../quodlibet/qltk/quodlibetwindow.py:1051 #, fuzzy msgid "_Next" msgstr "Siguiente" #: ../quodlibet/ext/events/trayicon/menu.py:76 msgid "_Shuffle" msgstr "_Aleatoriamente" #: ../quodlibet/ext/events/trayicon/menu.py:81 msgid "_Repeat" msgstr "_Repetir" #: ../quodlibet/ext/events/trayicon/menu.py:86 #, fuzzy msgid "Stop _After This Song" msgstr "Parar después de esta canción" #: ../quodlibet/ext/events/trayicon/menu.py:92 #: ../quodlibet/qltk/quodlibetwindow.py:1012 #, fuzzy msgid "Open _Browser" msgstr "Abrir un nuevo navegador" #: ../quodlibet/ext/events/trayicon/menu.py:103 #: ../quodlibet/qltk/quodlibetwindow.py:1031 ../quodlibet/qltk/songsmenu.py:411 msgid "Edit _Tags" msgstr "Editar las _etiquetas" #: ../quodlibet/ext/events/trayicon/menu.py:112 #: ../quodlibet/qltk/quodlibetwindow.py:975 ../quodlibet/qltk/songsmenu.py:424 msgid "_Information" msgstr "_Información" #: ../quodlibet/ext/events/trayicon/menu.py:114 #: ../quodlibet/qltk/songsmenu.py:340 #, fuzzy msgid "Play_lists" msgstr "Listas" #: ../quodlibet/ext/events/trayicon/menu.py:132 #: ../quodlibet/qltk/quodlibetwindow.py:1026 msgid "_Quit" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:32 ../quodlibet/qltk/prefs.py:69 msgid "Behavior" msgstr "Comportamiento" #: ../quodlibet/ext/events/trayicon/prefs.py:42 #, fuzzy msgid "Scroll wheel adjusts volume" msgstr "" "La rueda del ratón ajusta el volumen\n" "Shift y la rueda del ratón cambia de canción" #: ../quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel changes song" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll _Wheel" msgstr "Rueda del _Ratón" #: ../quodlibet/ext/events/trayicon/prefs.py:84 msgid "Tooltip Display" msgstr "Editar vista" #: ../quodlibet/ext/events/viewlyrics.py:23 #, fuzzy msgid "View Lyrics" msgstr "Letra" #: ../quodlibet/ext/events/viewlyrics.py:24 msgid "Automatically displays lyrics beneath the song list in the main window." msgstr "" #: ../quodlibet/ext/events/viewlyrics.py:29 #, fuzzy msgid "_Lyrics" msgstr "Letra" #: ../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 "Errores" #: ../quodlibet/ext/events/visualisations.py:76 msgid "Visualiser executable:" msgstr "" #: ../quodlibet/ext/events/visualisations.py:91 msgid "Reload" msgstr "" #: ../quodlibet/ext/events/waveformseekbar.py:406 #, fuzzy msgid "Waveform Seek Bar" msgstr "Alternativa" #: ../quodlibet/ext/events/waveformseekbar.py:410 msgid "A seekbar in the shape of the waveform of the current song." msgstr "" #: ../quodlibet/ext/events/waveformseekbar.py:443 msgid "Override foreground color:" msgstr "" #: ../quodlibet/ext/events/write_cover.py:32 msgid "Picture Saver" msgstr "" #: ../quodlibet/ext/events/write_cover.py:33 msgid "Saves the cover image of the current song to a file." msgstr "" #: ../quodlibet/ext/events/write_cover.py:66 #, fuzzy msgid "File:" msgstr "Archivos" #: ../quodlibet/ext/gstreamer/compressor.py:20 msgid "_Threshold:" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:21 msgid "Threshold until the filter is activated" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:22 msgid "R_atio:" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:22 msgid "Compression ratio" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:74 #: ../quodlibet/ext/gstreamer/karaoke.py:91 #, python-format msgid "%d %%" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:105 msgid "Audio Compressor" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:106 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:19 #, fuzzy msgid "_Preset:" msgstr "_Prever" #: ../quodlibet/ext/gstreamer/crossfeed.py:19 #, fuzzy msgid "Filter preset" msgstr "Filtrar por _artista" #: ../quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Frequency cut:" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Low-pass filter cut frequency" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed _level:" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed level" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:25 #, fuzzy msgid "Default" msgstr "Predefinida" #: ../quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Chu Moy" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Jan Meier" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:31 #, fuzzy msgid "Custom settings" msgstr "_Personalizada" #: ../quodlibet/ext/gstreamer/crossfeed.py:152 msgid "Crossfeed" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:153 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:20 #, fuzzy msgid "Filter _band:" msgstr "Filtrar por _género" #: ../quodlibet/ext/gstreamer/karaoke.py:21 msgid "The Frequency band of the filter" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:22 #, fuzzy msgid "Filter _width:" msgstr "Filtrar por _artista" #: ../quodlibet/ext/gstreamer/karaoke.py:23 msgid "The Frequency width of the filter" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:24 msgid "_Level:" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:24 msgid "Level of the effect" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:105 msgid "Karaoke" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:106 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:20 msgid "R_ate:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:21 msgid "_Tempo:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:22 msgid "_Pitch:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:89 #, fuzzy msgid "Audio Pitch / Speed" msgstr "Fuentes de audio" #: ../quodlibet/ext/gstreamer/pitch.py:90 #, fuzzy msgid "Controls the pitch of an audio stream." msgstr "Introduce la direcciónde la fuente de audio (feed)" #: ../quodlibet/ext/playlist/export_to_folder.py:29 #: ../quodlibet/ext/playlist/export_to_folder.py:97 #: ../quodlibet/ext/playlist/export_to_folder.py:138 #, fuzzy msgid "Export Playlist to Folder" msgstr "Importar lista" #: ../quodlibet/ext/playlist/export_to_folder.py:38 #, fuzzy msgid "_Export" msgstr "_Importar" #: ../quodlibet/ext/playlist/export_to_folder.py:43 #, fuzzy msgid "Destination folder:" msgstr "No se han encontrado emisoras" #: ../quodlibet/ext/playlist/export_to_folder.py:58 #, fuzzy msgid "Filename pattern:" msgstr "Patrón para el nombre de _archivo:" #: ../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:156 #, fuzzy msgid "Default filename pattern:" msgstr "Patrón para el nombre de _archivo:" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:23 msgid "Export to Squeezebox" msgstr "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:25 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 "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Export playlist to Squeezebox" msgstr "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:80 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 la etiqueta 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á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?" #: ../quodlibet/ext/playlist/remove_duplicates.py:52 #, python-format msgid "The duplicate songs will be removed from the playlist '%s'." msgstr "Las canciones duplicadas serán eliminadas de la lista '%s'." #: ../quodlibet/ext/playlist/shuffle.py:15 #, fuzzy msgid "Shuffle Playlist" msgstr "Nueva 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 "" "Playback follows your selection, or the next song in the list once exhausted." msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:22 msgid "Playcount Equalizer" msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:23 msgid "Shuffle, preferring songs with fewer total plays." msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:25 #, fuzzy msgid "Prefer less played" msgstr "última reproducción" #: ../quodlibet/ext/playorder/queue.py:19 #, fuzzy msgid "Queue Only" msgstr "En cola" #: ../quodlibet/ext/playorder/queue.py:21 msgid "" "Limits playing of songs to the queue. Select this play order in the main " "window, then double-clicking any song will enqueue it instead of playing." msgstr "" #: ../quodlibet/ext/playorder/reverse.py:14 #, fuzzy msgid "Reverse" msgstr "Nunca" #: ../quodlibet/ext/playorder/reverse.py:16 msgid "Reverses the play order of songs." msgstr "" #: ../quodlibet/ext/playorder/skip_songs.py:25 #, fuzzy msgid "Skip Songs" msgstr "saltar el contador" #: ../quodlibet/ext/playorder/skip_songs.py:27 msgid "" "Playback skips over songs with a rating equal or below a given threshold." msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:30 msgid "Repeat Each Track" msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:32 msgid "Shuffle songs, but repeat every track a set number of times." msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:51 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. Syntax is '@(if: " "condition, then, else)'." msgstr "" #: ../quodlibet/ext/query/pythonexpression.py:14 msgid "Python Query" msgstr "" #: ../quodlibet/ext/query/pythonexpression.py:15 msgid "" "Use Python expressions in queries. Syntax is '@(python: expression)'. The " "variable 's' is the song being matched." msgstr "" #: ../quodlibet/ext/query/savedsearch.py:19 #, fuzzy msgid "Include Saved Search" msgstr "Valores guardados" #: ../quodlibet/ext/query/savedsearch.py:20 msgid "" "Include the results of a saved search as part of another query. Syntax is " "'@(saved: search name)'." 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 "No se ha podido conectar a una infraestructura de dispositivos" #: ../quodlibet/ext/_shared/squeezebox/base.py:110 msgid "Hostname:" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:116 msgid "Port:" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:121 #, fuzzy msgid "Username:" msgstr "_Cambiar el nombre" #: ../quodlibet/ext/_shared/squeezebox/base.py:126 msgid "Password:" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:130 msgid "Library directory the server connects to." msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:132 #, fuzzy msgid "Library path:" msgstr "Colección" #. Add verify button #: ../quodlibet/ext/_shared/squeezebox/base.py:141 msgid "_Verify settings" msgstr "" #. Server settings Frame #: ../quodlibet/ext/_shared/squeezebox/base.py:147 msgid "Squeezebox Server" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:150 msgid "Debug" msgstr "Debug" #: ../quodlibet/ext/_shared/squeezebox/server.py:26 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:28 msgid "unidentified Squeezebox server" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:37 #, 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:20 #: ../quodlibet/ext/songsmenu/importexport.py:34 #: ../quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:329 #, fuzzy msgid "Fit image to _window" msgstr "Esconder la ventana principal" #. Both labels #: ../quodlibet/ext/songsmenu/albumart.py:338 msgid "_Program:" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:343 msgid "_Edit image after saving" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:345 #, fuzzy msgid "File_name:" msgstr "Nombre del archivo" #: ../quodlibet/ext/songsmenu/albumart.py:457 msgid "Saving failed" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:458 #, fuzzy, python-format msgid "Unable to save \"%s\"." msgstr "No ha sido posible guardar la canción" #: ../quodlibet/ext/songsmenu/albumart.py:556 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:613 #, fuzzy msgid "Album Art Downloader" msgstr "Lista de álbumes" #: ../quodlibet/ext/songsmenu/albumart.py:666 #, python-format msgid "from %(source)s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:669 #, python-format msgid "Resolution: %s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:672 #, fuzzy, python-format msgid "Size: %s" msgstr "Tamaño" #: ../quodlibet/ext/songsmenu/albumart.py:690 #, fuzzy msgid "_Search" msgstr "_Buscar" #: ../quodlibet/ext/songsmenu/albumart.py:741 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:451 #, fuzzy msgid "Searching…" msgstr "Buscar" #: ../quodlibet/ext/songsmenu/albumart.py:804 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:922 #, fuzzy msgid "Download Album Art" msgstr "Lista de álbumes" #: ../quodlibet/ext/songsmenu/albumart.py:923 msgid "Downloads album covers from various websites." msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:936 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 los 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 los 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 según 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 #: ../quodlibet/qltk/downloader.py:52 msgid "Filename" msgstr "Nombre del archivo" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:130 #, fuzzy msgid "Disc" msgstr "_Disco" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:131 #: ../quodlibet/ext/songsmenu/replaygain.py:404 #: ../quodlibet/qltk/tracknumbers.py:92 msgid "Track" msgstr "Pista" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:132 #, 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 según MusicBrainz" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:375 #, fuzzy msgid "_Query:" msgstr "búsqueda" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:378 #, fuzzy msgid "S_earch" msgstr "Buscar" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:391 msgid "Results <i>(drag to reorder)</i>" msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:447 msgid "Please enter a query." msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:465 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:496 msgid "Error encountered. Please retry." msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:472 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:488 msgid "Loading result…" msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:475 #, fuzzy msgid "No results found." msgstr "No se ha encontrado extensión alguna" #: ../quodlibet/ext/songsmenu/browsefolders.py:159 #, fuzzy msgid "Browse Folders" msgstr "Navegadores" #: ../quodlibet/ext/songsmenu/browsefolders.py:160 msgid "Opens the songs' folders in a file manager." msgstr "" #: ../quodlibet/ext/songsmenu/browsefolders.py:172 #, fuzzy msgid "Unable to open folders" msgstr "No se ha podido crear la carpeta" #: ../quodlibet/ext/songsmenu/browsefolders.py:173 msgid "No program available to open folders." msgstr "" #: ../quodlibet/ext/songsmenu/console.py:40 msgid "Python Console" msgstr "" #: ../quodlibet/ext/songsmenu/console.py:41 msgid "Interactive Python console." msgstr "" #: ../quodlibet/ext/songsmenu/console.py:72 msgid "You can access the following objects by default:" msgstr "" #: ../quodlibet/ext/songsmenu/console.py:82 msgid "Your current working directory is:" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:41 #, fuzzy msgid "Command" msgstr "etiqueta" #: ../quodlibet/ext/songsmenu/custom_commands.py:44 #, fuzzy msgid "name" msgstr "_Cambiar el nombre" #: ../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:55 #, fuzzy msgid "pattern" msgstr "Patrón inválido" #: ../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:91 #, fuzzy msgid "Input value" msgstr "Valor inválido" #: ../quodlibet/ext/songsmenu/custom_commands.py:92 #, python-format msgid "Value for %s?" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:136 #, fuzzy msgid "Custom Commands" msgstr "_Personalizada" #: ../quodlibet/ext/songsmenu/custom_commands.py:137 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:188 #: ../quodlibet/ext/songsmenu/custom_commands.py:198 #: ../quodlibet/ext/songsmenu/custom_commands.py:252 msgid "Edit Custom Commands" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:199 msgid "" "Supports QL patterns\n" "eg <tt><~artist~title></tt>" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:283 #, fuzzy, python-format msgid "Unable to run custom command %s" msgstr "No ha sido posible copiar las canciones" #: ../quodlibet/ext/songsmenu/duplicates.py:290 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "" msgstr[1] "" #: ../quodlibet/ext/songsmenu/duplicates.py:343 msgid "Collapse / Expand all" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:347 #, python-format msgid "Duplicate key expression is '%s'" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:363 #, fuzzy msgid "Duplicates Browser" msgstr "Desactivar el navegador" #: ../quodlibet/ext/songsmenu/duplicates.py:364 msgid "Finds and displays similarly tagged versions of songs." msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:407 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:409 msgid "_Group duplicates by:" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:414 #, fuzzy msgid "Duplicate Key" msgstr "Eliminar la etiqueta seleccionada" #: ../quodlibet/ext/songsmenu/duplicates.py:419 #, fuzzy msgid "Remove _Whitespace" msgstr "Eliminar la etiqueta seleccionada" #: ../quodlibet/ext/songsmenu/duplicates.py:420 #, fuzzy msgid "Remove _Diacritics" msgstr "Eliminar la etiqueta seleccionada" #: ../quodlibet/ext/songsmenu/duplicates.py:421 #, fuzzy msgid "Remove _Punctuation" msgstr "_Eliminar la emisora" #: ../quodlibet/ext/songsmenu/duplicates.py:422 msgid "Case _Insensitive" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:430 msgid "Matching options" msgstr "" #. Create a dialog. #: ../quodlibet/ext/songsmenu/editplaycount.py:19 #: ../quodlibet/ext/songsmenu/editplaycount.py:41 #, fuzzy msgid "Edit Playcount" msgstr "Editar la vista" #: ../quodlibet/ext/songsmenu/editplaycount.py:20 msgid "" "Edit a song's ~#playcount and ~#skipcount.\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's ~#playcount to 0, the ~#lastplayed and ~#laststarted " "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:68 msgid "Play Count" msgstr "" #: ../quodlibet/ext/songsmenu/editplaycount.py:69 #, fuzzy msgid "Skip Count" msgstr "saltar el contador" #: ../quodlibet/ext/songsmenu/embedded.py:24 #, fuzzy msgid "Edit Embedded Images" msgstr "Extraer las imágenes incrustadas" #: ../quodlibet/ext/songsmenu/embedded.py:25 #, fuzzy msgid "Removes or replaces embedded images." msgstr "Extraer las imágenes incrustadas" #: ../quodlibet/ext/songsmenu/embedded.py:78 #, fuzzy msgid "_Remove all Images" msgstr "Eliminar la etiqueta seleccionada" #: ../quodlibet/ext/songsmenu/embedded.py:82 #, fuzzy msgid "_Embed Current Image" msgstr "Extraer las imágenes incrustadas" #: ../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 "Filtro en un valor de las etiquetas" #: ../quodlibet/ext/songsmenu/filterall.py:81 #, fuzzy msgid "Creates a search query based on tags of the selected songs." msgstr "GStreamer no ha podido cargar la canción seleccionada" #: ../quodlibet/ext/songsmenu/filterbrowser.py:19 #, fuzzy msgid "Filter on Directory" msgstr "Filtrar por _género" #: ../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:41 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 #: ../quodlibet/qltk/downloader.py:67 msgid "Queued" msgstr "En cola" #: ../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 "Guardar" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" 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 de la pista" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:296 #, fuzzy msgid "Group by directory" msgstr "ruta" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:305 #, fuzzy msgid "Album Mode" msgstr "Cabeceras de _álbumes" #: ../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:49 msgid "Generating fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:63 msgid "_Details" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:85 msgid "_Submit" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:115 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:118 msgid "Fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Songs with MBIDs:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with sufficient tags:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs to submit:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:162 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:178 msgid "Submitting fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:186 msgid "Submitting…" msgstr "" #: ../quodlibet/ext/songsmenu/forcewrite.py:17 #, fuzzy msgid "Update Tags in Files" msgstr "_Nueva 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/id3tlen.py:21 msgid "Fix MP3 Duration" msgstr "" #: ../quodlibet/ext/songsmenu/id3tlen.py:22 msgid "" "Removes TLEN frames from ID3 tags which can be the cause for invalid song " "durations." msgstr "" #: ../quodlibet/ext/songsmenu/ifp.py:20 msgid "Send to iFP" msgstr "" #: ../quodlibet/ext/songsmenu/ifp.py:21 msgid "Uploads songs to an iRiver iFP device." msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:51 msgid "Export Metadata" msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:52 msgid "Exports metadata of selected songs as a .tags file." msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:92 #, fuzzy msgid "Import Metadata" msgstr "Importar lista" #: ../quodlibet/ext/songsmenu/importexport.py:93 msgid "Imports metadata for selected songs from a .tags file." msgstr "" #: ../quodlibet/ext/songsmenu/k3b.py:23 msgid "Burn CD" msgstr "" #: ../quodlibet/ext/songsmenu/k3b.py:24 msgid "Burns CDs with K3b, Brasero or xfburn." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:96 msgid "Updating chart list." msgstr "" #. No charts to fetch, no update scheduled. #: ../quodlibet/ext/songsmenu/lastfmsync.py:114 msgid "Already up-to-date." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:121 #, python-format msgid "Fetching chart for week of %s." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:143 msgid "Sync complete." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:149 #, fuzzy msgid "Error during sync" msgstr "Error al cargar %r" #: ../quodlibet/ext/songsmenu/lastfmsync.py:214 #: ../quodlibet/ext/songsmenu/lastfmsync.py:244 msgid "Last.fm Sync" msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:245 msgid "Updates your library's statistics from your Last.fm profile." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:293 #, fuzzy msgid "_Username:" msgstr "_Cambiar el nombre" #: ../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 "" #. Create a dialog. #: ../quodlibet/ext/songsmenu/migratemetadata.py:29 #: ../quodlibet/ext/songsmenu/migratemetadata.py:38 #, fuzzy msgid "Migrate Metadata" msgstr "Importar lista" #: ../quodlibet/ext/songsmenu/migratemetadata.py:32 msgid "Copies the quodlibet-specific metadata between songs." msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:45 msgid "_Copy" msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:47 msgid "_Paste" msgstr "" #. Create the tag table. #: ../quodlibet/ext/songsmenu/migratemetadata.py:57 #, fuzzy msgid "Information to copy/paste" msgstr "Información" #. Create the indexing box. #: ../quodlibet/ext/songsmenu/migratemetadata.py:79 msgid "Map tracks by disc and track number" msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:80 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 "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:96 #, python-format msgid "There is %d stored track." msgid_plural "There are %d stored tracks." msgstr[0] "" msgstr[1] "" #: ../quodlibet/ext/songsmenu/playlist.py:31 #, fuzzy msgid "Export as Playlist" msgstr "Importar lista" #: ../quodlibet/ext/songsmenu/playlist.py:32 msgid "Exports songs to an M3U or PLS playlist." msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:77 msgid "Use relative paths" msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:77 msgid "Use absolute paths" msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:132 #, fuzzy msgid "Unable to export playlist" msgstr "No ha sido posible importar la lista de reproducción" #: ../quodlibet/ext/songsmenu/playlist.py:133 #, fuzzy, python-format msgid "Writing to <b>%s</b> failed." msgstr "Error al expulsar <b>%s</b>." #. Translators: Plugin name #: ../quodlibet/ext/songsmenu/refresh.py:22 #, fuzzy msgid "Rescan Songs" msgstr "Ac_tualizar la colección" #: ../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 la colección" #: ../quodlibet/ext/songsmenu/replaygain.py:362 msgid "ReplayGain Analyzer" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:418 msgid "Progress" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:433 msgid "Gain" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:448 msgid "Peak" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:463 #, python-format msgid "There is <b>%(to-process)s</b> album to update (of %(all)s)" msgid_plural "There are <b>%(to-process)s</b> albums to update (of %(all)s)" msgstr[0] "" msgstr[1] "" #: ../quodlibet/ext/songsmenu/replaygain.py:578 msgid "Replay Gain" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:579 msgid "" "Analyzes and updates ReplayGain information, using GStreamer. Results are " "grouped by album." msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:617 msgid "always" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:618 msgid "if <b>any</b> RG tags are missing" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:620 msgid "if <b>album</b> RG tags are missing" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:637 msgid "_Process albums:" msgstr "" #. Server settings Frame #: ../quodlibet/ext/songsmenu/replaygain.py:649 #, fuzzy msgid "Existing Tags" msgstr "Editar etiquetas" #: ../quodlibet/ext/songsmenu/splitting.py:31 #, fuzzy msgid "Split Tags" msgstr "Editar 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 los álbumes" #: ../quodlibet/ext/songsmenu/splitting.py:57 msgid "Split out disc number." msgstr "" #. TRANSLATORS: BPM mean "beats per minute" #: ../quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "" #: ../quodlibet/ext/songsmenu/tapbpm.py:32 #: ../quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" msgstr "" #: ../quodlibet/ext/songsmenu/tapbpm.py:36 #, fuzzy msgid "Reset" msgstr "_Prever" #: ../quodlibet/ext/songsmenu/tapbpm.py:42 #, fuzzy msgid "Tap" msgstr "Etiqueta" #: ../quodlibet/ext/songsmenu/tapbpm.py:172 #: ../quodlibet/ext/songsmenu/tapbpm.py:179 msgid "Tap BPM" msgstr "" #: ../quodlibet/ext/songsmenu/tapbpm.py:173 #, fuzzy msgid "Tap BPM for the selected song." msgstr "No se han podido eliminar las canciones" #: ../quodlibet/ext/songsmenu/website_search.py:35 #, fuzzy msgid "Website Search" msgstr "Buscar" #: ../quodlibet/ext/songsmenu/website_search.py:36 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern-example)s." msgstr "" #: ../quodlibet/ext/songsmenu/website_search.py:78 #, fuzzy msgid "Search URL patterns" msgstr "patrón" #: ../quodlibet/ext/songsmenu/website_search.py:88 #, fuzzy msgid "Edit search URLs" msgstr "Editar los valores guardados..." #. Add link to editor #: ../quodlibet/ext/songsmenu/website_search.py:114 #, fuzzy msgid "Configure Searches…" msgstr "Colorear los términos de la _búsqueda" #: ../quodlibet/ext/songsmenu/wikipedia.py:46 #, python-format msgid "Search at %(website)s" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:63 msgid "Search Artist in Wikipedia" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:64 msgid "" "Opens a browser window with Wikipedia article on the playing song artist." msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:71 msgid "Search Album in Wikipedia" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:72 msgid "" "Opens a browser window with Wikipedia article on the playing song album." msgstr "" #. then (try to) load all new files #: ../quodlibet/library/libraries.py:650 ../quodlibet/library/libraries.py:660 #: ../quodlibet/library/libraries.py:726 ../quodlibet/library/libraries.py:745 #: ../quodlibet/qltk/information.py:268 ../quodlibet/qltk/prefs.py:639 #: ../quodlibet/util/library.py:124 msgid "Library" msgstr "Colección" #: ../quodlibet/library/libraries.py:650 msgid "Checking mount points" msgstr "Comprobando los puntos de montaje" #: ../quodlibet/library/libraries.py:660 msgid "Scanning library" msgstr "Analizando la colección" #: ../quodlibet/library/libraries.py:725 #, python-format msgid "Scanning %s" msgstr "Analizando %s" #: ../quodlibet/library/libraries.py:745 msgid "Loading files" msgstr "" #: ../quodlibet/operon/base.py:70 #, python-format msgid "Failed to load file: %r" msgstr "Error al abrir el archivo: %r" #: ../quodlibet/operon/commands.py:37 msgid "List tags" msgstr "Mostrar las etiquetas" #: ../quodlibet/operon/commands.py:42 ../quodlibet/operon/commands.py:81 #: ../quodlibet/operon/commands.py:461 msgid "Print terse output" msgstr "Mostrar salida para depuración" #: ../quodlibet/operon/commands.py:44 ../quodlibet/operon/commands.py:83 #: ../quodlibet/operon/commands.py:463 #, 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:47 ../quodlibet/operon/commands.py:86 #, fuzzy msgid "Also list programmatic tags" msgstr "Mostrar _mensajes adicionales para depuración" #: ../quodlibet/operon/commands.py:51 ../quodlibet/operon/commands.py:129 #: ../quodlibet/operon/commands.py:220 ../quodlibet/operon/commands.py:293 #: ../quodlibet/operon/commands.py:336 ../quodlibet/operon/commands.py:340 #: ../quodlibet/operon/commands.py:391 ../quodlibet/operon/commands.py:394 #: ../quodlibet/operon/commands.py:433 ../quodlibet/operon/commands.py:468 #: ../quodlibet/operon/commands.py:508 ../quodlibet/operon/commands.py:543 #: ../quodlibet/operon/commands.py:585 msgid "Not enough arguments" msgstr "Sin argumentos suficientes" #: ../quodlibet/operon/commands.py:53 ../quodlibet/operon/commands.py:90 #: ../quodlibet/operon/commands.py:131 ../quodlibet/operon/commands.py:222 #: ../quodlibet/operon/commands.py:470 #, fuzzy msgid "Too many arguments" msgstr "Demasiados errores" #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:92 #: ../quodlibet/operon/commands.py:475 ../quodlibet/qltk/data_editors.py:363 #, fuzzy msgid "Description" msgstr "descripción" #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:475 #: ../quodlibet/qltk/edittags.py:454 msgid "Value" msgstr "Valor" #: ../quodlibet/operon/commands.py:76 msgid "List all common tags" msgstr "Mostrar las etiquetas habituales" #: ../quodlibet/operon/commands.py:118 msgid "Copy tags from one file to another" msgstr "Copiar las etiquetas de un archivo a otro" #: ../quodlibet/operon/commands.py:123 ../quodlibet/operon/commands.py:164 #: ../quodlibet/operon/commands.py:289 ../quodlibet/operon/commands.py:324 #: ../quodlibet/operon/commands.py:384 msgid "Show changes, don't apply them" msgstr "Mostrar los cambios, sin aplicarlos" #: ../quodlibet/operon/commands.py:125 msgid "Skip tags that can't be written" msgstr "Saltar las etiquetas que no se puedan escribir" #: ../quodlibet/operon/commands.py:145 #, python-format msgid "Can't copy tag %r to file: %r" msgstr "No se ha podido copiar la etiqueta %r al archivo: %r" #: ../quodlibet/operon/commands.py:157 #, fuzzy msgid "Edit tags in a text editor" msgstr "Editor de etiquetas de 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 "No se ha seleccionado canción alguna" #: ../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:304 ../quodlibet/operon/commands.py:444 #: ../quodlibet/operon/commands.py:676 #, python-format msgid "Can not set %r" msgstr "No se ha podido establecer %r" #: ../quodlibet/operon/commands.py:319 #, fuzzy msgid "Remove tags" msgstr "_Eliminar la emisora" #: ../quodlibet/operon/commands.py:326 ../quodlibet/operon/commands.py:386 msgid "Value is a regular expression" msgstr "El valor es una expresión regular" #: ../quodlibet/operon/commands.py:328 #, fuzzy msgid "Remove all tags" msgstr "Eliminar la etiqueta seleccionada" #: ../quodlibet/operon/commands.py:332 msgid "Can't combine '--all' with '--regexp'" msgstr "No se puede combinar '--all' con '--regexp'" #: ../quodlibet/operon/commands.py:366 #, python-format msgid "Can't remove %r from %r" msgstr "No se ha podido eliminar %r de %r" #: ../quodlibet/operon/commands.py:379 #, fuzzy msgid "Remove a tag value" msgstr "Filtro en un valor de las etiquetas" #: ../quodlibet/operon/commands.py:428 #, fuzzy msgid "Add a tag value" msgstr "Filtro en un valor de las etiquetas" #: ../quodlibet/operon/commands.py:456 #, fuzzy msgid "List file information" msgstr "No existe información sobre la duración" #: ../quodlibet/operon/commands.py:502 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" #: ../quodlibet/operon/commands.py:515 #, fuzzy, python-format msgid "Failed to load image file: %r" msgstr "Error al abrir el archivo: %r" #: ../quodlibet/operon/commands.py:522 ../quodlibet/operon/commands.py:551 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" #: ../quodlibet/operon/commands.py:538 #, fuzzy msgid "Remove all embedded images" msgstr "Extraer las imágenes incrustadas" #: ../quodlibet/operon/commands.py:568 #, fuzzy, python-format msgid "Extract embedded images to %(filepath)s" msgstr "Extraer las imágenes incrustadas" #: ../quodlibet/operon/commands.py:580 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" #: ../quodlibet/operon/commands.py:639 msgid "Rename files based on tags" msgstr "Renombrar los archivos según las etiquetas" #: ../quodlibet/operon/commands.py:654 msgid "Fill tags based on the file path" msgstr "Rellenar las etiquetas según la ruta al archivo" #: ../quodlibet/operon/commands.py:704 ../quodlibet/qltk/information.py:305 #: ../quodlibet/qltk/properties.py:84 ../quodlibet/qltk/renamefiles.py:176 #: ../quodlibet/qltk/tagsfrompath.py:229 ../quodlibet/qltk/tracknumbers.py:79 msgid "File" msgstr "Archivo" #: ../quodlibet/operon/commands.py:712 msgid "Fill tracknumbers for all files" msgstr "Rellenar los números de pista de todos los archivos" #: ../quodlibet/operon/commands.py:731 msgid "Print tags based on the given pattern" msgstr "Mostrar las etiquetas basándose en el patrón indicado" #: ../quodlibet/operon/commands.py:768 #, fuzzy msgid "Display help information" msgstr "Muestra información sumaria sobre los distintos comandos" #: ../quodlibet/operon/util.py:40 #, fuzzy, python-format msgid "'%(column-id)s' is not a valid column name (%(all-column-ids)s)." msgstr "<b>%s</b> no es una dirección válida." #: ../quodlibet/order/__init__.py:30 msgid "_Unknown" msgstr "_Desconocido" #: ../quodlibet/order/__init__.py:142 msgid "In Order" msgstr "En orden" #: ../quodlibet/order/__init__.py:143 msgid "_In Order" msgstr "_En orden" #: ../quodlibet/order/reorder.py:23 #, fuzzy msgid "Random" msgstr "Aleato_rio" #: ../quodlibet/order/reorder.py:24 ../quodlibet/qltk/queue.py:119 msgid "_Random" msgstr "Aleato_rio" #: ../quodlibet/order/reorder.py:39 ../quodlibet/order/reorder.py:40 msgid "Prefer higher rated" msgstr "" #: ../quodlibet/order/repeat.py:43 ../quodlibet/order/repeat.py:44 msgid "Repeat this track" msgstr "" #: ../quodlibet/order/repeat.py:57 ../quodlibet/order/repeat.py:58 #, fuzzy msgid "Repeat all" msgstr "_Repetir" #: ../quodlibet/order/repeat.py:73 ../quodlibet/order/repeat.py:74 msgid "One Song" msgstr "Una canción" #: ../quodlibet/player/gstbe/player.py:98 msgid "Stream" msgstr "Stream" #: ../quodlibet/player/gstbe/player.py:98 msgid "Buffering" msgstr "Llenando el buffer" #: ../quodlibet/player/gstbe/player.py:319 #, fuzzy msgid "Could not create GStreamer pipeline" msgstr "No se ha podido crear la pipeline GStreamer predefinida" #: ../quodlibet/player/gstbe/player.py:560 msgid "No GStreamer element found to handle media format" msgstr "" #: ../quodlibet/player/gstbe/player.py:561 #, 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:25 #, fuzzy msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. In case the pipeline contains a sink, it will be used instead of " "the default one." msgstr "" "La infraestructura de salida GStreamer utilizada para la reproducción, e.g. " "'alsasink device=default'.\n" "Déjalo en blanco para utilizar la predeterminada." #: ../quodlibet/player/gstbe/prefs.py:36 msgid "_Output pipeline:" msgstr "_Infraestructura de salida de sonido:" #: ../quodlibet/player/gstbe/prefs.py:43 #, fuzzy, python-format msgid "%.1f seconds" msgstr "%d segundo" #: ../quodlibet/player/gstbe/prefs.py:57 msgid "_Buffer duration:" msgstr "Duración del _buffer:" #: ../quodlibet/player/gstbe/prefs.py:66 msgid "Disable _gapless playback" msgstr "" #: ../quodlibet/player/gstbe/prefs.py:70 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions." msgstr "" #: ../quodlibet/player/gstbe/util.py:93 #, fuzzy msgid "No GStreamer audio sink found" msgstr "No se encontró dispositivo de sonido" #: ../quodlibet/player/gstbe/util.py:112 #, fuzzy msgid "Invalid GStreamer output pipeline" msgstr "Salida de GStreamer inválida, intentando la predeterminada." #: ../quodlibet/player/xinebe/player.py:90 msgid "Unable to create audio output" msgstr "No fue posible generar salida de audio" #: ../quodlibet/player/xinebe/player.py:91 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "" "No se ha encontrado el dispositivo de sonido %r. Comprueba la configuración " "de Xine en ~/.quodlibet/config." #: ../quodlibet/plugins/__init__.py:62 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" #: ../quodlibet/plugins/__init__.py:71 #, fuzzy, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "No se ha podido enlazar la pipeline GStreamer: '%s'" #: ../quodlibet/plugins/playlist.py:30 #, 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:41 ../quodlibet/qltk/songsmenu.py:46 #: ../quodlibet/qltk/songsmenu.py:74 #, fuzzy msgid "_Run Plugin" msgstr "_Extensiones" #: ../quodlibet/qltk/about.py:40 #, python-format msgid "Supported formats: %s" msgstr "Formatos admitidos: %s" #: ../quodlibet/qltk/about.py:43 #, python-format msgid "Audio device: %s" msgstr "Dispositivo de sonido: %s" #. 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:207 ../quodlibet/qltk/information.py:131 msgid "Bookmarks" msgstr "Marcadores" #: ../quodlibet/qltk/browser.py:56 msgid "_Filters" msgstr "_Filtros" #: ../quodlibet/qltk/browser.py:57 #, fuzzy msgid "Recently _Played" msgstr "_Nunca reproducidas" #: ../quodlibet/qltk/browser.py:59 msgid "Recently _Added" msgstr "Añadidas _recientemente" #: ../quodlibet/qltk/browser.py:61 msgid "_Top 40" msgstr "40 más _eschuchadas" #: ../quodlibet/qltk/browser.py:63 #, fuzzy msgid "All _Songs" msgstr "Nueva 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 "_Género aleatorio" #: ../quodlibet/qltk/browser.py:82 msgid "Random _Artist" msgstr "_Artista 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 "" "Las 40 canciones que más has escuchado (pueden mostrarse más de 40 si " "algunas se reproducieron el mismo número de veces)" #: ../quodlibet/qltk/cbes.py:48 ../quodlibet/qltk/edittags.py:311 msgid "_Value:" msgstr "_Valor:" #: ../quodlibet/qltk/cbes.py:262 msgid "Saved Values" msgstr "Valores guardados" #: ../quodlibet/qltk/cbes.py:263 #, fuzzy msgid "Edit saved values…" msgstr "Editar los valores guardados..." #: ../quodlibet/qltk/controls.py:111 msgid "Auto_matic" msgstr "Auto_mática" #: ../quodlibet/qltk/controls.py:112 #, fuzzy msgid "_Track Mode" msgstr "Cabeceras de _fichero" #: ../quodlibet/qltk/controls.py:113 #, fuzzy msgid "_Album Mode" msgstr "Cabeceras de _álbumes" #. Translators: player state, no action #: ../quodlibet/qltk/controls.py:122 msgid "_Mute" msgstr "" #: ../quodlibet/qltk/controls.py:128 #, fuzzy msgid "_Replay Gain Mode" msgstr "Ajuste de volumen _replay gain" #. Translators: New Command/Entry/Item/... #: ../quodlibet/qltk/data_editors.py:119 #, python-format msgid "New %s" msgstr "" #: ../quodlibet/qltk/data_editors.py:218 #, fuzzy msgid "(unknown)" msgstr "Desconocido" #: ../quodlibet/qltk/data_editors.py:355 #, fuzzy msgid "Tag expression" msgstr "El valor es una expresión regular" #: ../quodlibet/qltk/data_editors.py:382 msgid "Tag expression e.g. people:real or ~album~year." msgstr "" #: ../quodlibet/qltk/data_editors.py:383 #, fuzzy msgid "Enter new tag" msgstr "Filtro en un valor de las etiquetas" #: ../quodlibet/qltk/delete.py:37 #, fuzzy msgid "Files:" msgstr "Archivos" #: ../quodlibet/qltk/delete.py:63 #, fuzzy msgid "" "The selected songs will be removed from the library and their files deleted " "from disk." msgstr "Las canciones duplicadas serán eliminadas de la lista '%s'." #: ../quodlibet/qltk/delete.py:72 #, fuzzy msgid "The selected files will be deleted from disk." msgstr "Las canciones duplicadas serán eliminadas de la 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 los archivos" #: ../quodlibet/qltk/delete.py:106 #, fuzzy msgid "" "The selected songs will be removed from the library and their files moved to " "the trash." msgstr "Las canciones duplicadas serán eliminadas de la lista '%s'." #: ../quodlibet/qltk/delete.py:115 #, fuzzy msgid "The selected files will be moved to the trash." msgstr "Las canciones duplicadas serán eliminadas de la 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 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 #, fuzzy msgid "Unable to move to trash" msgstr "No ha sido posible guardar la base de datos del iPod" #: ../quodlibet/qltk/delete.py:174 ../quodlibet/qltk/delete.py:206 #, fuzzy msgid "Moving one or more files to the trash failed." msgstr "Error al expulsar <b>%s</b>." #: ../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 #, fuzzy msgid "Unable to delete files" msgstr "No se ha podido eliminar el archivo" #: ../quodlibet/qltk/delete.py:237 ../quodlibet/qltk/delete.py:270 #, fuzzy msgid "Deleting one or more files failed." msgstr "Ha ocurrido un error al eliminar <b>%s</b>." #: ../quodlibet/qltk/downloader.py:38 msgid "Downloads" msgstr "Descargas" #: ../quodlibet/qltk/downloader.py:62 msgid "Size" msgstr "Tamaño" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: ../quodlibet/qltk/downloader.py:94 ../quodlibet/qltk/renamefiles.py:265 #: ../quodlibet/qltk/wlw.py:50 msgid "_Stop" msgstr "" #: ../quodlibet/qltk/edittags.py:63 ../quodlibet/qltk/edittags.py:74 #, 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:67 ../quodlibet/qltk/edittags.py:71 #, 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:193 msgid "Split into _Multiple Values" msgstr "Extraer en valores _múltiples" #: ../quodlibet/qltk/edittags.py:211 msgid "Split Disc out of _Album" msgstr "Extraer el disco del ál_bum" #: ../quodlibet/qltk/edittags.py:228 msgid "Split _Version out of Title" msgstr "Extraer la _versión del título" #: ../quodlibet/qltk/edittags.py:259 msgid "Split Arranger out of Ar_tist" msgstr "Extraer el arreglista del ar_tista" #: ../quodlibet/qltk/edittags.py:264 msgid "Split _Performer out of Artist" msgstr "Extraer el _intérprete del artista" #: ../quodlibet/qltk/edittags.py:270 #, fuzzy msgid "Split _Performer out of Title" msgstr "Extraer el _intérprete del artista" #: ../quodlibet/qltk/edittags.py:276 #, fuzzy msgid "Split _Originalartist out of Title" msgstr "Extraer la _versión del título" #: ../quodlibet/qltk/edittags.py:283 msgid "Add a Tag" msgstr "Añadir una etiqueta" #: ../quodlibet/qltk/edittags.py:302 msgid "_Tag:" msgstr "_Etiqueta:" #: ../quodlibet/qltk/edittags.py:404 msgid "Edit Tags" msgstr "Editar etiquetas" #: ../quodlibet/qltk/edittags.py:477 msgid "Show _programmatic tags" msgstr "Mostrar _mensajes adicionales para depuración" #: ../quodlibet/qltk/edittags.py:478 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" #. Translators: Revert button in the tag editor #: ../quodlibet/qltk/edittags.py:508 #, fuzzy msgctxt "edittags" msgid "_Revert" msgstr "Nunca" #. Translators: Save button in the tag editor #: ../quodlibet/qltk/edittags.py:513 msgctxt "edittags" msgid "_Save" msgstr "" #: ../quodlibet/qltk/edittags.py:659 msgid "Unable to add tag" msgstr "No se ha podido añadir la etiqueta" #: ../quodlibet/qltk/edittags.py:660 #, fuzzy, python-format msgid "Unable to add <b>%s</b>" msgstr "No a sido posible añadir la canción" #: ../quodlibet/qltk/edittags.py:662 #, fuzzy, python-format msgid "" "The files currently selected do not support multiple values for <b>%s</b>." msgstr "" "No se ha podido añadir <b>%s</b>\n" "\n" "Los archivos seleccionados no permiten valores múltiples." #. Can't add the new tag. #: ../quodlibet/qltk/edittags.py:689 ../quodlibet/qltk/edittags.py:856 #: ../quodlibet/qltk/tagsfrompath.py:212 ../quodlibet/util/__init__.py:554 #: ../quodlibet/util/tags.py:231 msgid "Invalid tag" msgstr "Etiqueta inválida" #: ../quodlibet/qltk/edittags.py:690 ../quodlibet/qltk/edittags.py:857 #: ../quodlibet/qltk/tagsfrompath.py:213 #, python-format msgid "" "Invalid tag <b>%s</b>\n" "\n" "The files currently selected do not support editing this tag." msgstr "" "Etiqueta inválida <b>%s</b>\n" "\n" "Los archivos seleccionados no permiten la edición de la etiqueta." #: ../quodlibet/qltk/edittags.py:828 ../quodlibet/qltk/edittags.py:868 msgid "Invalid value" msgstr "Valor inválido" #: ../quodlibet/qltk/edittags.py:829 ../quodlibet/qltk/edittags.py:869 #, python-format msgid "" "Invalid value: <b>%(value)s</b>\n" "\n" "%(error)s" msgstr "" "Valor inválido: <b>%(value)s</b>\n" "\n" "%(error)s" #: ../quodlibet/qltk/_editutils.py:28 msgid "Tag may not be accurate" msgstr "La etiqueta puede no ser correcta" #: ../quodlibet/qltk/_editutils.py:31 #, 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 "" "Se ha modificado <b>%s</b> mientras el programa estaba siendo ejecutado. Si " "se guardasen los cambios sin actualizar la colección podrían ser eliminadas " "otras modificaciones efectuadas.\n" "¿ Guardar de todos modos?" #: ../quodlibet/qltk/_editutils.py:47 msgid "Unable to save song" msgstr "No ha sido posible guardar la canción" #: ../quodlibet/qltk/_editutils.py:50 #, 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 ha podido guardar <b>%s</b>. Es posible que el archivo sea sólo de " "escritura, que esté corrupto o que no tengas permisos para editarlo." #: ../quodlibet/qltk/_editutils.py:142 #, fuzzy msgid "_More options…" msgstr "_Más opciones..." #: ../quodlibet/qltk/entry.py:80 msgid "_Undo" msgstr "" #: ../quodlibet/qltk/entry.py:82 msgid "_Redo" msgstr "" #: ../quodlibet/qltk/exfalsowindow.py:95 #: ../quodlibet/qltk/quodlibetwindow.py:1066 msgid "_About" msgstr "" #: ../quodlibet/qltk/exfalsowindow.py:99 #: ../quodlibet/qltk/quodlibetwindow.py:1088 msgid "_Check for Updates…" msgstr "" #: ../quodlibet/qltk/exfalsowindow.py:105 #: ../quodlibet/qltk/quodlibetwindow.py:1021 ../quodlibet/qltk/songsmenu.py:304 msgid "_Plugins" msgstr "_Extensiones" #: ../quodlibet/qltk/exfalsowindow.py:267 #, fuzzy, python-format msgid "%(title)s and %(count)s more" msgid_plural "%(title)s and %(count)s more" msgstr[0] "%(title)s y %(count)d más" msgstr[1] "%(title)s y %(count)d más" #: ../quodlibet/qltk/exfalsowindow.py:279 msgid "Ex Falso Preferences" msgstr "Configuración de Ex Falso" #: ../quodlibet/qltk/exfalsowindow.py:289 ../quodlibet/qltk/prefs.py:598 msgid "Split _on:" msgstr "Extraer _de:" #: ../quodlibet/qltk/exfalsowindow.py:295 ../quodlibet/qltk/prefs.py:613 msgid "Tag Editing" msgstr "Edición de etiquetas" #: ../quodlibet/qltk/filesel.py:210 msgid "Folders" msgstr "Directorio" #: ../quodlibet/qltk/filesel.py:253 #, fuzzy msgid "_New Folder…" msgstr "Nueva carpeta" #: ../quodlibet/qltk/filesel.py:262 #, fuzzy msgid "_Select all Sub-Folders" msgstr "Seleccionar todas las carpetas subordinadas" #: ../quodlibet/qltk/filesel.py:374 msgid "New Folder" msgstr "Nueva carpeta" #: ../quodlibet/qltk/filesel.py:374 msgid "Enter a name for the new folder:" msgstr "Introduce un nombre para la nueva carpeta" #: ../quodlibet/qltk/filesel.py:387 msgid "Unable to create folder" msgstr "No se ha podido crear la carpeta" #: ../quodlibet/qltk/filesel.py:404 msgid "Unable to delete folder" msgstr "No se ha podido eliminar la carpeta" #: ../quodlibet/qltk/filesel.py:519 ../quodlibet/qltk/pluginwin.py:167 msgid "Songs" msgstr "Canciones" #. Translators: As in "by Artist Name" #: ../quodlibet/qltk/info.py:42 #, python-format msgid "by %s" msgstr "por %s" #: ../quodlibet/qltk/info.py:43 ../quodlibet/qltk/information.py:167 #: ../quodlibet/qltk/information.py:448 #, python-format msgid "Disc %s" msgstr "Disco %s" #: ../quodlibet/qltk/info.py:44 ../quodlibet/qltk/information.py:172 #, python-format msgid "Track %s" msgstr "Pista %s" #: ../quodlibet/qltk/info.py:108 #, fuzzy msgid "_Edit Display…" msgstr "Editar la vista" #: ../quodlibet/qltk/information.py:105 msgid "No songs are selected." msgstr "No se ha seleccionado canción alguna" #: ../quodlibet/qltk/information.py:106 msgid "No Songs" msgstr "Sin canciones" #: ../quodlibet/qltk/information.py:121 ../quodlibet/qltk/information.py:338 #: ../quodlibet/qltk/information.py:471 ../quodlibet/qltk/information.py:531 msgid "Information" msgstr "Información" #: ../quodlibet/qltk/information.py:126 msgid "Lyrics" msgstr "Letra" #: ../quodlibet/qltk/information.py:184 ../quodlibet/qltk/information.py:396 #, python-format msgid "Produced by %s" msgstr "Producido por %s" #: ../quodlibet/qltk/information.py:199 ../quodlibet/util/tags.py:76 msgid "artist" msgstr "artista" #: ../quodlibet/qltk/information.py:200 ../quodlibet/qltk/information.py:561 #: ../quodlibet/util/tags.py:76 msgid "artists" msgstr "artistas" #. for backwards compat #: ../quodlibet/qltk/information.py:221 ../quodlibet/util/tags.py:86 #: ../quodlibet/util/tags.py:114 msgid "performers" msgstr "intérpretes" #: ../quodlibet/qltk/information.py:235 ../quodlibet/qltk/information.py:248 #: ../quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "Nunca" #: ../quodlibet/qltk/information.py:236 #, fuzzy, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] " %d vez" msgstr[1] " %d veces" #: ../quodlibet/qltk/information.py:254 ../quodlibet/util/tags.py:139 msgid "added" msgstr "añadida" #: ../quodlibet/qltk/information.py:255 ../quodlibet/util/tags.py:140 msgid "last played" msgstr "última reproducción" #: ../quodlibet/qltk/information.py:256 ../quodlibet/util/tags.py:150 msgid "plays" msgstr "contador" #: ../quodlibet/qltk/information.py:257 ../quodlibet/util/tags.py:151 msgid "skips" msgstr "saltada" #: ../quodlibet/qltk/information.py:258 ../quodlibet/util/tags.py:156 msgid "rating" msgstr "puntuación" #: ../quodlibet/qltk/information.py:287 msgid "path" msgstr "" #: ../quodlibet/qltk/information.py:288 ../quodlibet/util/tags.py:154 msgid "length" msgstr "duración" #: ../quodlibet/qltk/information.py:289 #, fuzzy msgid "format" msgstr "Información" #: ../quodlibet/qltk/information.py:290 ../quodlibet/util/tags.py:163 msgid "codec" msgstr "" #: ../quodlibet/qltk/information.py:291 ../quodlibet/util/tags.py:164 #, fuzzy msgid "encoding" msgstr "Ascendiente" #: ../quodlibet/qltk/information.py:292 ../quodlibet/util/tags.py:160 msgid "bitrate" msgstr "tasa de bits" #: ../quodlibet/qltk/information.py:293 ../quodlibet/util/tags.py:161 msgid "file size" msgstr "tamaño" #: ../quodlibet/qltk/information.py:294 ../quodlibet/util/tags.py:149 msgid "modified" msgstr "modificada" #: ../quodlibet/qltk/information.py:331 msgid "Additional" msgstr "" #: ../quodlibet/qltk/information.py:383 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d seleccionada" msgstr[1] "%d seleccionadas" #: ../quodlibet/qltk/information.py:458 msgid "Track unavailable" msgstr "Pista no disponible" #: ../quodlibet/qltk/information.py:464 msgid "Track List" msgstr "Lista de pistas" #: ../quodlibet/qltk/information.py:505 ../quodlibet/qltk/information.py:578 #, 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:508 msgid "Selected Discography" msgstr "Discografía seleccionada" #: ../quodlibet/qltk/information.py:558 #, 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:586 ../quodlibet/util/tags.py:74 msgid "albums" msgstr "álbumes" #: ../quodlibet/qltk/information.py:599 msgid "Total length:" msgstr "Duración total:" #: ../quodlibet/qltk/information.py:603 msgid "Total size:" msgstr "Tamaño total:" #: ../quodlibet/qltk/information.py:606 msgid "Files" msgstr "Archivos" #: ../quodlibet/qltk/lyrics.py:37 msgid "_Download" msgstr "_Descargar" #: ../quodlibet/qltk/lyrics.py:40 #, fuzzy msgid "_Edit" msgstr "_Editar la vista..." #. buffer.set_text(_("No lyrics found.\n\nYou can click the " #. "Download button to have Quod Libet search " #. "for lyrics online. You can also enter them " #. "yourself and click save.")) #: ../quodlibet/qltk/lyrics.py:73 ../quodlibet/qltk/lyrics.py:109 msgid "No lyrics found for this song." msgstr "No se ha encontrado la letra de esta canción." #: ../quodlibet/qltk/lyrics.py:82 #, fuzzy msgid "Searching for lyrics…" msgstr "Buscando la letra de la canción..." #: ../quodlibet/qltk/maskedbox.py:20 #, fuzzy msgid "Are you sure you want to remove all songs?" msgstr "" "Estás a punto de cambiar la puntuación de %d canciones.\\n\n" "Deseas continuar?" #: ../quodlibet/qltk/maskedbox.py:21 #, fuzzy msgid "The selected songs will be removed from the library." msgstr "Las canciones duplicadas serán eliminadas de la lista '%s'." #: ../quodlibet/qltk/maskedbox.py:44 msgid "Unhide" msgstr "" #: ../quodlibet/qltk/maskedbox.py:86 msgid "_Unhide" msgstr "" #: ../quodlibet/qltk/msg.py:41 msgid "Discard tag changes?" msgstr "¿ Descartar las modificaciones en las etiquetas?" #: ../quodlibet/qltk/msg.py:42 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "" "Las etiquetas se han modificado pero no han sido guardadas. ¿Guardar eses " "ficheros o revertir y descartar dichos cambios?" #: ../quodlibet/qltk/msg.py:55 ../quodlibet/qltk/prefs.py:595 #: ../quodlibet/qltk/textedit.py:64 ../quodlibet/qltk/tracknumbers.py:117 #, fuzzy msgid "_Revert" msgstr "Nunca" #: ../quodlibet/qltk/msg.py:86 msgid "File exists" msgstr "El archivo ya existe" #: ../quodlibet/qltk/msg.py:88 #, python-format msgid "Replace %(file-name)s?" msgstr "" #: ../quodlibet/qltk/msg.py:94 #, fuzzy msgid "_Replace File" msgstr "Cambiar el nombre del archivo" #: ../quodlibet/qltk/notif.py:182 msgid "Active tasks" msgstr "Tareas activas" #: ../quodlibet/qltk/notif.py:188 #, fuzzy, python-format msgid "%d tasks running" msgstr "Quod Libet está siendo ejecutado" #: ../quodlibet/qltk/playorder.py:254 #, fuzzy msgid "Toggle shuffle mode" msgstr "Alternar reproducir y parar" #: ../quodlibet/qltk/playorder.py:270 #, fuzzy msgid "Toggle repeat mode" msgstr "Alternar reproducir y parar" #: ../quodlibet/qltk/pluginwin.py:44 msgid "Plugin Errors" msgstr "Errores en las extensiones" #: ../quodlibet/qltk/pluginwin.py:124 msgid "Enabled" msgstr "Activado" #: ../quodlibet/qltk/pluginwin.py:125 msgid "Disabled" msgstr "Desactivado" #: ../quodlibet/qltk/pluginwin.py:131 msgid "No category" msgstr "Sin categoría" #: ../quodlibet/qltk/pluginwin.py:169 msgid "Events" msgstr "" #: ../quodlibet/qltk/pluginwin.py:170 #, fuzzy msgid "Play Order" msgstr "_Orden de reproducción" #: ../quodlibet/qltk/pluginwin.py:171 #, fuzzy msgid "Editing" msgstr "Edición de etiquetas" #: ../quodlibet/qltk/pluginwin.py:173 #, fuzzy msgid "Covers" msgstr "Tamaño total:" #: ../quodlibet/qltk/pluginwin.py:309 msgid "No plugins found." msgstr "No se ha encontrado extensión alguna" #: ../quodlibet/qltk/pluginwin.py:358 #, fuzzy msgid "Plugins" msgstr "_Extensiones" #: ../quodlibet/qltk/pluginwin.py:402 msgid "Show _Errors" msgstr "Mostrar _Errores" #: ../quodlibet/qltk/prefs.py:45 msgid "_Disc" msgstr "_Disco" #: ../quodlibet/qltk/prefs.py:46 msgid "_Track" msgstr "Pis_ta" #: ../quodlibet/qltk/prefs.py:47 #, fuzzy msgid "Grou_ping" msgstr "agrupación" #: ../quodlibet/qltk/prefs.py:50 msgid "Al_bum" msgstr "Ál_bum" #: ../quodlibet/qltk/prefs.py:55 msgid "_Filename" msgstr "Nombre de _archivo" #: ../quodlibet/qltk/prefs.py:57 msgid "_Length" msgstr "Durac_ión" #: ../quodlibet/qltk/prefs.py:64 msgid "_Jump to playing song automatically" msgstr "_Ir automáticamente a la canción reproducida" #: ../quodlibet/qltk/prefs.py:66 msgid "When the playing song changes, scroll to it in the song list" msgstr "Cuando cambie la canción reproducida, centrar la lista en la misma." #: ../quodlibet/qltk/prefs.py:82 msgid "_Others:" msgstr "_Otras:" #: ../quodlibet/qltk/prefs.py:88 #, fuzzy msgid "_Edit…" msgstr "_Editar la vista..." #: ../quodlibet/qltk/prefs.py:91 msgid "Add or remove additional column headers" msgstr "Añadir o eliminar columnas de información adicional" #: ../quodlibet/qltk/prefs.py:101 msgid "Visible Columns" msgstr "Columnas visibles" #: ../quodlibet/qltk/prefs.py:104 msgid "Title includes _version" msgstr "El título incluye la _versión" #: ../quodlibet/qltk/prefs.py:106 #, fuzzy msgid "Artist includes all _people" msgstr "La _búsqueda incluye los \"componentes\"" #: ../quodlibet/qltk/prefs.py:108 msgid "Album includes _disc subtitle" msgstr "El álbum incluye el _subtítulo" #: ../quodlibet/qltk/prefs.py:110 msgid "Filename includes _folder" msgstr "El nombre incluye la _carpeta" #: ../quodlibet/qltk/prefs.py:123 #, fuzzy msgid "Column Preferences" msgstr "Preferencias" #: ../quodlibet/qltk/prefs.py:129 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:142 ../quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Lista de canciones" #: ../quodlibet/qltk/prefs.py:222 #, fuzzy msgid "Edit Columns" msgstr "Columnas adicionales" #: ../quodlibet/qltk/prefs.py:259 msgid "Duration totals" msgstr "" #: ../quodlibet/qltk/prefs.py:271 msgid "_Global filter:" msgstr "Filtro _globale:" #: ../quodlibet/qltk/prefs.py:277 msgid "Apply this query in addition to all others" msgstr "Aplicar esta búsqueda añadiéndola a las demás" #. Translators: The heading of the preference group, no action #: ../quodlibet/qltk/prefs.py:283 #, fuzzy msgctxt "heading" msgid "Search" msgstr "Buscar" #: ../quodlibet/qltk/prefs.py:287 ../quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Navegadores" #: ../quodlibet/qltk/prefs.py:293 msgid "Confirm _multiple ratings" msgstr "Confirmar la puntuación _múltiple" #: ../quodlibet/qltk/prefs.py:295 #, fuzzy 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:298 msgid "Enable _one-click ratings" msgstr "Activar las puntuaciones con _un click" #: ../quodlibet/qltk/prefs.py:300 #, 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:306 ../quodlibet/qltk/prefs.py:616 msgid "Ratings" msgstr "Puntuaciónes" #. Filename choice algorithm config #: ../quodlibet/qltk/prefs.py:312 msgid "Prefer _embedded art" msgstr "Preferir la carátula _incrustada" #: ../quodlibet/qltk/prefs.py:314 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:319 #, fuzzy msgid "_Fixed image filename:" msgstr "Nombre _forzoso de la imagen:" #: ../quodlibet/qltk/prefs.py:321 #, fuzzy msgid "The single image filename to use if selected" msgstr "El nombre de la imagen de portada para utilizar al predeterminarlo" #: ../quodlibet/qltk/prefs.py:327 msgid "The album art image file to use when forced" msgstr "El nombre de la imagen de portada para utilizar al predeterminarlo" #: ../quodlibet/qltk/prefs.py:336 #, fuzzy msgid "Album Art" msgstr "Lista de álbumes" #: ../quodlibet/qltk/prefs.py:357 #, fuzzy msgid "Playback" msgstr "Parar la reproducción" #: ../quodlibet/qltk/prefs.py:362 #, fuzzy msgid "Output Configuration" msgstr "Registro" #: ../quodlibet/qltk/prefs.py:373 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" "Si no existe información sobre el ajuste Replay Gain para una canción,\n" "multiplicar el volumen por este valor" #: ../quodlibet/qltk/prefs.py:376 #, fuzzy msgid "_Fall-back gain (dB):" msgstr "Ganancia por defecto (dB):" #: ../quodlibet/qltk/prefs.py:387 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:390 #, fuzzy msgid "_Pre-amp gain (dB):" msgstr "Ganancia de _volumen (dB):" #: ../quodlibet/qltk/prefs.py:395 msgid "_Enable Replay Gain volume adjustment" msgstr "Activar el ajuste de volumen _replay gain" #: ../quodlibet/qltk/prefs.py:420 msgid "Replay Gain Volume Adjustment" msgstr "Ajuste de volumen _replay gain" #: ../quodlibet/qltk/prefs.py:450 #, fuzzy msgid "_Default rating:" msgstr "Predefinida" #: ../quodlibet/qltk/prefs.py:493 #, fuzzy msgid "Rating _scale:" msgstr "Puntuaciónes" #: ../quodlibet/qltk/prefs.py:542 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 las puntuaciones agregadas.\n" "0 significa una media convencional, valores mayores implican que los álbumes " "con \n" "pocas pistas tendrán menores puntuaciones extremas. Al cambiar este valor se " "inicia un \n" "recálculo para todos los álbumes." #: ../quodlibet/qltk/prefs.py:547 msgid "_Bayesian averaging amount:" msgstr "Cantidad de la media _Bayesiana:" #: ../quodlibet/qltk/prefs.py:556 msgid "Save ratings and play _counts" msgstr "Guardar puntuaciones y co_ntadores" #: ../quodlibet/qltk/prefs.py:560 msgid "_Email:" msgstr "Correo _electrónico:" #: ../quodlibet/qltk/prefs.py:562 msgid "Ratings and play counts will be set for this email address" msgstr "" "Las puntuaciones y los contadores se configurarán para esta dirección de " "correo-e" #: ../quodlibet/qltk/prefs.py:577 #, fuzzy msgid "Auto-save tag changes" msgstr "¿ Descartar las modificaciones en las etiquetas?" #: ../quodlibet/qltk/prefs.py:579 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:587 #, fuzzy msgid "" "A set of separators to use when splitting tag values in the tag editor. The " "list is space-separated" msgstr "" "Relación de separadores para utilizar al extraer valores de etiqueta. La " "lista está separa por espacios" #: ../quodlibet/qltk/prefs.py:610 #, fuzzy msgid "Tags" msgstr "Editar etiquetas" #: ../quodlibet/qltk/prefs.py:631 #, fuzzy msgid "Updating for new ratings" msgstr "_Nueva emisora" #: ../quodlibet/qltk/prefs.py:641 #, fuzzy msgid "Scan library _on start" msgstr "A_ctualizar la colección al iniciar" #: ../quodlibet/qltk/prefs.py:651 ../quodlibet/qltk/quodlibetwindow.py:1100 #, fuzzy msgid "_Scan Library" msgstr "_Buscar en la colección" #: ../quodlibet/qltk/prefs.py:653 ../quodlibet/qltk/quodlibetwindow.py:1162 msgid "Check for changes in your library" msgstr "Buscar cambios en la colección" #: ../quodlibet/qltk/prefs.py:658 #, fuzzy msgid "Re_build Library" msgstr "Rec_argar la colección" #: ../quodlibet/qltk/prefs.py:661 #, fuzzy msgid "Reload all songs in your library. This can take a long time." msgstr "" "Recarga todas las canciones de tu colección (puede llevar bastante tiempo... " "un cafetito?)" #: ../quodlibet/qltk/prefs.py:671 #, fuzzy msgid "Scan Directories" msgstr "Analizar _Carpetas" #: ../quodlibet/qltk/prefs.py:677 #, fuzzy msgid "Hidden Songs" msgstr "Sin canciones" #: ../quodlibet/qltk/properties.py:158 ../quodlibet/util/collection.py:398 #, 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:162 ../quodlibet/qltk/properties.py:164 msgid "Properties" msgstr "Propiedades" #: ../quodlibet/qltk/queue.py:101 msgid "_Queue" msgstr "_Cola de reproducción" #: ../quodlibet/qltk/queue.py:126 msgid "Stop Once Empty" msgstr "" #: ../quodlibet/qltk/queue.py:130 #, fuzzy msgid "_Clear Queue" msgstr "_Eliminar errores" #: ../quodlibet/qltk/queue.py:242 #, 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:198 msgid "_Browse Library" msgstr "_Examinar la colección" #: ../quodlibet/qltk/quodlibetwindow.py:395 #, fuzzy msgid "Toggle queue visibility" msgstr "Alternar la visibilidad de la ventana principal" #: ../quodlibet/qltk/quodlibetwindow.py:516 #, fuzzy msgid "Playback Error" msgstr "Parar la reproducción" #: ../quodlibet/qltk/quodlibetwindow.py:524 #, fuzzy msgid "Set up library directories?" msgstr "Seleccionar Directorios" #: ../quodlibet/qltk/quodlibetwindow.py:525 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:531 msgid "_Not Now" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:532 msgid "_Set Up" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:956 msgid "Unable to add songs" msgstr "No ha sido posible añadir las canciones" #: ../quodlibet/qltk/quodlibetwindow.py:957 #: ../quodlibet/qltk/quodlibetwindow.py:1364 #, fuzzy, python-format msgid "%s uses an unsupported protocol." msgstr "<b>%s</b> utiliza un protocolo no permitido." #: ../quodlibet/qltk/quodlibetwindow.py:980 msgid "_Jump to Playing Song" msgstr "_Ir a la canción reproducida" #: ../quodlibet/qltk/quodlibetwindow.py:986 #, fuzzy msgid "_File" msgstr "Archivo" #: ../quodlibet/qltk/quodlibetwindow.py:987 msgid "_Song" msgstr "Canción" #: ../quodlibet/qltk/quodlibetwindow.py:988 msgid "_View" msgstr "_Ver" #: ../quodlibet/qltk/quodlibetwindow.py:989 #, fuzzy msgid "_Browse" msgstr "Navegadores" #: ../quodlibet/qltk/quodlibetwindow.py:990 msgid "_Control" msgstr "_Control" #: ../quodlibet/qltk/quodlibetwindow.py:991 msgid "_Help" msgstr "_Ayuda" #: ../quodlibet/qltk/quodlibetwindow.py:997 #, fuzzy msgid "_Add a Folder…" msgstr "_Añadir un directorio..." #: ../quodlibet/qltk/quodlibetwindow.py:1002 #, fuzzy msgid "_Add a File…" msgstr "_Añadir un archivo..." #: ../quodlibet/qltk/quodlibetwindow.py:1007 #, fuzzy msgid "_Add a Location…" msgstr "Añadir una dirección" #: ../quodlibet/qltk/quodlibetwindow.py:1036 #, fuzzy msgid "Edit Bookmarks…" msgstr "_Editar los marcadores..." #: ../quodlibet/qltk/quodlibetwindow.py:1056 #, fuzzy msgid "Stop After This Song" msgstr "Parar después de esta canción" #: ../quodlibet/qltk/quodlibetwindow.py:1062 msgid "_Keyboard Shortcuts" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:1071 msgid "Online Help" msgstr "Ayuda en Internet" #: ../quodlibet/qltk/quodlibetwindow.py:1080 #, fuzzy msgid "Search Help" msgstr "Buscar" #: ../quodlibet/qltk/quodlibetwindow.py:1352 msgid "Add a Location" msgstr "Añadir una dirección" #: ../quodlibet/qltk/quodlibetwindow.py:1353 msgid "Enter the location of an audio file:" msgstr "Introduce la ubicación del archivo de audio" #: ../quodlibet/qltk/quodlibetwindow.py:1358 #: ../quodlibet/qltk/quodlibetwindow.py:1363 msgid "Unable to add location" msgstr "No ha sido posible añadir la dirección" #: ../quodlibet/qltk/quodlibetwindow.py:1359 #, fuzzy, python-format msgid "%s is not a valid location." msgstr "<b>%s</b> no es una dirección válida." #: ../quodlibet/qltk/quodlibetwindow.py:1372 #: ../quodlibet/qltk/quodlibetwindow.py:1381 msgid "Add Music" msgstr "Añadir música" #: ../quodlibet/qltk/quodlibetwindow.py:1372 ../quodlibet/qltk/scanbox.py:99 #, fuzzy msgid "_Add Folders" msgstr "_Añadir un directorio..." #: ../quodlibet/qltk/quodlibetwindow.py:1379 #, fuzzy msgid "Music Files" msgstr "Reproductor de música" #: ../quodlibet/qltk/quodlibetwindow.py:1381 #, fuzzy msgid "_Add Files" msgstr "_Añadir un archivo..." #: ../quodlibet/qltk/ratingsmenu.py:24 #, fuzzy, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "" "Estás a punto de cambiar la puntuación de %d canciones.\\n\n" "Deseas continuar?" #: ../quodlibet/qltk/ratingsmenu.py:26 #, fuzzy msgid "The saved ratings will be removed" msgstr "Las canciones duplicadas serán eliminadas de la lista '%s'." #: ../quodlibet/qltk/ratingsmenu.py:27 #, 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:57 ../quodlibet/qltk/ratingsmenu.py:111 #, fuzzy msgid "_Remove Rating" msgstr "_Eliminar la emisora" #: ../quodlibet/qltk/ratingsmenu.py:98 #, fuzzy msgid "Change _Rating" msgstr "_Puntuación" #: ../quodlibet/qltk/renamefiles.py:46 msgid "Replace spaces with _underscores" msgstr "Reemplazar los espacios con _guiones bajos" #: ../quodlibet/qltk/renamefiles.py:56 msgid "Strip _Windows-incompatible characters" msgstr "Eliminar los caracteres incompatibles con _Windows" #: ../quodlibet/qltk/renamefiles.py:74 msgid "Strip _diacritical marks" msgstr "Eliminar las marcas _diacríticas" #: ../quodlibet/qltk/renamefiles.py:85 msgid "Strip non-_ASCII characters" msgstr "Eliminar los caracteres no-_ASCII" #: ../quodlibet/qltk/renamefiles.py:95 msgid "Use only _lowercase characters" msgstr "Utilizar únicamente caracteres en minúscula" #: ../quodlibet/qltk/renamefiles.py:123 msgid "Rename Files" msgstr "Cambiar el nombre del archivo" #: ../quodlibet/qltk/renamefiles.py:139 ../quodlibet/qltk/tagsfrompath.py:116 #, fuzzy msgid "Path Patterns" msgstr "patrón" #: ../quodlibet/qltk/renamefiles.py:140 ../quodlibet/qltk/tagsfrompath.py:117 #, fuzzy msgid "Edit saved patterns…" msgstr "Editar los valores guardados..." #: ../quodlibet/qltk/renamefiles.py:143 ../quodlibet/qltk/tagsfrompath.py:120 #: ../quodlibet/qltk/tracknumbers.py:58 msgid "_Preview" msgstr "_Prever" #: ../quodlibet/qltk/renamefiles.py:190 msgid "New Name" msgstr "Nuevo nombre" #: ../quodlibet/qltk/renamefiles.py:255 msgid "Unable to rename file" msgstr "No ha sido posible cambiar el nombre del archivo" #: ../quodlibet/qltk/renamefiles.py:256 #, fuzzy, python-format msgid "" "Renaming <b>%(old-name)s</b> to <b>%(new-name)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." msgstr "" "Error al cambiar el nombre de <b>%s</b> a <b>%s</b>. Puede ser que ya exista " "el archivo de destino o que no tengas permiso para crear el nuevo fichero o " "eliminar el antiguo." #: ../quodlibet/qltk/renamefiles.py:264 msgid "Ignore _All Errors" msgstr "_Ignorar todos los errores" #: ../quodlibet/qltk/renamefiles.py:267 msgid "_Continue" msgstr "_Continuar" #: ../quodlibet/qltk/renamefiles.py:296 msgid "Path is not absolute" msgstr "La dirección no es absoluta" #: ../quodlibet/qltk/renamefiles.py:297 #, python-format msgid "" "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 ~/." msgstr "" "El patrón\n" "\t<b>%s</b>\n" "contiene / pero no comienza por root (/). Para evitar errores, comienza el " "patrón con / o ~/" #: ../quodlibet/qltk/scanbox.py:47 #, fuzzy msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "" "Las canciones localizadas en estas carpetas (separadas por ':') serán " "añadidas a la colección" #: ../quodlibet/qltk/scanbox.py:99 msgid "Select Directories" msgstr "Seleccionar Directorios" #: ../quodlibet/qltk/searchbar.py:52 #, fuzzy msgid "Saved Searches" msgstr "Valores guardados" #: ../quodlibet/qltk/searchbar.py:53 #, fuzzy msgid "Edit saved searches…" msgstr "Editar los valores guardados..." #: ../quodlibet/qltk/searchbar.py:74 msgid "Search your library, using free text or QL queries" msgstr "Busca en tu colección, mediante texto o búsquedas QL" #: ../quodlibet/qltk/searchbar.py:129 msgid "Search after _typing" msgstr "Buscar despues de _escribir" #: ../quodlibet/qltk/searchbar.py:132 msgid "Show search results after the user stops typing" msgstr "Mostrar los resultados después de terminar de escribir" #: ../quodlibet/qltk/searchbar.py:187 msgid "_Limit:" msgstr "Lím_ite:" #: ../quodlibet/qltk/searchbar.py:200 msgid "_Weight" msgstr "_Importancia" #: ../quodlibet/qltk/seekbutton.py:238 msgid "Display remaining time" msgstr "Mostrar el tiempo 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 "Centrarse en el reproductor" #: ../quodlibet/qltk/shortcuts.py:22 #, fuzzy msgid "Reset filters and jump to the playing song" msgstr "Avanzar en la canción activa" #: ../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 "No se han podido eliminar las canciones" #: ../quodlibet/qltk/shortcuts.py:29 #, fuzzy msgid "Delete the selected songs" msgstr "No se han podido eliminar las canciones" #: ../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 ../quodlibet/qltk/shortcuts.py:41 msgid "Collapses the element or select the parent element" msgstr "" #: ../quodlibet/qltk/shortcuts.py:37 #, fuzzy msgid "Expands the element" msgstr "Columnas adicionales" #: ../quodlibet/qltk/shortcuts.py:39 msgid "Text Entries" 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:377 #, python-format msgid "_Filter on %s" msgstr "_Filtrar por %s" #: ../quodlibet/qltk/songlist.py:1094 #, fuzzy msgid "All _Headers" msgstr "Cabeceras de _álbumes" #: ../quodlibet/qltk/songlist.py:1095 msgid "_Track Headers" msgstr "Cabeceras de _fichero" #: ../quodlibet/qltk/songlist.py:1096 msgid "_Album Headers" msgstr "Cabeceras de _álbumes" #: ../quodlibet/qltk/songlist.py:1097 msgid "_People Headers" msgstr "Cabeceras de los _componentes" #: ../quodlibet/qltk/songlist.py:1098 msgid "_Date Headers" msgstr "Cabeceras de la _fecha" #: ../quodlibet/qltk/songlist.py:1099 msgid "_File Headers" msgstr "Cabeceras de _archivo" #: ../quodlibet/qltk/songlist.py:1100 msgid "_Production Headers" msgstr "Cabeceras de la _producción" #: ../quodlibet/qltk/songlist.py:1115 #, fuzzy msgid "_Customize Headers…" msgstr "_Personalizar cabeceras..." #: ../quodlibet/qltk/songlist.py:1120 #, fuzzy msgid "_Expand Column" msgstr "Columnas adicionales" #: ../quodlibet/qltk/songsmenu.py:36 #, 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:64 #, 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:149 #, fuzzy msgid "Configure Plugins…" msgstr "Colorear los términos de la _búsqueda" #: ../quodlibet/qltk/songsmenu.py:345 msgid "Add to _Queue" msgstr "Añadir a la _cola" #: ../quodlibet/qltk/songsmenu.py:368 msgid "_Copy to Device" msgstr "_Copiar al dispositivo" #: ../quodlibet/qltk/songsmenu.py:379 #, fuzzy msgid "_Remove from Library" msgstr "_Eliminar de la Colección" #: ../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 "C_on mayúscula inicial los valores resultantes" #: ../quodlibet/qltk/tagsfrompath.py:67 msgid "Split into multiple _values" msgstr "Extraer en valores _múltiples" #: ../quodlibet/qltk/tagsfrompath.py:101 msgid "Tags From Path" msgstr "Etiquetas a partir de la dirección" #: ../quodlibet/qltk/tagsfrompath.py:138 msgid "Tags replace existing ones" msgstr "Las etiquetas reemplazan a las existentes" #: ../quodlibet/qltk/tagsfrompath.py:139 msgid "Tags are added to existing ones" msgstr "Las etiquetas se añaden a las existentes" #. Save button #: ../quodlibet/qltk/tagsfrompath.py:153 msgid "Save" msgstr "" #: ../quodlibet/qltk/tagsfrompath.py:195 #, python-format msgid "" "The pattern\n" "\t<b>%s</b>\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/tagsfrompath.py:216 msgid "Invalid tags" msgstr "Etiquetas inválidas" #: ../quodlibet/qltk/tagsfrompath.py:217 #, 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" "Los archivos seleccionados no permiten la edición de etiquetas." #: ../quodlibet/qltk/textedit.py:142 #, 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 "" "El patrón introducido es inválido. Asegúrate de introducir < y > " "como \n" "\\< y \\> y que las etiquetas estén bien ajustadas.\n" " \n" "%s" #: ../quodlibet/qltk/textedit.py:158 msgid "Edit Display" msgstr "Editar la vista" #: ../quodlibet/qltk/tracknumbers.py:39 msgid "Track Numbers" msgstr "Números de pista" #: ../quodlibet/qltk/tracknumbers.py:42 msgid "Start fro_m:" msgstr "Comienza de_sde:" #: ../quodlibet/qltk/tracknumbers.py:51 msgid "_Total tracks:" msgstr "Pistas _totales:" #: ../quodlibet/qltk/unity.py:52 #, fuzzy msgid "Play/Pause" msgstr "Reproductor" #: ../quodlibet/qltk/unity.py:75 #, fuzzy msgid "Previous" msgstr "_Prever" #: ../quodlibet/qltk/views.py:923 #, fuzzy, 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 #, fuzzy, python-format msgid "%(current)s of %(all)s" msgstr "Moviendo %(current)d/%(total)d." #: ../quodlibet/update.py:89 #, fuzzy msgid "Checking for Updates" msgstr "Comprobando los puntos de montaje" #: ../quodlibet/update.py:124 #, fuzzy msgid "Connection failed" msgstr "ubicación" #: ../quodlibet/update.py:133 #, python-format msgid "You are already using the newest version %(version)s" msgstr "" #: ../quodlibet/update.py:136 #, 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:420 msgid "Playlists must have a name" msgstr "" #: ../quodlibet/util/collection.py:603 #, python-format msgid "A playlist named %s already exists." msgstr "Una lista de reproducción con nombre %s ya existe." #: ../quodlibet/util/cover/built_in.py:26 #, fuzzy msgid "Embedded album covers" msgstr "Mostrar _carátulas" #: ../quodlibet/util/cover/built_in.py:27 msgid "Uses covers embedded into audio files." msgstr "" #: ../quodlibet/util/cover/built_in.py:49 #, fuzzy msgid "Filesystem cover" msgstr "Vista de sistema de ficheros" #: ../quodlibet/util/cover/built_in.py:50 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "" #: ../quodlibet/util/__init__.py:93 msgid "Display brief usage information" msgstr "Muestra información sumaria sobre los distintos comandos" #: ../quodlibet/util/__init__.py:95 msgid "Display version and copyright" msgstr "Muestra la versión y el copyright" #: ../quodlibet/util/__init__.py:135 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "" #: ../quodlibet/util/__init__.py:137 msgid "[options]" msgstr "[opciones]" #: ../quodlibet/util/__init__.py:182 #, python-format msgid "Option %r not recognized." msgstr "Opción %r no reconocida." #: ../quodlibet/util/__init__.py:185 #, python-format msgid "Option %r requires an argument." msgstr "La opción %r requiere un argumento." #: ../quodlibet/util/__init__.py:188 #, python-format msgid "%r is not a unique prefix." msgstr "%r no es un prefijo único" #: ../quodlibet/util/__init__.py:364 #, python-format msgid "%d kbps" msgstr "%d kbps" #: ../quodlibet/util/__init__.py:419 #, fuzzy, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%d segundo" msgstr[1] "%d segundos" #: ../quodlibet/util/__init__.py:432 msgid "No time information" msgstr "No existe información sobre la duración" #: ../quodlibet/util/__init__.py:435 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d segundo" msgstr[1] "%d segundos" #: ../quodlibet/util/__init__.py:436 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d minuto" msgstr[1] "%d minutos" #: ../quodlibet/util/__init__.py:437 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d hora" msgstr[1] "%d horas" #: ../quodlibet/util/__init__.py:438 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d día" msgstr[1] "%d días" #: ../quodlibet/util/__init__.py:439 #, 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:563 #, fuzzy msgctxt "check" msgid "titlecase?" msgstr "La title case 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 ser introducida 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 han de ser introducidas 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 han de ser introducidos en el formato 'x.yy'" #: ../quodlibet/util/massagers.py:173 msgid "MusicBrainz IDs must be in UUID format." msgstr "Los ID de MusicBrainz han de 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 "" "La versió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 msgid "Unable to edit song" msgstr "No ha sido posible editar la canción" #: ../quodlibet/util/songwrapper.py:113 #, python-format msgid "" "Saving <b>%s</b> failed. The file may be read-only, corrupted, or you do not " "have permission to edit it." msgstr "" "No se ha podido guardar <b>%s</b>. Es posible que el archivo sea sólo de " "escritura, que esté corrupto o que no tengas permisos para editarlo." #: ../quodlibet/util/string/__init__.py:34 #: ../quodlibet/util/string/__init__.py:44 msgid "[Invalid Encoding]" msgstr "[Codificación inválida]" #: ../quodlibet/util/tags.py:74 msgid "album" msgstr "álbum" #: ../quodlibet/util/tags.py:75 msgid "arranger" msgstr "arreglista" #: ../quodlibet/util/tags.py:75 msgid "arrangers" msgstr "arreglistas" #: ../quodlibet/util/tags.py:75 #, fuzzy msgid "arrangement" msgstr "arreglista" #: ../quodlibet/util/tags.py:77 msgid "author" msgstr "autor" #: ../quodlibet/util/tags.py:77 msgid "authors" msgstr "autores" #: ../quodlibet/util/tags.py:78 msgid "composer" msgstr "compositor/a" #: ../quodlibet/util/tags.py:78 msgid "composers" msgstr "compositores/as" #: ../quodlibet/util/tags.py:78 #, fuzzy msgid "composition" msgstr "compositor/a" #. Translators: conducting as in conducting a musical performance #: ../quodlibet/util/tags.py:80 msgid "conductor" msgstr "director/a" #: ../quodlibet/util/tags.py:80 msgid "conductors" msgstr "directores/as" #: ../quodlibet/util/tags.py:80 #, fuzzy msgid "conducting" msgstr "director/a" #: ../quodlibet/util/tags.py:81 msgid "contact" msgstr "contacto" #: ../quodlibet/util/tags.py:82 msgid "copyright" msgstr "copyright" #: ../quodlibet/util/tags.py:83 msgid "date" msgstr "fecha" #: ../quodlibet/util/tags.py:84 msgid "description" msgstr "descripción" #: ../quodlibet/util/tags.py:85 msgid "genre" msgstr "estilo" #: ../quodlibet/util/tags.py:85 #, fuzzy msgid "genres" msgstr "estilo" #: ../quodlibet/util/tags.py:86 msgid "performer" msgstr "intérprete" #: ../quodlibet/util/tags.py:87 msgid "grouping" msgstr "agrupación" #: ../quodlibet/util/tags.py:88 msgid "language" msgstr "idioma" #: ../quodlibet/util/tags.py:89 msgid "license" msgstr "licencia" #: ../quodlibet/util/tags.py:90 msgid "location" msgstr "ubicación" #: ../quodlibet/util/tags.py:91 msgid "lyricist" msgstr "letrista" #: ../quodlibet/util/tags.py:91 msgid "lyricists" msgstr "letristas" #: ../quodlibet/util/tags.py:91 #, fuzzy msgid "lyrics" msgstr "letrista" #. Translators: Also e.g. "record label", "publisher" #: ../quodlibet/util/tags.py:93 msgid "organization" msgstr "compañía" #: ../quodlibet/util/tags.py:94 msgid "title" msgstr "título" #: ../quodlibet/util/tags.py:95 msgid "version" msgstr "versión" #: ../quodlibet/util/tags.py:96 msgid "website" msgstr "página de Internet" #: ../quodlibet/util/tags.py:98 msgid "album artist" msgstr "artista del álbum" #: ../quodlibet/util/tags.py:99 msgid "BPM" msgstr "BPM" #. Translators: This used to be called "part". #: ../quodlibet/util/tags.py:102 ../quodlibet/util/tags.py:103 msgid "disc subtitle" msgstr "parte" #: ../quodlibet/util/tags.py:104 ../quodlibet/util/tags.py:141 msgid "disc" msgstr "disco" #: ../quodlibet/util/tags.py:105 ../quodlibet/util/tags.py:143 msgid "track" msgstr "pista" #: ../quodlibet/util/tags.py:106 msgid "label ID" msgstr "número de catálogo" #: ../quodlibet/util/tags.py:107 msgid "original release date" msgstr "fecha de publicación original" #: ../quodlibet/util/tags.py:108 msgid "original album" msgstr "álbum original" #: ../quodlibet/util/tags.py:109 msgid "original artist" msgstr "artista original" #: ../quodlibet/util/tags.py:110 msgid "recording date" msgstr "fecha de grabación" #: ../quodlibet/util/tags.py:111 msgid "release country" msgstr "país de publicación" #. 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:120 #, fuzzy msgid "MusicBrainz recording ID" msgstr "ID MusicBrainz de la pista" #: ../quodlibet/util/tags.py:121 #, fuzzy msgid "MusicBrainz release track ID" msgstr "ID MusicBrainz de la publicación" #: ../quodlibet/util/tags.py:122 msgid "MusicBrainz release ID" msgstr "ID MusicBrainz de la publicación" #: ../quodlibet/util/tags.py:123 #, fuzzy msgid "MusicBrainz artist ID" msgstr "ID MusicBrainz del artista" #: ../quodlibet/util/tags.py:124 #, fuzzy msgid "MusicBrainz release artist ID" msgstr "ID MusicBrainz de la publicación" #: ../quodlibet/util/tags.py:125 msgid "MusicBrainz TRM ID" msgstr "ID MusicBrainz del TRM" #: ../quodlibet/util/tags.py:126 msgid "MusicIP PUID" msgstr "PUID de MusicIP" #: ../quodlibet/util/tags.py:127 msgid "MusicBrainz album status" msgstr "Estado del álbum según MusicBrainz" #: ../quodlibet/util/tags.py:128 msgid "MusicBrainz album type" msgstr "Tipo de álbum según MusicBrainz" #: ../quodlibet/util/tags.py:129 #, 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:132 msgid "track gain" msgstr "ganancia de volumen de la pista" #: ../quodlibet/util/tags.py:133 msgid "track peak" msgstr "pico de ganancia de la pista" #. Translators: "gain" means a volume adjustment, not "to acquire". #: ../quodlibet/util/tags.py:135 msgid "album gain" msgstr "ganancia de volumen del álbum" #: ../quodlibet/util/tags.py:136 msgid "album peak" msgstr "pico de ganancia del álbum" #: ../quodlibet/util/tags.py:137 #, fuzzy msgid "reference loudness" msgstr "Preferencias" #: ../quodlibet/util/tags.py:142 msgid "discs" msgstr "discos" #: ../quodlibet/util/tags.py:144 msgid "tracks" msgstr "pistas" #: ../quodlibet/util/tags.py:145 msgid "last started" msgstr "comenzada por última vez" #: ../quodlibet/util/tags.py:146 msgid "full name" msgstr "nombre completo" #: ../quodlibet/util/tags.py:153 msgid "mount point" msgstr "punto de montaje" #: ../quodlibet/util/tags.py:155 msgid "people" msgstr "componentes" #: ../quodlibet/util/tags.py:157 msgid "year" msgstr "año" #: ../quodlibet/util/tags.py:158 #, fuzzy msgid "original release year" msgstr "fecha de publicación original" #: ../quodlibet/util/tags.py:159 msgid "bookmark" msgstr "marcador" #: ../quodlibet/util/tags.py:162 #, fuzzy msgid "file format" msgstr "formato" #: ../quodlibet/util/tags.py:165 #, fuzzy msgid "playlists" msgstr "Listas" #: ../quodlibet/util/tags.py:166 msgid "channel count" msgstr "" #. Translators: e.g. "artist (sort)" #: ../quodlibet/util/tags.py:256 msgid "sort" msgstr "" #. Translators: e.g. "performer (roles)" #: ../quodlibet/util/tags.py:264 msgid "roles" msgstr "" #, 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 "Remove all songs from the queue" #~ msgstr "Elimina todas las canciones de la cola de reproducción" #~ msgid "Watch this folder for new songs" #~ msgstr "Monitorizar este directorio en busca de nuevas canciones" #~ 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 "Model:" #~ msgstr "Modelo:" #~ msgid "Capacity:" #~ msgstr "Capacidad:" #~ msgid "Firmware:" #~ msgstr "Firmware:" #~ msgid "Removing orphaned iPod track" #~ msgstr "Eliminando pistas huérfanas del iPod" #, 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 "General" #~ msgstr "General" #~ 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 "_Select" #~ msgstr "_Seleccionar" #~ 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 "Choose New Stations" #~ msgstr "Escoger nuevas emisoras" #~ msgid "Add" #~ msgstr "Añadir" #~ msgid "Bitrate" #~ msgstr "Tasa de bits" #~ msgid "_Stations..." #~ msgstr "_Emisoras..." #~ msgid "Quod Libet" #~ msgstr "Quod Libet" #~ 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 "Recommend" #~ msgstr "Recomendado" #~ 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 "Tag by Filename" #~ msgstr "Etiqueta a partir del nombre de fichero" #~ 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 "Search Bar" #~ msgstr "Barra de búsqueda" #~ 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9551857 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/po/eu.po����������������������������������������������������������������������������0000644�0001750�0001750�00000551474�00000000000�014105� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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: 2017-05-17 18:58+0200\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" #: ../data/exfalso.appdata.xml.in.h:1 ../data/exfalso.desktop.in.h:2 msgid "Edit tags in your audio files" msgstr "Editatu zure audio fitxategietako etiketak" #: ../data/exfalso.appdata.xml.in.h:2 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/exfalso.appdata.xml.in.h:3 ../data/quodlibet.appdata.xml.in.h:3 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/exfalso.desktop.in.h:1 msgid "Audio tag editor" msgstr "Audio etiketa editorea" #: ../data/quodlibet.appdata.xml.in.h:1 ../data/quodlibet.desktop.in.h:2 msgid "Listen to, browse, or edit your audio collection" msgstr "Entzun, arakatu edo editatu zure audio bilduma" #: ../data/quodlibet.appdata.xml.in.h:2 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 "" #: ../data/quodlibet.desktop.in.h:1 msgid "Music Player" msgstr "Musika erreproduzigailua" #: ../quodlibet/browsers/albums/main.py:168 #: ../quodlibet/browsers/covergrid/main.py:54 #, fuzzy msgid "_Title" msgstr "Titulua" #: ../quodlibet/browsers/albums/main.py:169 #: ../quodlibet/browsers/covergrid/main.py:55 ../quodlibet/qltk/prefs.py:49 msgid "_Artist" msgstr "_Artista" #: ../quodlibet/browsers/albums/main.py:170 #: ../quodlibet/browsers/covergrid/main.py:56 ../quodlibet/qltk/prefs.py:54 msgid "_Date" msgstr "_Data" #: ../quodlibet/browsers/albums/main.py:171 #: ../quodlibet/browsers/covergrid/main.py:57 ../quodlibet/qltk/prefs.py:53 #, fuzzy msgid "_Genre" msgstr "Genero" #: ../quodlibet/browsers/albums/main.py:172 #: ../quodlibet/browsers/covergrid/main.py:58 ../quodlibet/qltk/prefs.py:58 #: ../quodlibet/qltk/ratingsmenu.py:39 msgid "_Rating" msgstr "_Balorazioa" #: ../quodlibet/browsers/albums/main.py:178 #: ../quodlibet/browsers/covergrid/main.py:64 #, fuzzy msgid "Sort _by…" msgstr "Ordena_tu:" #: ../quodlibet/browsers/albums/main.py:199 #: ../quodlibet/browsers/covergrid/main.py:85 #: ../quodlibet/browsers/paned/prefs.py:166 #: ../quodlibet/browsers/playlists/main.py:629 #: ../quodlibet/qltk/exfalsowindow.py:109 ../quodlibet/qltk/pluginwin.py:341 #: ../quodlibet/qltk/quodlibetwindow.py:1016 #, fuzzy msgid "_Preferences" msgstr "Hobespenak" #: ../quodlibet/browsers/albums/main.py:361 msgid "Album List" msgstr "Album zerrenda" #: ../quodlibet/browsers/albums/main.py:362 msgid "_Album List" msgstr "_Album zerrenda" #: ../quodlibet/browsers/albums/main.py:472 #: ../quodlibet/browsers/covergrid/main.py:279 #: ../quodlibet/browsers/covergrid/main.py:488 msgid "All Albums" msgstr "Album guztiak" #: ../quodlibet/browsers/albums/main.py:473 #: ../quodlibet/browsers/covergrid/main.py:280 #: ../quodlibet/browsers/covergrid/main.py:489 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "album %d" msgstr[1] "%d album" #: ../quodlibet/browsers/albums/main.py:650 #: ../quodlibet/browsers/covergrid/main.py:467 #, 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:381 ../quodlibet/util/collection.py:245 #, 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:379 ../quodlibet/util/collection.py:249 #, 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:120 #, fuzzy msgid "Options" msgstr "[aukerak]" #: ../quodlibet/browsers/albums/prefs.py:74 #: ../quodlibet/browsers/covergrid/prefs.py:123 msgid "Album Display" msgstr "Album bistaratzea" #: ../quodlibet/browsers/albums/prefs.py:78 #: ../quodlibet/browsers/covergrid/prefs.py:127 #: ../quodlibet/browsers/media.py:39 #: ../quodlibet/browsers/playlists/prefs.py:56 #: ../quodlibet/ext/songsmenu/albumart.py:326 #: ../quodlibet/ext/songsmenu/duplicates.py:350 #: ../quodlibet/ext/songsmenu/filterall.py:48 #: ../quodlibet/qltk/bookmarks.py:101 ../quodlibet/qltk/cbes.py:93 #: ../quodlibet/qltk/data_editors.py:99 ../quodlibet/qltk/data_editors.py:324 #: ../quodlibet/qltk/exfalsowindow.py:297 ../quodlibet/qltk/pluginwin.py:79 #: ../quodlibet/qltk/pluginwin.py:427 ../quodlibet/qltk/prefs.py:707 #: ../quodlibet/qltk/textedit.py:164 ../quodlibet/update.py:148 msgid "_Close" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:55 #: ../quodlibet/browsers/audiofeeds.py:67 #: ../quodlibet/browsers/audiofeeds.py:69 #: ../quodlibet/browsers/audiofeeds.py:159 #: ../quodlibet/browsers/paned/models.py:86 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:46 #: ../quodlibet/formats/_audio.py:495 ../quodlibet/order/__init__.py:27 #: ../quodlibet/qltk/information.py:240 ../quodlibet/qltk/information.py:247 #: ../quodlibet/qltk/information.py:273 ../quodlibet/qltk/wlw.py:70 msgid "Unknown" msgstr "Ezezaguna" #: ../quodlibet/browsers/audiofeeds.py:246 msgid "New Feed" msgstr "Jario berria" #: ../quodlibet/browsers/audiofeeds.py:247 msgid "Enter the location of an audio feed:" msgstr "Idatzi audio jarioaren kokapena:" #: ../quodlibet/browsers/audiofeeds.py:248 #: ../quodlibet/browsers/collection/prefs.py:90 #: ../quodlibet/browsers/iradio.py:341 ../quodlibet/browsers/paned/prefs.py:78 #: ../quodlibet/browsers/playlists/menu.py:96 #: ../quodlibet/browsers/playlists/util.py:52 ../quodlibet/qltk/bookmarks.py:62 #: ../quodlibet/qltk/cbes.py:55 ../quodlibet/qltk/data_editors.py:311 #: ../quodlibet/qltk/edittags.py:288 ../quodlibet/qltk/edittags.py:488 #: ../quodlibet/qltk/quodlibetwindow.py:1354 ../quodlibet/qltk/scanbox.py:61 msgid "_Add" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:265 msgid "Audio Feeds" msgstr "Audio jarioak" #: ../quodlibet/browsers/audiofeeds.py:266 msgid "_Audio Feeds" msgstr "_Audio jarioak" #: ../quodlibet/browsers/audiofeeds.py:345 #: ../quodlibet/browsers/audiofeeds.py:350 #, fuzzy msgid "_Download…" msgstr "_Deskargatu" #: ../quodlibet/browsers/audiofeeds.py:359 msgid "Download Files" msgstr "Deskargatu fitxategiak" #. Save button #: ../quodlibet/browsers/audiofeeds.py:359 #: ../quodlibet/browsers/audiofeeds.py:371 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:81 #: ../quodlibet/ext/songsmenu/albumart.py:322 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:355 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:278 #: ../quodlibet/ext/songsmenu/html.py:76 #: ../quodlibet/ext/songsmenu/lastfmsync.py:216 #: ../quodlibet/ext/songsmenu/playlist.py:51 #: ../quodlibet/ext/songsmenu/replaygain.py:365 #: ../quodlibet/ext/songsmenu/tapbpm.py:182 ../quodlibet/qltk/_editutils.py:39 #: ../quodlibet/qltk/lyrics.py:38 ../quodlibet/qltk/msg.py:52 #: ../quodlibet/qltk/renamefiles.py:168 ../quodlibet/qltk/tracknumbers.py:113 msgid "_Save" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:371 msgid "Download File" msgstr "Deskargatu fitxategia" #: ../quodlibet/browsers/audiofeeds.py:394 #: ../quodlibet/browsers/playlists/main.py:213 #: ../quodlibet/qltk/data_editors.py:96 msgid "_New" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:454 #: ../quodlibet/browsers/audiofeeds.py:513 msgid "Unable to add feed" msgstr "Ezin da jarioa gehitu" #: ../quodlibet/browsers/audiofeeds.py:455 #: ../quodlibet/browsers/audiofeeds.py:514 #, fuzzy, python-format msgid "" "%s could not be added. The server may be down, or the location may not be an " "audio feed." msgstr "" "<b>%s</b> ezin da gehitu. Zerbitzaria eroria egon liteke edo kokapena ez da " "audio jario bat." #. refresh button #: ../quodlibet/browsers/audiofeeds.py:462 ../quodlibet/browsers/media.py:217 #: ../quodlibet/browsers/media.py:386 ../quodlibet/qltk/filesel.py:259 #: ../quodlibet/qltk/pluginwin.py:413 #, fuzzy msgid "_Refresh" msgstr "_Freskatu liburutegia" #: ../quodlibet/browsers/audiofeeds.py:463 #: ../quodlibet/browsers/playlists/main.py:457 #: ../quodlibet/browsers/playlists/util.py:43 ../quodlibet/qltk/delete.py:143 #: ../quodlibet/qltk/filesel.py:256 ../quodlibet/qltk/lyrics.py:39 #: ../quodlibet/qltk/maskedbox.py:28 ../quodlibet/qltk/songsmenu.py:392 #, fuzzy msgid "_Delete" msgstr "Ezabatu fitxategiak" #: ../quodlibet/browsers/audiofeeds.py:530 msgid "" "The current audio backend does not support URLs, Audio Feeds browser " "disabled." msgstr "" "Uneko audio azpiegiturak ez ditu URLak onartzen, audio jario nabigatzailea " "ezgaiturik." #: ../quodlibet/browsers/_base.py:147 ../quodlibet/browsers/_base.py:150 msgid "Library Browser" msgstr "Liburutegi nabigatzailea" #: ../quodlibet/browsers/_base.py:274 ../quodlibet/ext/songsmenu/refresh.py:30 #: ../quodlibet/qltk/exfalsowindow.py:241 ../quodlibet/qltk/information.py:542 #: ../quodlibet/qltk/maskedbox.py:68 ../quodlibet/util/collection.py:527 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "kanta %d" msgstr[1] "%d kanta" #: ../quodlibet/browsers/_base.py:402 ../quodlibet/browsers/_base.py:407 #: ../quodlibet/qltk/tagsfrompath.py:194 ../quodlibet/qltk/textedit.py:141 #: ../quodlibet/util/__init__.py:622 msgid "Invalid pattern" msgstr "Patroi baliogabea" #: ../quodlibet/browsers/collection/main.py:78 msgid "Album Collection" msgstr "Diska bilduma" #: ../quodlibet/browsers/collection/main.py:79 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:66 #: ../quodlibet/browsers/paned/prefs.py:51 msgid "_Custom" msgstr "_Personalizatu" #. Remove button #: ../quodlibet/browsers/collection/prefs.py:94 #: ../quodlibet/browsers/paned/prefs.py:82 #: ../quodlibet/browsers/playlists/menu.py:97 #: ../quodlibet/ext/playlist/remove_duplicates.py:60 #: ../quodlibet/qltk/bookmarks.py:97 ../quodlibet/qltk/bookmarks.py:127 #: ../quodlibet/qltk/cbes.py:82 ../quodlibet/qltk/cbes.py:89 #: ../quodlibet/qltk/data_editors.py:81 ../quodlibet/qltk/data_editors.py:94 #: ../quodlibet/qltk/data_editors.py:301 ../quodlibet/qltk/data_editors.py:314 #: ../quodlibet/qltk/data_editors.py:322 ../quodlibet/qltk/edittags.py:494 #: ../quodlibet/qltk/edittags.py:634 ../quodlibet/qltk/maskedbox.py:48 #: ../quodlibet/qltk/maskedbox.py:88 ../quodlibet/qltk/queue.py:350 #: ../quodlibet/qltk/scanbox.py:36 ../quodlibet/qltk/scanbox.py:63 #, fuzzy msgid "_Remove" msgstr "Bikoiztuak ezabatu" #: ../quodlibet/browsers/collection/prefs.py:122 #: ../quodlibet/ext/songsmenu/filterall.py:34 #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:92 #: ../quodlibet/qltk/edittags.py:431 msgid "Tag" msgstr "Etiketa" #: ../quodlibet/browsers/collection/prefs.py:128 msgid "Merge" msgstr "Batu" #: ../quodlibet/browsers/collection/prefs.py:188 #, fuzzy msgid "Album Collection Preferences" msgstr "Album zerrenda hobespenak" #: ../quodlibet/browsers/collection/prefs.py:195 #: ../quodlibet/browsers/paned/prefs.py:209 #: ../quodlibet/ext/songsmenu/editplaycount.py:45 #: ../quodlibet/ext/songsmenu/exact_rating.py:38 #: ../quodlibet/player/gstbe/prefs.py:40 ../quodlibet/qltk/prefs.py:127 #: ../quodlibet/qltk/textedit.py:65 msgid "_Apply" msgstr "" #: ../quodlibet/browsers/collection/prefs.py:198 #: ../quodlibet/browsers/paned/prefs.py:213 #: ../quodlibet/browsers/playlists/menu.py:95 #: ../quodlibet/browsers/playlists/util.py:42 #: ../quodlibet/errorreport/ui.py:108 #: ../quodlibet/ext/playlist/export_to_folder.py:37 #: ../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:44 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:281 #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:88 #: ../quodlibet/ext/songsmenu/importexport.py:35 #: ../quodlibet/ext/songsmenu/lastfmsync.py:215 #: ../quodlibet/ext/songsmenu/playlist.py:50 #: ../quodlibet/ext/songsmenu/replaygain.py:364 #: ../quodlibet/ext/songsmenu/tapbpm.py:181 ../quodlibet/plugins/playlist.py:39 #: ../quodlibet/qltk/chooser.py:184 ../quodlibet/qltk/chooser.py:205 #: ../quodlibet/qltk/chooser.py:229 ../quodlibet/qltk/chooser.py:253 #: ../quodlibet/qltk/delete.py:90 ../quodlibet/qltk/delete.py:133 #: ../quodlibet/qltk/edittags.py:287 ../quodlibet/qltk/_editutils.py:38 #: ../quodlibet/qltk/getstring.py:28 ../quodlibet/qltk/maskedbox.py:27 #: ../quodlibet/qltk/msg.py:54 ../quodlibet/qltk/msg.py:93 #: ../quodlibet/qltk/ratingsmenu.py:33 ../quodlibet/qltk/songsmenu.py:45 #: ../quodlibet/qltk/songsmenu.py:73 ../quodlibet/update.py:94 msgid "_Cancel" msgstr "" #: ../quodlibet/browsers/covergrid/main.py:125 #, fuzzy msgid "Cover Grid" msgstr "Tamaina guztira:" #: ../quodlibet/browsers/covergrid/main.py:126 #, 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:71 #, fuzzy msgid "Show \"All Albums\" Item" msgstr "Album guztiak" #: ../quodlibet/browsers/covergrid/prefs.py:78 msgid "Vertical Split" msgstr "" #: ../quodlibet/browsers/covergrid/prefs.py:110 #: ../quodlibet/browsers/covergrid/prefs.py:111 #, fuzzy msgid "Cover Magnification" msgstr "erakundea" #: ../quodlibet/browsers/filesystem.py:40 msgid "File System" msgstr "Fitxategi sistema" #: ../quodlibet/browsers/filesystem.py:41 msgid "_File System" msgstr "_Fixtategi sistema" #: ../quodlibet/browsers/filesystem.py:113 ../quodlibet/browsers/media.py:491 #: ../quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "Ezin dira kantak kopiatu" #: ../quodlibet/browsers/filesystem.py:114 ../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:189 msgid "_Add to Library" msgstr "_Gehitu liburutegira" #: ../quodlibet/browsers/iradio.py:178 msgid "Unsupported file type" msgstr "Onartzen ez den fitxategi mota" #: ../quodlibet/browsers/iradio.py:179 #, 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:219 ../quodlibet/browsers/iradio.py:232 #: ../quodlibet/browsers/iradio.py:810 msgid "Unable to add station" msgstr "Ezin da katea gehitu" #: ../quodlibet/browsers/iradio.py:243 ../quodlibet/browsers/iradio.py:471 msgid "Internet Radio" msgstr "Internet irratia" #: ../quodlibet/browsers/iradio.py:243 #, fuzzy msgid "Downloading station list" msgstr "Deskargatu fitxategiak" #: ../quodlibet/browsers/iradio.py:339 msgid "New Station" msgstr "Kate berria" #: ../quodlibet/browsers/iradio.py:340 msgid "Enter the location of an Internet radio station:" msgstr "Sar Internet bidezko irrati kate kokapena:" #: ../quodlibet/browsers/iradio.py:358 msgid "Electronic" msgstr "Elektronikoa" #: ../quodlibet/browsers/iradio.py:361 msgid "Hip Hop / Rap" msgstr "Hip Hop / Rap" #: ../quodlibet/browsers/iradio.py:362 msgid "Oldies" msgstr "Oldies" #: ../quodlibet/browsers/iradio.py:363 msgid "R&B" msgstr "R&B" #: ../quodlibet/browsers/iradio.py:364 msgid "Japanese" msgstr "Japaniarra" #: ../quodlibet/browsers/iradio.py:365 msgid "Indian" msgstr "Indiarra" #: ../quodlibet/browsers/iradio.py:367 msgid "Religious" msgstr "Erlijio-musika" #: ../quodlibet/browsers/iradio.py:369 msgid "Charts" msgstr "Salduenak" #: ../quodlibet/browsers/iradio.py:370 msgid "Turkish" msgstr "Turkiarra" #: ../quodlibet/browsers/iradio.py:371 msgid "Reggae / Dancehall" msgstr "Reggae / Dantzatzeko" #: ../quodlibet/browsers/iradio.py:372 #, fuzzy msgid "Latin" msgstr "balorazioa" #: ../quodlibet/browsers/iradio.py:373 msgid "College Radio" msgstr "Unibertsitate irratia" #: ../quodlibet/browsers/iradio.py:374 msgid "Talk / News" msgstr "Eztabaidak / Berriak" #: ../quodlibet/browsers/iradio.py:375 msgid "Ambient" msgstr "Ambient" #: ../quodlibet/browsers/iradio.py:376 msgid "Jazz" msgstr "Jazz" #: ../quodlibet/browsers/iradio.py:377 ../quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "Klasikoa" #: ../quodlibet/browsers/iradio.py:378 ../quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "Pop" #: ../quodlibet/browsers/iradio.py:379 msgid "Alternative" msgstr "Alternatiboa" #: ../quodlibet/browsers/iradio.py:380 msgid "Metal" msgstr "Metal" #: ../quodlibet/browsers/iradio.py:381 msgid "Country" msgstr "Country" #: ../quodlibet/browsers/iradio.py:382 msgid "News" msgstr "Berriak" #: ../quodlibet/browsers/iradio.py:383 msgid "Schlager" msgstr "Schlager" #: ../quodlibet/browsers/iradio.py:384 msgid "Funk" msgstr "Funk" #: ../quodlibet/browsers/iradio.py:385 msgid "Indie" msgstr "Indie" #: ../quodlibet/browsers/iradio.py:386 msgid "Blues" msgstr "Blues" #: ../quodlibet/browsers/iradio.py:387 msgid "Soul" msgstr "Soul" #: ../quodlibet/browsers/iradio.py:388 msgid "Lounge" msgstr "Lounge" #: ../quodlibet/browsers/iradio.py:389 msgid "Punk" msgstr "Punk" #: ../quodlibet/browsers/iradio.py:390 msgid "Reggaeton" msgstr "Reggaeton" #: ../quodlibet/browsers/iradio.py:392 msgid "Slavic" msgstr "Eslaboa" #: ../quodlibet/browsers/iradio.py:394 msgid "Greek" msgstr "Greziarra" #: ../quodlibet/browsers/iradio.py:395 msgid "Gothic" msgstr "Gotikoa" #: ../quodlibet/browsers/iradio.py:396 ../quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "Rock" #: ../quodlibet/browsers/iradio.py:449 msgid "Would you like to load a list of popular radio stations?" msgstr "" #: ../quodlibet/browsers/iradio.py:455 #, fuzzy msgid "_Load Stations" msgstr "_Kate berria" #: ../quodlibet/browsers/iradio.py:472 msgid "_Internet Radio" msgstr "_Internet irratia" #: ../quodlibet/browsers/iradio.py:538 #, fuzzy msgid "_New Station…" msgstr "Kate berria" #: ../quodlibet/browsers/iradio.py:541 #, fuzzy msgid "_Update Stations" msgstr "_Kate berria" #: ../quodlibet/browsers/iradio.py:568 #, fuzzy msgid "All Stations" msgstr "Kate berria" #. TODO: support for ~#rating=!None etc (#1940) #: ../quodlibet/browsers/iradio.py:572 #: ../quodlibet/browsers/soundcloud/main.py:64 msgid "Favorites" msgstr "Kuttunak" #: ../quodlibet/browsers/iradio.py:580 #, fuzzy msgid "No Category" msgstr "Kategoria gabe" #: ../quodlibet/browsers/iradio.py:802 msgid "No stations found" msgstr "Ez da katerik aurkitu" #: ../quodlibet/browsers/iradio.py:803 #, python-format msgid "No Internet radio stations were found at %s." msgstr "Ez da Intenet irrati katerik topatu %s-en." #: ../quodlibet/browsers/iradio.py:811 msgid "All stations listed are already in your library." msgstr "Zerrendatutako kate guztiak dagoeneko badaude liburutegian." #: ../quodlibet/browsers/iradio.py:828 #, fuzzy msgid "Add to Favorites" msgstr "_Gehitu erreprodukzio-zerrendara" #: ../quodlibet/browsers/iradio.py:832 #, fuzzy msgid "Remove from Favorites" msgstr "_Kendu erreprodukzio-zerrendatik" #: ../quodlibet/browsers/iradio.py:932 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "%(count)d kate" msgstr[1] "%(count)d kate" #: ../quodlibet/browsers/media.py:36 msgid "Device Properties" msgstr "Gailu propietateak" #: ../quodlibet/browsers/media.py:52 msgid "Device:" msgstr "Gailua:" #: ../quodlibet/browsers/media.py:54 msgid "Not mounted" msgstr "Ez dago muntaturik" #: ../quodlibet/browsers/media.py:55 #, fuzzy msgid "Mount point:" msgstr "Muntatze puntua:" #: ../quodlibet/browsers/media.py:61 ../quodlibet/qltk/cbes.py:40 msgid "_Name:" msgstr "Ize_na:" #: ../quodlibet/browsers/media.py:135 msgid "Media Devices" msgstr "Medio gailuak" #: ../quodlibet/browsers/media.py:136 msgid "_Media Devices" msgstr "_Medio gailuak" #. eject button #: ../quodlibet/browsers/media.py:224 ../quodlibet/browsers/media.py:378 msgid "_Eject" msgstr "_Ebatzi" #: ../quodlibet/browsers/media.py:360 #, fuzzy msgid "_Properties" msgstr "Propietateak" #: ../quodlibet/browsers/media.py:365 #: ../quodlibet/browsers/playlists/main.py:464 msgid "_Rename" msgstr "Be_rrizendatu" #: ../quodlibet/browsers/media.py:461 #, fuzzy, python-format msgid "%(used-size)s used, %(free-size)s available" msgstr "<b>%s</b> erabilia, <b>%s</b> erabilgarri" #: ../quodlibet/browsers/media.py:479 #, fuzzy, python-format msgid "%s is not connected." msgstr "<b>%s</b> ez dago konektaturik." #: ../quodlibet/browsers/media.py:499 #, fuzzy, python-format msgid "Copying %(song)s" msgstr "<b>%(song)s</b> kopiatzen" #: ../quodlibet/browsers/media.py:513 ../quodlibet/browsers/media.py:529 msgid "Unable to copy song" msgstr "Ezin da kanta kopiatu" #: ../quodlibet/browsers/media.py:514 msgid "There is not enough free space for this song." msgstr "Ez kanta honentzako behar aina leku." #: ../quodlibet/browsers/media.py:526 #, fuzzy, python-format msgid "%s could not be copied." msgstr "<b>%s</b> ezin izan da kopiatu." #: ../quodlibet/browsers/media.py:545 msgid "Unable to delete songs" msgstr "Ezin dira kantak ezabatu" #: ../quodlibet/browsers/media.py:557 #, fuzzy, python-format msgid "Deleting %(song)s" msgstr "<b>%(song)s</b> ezabatzen" #: ../quodlibet/browsers/media.py:575 #, fuzzy, python-format msgid "%s could not be deleted." msgstr "<b>%s</b> ezin izan da ezabatu." #: ../quodlibet/browsers/media.py:579 msgid "Unable to delete song" msgstr "Ezin da abestiak ezabatu" #: ../quodlibet/browsers/media.py:594 #, fuzzy, python-format msgid "Ejecting %s failed." msgstr "<b>%s</b> ebazteak huts egin du." #: ../quodlibet/browsers/media.py:597 msgid "Unable to eject device" msgstr "Ezin da gailua ebatzi" #: ../quodlibet/browsers/media.py:603 msgid "No device backend, Media Devices browser disabled." msgstr "Ez dago gailu azpiegiturarik, media gailu nabigatzailea desgaiturik." #: ../quodlibet/browsers/paned/main.py:40 ../quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "Paneldun nabigatzailea" #: ../quodlibet/browsers/paned/main.py:41 msgid "_Paned Browser" msgstr "_Paneldun nabigatzailea" #: ../quodlibet/browsers/paned/main.py:90 msgid "Select _All" msgstr "Hautatu _denak" #: ../quodlibet/browsers/paned/models.py:104 ../quodlibet/qltk/pluginwin.py:122 #: ../quodlibet/qltk/pluginwin.py:164 msgid "All" msgstr "Dena" #: ../quodlibet/browsers/paned/prefs.py:67 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "<tt>%s</tt>" msgstr "" #: ../quodlibet/browsers/paned/prefs.py:162 msgid "_Wide Mode" msgstr "" #: ../quodlibet/browsers/paned/prefs.py:197 msgid "Paned Browser Preferences" msgstr "Paneldun nabigatzaile hobespenak" #: ../quodlibet/browsers/paned/prefs.py:204 msgid "Equal pane width" msgstr "" #: ../quodlibet/browsers/playlists/main.py:48 #: ../quodlibet/browsers/playlists/main.py:575 #: ../quodlibet/qltk/pluginwin.py:168 msgid "Playlists" msgstr "Erreprodukzio-zerrendak" #: ../quodlibet/browsers/playlists/main.py:49 msgid "_Playlists" msgstr "_Erreprodukzio-zerrendak" #: ../quodlibet/browsers/playlists/main.py:152 msgid "_Remove from Playlist" msgstr "_Kendu erreprodukzio-zerrendatik" #: ../quodlibet/browsers/playlists/main.py:215 #: ../quodlibet/browsers/playlists/main.py:576 msgid "_Import" msgstr "_Inporatu" #: ../quodlibet/browsers/playlists/main.py:391 #: ../quodlibet/browsers/playlists/util.py:50 #: ../quodlibet/util/collection.py:570 msgid "New Playlist" msgstr "Sortu erreprodukzio-zerrenda" #: ../quodlibet/browsers/playlists/main.py:413 msgid "Unable to import playlist" msgstr "Ezin da erreprodukzio-zerrenda inportatu" #: ../quodlibet/browsers/playlists/main.py:414 msgid "Quod Libet can only import playlists in the M3U and PLS formats." msgstr "" "Quod Libet M3U eta PLS formatuko erreprodukzio-zerrendak bakarrik " "inportatzeko gai da." #: ../quodlibet/browsers/playlists/main.py:565 msgid "Unable to rename playlist" msgstr "Ezin da erreprodukzio-zerrenda berrizendatu" #: ../quodlibet/browsers/playlists/main.py:576 msgid "Import Playlist" msgstr "Inportatu erreprodukzio-zerrenda" #: ../quodlibet/browsers/playlists/menu.py:25 #, fuzzy msgid "_New Playlist…" msgstr "_Sortu erreprodukzio-zerrenda" #: ../quodlibet/browsers/playlists/menu.py:86 #, 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:90 #, 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:33 #, 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:35 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:51 msgid "Enter a name for the new playlist:" msgstr "Idatzi erreprodukzio-zerrenda berriaren izena:" #: ../quodlibet/browsers/playlists/util.py:102 #, 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/search.py:33 msgid "_Limit Results" msgstr "_Emaitza muga" #: ../quodlibet/browsers/search.py:48 msgid "Search Library" msgstr "Bilatu liburutegia" #: ../quodlibet/browsers/search.py:49 msgid "_Search Library" msgstr "_Bilatu liburutegia" #: ../quodlibet/browsers/soundcloud/main.py:38 #, fuzzy msgid "Soundcloud Browser" msgstr "Paneldun nabigatzailea" #: ../quodlibet/browsers/soundcloud/main.py:39 msgid "Sound_cloud" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:59 #: ../quodlibet/qltk/searchbar.py:73 msgid "Search" msgstr "Bilatu" #: ../quodlibet/browsers/soundcloud/main.py:136 #, python-format msgid "Go to %s" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:380 #, fuzzy msgid "Connected" msgstr "kokapena" #: ../quodlibet/browsers/soundcloud/main.py:381 #, python-format msgid "Quod Libet is now connected, <b>%s</b>!" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:393 #, python-format msgid "Log out of %s" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:395 msgid "Enter code…" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:396 #, python-format msgid "Log in to %s" msgstr "" #: ../quodlibet/browsers/soundcloud/util.py:86 msgid "Soundcloud authorisation" msgstr "" #: ../quodlibet/browsers/soundcloud/util.py:87 msgid "Enter Soundcloud auth code:" msgstr "" #: ../quodlibet/cli.py:50 #, fuzzy msgid "Quod Libet is not running (add '--run' to start it)" msgstr "Quod Libet ez dago martxan." #: ../quodlibet/cli.py:85 msgid "a music library and player" msgstr "musika liburutegi eta erreproduzigailua" #: ../quodlibet/cli.py:86 #, fuzzy msgid "[option]" msgstr "[aukerak]" #: ../quodlibet/cli.py:88 msgid "Print the playing song and exit" msgstr "Erreproduzitzen den abestia inprimatu eta irten" #: ../quodlibet/cli.py:89 msgid "Begin playing immediately" msgstr "Segituan erreproduzitzen hasiko da" #: ../quodlibet/cli.py:90 msgid "Don't show any windows on start" msgstr "" #: ../quodlibet/cli.py:93 msgid "Jump to next song" msgstr "Salto hurrengo abestira" #: ../quodlibet/cli.py:95 msgid "Jump to previous song or restart if near the beginning" msgstr "Salto aurreko abestira, edota, hasieratik gertu balego, berrabiatu" #: ../quodlibet/cli.py:96 msgid "Jump to previous song" msgstr "Salto aurreko abestira" #: ../quodlibet/cli.py:97 msgid "Start playback" msgstr "Hasi erreproduzitzen" #: ../quodlibet/cli.py:98 msgid "Pause playback" msgstr "Gelditu erreproduzitzeaz" #: ../quodlibet/cli.py:99 msgid "Toggle play/pause mode" msgstr "Txandakatu erreproduzitu/gelditu modua" #: ../quodlibet/cli.py:100 #, fuzzy msgid "Stop playback" msgstr "Hasi erreproduzitzen" #: ../quodlibet/cli.py:101 msgid "Turn up volume" msgstr "Igo bolumena" #: ../quodlibet/cli.py:102 msgid "Turn down volume" msgstr "Beheratu bolumena" #: ../quodlibet/cli.py:103 msgid "Print player status" msgstr "Inprimatu erreproduzigailu egoera" #: ../quodlibet/cli.py:104 msgid "Hide main window" msgstr "Ezkutatu leiho nagusia" #: ../quodlibet/cli.py:105 msgid "Show main window" msgstr "Ikusi leiho nagusia" #: ../quodlibet/cli.py:106 msgid "Toggle main window visibility" msgstr "Txandakatu leiho nagusi ikusgarritasuna" #: ../quodlibet/cli.py:107 msgid "Focus the running player" msgstr "Fokoa ipini erreproduzigailua martxan" #: ../quodlibet/cli.py:108 msgid "Remove active browser filters" msgstr "Kendu nabigatzaile filtroak" #: ../quodlibet/cli.py:109 msgid "Refresh and rescan library" msgstr "Freskatu eta liburutegia berrarakatu" #: ../quodlibet/cli.py:110 #, fuzzy msgid "List available browsers" msgstr "Desgaitu nabigatzailea" #: ../quodlibet/cli.py:111 msgid "Print the current playlist" msgstr "Inprimatu uneko erreprodukzio-zerrenda" #: ../quodlibet/cli.py:112 msgid "Print the contents of the queue" msgstr "Inprimatu ilararen edukiak" #: ../quodlibet/cli.py:113 #, fuzzy msgid "Print the active text query" msgstr "Inprimatu ilararen edukiak" #: ../quodlibet/cli.py:114 msgid "Start without plugins" msgstr "Hasi pluginik gabe" #: ../quodlibet/cli.py:115 #, fuzzy msgid "Start Quod Libet if it isn't running" msgstr "Quod Libet ez dago martxan." #: ../quodlibet/cli.py:116 msgid "Exit Quod Libet" msgstr "Itxi Qoud Libet" #: ../quodlibet/cli.py:121 msgid "Seek within the playing song" msgstr "Bilatu jotzen ari den anestian" #: ../quodlibet/cli.py:121 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: ../quodlibet/cli.py:122 #, fuzzy msgid "Set or toggle shuffle mode" msgstr "Txandakatu erreproduzitu/gelditu modua" #: ../quodlibet/cli.py:123 msgid "Turn repeat off, on, or toggle it" msgstr "Errepikapenak gaitu, desgaitu edo txanda" #: ../quodlibet/cli.py:124 msgid "Set the volume" msgstr "Ezarri bolumena" #: ../quodlibet/cli.py:125 msgid "Search your audio library" msgstr "Bilatu audio liburutegian" #: ../quodlibet/cli.py:125 ../quodlibet/cli.py:137 ../quodlibet/cli.py:141 #: ../quodlibet/cli.py:143 msgid "query" msgstr "bilaketa" #: ../quodlibet/cli.py:126 msgid "Play a file" msgstr "Erreproduzitu fitxategi bat" #: ../quodlibet/cli.py:126 ../quodlibet/cli.py:137 ../quodlibet/cli.py:143 #, fuzzy msgctxt "command" msgid "filename" msgstr "fitxategi-izena" #: ../quodlibet/cli.py:127 msgid "Rate the playing song" msgstr "Baloratu erreproduzitutako abestia" #: ../quodlibet/cli.py:128 msgid "Set the current browser" msgstr "Ezarri nabigatzailea" #: ../quodlibet/cli.py:129 #, fuzzy msgid "Stop after the playing song" msgstr "Baloratu erreproduzitutako abestia" #: ../quodlibet/cli.py:130 msgid "Open a new browser" msgstr "Ireki nabigatzaile berri bat" #: ../quodlibet/cli.py:131 msgid "Show or hide the queue" msgstr "Erakutsi edo ezkutatu ilara" #: ../quodlibet/cli.py:133 #, fuzzy msgid "Show or hide the main song list (deprecated)" msgstr "Erakutsi edo ezkutatu kanten zerrenda nagusia" #: ../quodlibet/cli.py:134 msgid "Filter on a random value" msgstr "Iragazi ausazko balio batez" #: ../quodlibet/cli.py:134 #, fuzzy msgctxt "command" msgid "tag" msgstr "Etiketa" #: ../quodlibet/cli.py:135 msgid "Filter on a tag value" msgstr "Iragazi etiketa balio batez" #: ../quodlibet/cli.py:135 msgid "tag=value" msgstr "etiketa=balioa" #: ../quodlibet/cli.py:136 msgid "Enqueue a file or query" msgstr "Ilaran ipini fitxategi bat edo bilatu" #: ../quodlibet/cli.py:138 msgid "Enqueue comma-separated files" msgstr "Ilaran ipini komaz bereiztutako fitxategiak" #: ../quodlibet/cli.py:139 ../quodlibet/util/tags.py:147 msgid "filename" msgstr "fitxategi-izena" #: ../quodlibet/cli.py:140 msgid "Print filenames of results of query to stdout" msgstr "Erakutsi bilaketaren emaitzen izenak" #: ../quodlibet/cli.py:142 msgid "Unqueue a file or query" msgstr "Ilaratik kendu fitxategi bat edo bilatu" #: ../quodlibet/cli.py:203 #, python-format msgid "Invalid argument for '%s'." msgstr "Argumentu baliogabea '%s'-rentzat." #: ../quodlibet/cli.py:204 ../quodlibet/util/__init__.py:190 #, python-format msgid "Try %s --help." msgstr "Saiatu %s --help." #: ../quodlibet/devices/_base.py:65 msgid "Unknown Device" msgstr "Gailu ezezaguna" #: ../quodlibet/devices/__init__.py:32 #, fuzzy, python-format msgid "Could not import %s, which is needed for device support." msgstr "Ezin da dbus-python inportatu, beharrezkoa da gailu euskarriarentzat." #: ../quodlibet/devices/__init__.py:153 #, python-format msgid "%r is not a supported device." msgstr "%r ez da onartzen den gailu bat." #: ../quodlibet/devices/__init__.py:245 ../quodlibet/devices/__init__.py:251 #, fuzzy, python-format msgid "Could not find '%s'." msgstr "%s: Ezin da media-player-info aurkitu." #: ../quodlibet/devices/__init__.py:450 msgid "Initializing device backend." msgstr "Gailu azpiegitura abiarazten." #: ../quodlibet/devices/__init__.py:451 #, python-format msgid "Trying '%s'" msgstr "'%s' saiatzen" #: ../quodlibet/devices/__init__.py:461 msgid "Couldn't connect to a device backend." msgstr "Ezin da gailu azpiegiturarekin konektatu." #: ../quodlibet/devices/__init__.py:463 msgid "Device backend initialized." msgstr "Gailu azpiegitura abiarazia." #: ../quodlibet/devices/storage.py:57 #, fuzzy msgid "_Filename pattern:" msgstr "_Fixategi-izen patroia:" #: ../quodlibet/devices/storage.py:61 msgid "Copy _album covers" msgstr "Kopiatu _album karatulak" #: ../quodlibet/devices/storage.py:65 msgid "_Remove unused covers and directories" msgstr "_Kendu erabili gabeko karatula eta direktorioak" #: ../quodlibet/errorreport/ui.py:60 #, fuzzy msgid "An Error Occurred" msgstr "Errore bat gertatu da" #: ../quodlibet/errorreport/ui.py:62 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:72 msgid "File Bug Report" msgstr "" #: ../quodlibet/errorreport/ui.py:74 ../quodlibet/errorreport/ui.py:90 msgid "Submit Error Report" msgstr "" #: ../quodlibet/errorreport/ui.py:75 msgid "Quit Program" msgstr "" #: ../quodlibet/errorreport/ui.py:76 #, fuzzy msgid "Ignore Error" msgstr "Baztertu errore _guztiak" #: ../quodlibet/errorreport/ui.py:80 msgid "Error details:" msgstr "" #: ../quodlibet/errorreport/ui.py:92 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:100 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "" #: ../quodlibet/errorreport/ui.py:109 msgid "_Send" msgstr "" #: ../quodlibet/errorreport/ui.py:115 #, fuzzy msgid "Short description…" msgstr "azalpena" #: ../quodlibet/errorreport/ui.py:118 msgid "Data to be sent:" msgstr "" #: ../quodlibet/exfalso.py:34 msgid "an audio tag editor" msgstr "audio etiketa editorea" #: ../quodlibet/exfalso.py:34 ../quodlibet/util/tags.py:148 msgid "directory" msgstr "direktorioa" #: ../quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "" #: ../quodlibet/ext/covers/artwork_url.py:20 msgid "" "Downloads covers linked to by the artwork_url tag.This works with the " "Soundcloud browser." msgstr "" #: ../quodlibet/ext/covers/discogs.py:25 #, fuzzy msgid "Discogs Cover Source" msgstr "MusicBrainz pista IDa" #: ../quodlibet/ext/covers/discogs.py:26 msgid "Downloads covers from Discogs." msgstr "" #: ../quodlibet/ext/covers/lastfm.py:22 msgid "Last.fm Cover Source" msgstr "" #: ../quodlibet/ext/covers/lastfm.py:23 msgid "Downloads covers from Last.fm's cover art archive." msgstr "" #: ../quodlibet/ext/covers/musicbrainz.py:19 #, fuzzy msgid "MusicBrainz Cover Source" msgstr "MusicBrainz pista IDa" #: ../quodlibet/ext/covers/musicbrainz.py:20 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:25 msgid "Kana/Kanji Simple Inverter" msgstr "" #: ../quodlibet/ext/editing/kakasi.py:26 msgid "Converts kana/kanji to romaji before renaming." msgstr "" #: ../quodlibet/ext/editing/kakasi.py:35 msgid "Romanize _Japanese text" msgstr "" #: ../quodlibet/ext/editing/kakasi.py:63 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:19 msgid "" "Allows arbitrary regex substitutions (s///) 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:69 #, fuzzy msgid "Advanced Preferences" msgstr "Paneldun nabigatzaile hobespenak" #: ../quodlibet/ext/events/advanced_preferences.py:70 msgid "Allow editing of advanced config settings." msgstr "" #: ../quodlibet/ext/events/advanced_preferences.py:162 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:153 msgid "Top of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:154 msgid "Middle of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:155 msgid "Bottom of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:158 msgid "_Position:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:171 #, fuzzy msgid "_Cover size:" msgstr "Tamaina guztira:" #: ../quodlibet/ext/events/animosd/prefs.py:177 #: ../quodlibet/ext/events/lyricswindow.py:334 ../quodlibet/qltk/prefs.py:266 #, fuzzy msgid "Display" msgstr "Editatu bistaratzea" #: ../quodlibet/ext/events/animosd/prefs.py:190 msgid "_Font:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:195 msgid "Left" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:196 msgid "Center" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:197 #, fuzzy msgid "Right" msgstr "_Tamaina" #: ../quodlibet/ext/events/animosd/prefs.py:200 msgid "_Align text:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:206 msgid "Text" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:217 msgid "_Text:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:227 msgid "_Fill:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:232 #: ../quodlibet/ext/events/synchronizedlyrics.py:63 msgid "Colors" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:240 msgid "_Shadows" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:241 #, fuzzy msgid "_Outline" msgstr "_Irteera kanalizazioa:" #: ../quodlibet/ext/events/animosd/prefs.py:242 msgid "Rou_nded Corners" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:258 msgid "_Delay:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:264 #: ../quodlibet/qltk/pluginwin.py:172 msgid "Effects" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:270 #, fuzzy msgid "Ed_it Display Pattern…" msgstr "Editatu bistaratzea" #: ../quodlibet/ext/events/animosd/prefs.py:274 #: ../quodlibet/ext/events/trayicon/prefs.py:78 #, fuzzy msgid "Preview" msgstr "_Aurreikusi" #: ../quodlibet/ext/events/auto_library_update.py:136 msgid "Automatic Library Update" msgstr "" #: ../quodlibet/ext/events/auto_library_update.py:137 #, python-format msgid "Keeps your library up to date with inotify. Requires %s." msgstr "" #: ../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 by Brian Nelson." 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/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:97 msgid "Equalizer" msgstr "" #: ../quodlibet/ext/events/equalizer.py:98 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:132 #, 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:138 #, python-format msgid "%.1f kHz" msgstr "" #: ../quodlibet/ext/events/equalizer.py:139 #: ../quodlibet/ext/gstreamer/crossfeed.py:93 #: ../quodlibet/ext/gstreamer/karaoke.py:95 #, python-format msgid "%d Hz" msgstr "" #: ../quodlibet/ext/events/equalizer.py:173 #: ../quodlibet/ext/gstreamer/crossfeed.py:112 #, fuzzy, python-format msgid "%.1f dB" msgstr "segundo %d" #: ../quodlibet/ext/events/equalizer.py:192 #: ../quodlibet/ext/gstreamer/crossfeed.py:31 #, fuzzy msgid "Custom" msgstr "_Personalizatu" #: ../quodlibet/ext/events/equalizer.py:199 #, fuzzy msgid "_Clear" msgstr "_Garbitu errorea" #. Translators: statuses relating to Instant Messenger apps #: ../quodlibet/ext/events/gajim_status.py:27 msgid "online" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:28 msgid "offline" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:29 msgid "chat" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:30 msgid "away" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:31 msgid "xa" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:32 msgid "invisible" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:37 msgid "Gajim Status Message" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:38 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:45 #: ../quodlibet/ext/events/telepathy_status.py:69 msgid "paused" 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:160 msgid "Add '[paused]'" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:163 msgid "If checked, '[paused]' will be added to status message on pause." msgstr "" #: ../quodlibet/ext/events/gajim_status.py:187 msgid "Statuses for which message will be changed" msgstr "" #: ../quodlibet/ext/events/headphonemon.py:156 msgid "Pause on Headphone Unplug" msgstr "" #: ../quodlibet/ext/events/headphonemon.py:157 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" #: ../quodlibet/ext/events/inhibit.py:41 msgid "Inhibit Screensaver" msgstr "" #: ../quodlibet/ext/events/inhibit.py:42 msgid "Prevents the GNOME screensaver from activating while a song is playing." msgstr "" #: ../quodlibet/ext/events/inhibit.py:51 #, fuzzy msgid "Music is playing" msgstr "Musika erreproduzigailua" #: ../quodlibet/ext/events/iradiolog.py:16 #, fuzzy msgid "Internet Radio Log" msgstr "Internet irratia" #: ../quodlibet/ext/events/iradiolog.py:17 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" #: ../quodlibet/ext/events/jep118.py:29 msgid "JEP-118" msgstr "" #: ../quodlibet/ext/events/jep118.py:30 msgid "Outputs a Jabber User Tunes file to ~/.quodlibet/jabber." 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 msgid "A restart is required for any changes to take effect" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:199 #, fuzzy msgid "No active song" msgstr "Ezin da abestia gorde" #: ../quodlibet/ext/events/lyricswindow.py:215 #, fuzzy msgid "No lyrics found" msgstr "Ez da pluginik aurkitu." #: ../quodlibet/ext/events/lyricswindow.py:227 #, fuzzy msgid "Lyrics:" msgstr "Hitzak" #: ../quodlibet/ext/events/lyricswindow.py:284 msgid "_Zoom level:" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:302 msgid "URL:" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:307 msgid "Revert to default" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:322 msgid "Search via above URL if the lyrics couldn't be found in LyricsWikia." msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:339 #, fuzzy msgid "Alternate search" msgstr "Garbitu bilaketa" #: ../quodlibet/ext/events/lyricswindow.py:347 #, fuzzy msgid "Lyrics Window" msgstr "Hitzak" #: ../quodlibet/ext/events/lyricswindow.py:348 msgid "Shows a window containing lyrics of the playing song." msgstr "" #: ../quodlibet/ext/events/mediaserver.py:38 msgid "UPnP AV Media Server" msgstr "" #: ../quodlibet/ext/events/mediaserver.py:39 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." 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:39 msgid "" "Allows control of Quod Libet using the MPRIS 1.0/2.0 D-Bus Interface " "Specification." msgstr "" #: ../quodlibet/ext/events/mpris/__init__.py:45 #: ../quodlibet/ext/events/trayicon/prefs.py:30 #, fuzzy msgid "Hide main window on close" msgstr "Ezkutatu leiho nagusia" #: ../quodlibet/ext/events/mpris/__init__.py:48 #: ../quodlibet/ext/events/themeswitcher.py:84 #: ../quodlibet/ext/gstreamer/compressor.py:99 #: ../quodlibet/ext/gstreamer/crossfeed.py:136 #: ../quodlibet/ext/gstreamer/karaoke.py:99 #: ../quodlibet/ext/gstreamer/pitch.py:83 ../quodlibet/qltk/prefs.py:688 #, fuzzy msgid "Preferences" msgstr "Hobespenak" #: ../quodlibet/ext/events/mqtt.py:50 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/mqtt.py:56 msgid "MQTT Publisher" msgstr "" #: ../quodlibet/ext/events/mqtt.py:57 msgid "Publishes status messages to an MQTT topic." msgstr "" #: ../quodlibet/ext/events/mqtt.py:122 msgid "Broker hostname" msgstr "" #: ../quodlibet/ext/events/mqtt.py:122 msgid "broker hostname / IP" msgstr "" #: ../quodlibet/ext/events/mqtt.py:124 msgid "Broker port" msgstr "" #: ../quodlibet/ext/events/mqtt.py:124 msgid "broker port" msgstr "" #: ../quodlibet/ext/events/mqtt.py:126 msgid "Topic" msgstr "" #: ../quodlibet/ext/events/mqtt.py:128 #, fuzzy msgid "Playing Pattern" msgstr "Bide patroiak" #: ../quodlibet/ext/events/mqtt.py:130 msgid "Status text when a song is started." msgstr "" #: ../quodlibet/ext/events/mqtt.py:132 #, fuzzy msgid "Paused Pattern" msgstr "Bide patroiak" #: ../quodlibet/ext/events/mqtt.py:134 msgid "Text when a song is paused." msgstr "" #: ../quodlibet/ext/events/mqtt.py:136 #, fuzzy msgid "No-song Text" msgstr "kanta %d" #: ../quodlibet/ext/events/mqtt.py:138 msgid "Plain text for when there is no current song" msgstr "" #: ../quodlibet/ext/events/mqtt.py:149 #, fuzzy msgid "MQTT Configuration" msgstr "Erregistro irteera" #: ../quodlibet/ext/events/mqtt.py:153 #, fuzzy msgid "Status Text" msgstr "Bide patroiak" #: ../quodlibet/ext/events/mqtt.py:185 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "" #: ../quodlibet/ext/events/mqtt.py:189 #, 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:192 #, fuzzy msgid "Connection error" msgstr "kokapena" #: ../quodlibet/ext/events/notify.py:80 msgid "Notification text" msgstr "" #: ../quodlibet/ext/events/notify.py:88 #, fuzzy msgid "_Title:" msgstr "Titulua" #: ../quodlibet/ext/events/notify.py:99 ../quodlibet/ext/events/notify.py:128 msgid "Revert to default pattern" msgstr "" #: ../quodlibet/ext/events/notify.py:118 msgid "_Body:" msgstr "" #: ../quodlibet/ext/events/notify.py:138 msgid "_Show notification" msgstr "" #: ../quodlibet/ext/events/notify.py:156 msgid "Show notifications" msgstr "" #: ../quodlibet/ext/events/notify.py:162 msgid "Only on <i>_manual</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:170 msgid "Only on <i>_automatic</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:178 msgid "On <i>a_ll</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:196 msgid "Only when the main window is not _focused" msgstr "" #: ../quodlibet/ext/events/notify.py:204 msgid "Show \"_Next\" button" msgstr "" #: ../quodlibet/ext/events/notify.py:236 msgid "Connection Error" msgstr "" #: ../quodlibet/ext/events/notify.py:237 ../quodlibet/ext/events/notify.py:391 #: ../quodlibet/ext/events/notify.py:433 #, fuzzy msgid "Couldn't connect to notification daemon." msgstr "Ezin da gailu azpiegiturarekin konektatu." #: ../quodlibet/ext/events/notify.py:251 msgid "Song Notifications" msgstr "" #: ../quodlibet/ext/events/notify.py:252 msgid "Displays a notification when the song changes." msgstr "" #: ../quodlibet/ext/events/notify.py:415 ../quodlibet/qltk/unity.py:65 msgid "Next" msgstr "Hurrengoa" #: ../quodlibet/ext/events/qlscrobbler.py:178 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:254 #, fuzzy, python-format msgid "Could not contact service '%s'." msgstr "Ezin da gailu azpiegiturarekin konektatu." #: ../quodlibet/ext/events/qlscrobbler.py:260 msgid "Authentication failed: invalid URL." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:277 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:282 msgid "Client is banned. Contact the author." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:286 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:351 msgid "AudioScrobbler Submission" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:352 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:450 msgid "Authentication successful." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:462 #, fuzzy msgid "_Service:" msgstr "Gailua:" #: ../quodlibet/ext/events/qlscrobbler.py:462 msgid "_URL:" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:462 #, fuzzy msgid "User_name:" msgstr "Ize_na:" #: ../quodlibet/ext/events/qlscrobbler.py:463 msgid "_Password:" msgstr "" #. Translators: Other service #: ../quodlibet/ext/events/qlscrobbler.py:479 #, fuzzy msgid "Other…" msgstr "_Besteak:" #. verify data #: ../quodlibet/ext/events/qlscrobbler.py:517 msgid "_Verify account data" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:522 #: ../quodlibet/ext/songsmenu/lastfmsync.py:304 msgid "Account" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:530 #, fuzzy msgid "_Artist pattern:" msgstr "_Artista" #: ../quodlibet/ext/events/qlscrobbler.py:530 #, fuzzy msgid "_Title pattern:" msgstr "_Fixategi-izen patroia:" #: ../quodlibet/ext/events/qlscrobbler.py:531 msgid "Exclude _filter:" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:549 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:559 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:568 msgid "Songs matching this filter will not be submitted." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:576 msgid "_Offline mode (don't submit anything)" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:580 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:27 #, fuzzy msgid "Random Album Playback" msgstr "Ausazko Al_buma" #: ../quodlibet/ext/events/randomalbum.py:28 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:38 msgid "Rated higher" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:39 msgid "Played more often" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:40 msgid "Skipped more often" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:41 msgid "Played more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:42 msgid "Started more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:43 msgid "Added more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:44 #, fuzzy msgid "Longer albums" msgstr "album" #: ../quodlibet/ext/events/randomalbum.py:83 msgid "seconds before starting next album" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:87 #, fuzzy msgid "Weights" msgstr "_Tamaina" #: ../quodlibet/ext/events/randomalbum.py:89 msgid "Play some albums more than others" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:103 msgid "avoid" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:114 msgid "prefer" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:201 #, fuzzy msgid "Random Album" msgstr "Ausazko Al_buma" #: ../quodlibet/ext/events/randomalbum.py:202 #, python-format msgid "Waiting to start %s" msgstr "" #: ../quodlibet/ext/events/rbimport.py:114 #, fuzzy msgid "Import Failed" msgstr "Inportatu erreprodukzio-zerrenda" #: ../quodlibet/ext/events/rbimport.py:119 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "" #: ../quodlibet/ext/events/rbimport.py:127 msgid "Rhythmbox Import" msgstr "" #: ../quodlibet/ext/events/rbimport.py:128 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "" #: ../quodlibet/ext/events/rbimport.py:132 #, fuzzy msgid "Start Import" msgstr "_Inporatu" #: ../quodlibet/ext/events/screensaver.py:25 msgid "Screensaver Pause" msgstr "" #: ../quodlibet/ext/events/screensaver.py:26 msgid "Pauses playback while the GNOME screensaver is active." msgstr "" #: ../quodlibet/ext/events/searchprovider.py:73 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "" #: ../quodlibet/ext/events/searchprovider.py:79 msgid "GNOME Search Provider" msgstr "" #: ../quodlibet/ext/events/searchprovider.py:80 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/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:29 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:57 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:58 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:34 #, fuzzy msgid "Synchronized Lyrics" msgstr "Hitzak" #: ../quodlibet/ext/events/synchronizedlyrics.py:35 msgid "Shows synchronized lyrics from .lrc file with same name as the track." msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:66 msgid "Text:" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:76 msgid "Background:" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:87 msgid "Font" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:90 msgid "Size (px):" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:62 msgid "Telepathy Status Messages" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:63 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:122 #, fuzzy msgid "Playing:" msgstr "Ez da erreproduzitzen" #: ../quodlibet/ext/events/telepathy_status.py:123 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:139 msgid "Paused:" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:140 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:156 msgid "Plain text for status when there is no current song" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:157 #, fuzzy msgid "No song:" msgstr "kanta %d" #. Frame #: ../quodlibet/ext/events/telepathy_status.py:164 #, 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/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:77 #: ../quodlibet/ext/events/trayicon/prefs.py:98 #: ../quodlibet/ext/events/trayicon/systemtray.py:177 #: ../quodlibet/qltk/info.py:47 msgid "Not playing" msgstr "Ez da erreproduzitzen" #: ../quodlibet/ext/events/trayicon/__init__.py:53 msgid "Tray Icon" msgstr "" #: ../quodlibet/ext/events/trayicon/__init__.py:54 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:183 #: ../quodlibet/qltk/quodlibetwindow.py:1046 #: ../quodlibet/qltk/quodlibetwindow.py:1238 #, fuzzy msgid "_Play" msgstr "_Erreprodukzio-zerrendak" #: ../quodlibet/ext/events/trayicon/menu.py:63 #: ../quodlibet/qltk/quodlibetwindow.py:185 #: ../quodlibet/qltk/quodlibetwindow.py:1240 ../quodlibet/qltk/wlw.py:51 #, fuzzy msgid "P_ause" msgstr "Erreproduzigailua" #: ../quodlibet/ext/events/trayicon/menu.py:68 #: ../quodlibet/qltk/quodlibetwindow.py:190 #: ../quodlibet/qltk/quodlibetwindow.py:1041 #, fuzzy msgid "Pre_vious" msgstr "_Aurreikusi" #: ../quodlibet/ext/events/trayicon/menu.py:71 #: ../quodlibet/qltk/quodlibetwindow.py:194 #: ../quodlibet/qltk/quodlibetwindow.py:1051 #, 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:1012 #, fuzzy msgid "Open _Browser" msgstr "Ireki nabigatzaile berri bat" #: ../quodlibet/ext/events/trayicon/menu.py:103 #: ../quodlibet/qltk/quodlibetwindow.py:1031 ../quodlibet/qltk/songsmenu.py:411 msgid "Edit _Tags" msgstr "Editatu etiketak" #: ../quodlibet/ext/events/trayicon/menu.py:112 #: ../quodlibet/qltk/quodlibetwindow.py:975 ../quodlibet/qltk/songsmenu.py:424 #, fuzzy msgid "_Information" msgstr "Informazioa" #: ../quodlibet/ext/events/trayicon/menu.py:114 #: ../quodlibet/qltk/songsmenu.py:340 #, fuzzy msgid "Play_lists" msgstr "Erreprodukzio-zerrendak" #: ../quodlibet/ext/events/trayicon/menu.py:132 #: ../quodlibet/qltk/quodlibetwindow.py:1026 msgid "_Quit" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:32 ../quodlibet/qltk/prefs.py:69 msgid "Behavior" msgstr "Portaera" #: ../quodlibet/ext/events/trayicon/prefs.py:42 msgid "Scroll wheel adjusts volume" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel changes song" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll _Wheel" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:84 #, fuzzy msgid "Tooltip Display" msgstr "Editatu bistaratzea" #: ../quodlibet/ext/events/viewlyrics.py:23 #, fuzzy msgid "View Lyrics" msgstr "Hitzak" #: ../quodlibet/ext/events/viewlyrics.py:24 msgid "Automatically displays lyrics beneath the song list in the main window." msgstr "" #: ../quodlibet/ext/events/viewlyrics.py:29 #, fuzzy msgid "_Lyrics" msgstr "Hitzak" #: ../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:406 #, fuzzy msgid "Waveform Seek Bar" msgstr "Alternatiboa" #: ../quodlibet/ext/events/waveformseekbar.py:410 msgid "A seekbar in the shape of the waveform of the current song." msgstr "" #: ../quodlibet/ext/events/waveformseekbar.py:443 msgid "Override foreground color:" msgstr "" #: ../quodlibet/ext/events/write_cover.py:32 msgid "Picture Saver" msgstr "" #: ../quodlibet/ext/events/write_cover.py:33 msgid "Saves the cover image of the current song to a file." msgstr "" #: ../quodlibet/ext/events/write_cover.py:66 #, fuzzy msgid "File:" msgstr "Fixategiak" #: ../quodlibet/ext/gstreamer/compressor.py:20 msgid "_Threshold:" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:21 msgid "Threshold until the filter is activated" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:22 msgid "R_atio:" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:22 msgid "Compression ratio" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:74 #: ../quodlibet/ext/gstreamer/karaoke.py:91 #, python-format msgid "%d %%" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:105 msgid "Audio Compressor" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:106 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:19 #, fuzzy msgid "_Preset:" msgstr "_Aurreikusi" #: ../quodlibet/ext/gstreamer/crossfeed.py:19 #, fuzzy msgid "Filter preset" msgstr "Iragazi _artistaz" #: ../quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Frequency cut:" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Low-pass filter cut frequency" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed _level:" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed level" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:25 #, fuzzy msgid "Default" msgstr "Berezkoa" #: ../quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Chu Moy" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Jan Meier" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:31 #, fuzzy msgid "Custom settings" msgstr "_Personalizatu" #: ../quodlibet/ext/gstreamer/crossfeed.py:152 msgid "Crossfeed" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:153 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:20 #, fuzzy msgid "Filter _band:" msgstr "Iragazi _generoz" #: ../quodlibet/ext/gstreamer/karaoke.py:21 msgid "The Frequency band of the filter" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:22 #, fuzzy msgid "Filter _width:" msgstr "Iragazi _artistaz" #: ../quodlibet/ext/gstreamer/karaoke.py:23 msgid "The Frequency width of the filter" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:24 msgid "_Level:" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:24 msgid "Level of the effect" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:105 msgid "Karaoke" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:106 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:20 msgid "R_ate:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:21 msgid "_Tempo:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:22 msgid "_Pitch:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:89 #, fuzzy msgid "Audio Pitch / Speed" msgstr "Audio jarioak" #: ../quodlibet/ext/gstreamer/pitch.py:90 #, fuzzy msgid "Controls the pitch of an audio stream." msgstr "Idatzi audio jarioaren kokapena:" #: ../quodlibet/ext/playlist/export_to_folder.py:29 #: ../quodlibet/ext/playlist/export_to_folder.py:97 #: ../quodlibet/ext/playlist/export_to_folder.py:138 #, fuzzy msgid "Export Playlist to Folder" msgstr "Inportatu erreprodukzio-zerrenda" #: ../quodlibet/ext/playlist/export_to_folder.py:38 #, fuzzy msgid "_Export" msgstr "_Inporatu" #: ../quodlibet/ext/playlist/export_to_folder.py:43 #, fuzzy msgid "Destination folder:" msgstr "Ez da katerik aurkitu" #: ../quodlibet/ext/playlist/export_to_folder.py:58 #, 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:156 #, fuzzy msgid "Default filename pattern:" msgstr "_Fixategi-izen patroia:" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:23 msgid "Export to Squeezebox" msgstr "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:25 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 "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Export playlist to Squeezebox" msgstr "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:80 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 "" "Playback follows your selection, or the next song in the list once exhausted." msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:22 msgid "Playcount Equalizer" msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:23 msgid "Shuffle, preferring songs with fewer total plays." msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:25 #, fuzzy msgid "Prefer less played" msgstr "azken erreproduzitua" #: ../quodlibet/ext/playorder/queue.py:19 #, fuzzy msgid "Queue Only" msgstr "Ilaran" #: ../quodlibet/ext/playorder/queue.py:21 msgid "" "Limits playing of songs to the queue. Select this play order in the main " "window, then double-clicking any song will enqueue it instead of playing." msgstr "" #: ../quodlibet/ext/playorder/reverse.py:14 #, fuzzy msgid "Reverse" msgstr "Inoiz" #: ../quodlibet/ext/playorder/reverse.py:16 msgid "Reverses the play order of songs." msgstr "" #: ../quodlibet/ext/playorder/skip_songs.py:25 #, fuzzy msgid "Skip Songs" msgstr "Abestirik ez" #: ../quodlibet/ext/playorder/skip_songs.py:27 msgid "" "Playback skips over songs with a rating equal or below a given threshold." msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:30 msgid "Repeat Each Track" msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:32 msgid "Shuffle songs, but repeat every track a set number of times." msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:51 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. Syntax is '@(if: " "condition, then, else)'." msgstr "" #: ../quodlibet/ext/query/pythonexpression.py:14 msgid "Python Query" msgstr "" #: ../quodlibet/ext/query/pythonexpression.py:15 msgid "" "Use Python expressions in queries. Syntax is '@(python: expression)'. The " "variable 's' is the song being matched." msgstr "" #: ../quodlibet/ext/query/savedsearch.py:19 #, fuzzy msgid "Include Saved Search" msgstr "Gordetako balioak" #: ../quodlibet/ext/query/savedsearch.py:20 msgid "" "Include the results of a saved search as part of another query. Syntax is " "'@(saved: search name)'." 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:116 msgid "Port:" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:121 #, fuzzy msgid "Username:" msgstr "Be_rrizendatu" #: ../quodlibet/ext/_shared/squeezebox/base.py:126 msgid "Password:" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:130 msgid "Library directory the server connects to." msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:132 #, fuzzy msgid "Library path:" msgstr "Liburutegia" #. Add verify button #: ../quodlibet/ext/_shared/squeezebox/base.py:141 msgid "_Verify settings" msgstr "" #. Server settings Frame #: ../quodlibet/ext/_shared/squeezebox/base.py:147 msgid "Squeezebox Server" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:150 msgid "Debug" msgstr "Debug" #: ../quodlibet/ext/_shared/squeezebox/server.py:26 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:28 msgid "unidentified Squeezebox server" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:37 #, 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:20 #: ../quodlibet/ext/songsmenu/importexport.py:34 #: ../quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:329 #, fuzzy msgid "Fit image to _window" msgstr "Ezkutatu leiho nagusia" #. Both labels #: ../quodlibet/ext/songsmenu/albumart.py:338 msgid "_Program:" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:343 msgid "_Edit image after saving" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:345 #, fuzzy msgid "File_name:" msgstr "Fitxategi-izena" #: ../quodlibet/ext/songsmenu/albumart.py:457 msgid "Saving failed" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:458 #, fuzzy, python-format msgid "Unable to save \"%s\"." msgstr "Ezin da abestia gorde" #: ../quodlibet/ext/songsmenu/albumart.py:556 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:613 #, fuzzy msgid "Album Art Downloader" msgstr "Album zerrenda" #: ../quodlibet/ext/songsmenu/albumart.py:666 #, python-format msgid "from %(source)s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:669 #, python-format msgid "Resolution: %s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:672 #, fuzzy, python-format msgid "Size: %s" msgstr "Tamaina" #: ../quodlibet/ext/songsmenu/albumart.py:690 #, fuzzy msgid "_Search" msgstr "_Bilaketa:" #: ../quodlibet/ext/songsmenu/albumart.py:741 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:451 #, fuzzy msgid "Searching…" msgstr "Bilatu" #: ../quodlibet/ext/songsmenu/albumart.py:804 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:922 #, fuzzy msgid "Download Album Art" msgstr "Album zerrenda" #: ../quodlibet/ext/songsmenu/albumart.py:923 msgid "Downloads album covers from various websites." msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:936 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 #: ../quodlibet/qltk/downloader.py:52 msgid "Filename" msgstr "Fitxategi-izena" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:130 #, fuzzy msgid "Disc" msgstr "_Diskoa" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:131 #: ../quodlibet/ext/songsmenu/replaygain.py:404 #: ../quodlibet/qltk/tracknumbers.py:92 msgid "Track" msgstr "Pista" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:132 #, 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:447 msgid "Please enter a query." msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:465 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:496 msgid "Error encountered. Please retry." msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:472 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:488 msgid "Loading result…" msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:475 #, fuzzy msgid "No results found." msgstr "Ez da pluginik aurkitu." #: ../quodlibet/ext/songsmenu/browsefolders.py:159 #, fuzzy msgid "Browse Folders" msgstr "Nabigatzaileak" #: ../quodlibet/ext/songsmenu/browsefolders.py:160 msgid "Opens the songs' folders in a file manager." msgstr "" #: ../quodlibet/ext/songsmenu/browsefolders.py:172 #, fuzzy msgid "Unable to open folders" msgstr "Ezinda karpeta sortu" #: ../quodlibet/ext/songsmenu/browsefolders.py:173 msgid "No program available to open folders." msgstr "" #: ../quodlibet/ext/songsmenu/console.py:40 msgid "Python Console" msgstr "" #: ../quodlibet/ext/songsmenu/console.py:41 msgid "Interactive Python console." msgstr "" #: ../quodlibet/ext/songsmenu/console.py:72 msgid "You can access the following objects by default:" msgstr "" #: ../quodlibet/ext/songsmenu/console.py:82 msgid "Your current working directory is:" 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:55 #, fuzzy msgid "pattern" msgstr "Patroi baliogabea" #: ../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:91 #, fuzzy msgid "Input value" msgstr "Okerreko balioa" #: ../quodlibet/ext/songsmenu/custom_commands.py:92 #, python-format msgid "Value for %s?" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:136 #, fuzzy msgid "Custom Commands" msgstr "_Personalizatu" #: ../quodlibet/ext/songsmenu/custom_commands.py:137 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:188 #: ../quodlibet/ext/songsmenu/custom_commands.py:198 #: ../quodlibet/ext/songsmenu/custom_commands.py:252 msgid "Edit Custom Commands" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:199 msgid "" "Supports QL patterns\n" "eg <tt><~artist~title></tt>" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:283 #, fuzzy, python-format msgid "Unable to run custom command %s" msgstr "Ezin dira kantak kopiatu" #: ../quodlibet/ext/songsmenu/duplicates.py:290 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "" msgstr[1] "" #: ../quodlibet/ext/songsmenu/duplicates.py:343 msgid "Collapse / Expand all" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:347 #, python-format msgid "Duplicate key expression is '%s'" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:363 #, fuzzy msgid "Duplicates Browser" msgstr "Desgaitu nabigatzailea" #: ../quodlibet/ext/songsmenu/duplicates.py:364 msgid "Finds and displays similarly tagged versions of songs." msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:407 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:409 msgid "_Group duplicates by:" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:414 #, fuzzy msgid "Duplicate Key" msgstr "Bikoiztuak ezabatu" #: ../quodlibet/ext/songsmenu/duplicates.py:419 #, fuzzy msgid "Remove _Whitespace" msgstr "Bikoiztuak ezabatu" #: ../quodlibet/ext/songsmenu/duplicates.py:420 #, fuzzy msgid "Remove _Diacritics" msgstr "Bikoiztuak ezabatu" #: ../quodlibet/ext/songsmenu/duplicates.py:421 #, fuzzy msgid "Remove _Punctuation" msgstr "Bikoiztuak ezabatu" #: ../quodlibet/ext/songsmenu/duplicates.py:422 msgid "Case _Insensitive" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:430 msgid "Matching options" msgstr "" #. Create a dialog. #: ../quodlibet/ext/songsmenu/editplaycount.py:19 #: ../quodlibet/ext/songsmenu/editplaycount.py:41 #, fuzzy msgid "Edit Playcount" msgstr "Editatu bistaratzea" #: ../quodlibet/ext/songsmenu/editplaycount.py:20 msgid "" "Edit a song's ~#playcount and ~#skipcount.\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's ~#playcount to 0, the ~#lastplayed and ~#laststarted " "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:68 msgid "Play Count" msgstr "" #: ../quodlibet/ext/songsmenu/editplaycount.py:69 msgid "Skip Count" msgstr "" #: ../quodlibet/ext/songsmenu/embedded.py:24 #, fuzzy msgid "Edit Embedded Images" msgstr "Atera irudi txertatuak" #: ../quodlibet/ext/songsmenu/embedded.py:25 #, fuzzy msgid "Removes or replaces embedded images." msgstr "Atera irudi txertatuak" #: ../quodlibet/ext/songsmenu/embedded.py:78 #, fuzzy msgid "_Remove all Images" msgstr "Bikoiztuak ezabatu" #: ../quodlibet/ext/songsmenu/embedded.py:82 #, fuzzy msgid "_Embed Current Image" msgstr "Atera irudi txertatuak" #: ../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:41 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 #: ../quodlibet/qltk/downloader.py:67 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" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" 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 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:49 msgid "Generating fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:63 msgid "_Details" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:85 msgid "_Submit" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:115 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:118 msgid "Fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Songs with MBIDs:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with sufficient tags:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs to submit:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:162 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:178 msgid "Submitting fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:186 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/id3tlen.py:21 msgid "Fix MP3 Duration" msgstr "" #: ../quodlibet/ext/songsmenu/id3tlen.py:22 msgid "" "Removes TLEN frames from ID3 tags which can be the cause for invalid song " "durations." msgstr "" #: ../quodlibet/ext/songsmenu/ifp.py:20 msgid "Send to iFP" msgstr "" #: ../quodlibet/ext/songsmenu/ifp.py:21 msgid "Uploads songs to an iRiver iFP device." msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:51 msgid "Export Metadata" msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:52 msgid "Exports metadata of selected songs as a .tags file." msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:92 #, fuzzy msgid "Import Metadata" msgstr "Inportatu erreprodukzio-zerrenda" #: ../quodlibet/ext/songsmenu/importexport.py:93 msgid "Imports metadata for selected songs from a .tags file." msgstr "" #: ../quodlibet/ext/songsmenu/k3b.py:23 msgid "Burn CD" msgstr "" #: ../quodlibet/ext/songsmenu/k3b.py:24 msgid "Burns CDs with K3b, Brasero or xfburn." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:96 msgid "Updating chart list." msgstr "" #. No charts to fetch, no update scheduled. #: ../quodlibet/ext/songsmenu/lastfmsync.py:114 msgid "Already up-to-date." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:121 #, python-format msgid "Fetching chart for week of %s." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:143 msgid "Sync complete." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:149 #, fuzzy msgid "Error during sync" msgstr "Errorea %r kargatzean" #: ../quodlibet/ext/songsmenu/lastfmsync.py:214 #: ../quodlibet/ext/songsmenu/lastfmsync.py:244 msgid "Last.fm Sync" msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:245 msgid "Updates your library's statistics from your Last.fm profile." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:293 #, 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 "" #. Create a dialog. #: ../quodlibet/ext/songsmenu/migratemetadata.py:29 #: ../quodlibet/ext/songsmenu/migratemetadata.py:38 #, fuzzy msgid "Migrate Metadata" msgstr "Inportatu erreprodukzio-zerrenda" #: ../quodlibet/ext/songsmenu/migratemetadata.py:32 msgid "Copies the quodlibet-specific metadata between songs." msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:45 msgid "_Copy" msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:47 msgid "_Paste" msgstr "" #. Create the tag table. #: ../quodlibet/ext/songsmenu/migratemetadata.py:57 #, fuzzy msgid "Information to copy/paste" msgstr "Informazioa" #. Create the indexing box. #: ../quodlibet/ext/songsmenu/migratemetadata.py:79 msgid "Map tracks by disc and track number" msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:80 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 "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:96 #, python-format msgid "There is %d stored track." msgid_plural "There are %d stored tracks." msgstr[0] "" msgstr[1] "" #: ../quodlibet/ext/songsmenu/playlist.py:31 #, fuzzy msgid "Export as Playlist" msgstr "Inportatu erreprodukzio-zerrenda" #: ../quodlibet/ext/songsmenu/playlist.py:32 msgid "Exports songs to an M3U or PLS playlist." msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:77 msgid "Use relative paths" msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:77 msgid "Use absolute paths" msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:132 #, fuzzy msgid "Unable to export playlist" msgstr "Ezin da erreprodukzio-zerrenda inportatu" #: ../quodlibet/ext/songsmenu/playlist.py:133 #, fuzzy, python-format msgid "Writing to <b>%s</b> 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:362 msgid "ReplayGain Analyzer" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:418 msgid "Progress" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:433 msgid "Gain" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:448 msgid "Peak" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:463 #, python-format msgid "There is <b>%(to-process)s</b> album to update (of %(all)s)" msgid_plural "There are <b>%(to-process)s</b> albums to update (of %(all)s)" msgstr[0] "" msgstr[1] "" #: ../quodlibet/ext/songsmenu/replaygain.py:578 msgid "Replay Gain" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:579 msgid "" "Analyzes and updates ReplayGain information, using GStreamer. Results are " "grouped by album." msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:617 msgid "always" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:618 msgid "if <b>any</b> RG tags are missing" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:620 msgid "if <b>album</b> RG tags are missing" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:637 msgid "_Process albums:" msgstr "" #. Server settings Frame #: ../quodlibet/ext/songsmenu/replaygain.py:649 #, 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 "" #. TRANSLATORS: BPM mean "beats per minute" #: ../quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "" #: ../quodlibet/ext/songsmenu/tapbpm.py:32 #: ../quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" 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:172 #: ../quodlibet/ext/songsmenu/tapbpm.py:179 msgid "Tap BPM" msgstr "" #: ../quodlibet/ext/songsmenu/tapbpm.py:173 #, fuzzy msgid "Tap BPM for the selected song." msgstr "Ezin dira kantak ezabatu" #: ../quodlibet/ext/songsmenu/website_search.py:35 #, fuzzy msgid "Website Search" msgstr "Bilatu" #: ../quodlibet/ext/songsmenu/website_search.py:36 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern-example)s." msgstr "" #: ../quodlibet/ext/songsmenu/website_search.py:78 #, fuzzy msgid "Search URL patterns" msgstr "Bide patroiak" #: ../quodlibet/ext/songsmenu/website_search.py:88 #, fuzzy msgid "Edit search URLs" msgstr "Editatu gordetako balioak..." #. Add link to editor #: ../quodlibet/ext/songsmenu/website_search.py:114 #, fuzzy msgid "Configure Searches…" msgstr "Kolore bil_keta terminoak" #: ../quodlibet/ext/songsmenu/wikipedia.py:46 #, python-format msgid "Search at %(website)s" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:63 msgid "Search Artist in Wikipedia" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:64 msgid "" "Opens a browser window with Wikipedia article on the playing song artist." msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:71 msgid "Search Album in Wikipedia" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:72 msgid "" "Opens a browser window with Wikipedia article on the playing song album." msgstr "" #. then (try to) load all new files #: ../quodlibet/library/libraries.py:650 ../quodlibet/library/libraries.py:660 #: ../quodlibet/library/libraries.py:726 ../quodlibet/library/libraries.py:745 #: ../quodlibet/qltk/information.py:268 ../quodlibet/qltk/prefs.py:639 #: ../quodlibet/util/library.py:124 msgid "Library" msgstr "Liburutegia" #: ../quodlibet/library/libraries.py:650 msgid "Checking mount points" msgstr "Muntatze puntuak arakatzen" #: ../quodlibet/library/libraries.py:660 msgid "Scanning library" msgstr "Liburutegia arakatzen" #: ../quodlibet/library/libraries.py:725 #, python-format msgid "Scanning %s" msgstr "%s arakatzen" #: ../quodlibet/library/libraries.py:745 msgid "Loading files" msgstr "" #: ../quodlibet/operon/base.py:70 #, python-format msgid "Failed to load file: %r" msgstr "%r fitxategia kargatzeak huts egin du" #: ../quodlibet/operon/commands.py:37 msgid "List tags" msgstr "Erakutsi etiketak" #: ../quodlibet/operon/commands.py:42 ../quodlibet/operon/commands.py:81 #: ../quodlibet/operon/commands.py:461 msgid "Print terse output" msgstr "Erakutsi debugarako informazioa" #: ../quodlibet/operon/commands.py:44 ../quodlibet/operon/commands.py:83 #: ../quodlibet/operon/commands.py:463 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "Zutabeak eta ordena Debugarako moduan (%s)" #: ../quodlibet/operon/commands.py:47 ../quodlibet/operon/commands.py:86 #, fuzzy msgid "Also list programmatic tags" msgstr "Ikusi etiketa _programatikoak" #: ../quodlibet/operon/commands.py:51 ../quodlibet/operon/commands.py:129 #: ../quodlibet/operon/commands.py:220 ../quodlibet/operon/commands.py:293 #: ../quodlibet/operon/commands.py:336 ../quodlibet/operon/commands.py:340 #: ../quodlibet/operon/commands.py:391 ../quodlibet/operon/commands.py:394 #: ../quodlibet/operon/commands.py:433 ../quodlibet/operon/commands.py:468 #: ../quodlibet/operon/commands.py:508 ../quodlibet/operon/commands.py:543 #: ../quodlibet/operon/commands.py:585 msgid "Not enough arguments" msgstr "Argumentu nahikorik ez" #: ../quodlibet/operon/commands.py:53 ../quodlibet/operon/commands.py:90 #: ../quodlibet/operon/commands.py:131 ../quodlibet/operon/commands.py:222 #: ../quodlibet/operon/commands.py:470 #, fuzzy msgid "Too many arguments" msgstr "Errore gehiegi" #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:92 #: ../quodlibet/operon/commands.py:475 ../quodlibet/qltk/data_editors.py:363 #, fuzzy msgid "Description" msgstr "azalpena" #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:475 #: ../quodlibet/qltk/edittags.py:454 msgid "Value" msgstr "Balioa" #: ../quodlibet/operon/commands.py:76 msgid "List all common tags" msgstr "Erakutsi ohiko etiketak" #: ../quodlibet/operon/commands.py:118 msgid "Copy tags from one file to another" msgstr "Kopiatu etiketak fitxategi batetik beste batera" #: ../quodlibet/operon/commands.py:123 ../quodlibet/operon/commands.py:164 #: ../quodlibet/operon/commands.py:289 ../quodlibet/operon/commands.py:324 #: ../quodlibet/operon/commands.py:384 msgid "Show changes, don't apply them" msgstr "Erakutsi aldaketak, ez ezarri" #: ../quodlibet/operon/commands.py:125 msgid "Skip tags that can't be written" msgstr "Jauzi egin idatzi ezin daitezkeen etiketak" #: ../quodlibet/operon/commands.py:145 #, python-format msgid "Can't copy tag %r to file: %r" 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:304 ../quodlibet/operon/commands.py:444 #: ../quodlibet/operon/commands.py:676 #, python-format msgid "Can not set %r" msgstr "Ezin da %r jarri" #: ../quodlibet/operon/commands.py:319 #, fuzzy msgid "Remove tags" msgstr "Bikoiztuak ezabatu" #: ../quodlibet/operon/commands.py:326 ../quodlibet/operon/commands.py:386 msgid "Value is a regular expression" msgstr "Balorea expresio erregularra da (RE)" #: ../quodlibet/operon/commands.py:328 #, fuzzy msgid "Remove all tags" msgstr "Bikoiztuak ezabatu" #: ../quodlibet/operon/commands.py:332 msgid "Can't combine '--all' with '--regexp'" msgstr "Ezin da '--all' eta '--regexp' aldi berean erabili" #: ../quodlibet/operon/commands.py:366 #, python-format msgid "Can't remove %r from %r" msgstr "Ezin da %r %r -tik ezabatu" #: ../quodlibet/operon/commands.py:379 #, fuzzy msgid "Remove a tag value" msgstr "Iragazi etiketa balio batez" #: ../quodlibet/operon/commands.py:428 #, fuzzy msgid "Add a tag value" msgstr "Iragazi etiketa balio batez" #: ../quodlibet/operon/commands.py:456 #, fuzzy msgid "List file information" msgstr "Ez dago denbora informaziorik" #: ../quodlibet/operon/commands.py:502 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" #: ../quodlibet/operon/commands.py:515 #, fuzzy, python-format msgid "Failed to load image file: %r" msgstr "%r fitxategia kargatzeak huts egin du" #: ../quodlibet/operon/commands.py:522 ../quodlibet/operon/commands.py:551 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" #: ../quodlibet/operon/commands.py:538 #, fuzzy msgid "Remove all embedded images" msgstr "Atera irudi txertatuak" #: ../quodlibet/operon/commands.py:568 #, fuzzy, python-format msgid "Extract embedded images to %(filepath)s" msgstr "Atera irudi txertatuak" #: ../quodlibet/operon/commands.py:580 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" #: ../quodlibet/operon/commands.py:639 msgid "Rename files based on tags" msgstr "Izenaz aldatu etiketeen arabera" #: ../quodlibet/operon/commands.py:654 msgid "Fill tags based on the file path" msgstr "Bete etiketak fitxategiaren helbidearen arabera" #: ../quodlibet/operon/commands.py:704 ../quodlibet/qltk/information.py:305 #: ../quodlibet/qltk/properties.py:84 ../quodlibet/qltk/renamefiles.py:176 #: ../quodlibet/qltk/tagsfrompath.py:229 ../quodlibet/qltk/tracknumbers.py:79 msgid "File" msgstr "Fitxategia" #: ../quodlibet/operon/commands.py:712 msgid "Fill tracknumbers for all files" msgstr "Bete pista zenbakiak fitxategi guztietan" #: ../quodlibet/operon/commands.py:731 msgid "Print tags based on the given pattern" msgstr "Erakutsi emandako patroiarekin bat datozen etiketak" #: ../quodlibet/operon/commands.py:768 #, fuzzy msgid "Display help information" msgstr "Erakutsi erabiltze argibide laburpena" #: ../quodlibet/operon/util.py:40 #, 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:30 msgid "_Unknown" msgstr "_Ezezaguna" #: ../quodlibet/order/__init__.py:142 msgid "In Order" msgstr "Ordenean" #: ../quodlibet/order/__init__.py:143 msgid "_In Order" msgstr "_Ordenean" #: ../quodlibet/order/reorder.py:23 #, fuzzy msgid "Random" msgstr "_Ausaz" #: ../quodlibet/order/reorder.py:24 ../quodlibet/qltk/queue.py:119 msgid "_Random" msgstr "_Ausaz" #: ../quodlibet/order/reorder.py:39 ../quodlibet/order/reorder.py:40 msgid "Prefer higher rated" msgstr "" #: ../quodlibet/order/repeat.py:43 ../quodlibet/order/repeat.py:44 msgid "Repeat this track" msgstr "" #: ../quodlibet/order/repeat.py:57 ../quodlibet/order/repeat.py:58 #, fuzzy msgid "Repeat all" msgstr "E_rrepikatu" #: ../quodlibet/order/repeat.py:73 ../quodlibet/order/repeat.py:74 msgid "One Song" msgstr "Abesti bat" #: ../quodlibet/player/gstbe/player.py:98 msgid "Stream" msgstr "Stream" #: ../quodlibet/player/gstbe/player.py:98 msgid "Buffering" msgstr "Buffering" #: ../quodlibet/player/gstbe/player.py:319 #, fuzzy msgid "Could not create GStreamer pipeline" msgstr "Ezin da berezko GStreamer pipeline-a sortu." #: ../quodlibet/player/gstbe/player.py:560 msgid "No GStreamer element found to handle media format" msgstr "" #: ../quodlibet/player/gstbe/player.py:561 #, 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:25 #, fuzzy msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. In case 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:36 msgid "_Output pipeline:" msgstr "_Irteera kanalizazioa:" #: ../quodlibet/player/gstbe/prefs.py:43 #, fuzzy, python-format msgid "%.1f seconds" msgstr "segundo %d" #: ../quodlibet/player/gstbe/prefs.py:57 msgid "_Buffer duration:" msgstr "_Buferren iraupena:" #: ../quodlibet/player/gstbe/prefs.py:66 msgid "Disable _gapless playback" msgstr "" #: ../quodlibet/player/gstbe/prefs.py:70 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions." msgstr "" #: ../quodlibet/player/gstbe/util.py:93 #, fuzzy msgid "No GStreamer audio sink found" msgstr "Ez da katerik aurkitu" #: ../quodlibet/player/gstbe/util.py:112 #, fuzzy msgid "Invalid GStreamer output pipeline" msgstr "GStreamer irteera kanalizazio baliogabea, lehenetsia saiatzen." #: ../quodlibet/player/xinebe/player.py:90 msgid "Unable to create audio output" msgstr "Ezin da audio irteera sortu" #: ../quodlibet/player/xinebe/player.py:91 #, 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:62 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" #: ../quodlibet/plugins/__init__.py:71 #, fuzzy, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "Ezin da GStreamer pipeline-a lotu: '%s'" #: ../quodlibet/plugins/playlist.py:30 #, 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:41 ../quodlibet/qltk/songsmenu.py:46 #: ../quodlibet/qltk/songsmenu.py:74 #, fuzzy msgid "_Run Plugin" msgstr "_Pluginak" #: ../quodlibet/qltk/about.py:40 #, python-format msgid "Supported formats: %s" msgstr "Onartutako formatuak: %s" #: ../quodlibet/qltk/about.py:43 #, python-format msgid "Audio device: %s" msgstr "Audio gailua: %s" #. 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:207 ../quodlibet/qltk/information.py:131 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:48 ../quodlibet/qltk/edittags.py:311 msgid "_Value:" msgstr "_Balioa:" #: ../quodlibet/qltk/cbes.py:262 msgid "Saved Values" msgstr "Gordetako balioak" #: ../quodlibet/qltk/cbes.py:263 #, fuzzy msgid "Edit saved values…" msgstr "Editatu gordetako balioak..." #: ../quodlibet/qltk/controls.py:111 msgid "Auto_matic" msgstr "Automati_koa" #: ../quodlibet/qltk/controls.py:112 #, fuzzy msgid "_Track Mode" msgstr "Pis_ta goiburuak" #: ../quodlibet/qltk/controls.py:113 #, fuzzy msgid "_Album Mode" msgstr "_Album goiburuak" #. Translators: player state, no action #: ../quodlibet/qltk/controls.py:122 msgid "_Mute" msgstr "" #: ../quodlibet/qltk/controls.py:128 #, fuzzy msgid "_Replay Gain Mode" msgstr "Erreprodukzio bolumen irabazi doitzea" #. Translators: New Command/Entry/Item/... #: ../quodlibet/qltk/data_editors.py:119 #, python-format msgid "New %s" msgstr "" #: ../quodlibet/qltk/data_editors.py:218 #, fuzzy msgid "(unknown)" msgstr "Ezezaguna" #: ../quodlibet/qltk/data_editors.py:355 #, fuzzy msgid "Tag expression" msgstr "Balorea expresio erregularra da (RE)" #: ../quodlibet/qltk/data_editors.py:382 msgid "Tag expression e.g. people:real or ~album~year." msgstr "" #: ../quodlibet/qltk/data_editors.py:383 #, fuzzy msgid "Enter new tag" msgstr "Iragazi etiketa balio batez" #: ../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/downloader.py:38 msgid "Downloads" msgstr "Deskargak" #: ../quodlibet/qltk/downloader.py:62 msgid "Size" msgstr "Tamaina" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: ../quodlibet/qltk/downloader.py:94 ../quodlibet/qltk/renamefiles.py:265 #: ../quodlibet/qltk/wlw.py:50 msgid "_Stop" msgstr "" #: ../quodlibet/qltk/edittags.py:63 ../quodlibet/qltk/edittags.py:74 #, 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:67 ../quodlibet/qltk/edittags.py:71 #, 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:193 msgid "Split into _Multiple Values" msgstr "Zatitu _hainbat baliotan" #: ../quodlibet/qltk/edittags.py:211 msgid "Split Disc out of _Album" msgstr "Atera diskoa _albumetik" #: ../quodlibet/qltk/edittags.py:228 msgid "Split _Version out of Title" msgstr "Atera _bertsioa izenburutik" #: ../quodlibet/qltk/edittags.py:259 msgid "Split Arranger out of Ar_tist" msgstr "Atera moldatzailea ar_tistatik" #: ../quodlibet/qltk/edittags.py:264 msgid "Split _Performer out of Artist" msgstr "Atera _interpretea atistatik" #: ../quodlibet/qltk/edittags.py:270 #, fuzzy msgid "Split _Performer out of Title" msgstr "Atera _interpretea atistatik" #: ../quodlibet/qltk/edittags.py:276 #, fuzzy msgid "Split _Originalartist out of Title" msgstr "Atera _bertsioa izenburutik" #: ../quodlibet/qltk/edittags.py:283 msgid "Add a Tag" msgstr "Gehitu etiketa bat" #: ../quodlibet/qltk/edittags.py:302 msgid "_Tag:" msgstr "E_tiketa:" #: ../quodlibet/qltk/edittags.py:404 msgid "Edit Tags" msgstr "Editatu etiketak" #: ../quodlibet/qltk/edittags.py:477 msgid "Show _programmatic tags" msgstr "Ikusi etiketa _programatikoak" #: ../quodlibet/qltk/edittags.py:478 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" #. Translators: Revert button in the tag editor #: ../quodlibet/qltk/edittags.py:508 #, fuzzy msgctxt "edittags" msgid "_Revert" msgstr "Inoiz" #. Translators: Save button in the tag editor #: ../quodlibet/qltk/edittags.py:513 msgctxt "edittags" msgid "_Save" msgstr "" #: ../quodlibet/qltk/edittags.py:659 msgid "Unable to add tag" msgstr "Ezin da etiketa gehitu" #: ../quodlibet/qltk/edittags.py:660 #, fuzzy, python-format msgid "Unable to add <b>%s</b>" msgstr "Ezin da abestia gehitu" #: ../quodlibet/qltk/edittags.py:662 #, fuzzy, python-format msgid "" "The files currently selected do not support multiple values for <b>%s</b>." 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:689 ../quodlibet/qltk/edittags.py:856 #: ../quodlibet/qltk/tagsfrompath.py:212 ../quodlibet/util/__init__.py:554 #: ../quodlibet/util/tags.py:231 msgid "Invalid tag" msgstr "Okerreko etiketa" #: ../quodlibet/qltk/edittags.py:690 ../quodlibet/qltk/edittags.py:857 #: ../quodlibet/qltk/tagsfrompath.py:213 #, python-format msgid "" "Invalid tag <b>%s</b>\n" "\n" "The files currently selected do not support editing this tag." msgstr "" "<b>%s</b> okerreko etiketa\n" "\n" "Unean hautatutako fitxategiak ez du ha editatzea onartzen." #: ../quodlibet/qltk/edittags.py:828 ../quodlibet/qltk/edittags.py:868 msgid "Invalid value" msgstr "Okerreko balioa" #: ../quodlibet/qltk/edittags.py:829 ../quodlibet/qltk/edittags.py:869 #, python-format msgid "" "Invalid value: <b>%(value)s</b>\n" "\n" "%(error)s" msgstr "" "Okerreko balioa: <b>%(value)s</b>\n" "\n" "%(error)s" #: ../quodlibet/qltk/_editutils.py:28 msgid "Tag may not be accurate" msgstr "Etiketa ez zehatza izatea liteke" #: ../quodlibet/qltk/_editutils.py:31 #, 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:47 msgid "Unable to save song" msgstr "Ezin da abestia gorde" #: ../quodlibet/qltk/_editutils.py:50 #, 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:142 #, 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:95 #: ../quodlibet/qltk/quodlibetwindow.py:1066 msgid "_About" msgstr "" #: ../quodlibet/qltk/exfalsowindow.py:99 #: ../quodlibet/qltk/quodlibetwindow.py:1088 msgid "_Check for Updates…" msgstr "" #: ../quodlibet/qltk/exfalsowindow.py:105 #: ../quodlibet/qltk/quodlibetwindow.py:1021 ../quodlibet/qltk/songsmenu.py:304 msgid "_Plugins" msgstr "_Pluginak" #: ../quodlibet/qltk/exfalsowindow.py:267 #, 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:279 msgid "Ex Falso Preferences" msgstr "Ex Falso hobespenak" #: ../quodlibet/qltk/exfalsowindow.py:289 ../quodlibet/qltk/prefs.py:598 msgid "Split _on:" msgstr "Zati_tu:" #: ../quodlibet/qltk/exfalsowindow.py:295 ../quodlibet/qltk/prefs.py:613 msgid "Tag Editing" msgstr "Etiketa editatzea" #: ../quodlibet/qltk/filesel.py:210 msgid "Folders" msgstr "Karpetak" #: ../quodlibet/qltk/filesel.py:253 #, fuzzy msgid "_New Folder…" msgstr "Sortu karpeta" #: ../quodlibet/qltk/filesel.py:262 #, fuzzy msgid "_Select all Sub-Folders" msgstr "__Hautatu azpikarpeta guztiak" #: ../quodlibet/qltk/filesel.py:374 msgid "New Folder" msgstr "Sortu karpeta" #: ../quodlibet/qltk/filesel.py:374 msgid "Enter a name for the new folder:" msgstr "Idatzi izen bat karpeta berriarentzat:" #: ../quodlibet/qltk/filesel.py:387 msgid "Unable to create folder" msgstr "Ezinda karpeta sortu" #: ../quodlibet/qltk/filesel.py:404 msgid "Unable to delete folder" msgstr "Ezin da karpeta ezabatu" #: ../quodlibet/qltk/filesel.py:519 ../quodlibet/qltk/pluginwin.py:167 msgid "Songs" msgstr "Abestiak" #. Translators: As in "by Artist Name" #: ../quodlibet/qltk/info.py:42 #, python-format msgid "by %s" msgstr "%s -ez" #: ../quodlibet/qltk/info.py:43 ../quodlibet/qltk/information.py:167 #: ../quodlibet/qltk/information.py:448 #, python-format msgid "Disc %s" msgstr "%s diskoa" #: ../quodlibet/qltk/info.py:44 ../quodlibet/qltk/information.py:172 #, python-format msgid "Track %s" msgstr "%s pista" #: ../quodlibet/qltk/info.py:108 #, fuzzy msgid "_Edit Display…" msgstr "Editatu bistaratzea" #: ../quodlibet/qltk/information.py:105 msgid "No songs are selected." msgstr "Ez da abestirik hautatu." #: ../quodlibet/qltk/information.py:106 msgid "No Songs" msgstr "Abestirik ez" #: ../quodlibet/qltk/information.py:121 ../quodlibet/qltk/information.py:338 #: ../quodlibet/qltk/information.py:471 ../quodlibet/qltk/information.py:531 msgid "Information" msgstr "Informazioa" #: ../quodlibet/qltk/information.py:126 msgid "Lyrics" msgstr "Hitzak" #: ../quodlibet/qltk/information.py:184 ../quodlibet/qltk/information.py:396 #, python-format msgid "Produced by %s" msgstr "%s-ek sortua" #: ../quodlibet/qltk/information.py:199 ../quodlibet/util/tags.py:76 msgid "artist" msgstr "artista" #: ../quodlibet/qltk/information.py:200 ../quodlibet/qltk/information.py:561 #: ../quodlibet/util/tags.py:76 msgid "artists" msgstr "artistak" #. for backwards compat #: ../quodlibet/qltk/information.py:221 ../quodlibet/util/tags.py:86 #: ../quodlibet/util/tags.py:114 msgid "performers" msgstr "interpreteak" #: ../quodlibet/qltk/information.py:235 ../quodlibet/qltk/information.py:248 #: ../quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "Inoiz" #: ../quodlibet/qltk/information.py:236 #, 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:254 ../quodlibet/util/tags.py:139 msgid "added" msgstr "gehiturik" #: ../quodlibet/qltk/information.py:255 ../quodlibet/util/tags.py:140 msgid "last played" msgstr "azken erreproduzitua" #: ../quodlibet/qltk/information.py:256 ../quodlibet/util/tags.py:150 msgid "plays" msgstr "erreproduzitzen" #: ../quodlibet/qltk/information.py:257 ../quodlibet/util/tags.py:151 msgid "skips" msgstr "salto" #: ../quodlibet/qltk/information.py:258 ../quodlibet/util/tags.py:156 msgid "rating" msgstr "balorazioa" #: ../quodlibet/qltk/information.py:287 msgid "path" msgstr "" #: ../quodlibet/qltk/information.py:288 ../quodlibet/util/tags.py:154 msgid "length" msgstr "iraupena" #: ../quodlibet/qltk/information.py:289 #, fuzzy msgid "format" msgstr "Informazioa" #: ../quodlibet/qltk/information.py:290 ../quodlibet/util/tags.py:163 msgid "codec" msgstr "" #: ../quodlibet/qltk/information.py:291 ../quodlibet/util/tags.py:164 #, fuzzy msgid "encoding" msgstr "Goraka" #: ../quodlibet/qltk/information.py:292 ../quodlibet/util/tags.py:160 msgid "bitrate" msgstr "bit-tasa" #: ../quodlibet/qltk/information.py:293 ../quodlibet/util/tags.py:161 msgid "file size" msgstr "fitxategi tamaina" #: ../quodlibet/qltk/information.py:294 ../quodlibet/util/tags.py:149 msgid "modified" msgstr "eraldatua" #: ../quodlibet/qltk/information.py:331 msgid "Additional" msgstr "" #: ../quodlibet/qltk/information.py:383 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d hautatua" msgstr[1] "%d hautatuak" #: ../quodlibet/qltk/information.py:458 msgid "Track unavailable" msgstr "Pista erabilezina" #: ../quodlibet/qltk/information.py:464 msgid "Track List" msgstr "Pista zerrenda" #: ../quodlibet/qltk/information.py:505 ../quodlibet/qltk/information.py:578 #, 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:508 msgid "Selected Discography" msgstr "Hautatu diskografia" #: ../quodlibet/qltk/information.py:558 #, 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:586 ../quodlibet/util/tags.py:74 msgid "albums" msgstr "album" #: ../quodlibet/qltk/information.py:599 msgid "Total length:" msgstr "Iraupena guztira:" #: ../quodlibet/qltk/information.py:603 msgid "Total size:" msgstr "Tamaina guztira:" #: ../quodlibet/qltk/information.py:606 msgid "Files" msgstr "Fixategiak" #: ../quodlibet/qltk/lyrics.py:37 msgid "_Download" msgstr "_Deskargatu" #: ../quodlibet/qltk/lyrics.py:40 #, fuzzy msgid "_Edit" msgstr "_Editatu bistaratzea..." #. buffer.set_text(_("No lyrics found.\n\nYou can click the " #. "Download button to have Quod Libet search " #. "for lyrics online. You can also enter them " #. "yourself and click save.")) #: ../quodlibet/qltk/lyrics.py:73 ../quodlibet/qltk/lyrics.py:109 msgid "No lyrics found for this song." msgstr "Ez da kanta honen letrarik aurkitu." #: ../quodlibet/qltk/lyrics.py:82 #, fuzzy msgid "Searching for lyrics…" msgstr "Letrak bilatzen..." #: ../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/msg.py:41 msgid "Discard tag changes?" msgstr "Baztertu etiketa aldaketak?" #: ../quodlibet/qltk/msg.py:42 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:55 ../quodlibet/qltk/prefs.py:595 #: ../quodlibet/qltk/textedit.py:64 ../quodlibet/qltk/tracknumbers.py:117 #, fuzzy msgid "_Revert" msgstr "Inoiz" #: ../quodlibet/qltk/msg.py:86 msgid "File exists" msgstr "Fitxategia badago" #: ../quodlibet/qltk/msg.py:88 #, python-format msgid "Replace %(file-name)s?" msgstr "" #: ../quodlibet/qltk/msg.py:94 #, fuzzy msgid "_Replace File" msgstr "Berrizendatu fitxategiak" #: ../quodlibet/qltk/notif.py:182 msgid "Active tasks" msgstr "Lan aktiboak" #: ../quodlibet/qltk/notif.py:188 #, python-format msgid "%d tasks running" msgstr "Lan aktiboak: %d" #: ../quodlibet/qltk/playorder.py:254 #, fuzzy msgid "Toggle shuffle mode" msgstr "Txandakatu erreproduzitu/gelditu modua" #: ../quodlibet/qltk/playorder.py:270 #, fuzzy msgid "Toggle repeat mode" msgstr "Txandakatu erreproduzitu/gelditu modua" #: ../quodlibet/qltk/pluginwin.py:44 msgid "Plugin Errors" msgstr "Plugin erroreak" #: ../quodlibet/qltk/pluginwin.py:124 msgid "Enabled" msgstr "Gaitua" #: ../quodlibet/qltk/pluginwin.py:125 msgid "Disabled" msgstr "Desgaitua" #: ../quodlibet/qltk/pluginwin.py:131 msgid "No category" msgstr "Kategoria gabe" #: ../quodlibet/qltk/pluginwin.py:169 msgid "Events" msgstr "" #: ../quodlibet/qltk/pluginwin.py:170 #, fuzzy msgid "Play Order" msgstr "_Ordena:" #: ../quodlibet/qltk/pluginwin.py:171 #, fuzzy msgid "Editing" msgstr "Etiketa editatzea" #: ../quodlibet/qltk/pluginwin.py:173 #, fuzzy msgid "Covers" msgstr "Tamaina guztira:" #: ../quodlibet/qltk/pluginwin.py:309 msgid "No plugins found." msgstr "Ez da pluginik aurkitu." #: ../quodlibet/qltk/pluginwin.py:358 #, fuzzy msgid "Plugins" msgstr "_Pluginak" #: ../quodlibet/qltk/pluginwin.py:402 msgid "Show _Errors" msgstr "Ikusi erroreak" #: ../quodlibet/qltk/prefs.py:45 msgid "_Disc" msgstr "_Diskoa" #: ../quodlibet/qltk/prefs.py:46 msgid "_Track" msgstr "_Pista" #: ../quodlibet/qltk/prefs.py:47 #, fuzzy msgid "Grou_ping" msgstr "taldekatzea" #: ../quodlibet/qltk/prefs.py:50 msgid "Al_bum" msgstr "Al_buma" #: ../quodlibet/qltk/prefs.py:55 msgid "_Filename" msgstr "_Fitxategi-izena" #: ../quodlibet/qltk/prefs.py:57 msgid "_Length" msgstr "_Iraupena" #: ../quodlibet/qltk/prefs.py:64 msgid "_Jump to playing song automatically" msgstr "_Salto erreproduzitzen den abestira automatikoki" #: ../quodlibet/qltk/prefs.py:66 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:82 msgid "_Others:" msgstr "_Besteak:" #: ../quodlibet/qltk/prefs.py:88 #, fuzzy msgid "_Edit…" msgstr "_Editatu bistaratzea..." #: ../quodlibet/qltk/prefs.py:91 msgid "Add or remove additional column headers" msgstr "Gehitu edo ezabatu informazio gehigarriko zutabeak" #: ../quodlibet/qltk/prefs.py:101 msgid "Visible Columns" msgstr "Zutabe ikusgarriak" #: ../quodlibet/qltk/prefs.py:104 msgid "Title includes _version" msgstr "Izenburuak bertsioa barneratzen du" #: ../quodlibet/qltk/prefs.py:106 #, fuzzy msgid "Artist includes all _people" msgstr "Sarezko _bilaketa jendea barneratuz" #: ../quodlibet/qltk/prefs.py:108 msgid "Album includes _disc subtitle" msgstr "Albumak _disko azpititulua barneratzen du" #: ../quodlibet/qltk/prefs.py:110 msgid "Filename includes _folder" msgstr "Fitxategi-izenak _karpeta barneratzen du" #: ../quodlibet/qltk/prefs.py:123 #, fuzzy msgid "Column Preferences" msgstr "Hobespenak" #: ../quodlibet/qltk/prefs.py:129 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:142 ../quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Abesti zerrenda" #: ../quodlibet/qltk/prefs.py:222 #, fuzzy msgid "Edit Columns" msgstr "Zutabe gehigarriak" #: ../quodlibet/qltk/prefs.py:259 msgid "Duration totals" msgstr "" #: ../quodlibet/qltk/prefs.py:271 msgid "_Global filter:" msgstr "Iragazki na_gusia:" #: ../quodlibet/qltk/prefs.py:277 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:283 #, fuzzy msgctxt "heading" msgid "Search" msgstr "Bilatu" #: ../quodlibet/qltk/prefs.py:287 ../quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Nabigatzaileak" #: ../quodlibet/qltk/prefs.py:293 msgid "Confirm _multiple ratings" msgstr "Berretsi balorazio a_nitz" #: ../quodlibet/qltk/prefs.py:295 #, 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:298 msgid "Enable _one-click ratings" msgstr "Gaitu klik-bakarreko balorazioak" #: ../quodlibet/qltk/prefs.py:300 #, 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:306 ../quodlibet/qltk/prefs.py:616 msgid "Ratings" msgstr "Balorazioak" #. Filename choice algorithm config #: ../quodlibet/qltk/prefs.py:312 msgid "Prefer _embedded art" msgstr "Hobetsi album arte lan _txertatuak" #: ../quodlibet/qltk/prefs.py:314 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:319 #, fuzzy msgid "_Fixed image filename:" msgstr "_Ezarritako irudiaren izena:" #: ../quodlibet/qltk/prefs.py:321 #, fuzzy msgid "The single image filename to use if selected" msgstr "Album arte lanaren irudia erabiltzeko, izena ezartzen denean" #: ../quodlibet/qltk/prefs.py:327 msgid "The album art image file to use when forced" msgstr "Album arte lanaren irudia erabiltzeko, izena ezartzen denean" #: ../quodlibet/qltk/prefs.py:336 #, fuzzy msgid "Album Art" msgstr "Album zerrenda" #: ../quodlibet/qltk/prefs.py:357 #, fuzzy msgid "Playback" msgstr "Gelditu erreproduzitzeaz" #: ../quodlibet/qltk/prefs.py:362 #, fuzzy msgid "Output Configuration" msgstr "Erregistro irteera" #: ../quodlibet/qltk/prefs.py:373 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:376 #, fuzzy msgid "_Fall-back gain (dB):" msgstr "Lehenetsiriko irabazia (dB):" #: ../quodlibet/qltk/prefs.py:387 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:390 #, fuzzy msgid "_Pre-amp gain (dB):" msgstr "Aurre-amp irabazia (dB):" #: ../quodlibet/qltk/prefs.py:395 msgid "_Enable Replay Gain volume adjustment" msgstr "_Gaitu erreprodukzio irabazte bolumen doitzea" #: ../quodlibet/qltk/prefs.py:420 msgid "Replay Gain Volume Adjustment" msgstr "Erreprodukzio bolumen irabazi doitzea" #: ../quodlibet/qltk/prefs.py:450 #, fuzzy msgid "_Default rating:" msgstr "Berezkoa" #: ../quodlibet/qltk/prefs.py:493 #, fuzzy msgid "Rating _scale:" msgstr "Balorazioak" #: ../quodlibet/qltk/prefs.py:542 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:547 msgid "_Bayesian averaging amount:" msgstr "_Batezbesteko Bayesianaren kopurua:" #: ../quodlibet/qltk/prefs.py:556 msgid "Save ratings and play _counts" msgstr "Gorde balorazio eta erreprodukzio _kontaketak" #: ../quodlibet/qltk/prefs.py:560 msgid "_Email:" msgstr "_Eposta:" #: ../quodlibet/qltk/prefs.py:562 msgid "Ratings and play counts will be set for this email address" msgstr "" "Balorazio eta erreprodukzio kontuak ezarriko dira posta helbide honentzat" #: ../quodlibet/qltk/prefs.py:577 #, fuzzy msgid "Auto-save tag changes" msgstr "Baztertu etiketa aldaketak?" #: ../quodlibet/qltk/prefs.py:579 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:587 #, 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:610 #, fuzzy msgid "Tags" msgstr "Editatu etiketak" #: ../quodlibet/qltk/prefs.py:631 #, fuzzy msgid "Updating for new ratings" msgstr "_Kate berria" #: ../quodlibet/qltk/prefs.py:641 #, fuzzy msgid "Scan library _on start" msgstr "F_reskatu liburutegia abiaraztean" #: ../quodlibet/qltk/prefs.py:651 ../quodlibet/qltk/quodlibetwindow.py:1100 #, fuzzy msgid "_Scan Library" msgstr "_Bilatu liburutegia" #: ../quodlibet/qltk/prefs.py:653 ../quodlibet/qltk/quodlibetwindow.py:1162 msgid "Check for changes in your library" msgstr "Aztertu zure liburutegiko aldaketak" #: ../quodlibet/qltk/prefs.py:658 #, fuzzy msgid "Re_build Library" msgstr "Birkargatu _liburutegia" #: ../quodlibet/qltk/prefs.py:661 #, 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:671 #, fuzzy msgid "Scan Directories" msgstr "Arakatu _direktorioak" #: ../quodlibet/qltk/prefs.py:677 #, fuzzy msgid "Hidden Songs" msgstr "Abestirik ez" #: ../quodlibet/qltk/properties.py:158 ../quodlibet/util/collection.py:398 #, 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:162 ../quodlibet/qltk/properties.py:164 msgid "Properties" msgstr "Propietateak" #: ../quodlibet/qltk/queue.py:101 msgid "_Queue" msgstr "_Ilara" #: ../quodlibet/qltk/queue.py:126 msgid "Stop Once Empty" msgstr "" #: ../quodlibet/qltk/queue.py:130 #, fuzzy msgid "_Clear Queue" msgstr "_Garbitu errorea" #: ../quodlibet/qltk/queue.py:242 #, 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:198 msgid "_Browse Library" msgstr "_Arakatu liburutegia" #: ../quodlibet/qltk/quodlibetwindow.py:395 #, fuzzy msgid "Toggle queue visibility" msgstr "Txandakatu leiho nagusi ikusgarritasuna" #: ../quodlibet/qltk/quodlibetwindow.py:516 #, fuzzy msgid "Playback Error" msgstr "Gelditu erreproduzitzeaz" #: ../quodlibet/qltk/quodlibetwindow.py:524 #, fuzzy msgid "Set up library directories?" msgstr "Hautatu direktorioak" #: ../quodlibet/qltk/quodlibetwindow.py:525 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:531 msgid "_Not Now" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:532 msgid "_Set Up" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:956 msgid "Unable to add songs" msgstr "Ezin dira abestiak gehitu" #: ../quodlibet/qltk/quodlibetwindow.py:957 #: ../quodlibet/qltk/quodlibetwindow.py:1364 #, 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:980 msgid "_Jump to Playing Song" msgstr "_Salto erreproduzitzen den abestira" #: ../quodlibet/qltk/quodlibetwindow.py:986 #, fuzzy msgid "_File" msgstr "Fitxategia" #: ../quodlibet/qltk/quodlibetwindow.py:987 #, fuzzy msgid "_Song" msgstr "Abestiak" #: ../quodlibet/qltk/quodlibetwindow.py:988 msgid "_View" msgstr "_Ikusi" #: ../quodlibet/qltk/quodlibetwindow.py:989 #, fuzzy msgid "_Browse" msgstr "Nabigatzaileak" #: ../quodlibet/qltk/quodlibetwindow.py:990 msgid "_Control" msgstr "_Kontrola" #: ../quodlibet/qltk/quodlibetwindow.py:991 msgid "_Help" msgstr "_Laguntza" #: ../quodlibet/qltk/quodlibetwindow.py:997 #, fuzzy msgid "_Add a Folder…" msgstr "_Gehitu karpeta bat..." #: ../quodlibet/qltk/quodlibetwindow.py:1002 #, fuzzy msgid "_Add a File…" msgstr "_Gehitu fitxategi bat..." #: ../quodlibet/qltk/quodlibetwindow.py:1007 #, fuzzy msgid "_Add a Location…" msgstr "Gehitu kokapena" #: ../quodlibet/qltk/quodlibetwindow.py:1036 #, fuzzy msgid "Edit Bookmarks…" msgstr "_Editatu laster-markak..." #: ../quodlibet/qltk/quodlibetwindow.py:1056 #, fuzzy msgid "Stop After This Song" msgstr "Gelditu kanta honen ondoren" #: ../quodlibet/qltk/quodlibetwindow.py:1062 msgid "_Keyboard Shortcuts" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:1071 msgid "Online Help" msgstr "Laguntza sarean" #: ../quodlibet/qltk/quodlibetwindow.py:1080 #, fuzzy msgid "Search Help" msgstr "Bilatu" #: ../quodlibet/qltk/quodlibetwindow.py:1352 msgid "Add a Location" msgstr "Gehitu kokapena" #: ../quodlibet/qltk/quodlibetwindow.py:1353 msgid "Enter the location of an audio file:" msgstr "Idatzi audio fitxategiaren kokapena:" #: ../quodlibet/qltk/quodlibetwindow.py:1358 #: ../quodlibet/qltk/quodlibetwindow.py:1363 msgid "Unable to add location" msgstr "Ezin da kokapena gehitu" #: ../quodlibet/qltk/quodlibetwindow.py:1359 #, fuzzy, python-format msgid "%s is not a valid location." msgstr "<b>%s</b> ez da baliozko kokapen bat." #: ../quodlibet/qltk/quodlibetwindow.py:1372 #: ../quodlibet/qltk/quodlibetwindow.py:1381 msgid "Add Music" msgstr "Gehitu musika" #: ../quodlibet/qltk/quodlibetwindow.py:1372 ../quodlibet/qltk/scanbox.py:99 #, fuzzy msgid "_Add Folders" msgstr "_Gehitu karpeta bat..." #: ../quodlibet/qltk/quodlibetwindow.py:1379 #, fuzzy msgid "Music Files" msgstr "Musika erreproduzigailua" #: ../quodlibet/qltk/quodlibetwindow.py:1381 #, fuzzy msgid "_Add Files" msgstr "_Gehitu fitxategi bat..." #: ../quodlibet/qltk/ratingsmenu.py:24 #, 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:26 #, fuzzy msgid "The saved ratings will be removed" msgstr "Kanta bikoiztuak '%s' zerrendatik ezabatuko dira." #: ../quodlibet/qltk/ratingsmenu.py:27 #, 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:57 ../quodlibet/qltk/ratingsmenu.py:111 #, fuzzy msgid "_Remove Rating" msgstr "Bikoiztuak ezabatu" #: ../quodlibet/qltk/ratingsmenu.py:98 #, fuzzy msgid "Change _Rating" msgstr "_Balorazioa" #: ../quodlibet/qltk/renamefiles.py:46 msgid "Replace spaces with _underscores" msgstr "Ordeztu zuriuneak a_zpimarrez" #: ../quodlibet/qltk/renamefiles.py:56 msgid "Strip _Windows-incompatible characters" msgstr "Kendu windows-ekin bateragarriak ez diren karaktereak" #: ../quodlibet/qltk/renamefiles.py:74 msgid "Strip _diacritical marks" msgstr "Kendu marka _diakritikoak" #: ../quodlibet/qltk/renamefiles.py:85 msgid "Strip non-_ASCII characters" msgstr "Kendu ASCII ez diren karaktereak" #: ../quodlibet/qltk/renamefiles.py:95 msgid "Use only _lowercase characters" msgstr "Erabili letra _xeheak bakarrik" #: ../quodlibet/qltk/renamefiles.py:123 msgid "Rename Files" msgstr "Berrizendatu fitxategiak" #: ../quodlibet/qltk/renamefiles.py:139 ../quodlibet/qltk/tagsfrompath.py:116 msgid "Path Patterns" msgstr "Bide patroiak" #: ../quodlibet/qltk/renamefiles.py:140 ../quodlibet/qltk/tagsfrompath.py:117 #, fuzzy msgid "Edit saved patterns…" msgstr "Editatu gordetako balioak..." #: ../quodlibet/qltk/renamefiles.py:143 ../quodlibet/qltk/tagsfrompath.py:120 #: ../quodlibet/qltk/tracknumbers.py:58 msgid "_Preview" msgstr "_Aurreikusi" #: ../quodlibet/qltk/renamefiles.py:190 msgid "New Name" msgstr "Izen berria" #: ../quodlibet/qltk/renamefiles.py:255 msgid "Unable to rename file" msgstr "Ezin da fitxategia berrizendatu" #: ../quodlibet/qltk/renamefiles.py:256 #, fuzzy, python-format msgid "" "Renaming <b>%(old-name)s</b> to <b>%(new-name)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." 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:264 msgid "Ignore _All Errors" msgstr "Baztertu errore _guztiak" #: ../quodlibet/qltk/renamefiles.py:267 msgid "_Continue" msgstr "_Jarraitu" #: ../quodlibet/qltk/renamefiles.py:296 msgid "Path is not absolute" msgstr "Bidea ez da absolutua" #: ../quodlibet/qltk/renamefiles.py:297 #, python-format msgid "" "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 ~/." 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:47 #, 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:99 msgid "Select Directories" msgstr "Hautatu direktorioak" #: ../quodlibet/qltk/searchbar.py:52 #, fuzzy msgid "Saved Searches" msgstr "Gordetako balioak" #: ../quodlibet/qltk/searchbar.py:53 #, fuzzy msgid "Edit saved searches…" msgstr "Editatu gordetako balioak..." #: ../quodlibet/qltk/searchbar.py:74 msgid "Search your library, using free text or QL queries" msgstr "Bilatu zure bilduman, testua edo QL bilaketak erabiliz" #: ../quodlibet/qltk/searchbar.py:129 msgid "Search after _typing" msgstr "Bilatu ida_tzi ondoren" #: ../quodlibet/qltk/searchbar.py:132 msgid "Show search results after the user stops typing" msgstr "" "Bistarazi bilaketa emaitzak erabiltzaileak tekleatzeari utzi bezain laster" #: ../quodlibet/qltk/searchbar.py:187 msgid "_Limit:" msgstr "_Muga:" #: ../quodlibet/qltk/searchbar.py:200 msgid "_Weight" msgstr "_Tamaina" #: ../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 ../quodlibet/qltk/shortcuts.py:41 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: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:377 #, python-format msgid "_Filter on %s" msgstr "_Iragazi %s-ez" #: ../quodlibet/qltk/songlist.py:1094 #, fuzzy msgid "All _Headers" msgstr "_Album goiburuak" #: ../quodlibet/qltk/songlist.py:1095 msgid "_Track Headers" msgstr "Pis_ta goiburuak" #: ../quodlibet/qltk/songlist.py:1096 msgid "_Album Headers" msgstr "_Album goiburuak" #: ../quodlibet/qltk/songlist.py:1097 msgid "_People Headers" msgstr "_Pertsona goiburuak" #: ../quodlibet/qltk/songlist.py:1098 msgid "_Date Headers" msgstr "_Data goiburuak" #: ../quodlibet/qltk/songlist.py:1099 msgid "_File Headers" msgstr "_fixategi goiburuak" #: ../quodlibet/qltk/songlist.py:1100 msgid "_Production Headers" msgstr "P_rodukzio goiburuak" #: ../quodlibet/qltk/songlist.py:1115 #, fuzzy msgid "_Customize Headers…" msgstr "_Pertsonalizatu goiburuak..." #: ../quodlibet/qltk/songlist.py:1120 #, fuzzy msgid "_Expand Column" msgstr "Zutabe gehigarriak" #: ../quodlibet/qltk/songsmenu.py:36 #, 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:64 #, 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:149 #, fuzzy msgid "Configure Plugins…" msgstr "Kolore bil_keta terminoak" #: ../quodlibet/qltk/songsmenu.py:345 msgid "Add to _Queue" msgstr "Gehitu _ilarara" #: ../quodlibet/qltk/songsmenu.py:368 msgid "_Copy to Device" msgstr "_Kopiatu gailura" #: ../quodlibet/qltk/songsmenu.py:379 #, fuzzy msgid "_Remove from Library" msgstr "_Kendu erreprodukzio-zerrendatik" #: ../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:101 msgid "Tags From Path" msgstr "Etiketak bidetik" #: ../quodlibet/qltk/tagsfrompath.py:138 msgid "Tags replace existing ones" msgstr "Etiketak daudenak ordezkatzen dituzte" #: ../quodlibet/qltk/tagsfrompath.py:139 msgid "Tags are added to existing ones" msgstr "Etiketak daudenei gehituko zaizkie" #. Save button #: ../quodlibet/qltk/tagsfrompath.py:153 msgid "Save" msgstr "" #: ../quodlibet/qltk/tagsfrompath.py:195 #, python-format msgid "" "The pattern\n" "\t<b>%s</b>\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/tagsfrompath.py:216 msgid "Invalid tags" msgstr "Etiketa baliogabeak" #: ../quodlibet/qltk/tagsfrompath.py:217 #, 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." #: ../quodlibet/qltk/textedit.py:142 #, 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:158 msgid "Edit Display" msgstr "Editatu bistaratzea" #: ../quodlibet/qltk/tracknumbers.py:39 msgid "Track Numbers" msgstr "Pista zenbakiak" #: ../quodlibet/qltk/tracknumbers.py:42 msgid "Start fro_m:" msgstr "Hasi he_mendik:" #: ../quodlibet/qltk/tracknumbers.py:51 msgid "_Total tracks:" msgstr "Pista _guztira:" #: ../quodlibet/qltk/unity.py:52 #, fuzzy msgid "Play/Pause" msgstr "Erreproduzigailua" #: ../quodlibet/qltk/unity.py:75 #, fuzzy msgid "Previous" msgstr "_Aurreikusi" #: ../quodlibet/qltk/views.py:923 #, 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:89 #, fuzzy msgid "Checking for Updates" msgstr "Muntatze puntuak arakatzen" #: ../quodlibet/update.py:124 #, fuzzy msgid "Connection failed" msgstr "kokapena" #: ../quodlibet/update.py:133 #, python-format msgid "You are already using the newest version %(version)s" msgstr "" #: ../quodlibet/update.py:136 #, 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:420 msgid "Playlists must have a name" msgstr "" #: ../quodlibet/util/collection.py:603 #, python-format msgid "A playlist named %s already exists." msgstr "Badago %s izeneko erreprodukzio-zerrenda bat." #: ../quodlibet/util/cover/built_in.py:26 #, fuzzy msgid "Embedded album covers" msgstr "Ikusi album _karatulak" #: ../quodlibet/util/cover/built_in.py:27 msgid "Uses covers embedded into audio files." msgstr "" #: ../quodlibet/util/cover/built_in.py:49 #, fuzzy msgid "Filesystem cover" msgstr "Fitxategi sistema" #: ../quodlibet/util/cover/built_in.py:50 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "" #: ../quodlibet/util/__init__.py:93 msgid "Display brief usage information" msgstr "Erakutsi erabiltze argibide laburpena" #: ../quodlibet/util/__init__.py:95 msgid "Display version and copyright" msgstr "Bertsio eta kopia-eskubideak bistarazi" #: ../quodlibet/util/__init__.py:135 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "" #: ../quodlibet/util/__init__.py:137 msgid "[options]" msgstr "[aukerak]" #: ../quodlibet/util/__init__.py:182 #, python-format msgid "Option %r not recognized." msgstr "Ez da %r aukera ezagutzen." #: ../quodlibet/util/__init__.py:185 #, python-format msgid "Option %r requires an argument." msgstr "%r aukerak argumentu bat behar du." #: ../quodlibet/util/__init__.py:188 #, python-format msgid "%r is not a unique prefix." msgstr "%r ez da aurrizki bakana." #: ../quodlibet/util/__init__.py:364 #, python-format msgid "%d kbps" msgstr "%d kbps" #: ../quodlibet/util/__init__.py:419 #, fuzzy, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "segundo %d" msgstr[1] "%d segundo" #: ../quodlibet/util/__init__.py:432 msgid "No time information" msgstr "Ez dago denbora informaziorik" #: ../quodlibet/util/__init__.py:435 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "segundo %d" msgstr[1] "%d segundo" #: ../quodlibet/util/__init__.py:436 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "minutu %d" msgstr[1] "%d minutu" #: ../quodlibet/util/__init__.py:437 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "ordu %d" msgstr[1] "%d ordu" #: ../quodlibet/util/__init__.py:438 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "egun %d" msgstr[1] "%d egun" #: ../quodlibet/util/__init__.py:439 #, 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:563 #, 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 msgid "Unable to edit song" msgstr "Ezin da abestia editatu" #: ../quodlibet/util/songwrapper.py:113 #, python-format msgid "" "Saving <b>%s</b> 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:34 #: ../quodlibet/util/string/__init__.py:44 msgid "[Invalid Encoding]" msgstr "[Kodeketa baliogabea]" #: ../quodlibet/util/tags.py:74 msgid "album" msgstr "albuma" #: ../quodlibet/util/tags.py:75 msgid "arranger" msgstr "Moldatzailea" #: ../quodlibet/util/tags.py:75 msgid "arrangers" msgstr "moldatzaileak" #: ../quodlibet/util/tags.py:75 #, fuzzy msgid "arrangement" msgstr "Moldatzailea" #: ../quodlibet/util/tags.py:77 msgid "author" msgstr "egilea" #: ../quodlibet/util/tags.py:77 msgid "authors" msgstr "egileak" #: ../quodlibet/util/tags.py:78 msgid "composer" msgstr "konposatzailea" #: ../quodlibet/util/tags.py:78 msgid "composers" msgstr "konposatzaileak" #: ../quodlibet/util/tags.py:78 #, fuzzy msgid "composition" msgstr "konposatzailea" #. Translators: conducting as in conducting a musical performance #: ../quodlibet/util/tags.py:80 msgid "conductor" msgstr "gidaria" #: ../quodlibet/util/tags.py:80 msgid "conductors" msgstr "gidariak" #: ../quodlibet/util/tags.py:80 #, fuzzy msgid "conducting" msgstr "gidaria" #: ../quodlibet/util/tags.py:81 msgid "contact" msgstr "kontaktua" #: ../quodlibet/util/tags.py:82 msgid "copyright" msgstr "Copyright-a" #: ../quodlibet/util/tags.py:83 msgid "date" msgstr "data" #: ../quodlibet/util/tags.py:84 msgid "description" msgstr "azalpena" #: ../quodlibet/util/tags.py:85 msgid "genre" msgstr "generoa" #: ../quodlibet/util/tags.py:85 #, fuzzy msgid "genres" msgstr "generoa" #: ../quodlibet/util/tags.py:86 msgid "performer" msgstr "interpretea" #: ../quodlibet/util/tags.py:87 msgid "grouping" msgstr "taldekatzea" #: ../quodlibet/util/tags.py:88 msgid "language" msgstr "hizkuntza" #: ../quodlibet/util/tags.py:89 msgid "license" msgstr "lizentzia" #: ../quodlibet/util/tags.py:90 msgid "location" msgstr "kokapena" #: ../quodlibet/util/tags.py:91 msgid "lyricist" msgstr "idazlea" #: ../quodlibet/util/tags.py:91 msgid "lyricists" msgstr "Idazleak" #: ../quodlibet/util/tags.py:91 #, fuzzy msgid "lyrics" msgstr "idazlea" #. Translators: Also e.g. "record label", "publisher" #: ../quodlibet/util/tags.py:93 msgid "organization" msgstr "erakundea" #: ../quodlibet/util/tags.py:94 msgid "title" msgstr "izenburua" #: ../quodlibet/util/tags.py:95 msgid "version" msgstr "bertsioa" #: ../quodlibet/util/tags.py:96 msgid "website" msgstr "webgunea" #: ../quodlibet/util/tags.py:98 msgid "album artist" msgstr "album artista" #: ../quodlibet/util/tags.py:99 msgid "BPM" msgstr "BPM" #. Translators: This used to be called "part". #: ../quodlibet/util/tags.py:102 ../quodlibet/util/tags.py:103 msgid "disc subtitle" msgstr "disko azpititulua" #: ../quodlibet/util/tags.py:104 ../quodlibet/util/tags.py:141 msgid "disc" msgstr "diskoa" #: ../quodlibet/util/tags.py:105 ../quodlibet/util/tags.py:143 msgid "track" msgstr "pista" #: ../quodlibet/util/tags.py:106 msgid "label ID" msgstr "etiketa IDa" #: ../quodlibet/util/tags.py:107 msgid "original release date" msgstr "jatorrizko argitaratze data" #: ../quodlibet/util/tags.py:108 msgid "original album" msgstr "jatorrizko albuma" #: ../quodlibet/util/tags.py:109 msgid "original artist" msgstr "jatorrizko artista" #: ../quodlibet/util/tags.py:110 msgid "recording date" msgstr "grabaketa data" #: ../quodlibet/util/tags.py:111 msgid "release country" msgstr "argitaratzen nazioa" #. 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:120 #, fuzzy msgid "MusicBrainz recording ID" msgstr "MusicBrainz pista IDa" #: ../quodlibet/util/tags.py:121 #, fuzzy msgid "MusicBrainz release track ID" msgstr "MusicBrainz argitaratze IDa" #: ../quodlibet/util/tags.py:122 msgid "MusicBrainz release ID" msgstr "MusicBrainz argitaratze IDa" #: ../quodlibet/util/tags.py:123 #, fuzzy msgid "MusicBrainz artist ID" msgstr "Musicbrainz artista IDa" #: ../quodlibet/util/tags.py:124 #, fuzzy msgid "MusicBrainz release artist ID" msgstr "MusicBrainz argitaratze IDa" #: ../quodlibet/util/tags.py:125 msgid "MusicBrainz TRM ID" msgstr "MusicBrainz TRM IDa" #: ../quodlibet/util/tags.py:126 msgid "MusicIP PUID" msgstr "MusicIP PUID" #: ../quodlibet/util/tags.py:127 msgid "MusicBrainz album status" msgstr "MusicBrainz album egoera" #: ../quodlibet/util/tags.py:128 msgid "MusicBrainz album type" msgstr "MusicBrainz album mota" #: ../quodlibet/util/tags.py:129 #, fuzzy msgid "MusicBrainz release group ID" msgstr "MusicBrainz argitaratze IDa" #. Translators: "gain" means a volume adjustment, not "to acquire". #: ../quodlibet/util/tags.py:132 msgid "track gain" msgstr "Pistaren irabazpena" #: ../quodlibet/util/tags.py:133 msgid "track peak" msgstr "Pistaren erpina" #. Translators: "gain" means a volume adjustment, not "to acquire". #: ../quodlibet/util/tags.py:135 msgid "album gain" msgstr "Albumaren irabazpena" #: ../quodlibet/util/tags.py:136 msgid "album peak" msgstr "Albumaren gailurra" #: ../quodlibet/util/tags.py:137 msgid "reference loudness" msgstr "erreferentzia ozena" #: ../quodlibet/util/tags.py:142 msgid "discs" msgstr "diskoak" #: ../quodlibet/util/tags.py:144 msgid "tracks" msgstr "pistak" #: ../quodlibet/util/tags.py:145 msgid "last started" msgstr "azken abiarazia" #: ../quodlibet/util/tags.py:146 msgid "full name" msgstr "Izen osoa" #: ../quodlibet/util/tags.py:153 msgid "mount point" msgstr "muntatze puntua" #: ../quodlibet/util/tags.py:155 msgid "people" msgstr "jendea" #: ../quodlibet/util/tags.py:157 msgid "year" msgstr "urtea" #: ../quodlibet/util/tags.py:158 #, fuzzy msgid "original release year" msgstr "jatorrizko argitaratze data" #: ../quodlibet/util/tags.py:159 msgid "bookmark" msgstr "laster-marka" #: ../quodlibet/util/tags.py:162 #, fuzzy msgid "file format" msgstr "Ez dago denbora informaziorik" #: ../quodlibet/util/tags.py:165 #, fuzzy msgid "playlists" msgstr "Erreprodukzio-zerrendak" #: ../quodlibet/util/tags.py:166 msgid "channel count" msgstr "" #. Translators: e.g. "artist (sort)" #: ../quodlibet/util/tags.py:256 msgid "sort" msgstr "" #. Translators: e.g. "performer (roles)" #: ../quodlibet/util/tags.py:264 msgid "roles" msgstr "" #, 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 "Remove all songs from the queue" #~ msgstr "Kendu ilarako abesti guztiak" #~ msgid "Watch this folder for new songs" #~ msgstr "Bilatu kanta berriak karpeta honetan" #~ 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 "Model:" #~ msgstr "Modeloa:" #~ msgid "Capacity:" #~ msgstr "Kapazitatea:" #~ msgid "Firmware:" #~ msgstr "Firmwarea:" #~ msgid "Removing orphaned iPod track" #~ msgstr "iPod pista umezurtzak kentzen" #, 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 "Unable to open input files" #~ msgstr "Ezin dira sarrera fitxategiak ireki" #~ 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 "General" #~ msgstr "Orokorra" #~ 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 "_Select" #~ msgstr "_Hautatu" #~ 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 "Choose New Stations" #~ msgstr "Hautatu kate berriak" #~ msgid "Add" #~ msgstr "Gehitu" #~ msgid "Bitrate" #~ msgstr "Bit-tasa" #~ msgid "_Stations..." #~ msgstr "Ka_teak..." #~ msgid "Quod Libet" #~ msgstr "Quod Libet" #~ 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9551857 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/po/fi.po����������������������������������������������������������������������������0000644�0001750�0001750�00000634037�00000000000�014067� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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: 2019-08-17 13:40+0300\n" "PO-Revision-Date: 2019-08-17 13:46+0300\n" "Last-Translator: Kristian Laakkonen\n" "Language-Team: Finnish <translation-team-fi@lists.sourceforge.net>\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: Poedit 2.0.6\n" #: quodlibet/browsers/albums/main.py:206 #: quodlibet/browsers/covergrid/main.py:54 msgid "_Title" msgstr "_Nimi" #: quodlibet/browsers/albums/main.py:207 #: quodlibet/browsers/covergrid/main.py:55 quodlibet/qltk/prefs.py:49 msgid "_Artist" msgstr "_Artisti" #: quodlibet/browsers/albums/main.py:208 #: quodlibet/browsers/covergrid/main.py:56 quodlibet/qltk/prefs.py:54 msgid "_Date" msgstr "_Päivämäärä" #: quodlibet/browsers/albums/main.py:209 msgid "_Original Date" msgstr "A_lkuperäinen päivämäärä" #: quodlibet/browsers/albums/main.py:210 #: quodlibet/browsers/covergrid/main.py:57 quodlibet/qltk/prefs.py:53 msgid "_Genre" msgstr "_Tyylilaji" #: quodlibet/browsers/albums/main.py:211 #: quodlibet/browsers/covergrid/main.py:58 quodlibet/qltk/prefs.py:58 #: quodlibet/qltk/ratingsmenu.py:39 msgid "_Rating" msgstr "Ar_vosana" #: quodlibet/browsers/albums/main.py:212 msgid "_Playcount" msgstr "Toistokertojen _määrä" #: quodlibet/browsers/albums/main.py:218 #: quodlibet/browsers/covergrid/main.py:64 msgid "Sort _by…" msgstr "_Järjestä…" #: quodlibet/browsers/albums/main.py:239 #: quodlibet/browsers/covergrid/main.py:85 #: quodlibet/browsers/paned/prefs.py:203 #: quodlibet/browsers/playlists/main.py:667 quodlibet/qltk/exfalsowindow.py:108 #: quodlibet/qltk/pluginwin.py:341 quodlibet/qltk/quodlibetwindow.py:906 msgid "_Preferences" msgstr "_Asetukset" #: quodlibet/browsers/albums/main.py:409 msgid "Album List" msgstr "Albumilista" #: quodlibet/browsers/albums/main.py:410 msgid "_Album List" msgstr "_Albumilista" #: quodlibet/browsers/albums/main.py:524 #: quodlibet/browsers/covergrid/main.py:285 #: quodlibet/browsers/covergrid/main.py:501 msgid "All Albums" msgstr "Kaikki albumit" #: quodlibet/browsers/albums/main.py:525 #: quodlibet/browsers/covergrid/main.py:286 #: quodlibet/browsers/covergrid/main.py:502 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d albumi" msgstr[1] "%d albumia" #: quodlibet/browsers/albums/main.py:706 #: quodlibet/browsers/covergrid/main.py:480 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:16 #: 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:385 quodlibet/util/collection.py:247 #, 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:383 quodlibet/util/collection.py:251 #, 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:124 #: quodlibet/ext/songsmenu/cover_download.py:243 msgid "Options" msgstr "Valinnat" #: quodlibet/browsers/albums/prefs.py:74 #: quodlibet/browsers/covergrid/prefs.py:127 msgid "Album Display" msgstr "Albuminäkymä" #: quodlibet/browsers/albums/prefs.py:78 #: quodlibet/browsers/covergrid/prefs.py:131 #: quodlibet/browsers/playlists/prefs.py:56 #: quodlibet/ext/songsmenu/albumart.py:328 #: quodlibet/ext/songsmenu/duplicates.py:345 #: quodlibet/ext/songsmenu/filterall.py:48 quodlibet/qltk/bookmarks.py:101 #: quodlibet/qltk/cbes.py:93 quodlibet/qltk/data_editors.py:96 #: quodlibet/qltk/data_editors.py:321 quodlibet/qltk/exfalsowindow.py:286 #: quodlibet/qltk/pluginwin.py:79 quodlibet/qltk/pluginwin.py:428 #: quodlibet/qltk/prefs.py:764 quodlibet/qltk/textedit.py:163 #: quodlibet/update.py:149 msgid "_Close" msgstr "_Sulje" #: quodlibet/browsers/audiofeeds.py:52 quodlibet/browsers/audiofeeds.py:64 #: quodlibet/browsers/audiofeeds.py:66 quodlibet/browsers/audiofeeds.py:156 #: quodlibet/browsers/paned/models.py:85 #: quodlibet/ext/songsmenu/fingerprint/search.py:46 #: quodlibet/formats/_audio.py:488 quodlibet/order/__init__.py:27 #: quodlibet/qltk/information.py:244 quodlibet/qltk/information.py:251 #: quodlibet/qltk/information.py:277 quodlibet/qltk/wlw.py:69 msgid "Unknown" msgstr "Tuntematon" #: quodlibet/browsers/audiofeeds.py:247 msgid "New Feed" msgstr "Uusi syöte" #: quodlibet/browsers/audiofeeds.py:248 msgid "Enter the location of an audio feed:" msgstr "Anna äänisyötteen sijainti:" #: quodlibet/browsers/audiofeeds.py:249 #: quodlibet/browsers/collection/prefs.py:89 quodlibet/browsers/iradio.py:357 #: quodlibet/browsers/paned/prefs.py:120 #: quodlibet/browsers/playlists/menu.py:96 #: quodlibet/browsers/playlists/util.py:52 quodlibet/qltk/bookmarks.py:62 #: quodlibet/qltk/cbes.py:55 quodlibet/qltk/data_editors.py:308 #: quodlibet/qltk/edittags.py:327 quodlibet/qltk/edittags.py:527 #: quodlibet/qltk/quodlibetwindow.py:1276 quodlibet/qltk/scanbox.py:61 msgid "_Add" msgstr "_Lisää" #: quodlibet/browsers/audiofeeds.py:303 msgid "Audio Feeds" msgstr "Äänisyötteet" #: quodlibet/browsers/audiofeeds.py:304 msgid "_Audio Feeds" msgstr "Äänis_yötteet" #: quodlibet/browsers/audiofeeds.py:407 quodlibet/qltk/data_editors.py:93 msgid "_New" msgstr "_Uusi" #: quodlibet/browsers/audiofeeds.py:467 quodlibet/browsers/audiofeeds.py:526 msgid "Unable to add feed" msgstr "Syötettä ei voitu lisätä" #: quodlibet/browsers/audiofeeds.py:468 quodlibet/browsers/audiofeeds.py:527 #, python-format msgid "" "%s could not be added. The server may be down, or the location may not be an " "audio feed." msgstr "" "Sijainnin %s lisääminen ei onnistunut. Ehkä palvelin ei ole linjoilla tai " "sijainti ei ole äänisyöte." #: quodlibet/browsers/audiofeeds.py:475 quodlibet/qltk/filesel.py:260 #: quodlibet/qltk/pluginwin.py:414 msgid "_Refresh" msgstr "_Päivitä" #: quodlibet/browsers/audiofeeds.py:476 #: quodlibet/browsers/playlists/main.py:487 #: quodlibet/browsers/playlists/util.py:43 quodlibet/qltk/delete.py:143 #: quodlibet/qltk/filesel.py:257 quodlibet/qltk/lyrics.py:35 #: quodlibet/qltk/maskedbox.py:28 quodlibet/qltk/songsmenu.py:364 msgid "_Delete" msgstr "_Poista" #: quodlibet/browsers/audiofeeds.py:543 msgid "" "The current audio backend does not support URLs, Audio Feeds browser " "disabled." msgstr "" "Nykyinen äänen taustaohjelma ei tue URL-osoitteita. Äänisyötteiden selain on " "poistettu käytöstä." #: quodlibet/browsers/_base.py:146 quodlibet/browsers/_base.py:149 msgid "Library Browser" msgstr "Kirjaston selain" #: quodlibet/browsers/_base.py:273 quodlibet/ext/songsmenu/console.py:45 #: quodlibet/ext/songsmenu/refresh.py:30 quodlibet/qltk/exfalsowindow.py:240 #: quodlibet/qltk/information.py:554 quodlibet/qltk/maskedbox.py:68 #: quodlibet/util/collection.py:532 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d kappale" msgstr[1] "%d kappaletta" #: quodlibet/browsers/_base.py:401 quodlibet/browsers/_base.py:406 #: quodlibet/qltk/tagsfrompath.py:193 quodlibet/qltk/textedit.py:140 #: quodlibet/util/__init__.py:573 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:23 #, python-format msgid "Unknown %s" msgstr "Tuntematon %s" #: quodlibet/browsers/collection/models.py:24 #, 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" #. Remove button #: quodlibet/browsers/collection/prefs.py:93 #: quodlibet/browsers/paned/prefs.py:124 #: quodlibet/browsers/playlists/menu.py:97 #: quodlibet/ext/playlist/remove_duplicates.py:60 #: quodlibet/qltk/bookmarks.py:97 quodlibet/qltk/bookmarks.py:127 #: quodlibet/qltk/cbes.py:82 quodlibet/qltk/cbes.py:89 #: quodlibet/qltk/data_editors.py:78 quodlibet/qltk/data_editors.py:91 #: quodlibet/qltk/data_editors.py:298 quodlibet/qltk/data_editors.py:311 #: quodlibet/qltk/data_editors.py:319 quodlibet/qltk/edittags.py:533 #: quodlibet/qltk/edittags.py:710 quodlibet/qltk/maskedbox.py:48 #: quodlibet/qltk/maskedbox.py:88 quodlibet/qltk/queue.py:427 #: quodlibet/qltk/scanbox.py:36 quodlibet/qltk/scanbox.py:63 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:470 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:247 #: quodlibet/ext/songsmenu/editplaycount.py:45 #: quodlibet/ext/songsmenu/exact_rating.py:38 #: quodlibet/player/gstbe/prefs.py:40 quodlibet/qltk/prefs.py:127 #: quodlibet/qltk/textedit.py:64 msgid "_Apply" msgstr "_Käytä" #: quodlibet/browsers/collection/prefs.py:197 #: quodlibet/browsers/paned/prefs.py:251 #: quodlibet/browsers/playlists/menu.py:95 #: quodlibet/browsers/playlists/util.py:42 quodlibet/errorreport/ui.py:103 #: quodlibet/ext/playlist/export_to_folder.py:38 #: 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:44 #: quodlibet/ext/songsmenu/fingerprint/search.py:281 #: quodlibet/ext/songsmenu/fingerprint/submit.py:90 #: quodlibet/ext/songsmenu/importexport.py:40 #: quodlibet/ext/songsmenu/lastfmsync.py:218 #: quodlibet/ext/songsmenu/playlist.py:50 #: 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:326 #: quodlibet/qltk/_editutils.py:39 quodlibet/qltk/getstring.py:28 #: quodlibet/qltk/maskedbox.py:27 quodlibet/qltk/msg.py:54 #: quodlibet/qltk/msg.py:93 quodlibet/qltk/msg.py:111 #: quodlibet/qltk/ratingsmenu.py:33 quodlibet/update.py:95 msgid "_Cancel" msgstr "_Peruuta" #: quodlibet/browsers/covergrid/main.py:126 msgid "Cover Grid" msgstr "Albumiruudukko" #: quodlibet/browsers/covergrid/main.py:127 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:71 msgid "Show \"All Albums\" Item" msgstr "Näytä ”Kaikki albumit” -valinta" #: quodlibet/browsers/covergrid/prefs.py:82 msgid "Wide Mode" msgstr "Leveä tila" #: quodlibet/browsers/covergrid/prefs.py:114 #: quodlibet/browsers/covergrid/prefs.py:115 msgid "Cover Magnification" msgstr "Kansikuvan koko" #: quodlibet/browsers/filesystem.py:39 msgid "File System" msgstr "Tiedostojärjestelmä" #: quodlibet/browsers/filesystem.py:40 msgid "_File System" msgstr "Tie_dostojärjestelmä" #: quodlibet/browsers/filesystem.py:124 quodlibet/qltk/songlist.py:255 msgid "Unable to copy songs" msgstr "Kappaleiden kopiointi epäonnistui" #: quodlibet/browsers/filesystem.py:125 quodlibet/qltk/songlist.py:256 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:197 msgid "_Add to Library" msgstr "_Lisää kirjastoon" #: quodlibet/browsers/iradio.py:182 msgid "Unsupported file type" msgstr "Tiedostomuotoa ei tueta" #: quodlibet/browsers/iradio.py:183 #, 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:230 quodlibet/browsers/iradio.py:243 #: quodlibet/browsers/iradio.py:836 msgid "Unable to add station" msgstr "Asemaa ei voitu lisätä" #: quodlibet/browsers/iradio.py:254 quodlibet/browsers/iradio.py:487 msgid "Internet Radio" msgstr "Internet-radio" #: quodlibet/browsers/iradio.py:254 msgid "Downloading station list" msgstr "Ladataan asemalistaa" #: quodlibet/browsers/iradio.py:355 msgid "New Station" msgstr "Uusi asema" #: quodlibet/browsers/iradio.py:356 msgid "Enter the location of an Internet radio station:" msgstr "Anna Internet-radioaseman sijainti:" #: quodlibet/browsers/iradio.py:374 msgid "Electronic" msgstr "Elektroninen" #: quodlibet/browsers/iradio.py:377 msgid "Hip Hop / Rap" msgstr "Hip hop / Rap" #: quodlibet/browsers/iradio.py:378 msgid "Oldies" msgstr "Klassikot" #: quodlibet/browsers/iradio.py:379 msgid "R&B" msgstr "R&B" #: quodlibet/browsers/iradio.py:380 msgid "Japanese" msgstr "Japanilainen" #: quodlibet/browsers/iradio.py:381 msgid "Indian" msgstr "Intialainen" #: quodlibet/browsers/iradio.py:383 msgid "Religious" msgstr "Uskonnollinen" #: quodlibet/browsers/iradio.py:385 msgid "Charts" msgstr "Listamusiikki" #: quodlibet/browsers/iradio.py:386 msgid "Turkish" msgstr "Turkkilainen" #: quodlibet/browsers/iradio.py:387 msgid "Reggae / Dancehall" msgstr "Reggae / Dancehall" #: quodlibet/browsers/iradio.py:388 msgid "Latin" msgstr "Latino" #: quodlibet/browsers/iradio.py:389 msgid "College Radio" msgstr "Kampusradio" #: quodlibet/browsers/iradio.py:390 msgid "Talk / News" msgstr "Puhe / Uutiset" #: quodlibet/browsers/iradio.py:391 msgid "Ambient" msgstr "Ambient" #: quodlibet/browsers/iradio.py:392 msgid "Jazz" msgstr "Jazz" #: quodlibet/browsers/iradio.py:393 quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "Klassinen" #: quodlibet/browsers/iradio.py:394 quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "Pop" #: quodlibet/browsers/iradio.py:395 msgid "Alternative" msgstr "Alternative" #: quodlibet/browsers/iradio.py:396 msgid "Metal" msgstr "Metalli" #: quodlibet/browsers/iradio.py:397 msgid "Country" msgstr "Country" #: quodlibet/browsers/iradio.py:398 msgid "News" msgstr "Uutiset" #: quodlibet/browsers/iradio.py:399 msgid "Schlager" msgstr "Iskelmä" #: quodlibet/browsers/iradio.py:400 msgid "Funk" msgstr "Funk" #: quodlibet/browsers/iradio.py:401 msgid "Indie" msgstr "Indie" #: quodlibet/browsers/iradio.py:402 msgid "Blues" msgstr "Blues" #: quodlibet/browsers/iradio.py:403 msgid "Soul" msgstr "Soul" #: quodlibet/browsers/iradio.py:404 msgid "Lounge" msgstr "Lounge" #: quodlibet/browsers/iradio.py:405 msgid "Punk" msgstr "Punk" #: quodlibet/browsers/iradio.py:406 msgid "Reggaeton" msgstr "Reggaeton" #: quodlibet/browsers/iradio.py:408 msgid "Slavic" msgstr "Slaavilainen" #: quodlibet/browsers/iradio.py:410 msgid "Greek" msgstr "Kreikkalainen" #: quodlibet/browsers/iradio.py:411 msgid "Gothic" msgstr "Goottilainen" #: quodlibet/browsers/iradio.py:412 quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "Rock" #: quodlibet/browsers/iradio.py:465 msgid "Would you like to load a list of popular radio stations?" msgstr "Ladataanko lista suosituista radioasemista?" #: quodlibet/browsers/iradio.py:471 msgid "_Load Stations" msgstr "_Lataa asemat" #: quodlibet/browsers/iradio.py:488 msgid "_Internet Radio" msgstr "I_nternet-radio" #: quodlibet/browsers/iradio.py:561 msgid "_New Station…" msgstr "_Uusi asema…" #: quodlibet/browsers/iradio.py:564 msgid "_Update Stations" msgstr "_Päivitä asemat" #: quodlibet/browsers/iradio.py:591 msgid "All Stations" msgstr "Kaikki asemat" #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:595 quodlibet/browsers/soundcloud/main.py:65 msgid "Favorites" msgstr "Suosikit" #: quodlibet/browsers/iradio.py:603 msgid "No Category" msgstr "Ei luokkaa" #: quodlibet/browsers/iradio.py:828 msgid "No stations found" msgstr "Asemia ei löytynyt" #: quodlibet/browsers/iradio.py:829 #, python-format msgid "No Internet radio stations were found at %s." msgstr "Internet-radioasemia ei löytynyt sijainnista %s." #: quodlibet/browsers/iradio.py:837 msgid "All stations listed are already in your library." msgstr "Kaikki luetellut asemat ovat jo kirjastossasi." #: quodlibet/browsers/iradio.py:854 msgid "Add to Favorites" msgstr "_Lisää suosikkeihin" #: quodlibet/browsers/iradio.py:858 msgid "Remove from Favorites" msgstr "_Poista suosikeista" #: quodlibet/browsers/iradio.py:958 #, 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:103 quodlibet/qltk/pluginwin.py:122 #: quodlibet/qltk/pluginwin.py:164 msgid "All" msgstr "Kaikki" #: quodlibet/browsers/paned/prefs.py:41 #: quodlibet/ext/songsmenu/cover_download.py:118 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" "<tt>%s</tt>" msgstr "" "Tunnistekaava, joka voi sisältää muotoiluja, esim. <tt>composer</tt> tai\n" "<tt>%s</tt>" #: quodlibet/browsers/paned/prefs.py:231 msgid "Paned Browser Preferences" msgstr "Paneeliselaimen asetukset" #: quodlibet/browsers/paned/prefs.py:236 msgid "Column layout" msgstr "Paneelien sijoittelu" #: quodlibet/browsers/paned/prefs.py:240 msgid "Column content" msgstr "Paneelien sisältö" #: quodlibet/browsers/paned/prefs.py:242 msgid "Equal pane width" msgstr "Samanlevyiset paneelit" #: quodlibet/browsers/playlists/main.py:48 #: quodlibet/browsers/playlists/main.py:603 quodlibet/qltk/pluginwin.py:168 msgid "Playlists" msgstr "Soittolistat" #: quodlibet/browsers/playlists/main.py:49 msgid "_Playlists" msgstr "_Soittolistat" #: quodlibet/browsers/playlists/main.py:152 msgid "_Remove from Playlist" msgstr "_Poista soittolistalta" #: quodlibet/browsers/playlists/main.py:217 msgid "New" msgstr "Uusi" #: quodlibet/browsers/playlists/main.py:221 msgid "Import" msgstr "Tuo" #: quodlibet/browsers/playlists/main.py:443 msgid "Unable to import playlist" msgstr "Soittolistan tuonti ei onnistu" #: quodlibet/browsers/playlists/main.py:444 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:494 msgid "_Rename" msgstr "_Nimeä uudelleen" #: quodlibet/browsers/playlists/main.py:592 msgid "Unable to rename playlist" msgstr "Soittolistan uudelleennimeäminen ei onnistu" #: quodlibet/browsers/playlists/main.py:604 msgid "Import Playlist" msgstr "Tuo soittolista" #: quodlibet/browsers/playlists/main.py:604 msgid "_Import" msgstr "_Tuo" #: quodlibet/browsers/playlists/menu.py:25 msgid "_New Playlist…" msgstr "_Uusi soittolista…" #: quodlibet/browsers/playlists/menu.py:86 #, 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:90 #, 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:33 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "Haluatko varmasti poistaa soittolistan ”%s”?" #: quodlibet/browsers/playlists/util.py:35 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:50 #: quodlibet/browsers/playlists/util.py:125 quodlibet/util/collection.py:575 msgid "New Playlist" msgstr "Uusi soittolista" #: quodlibet/browsers/playlists/util.py:51 msgid "Enter a name for the new playlist:" msgstr "Anna uuden soittolistan nimi:" #: quodlibet/browsers/playlists/util.py:89 #, 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/search.py:32 msgid "_Limit Results" msgstr "Rajoita tulosten _määrää" #: quodlibet/browsers/search.py:37 msgid "_Allow multiple queries" msgstr "_Salli useampi hakukysely" #: quodlibet/browsers/search.py:53 msgid "Search Library" msgstr "Hae kirjastosta" #: quodlibet/browsers/search.py:54 msgid "_Search Library" msgstr "_Hae kirjastosta" #: quodlibet/browsers/soundcloud/main.py:39 msgid "Soundcloud Browser" msgstr "Soundcloud-selain" #: quodlibet/browsers/soundcloud/main.py:40 msgid "Sound_cloud" msgstr "Sound_cloud" #: quodlibet/browsers/soundcloud/main.py:60 quodlibet/qltk/searchbar.py:81 msgid "Search" msgstr "Hae" #: quodlibet/browsers/soundcloud/main.py:69 msgid "My tracks" msgstr "Omat raidat" #: quodlibet/browsers/soundcloud/main.py:141 #, python-format msgid "Go to %s" msgstr "Siirry osoitteeseen %s" #: quodlibet/browsers/soundcloud/main.py:443 msgid "Connected" msgstr "Yhdistetty" #: quodlibet/browsers/soundcloud/main.py:444 #, python-format msgid "Quod Libet is now connected, <b>%s</b>!" msgstr "Quod Libet on nyt muodostanut yhteyden, <b>%s</b>!" #: quodlibet/browsers/soundcloud/main.py:456 #, python-format msgid "Log out of %s" msgstr "Kirjaudu ulos palvelusta %s" #: quodlibet/browsers/soundcloud/main.py:458 msgid "Enter code…" msgstr "Anna koodi…" #: quodlibet/browsers/soundcloud/main.py:459 #, python-format msgid "Log in to %s" msgstr "Kirjaudu palveluun %s" #: quodlibet/browsers/soundcloud/util.py:86 msgid "Soundcloud authorisation" msgstr "Soundcloud-valtuutus" #: quodlibet/browsers/soundcloud/util.py:87 msgid "Enter Soundcloud auth code:" msgstr "Anna Soundcloud-valtuutuskoodi:" #: quodlibet/cli.py:50 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:86 msgid "a music library and player" msgstr "musiikkikirjasto ja toistin" #: quodlibet/cli.py:87 msgid "[option]" msgstr "[valitsin]" #: quodlibet/cli.py:89 msgid "Print the playing song and exit" msgstr "Tulosta soiva kappale ja poistu" #: quodlibet/cli.py:90 msgid "Begin playing immediately" msgstr "Aloita toisto välittömästi" #: quodlibet/cli.py:91 msgid "Don't show any windows on start" msgstr "Älä avaa ikkunoita käynnistyksen yhteydessä" #: quodlibet/cli.py:94 msgid "Jump to next song" msgstr "Hyppää seuraavaan kappaleeseen" #: quodlibet/cli.py:96 msgid "Jump to previous song or restart if near the beginning" msgstr "Hyppää edelliseen kappaleeseen tai nykyisen alkuun" #: quodlibet/cli.py:97 msgid "Jump to previous song" msgstr "Hyppää edelliseen kappaleeseen" #: quodlibet/cli.py:98 msgid "Start playback" msgstr "Aloita toisto" #: quodlibet/cli.py:99 msgid "Pause playback" msgstr "Keskeytä toisto" #: quodlibet/cli.py:100 msgid "Toggle play/pause mode" msgstr "Keskeytä toisto tai jatka sitä" #: quodlibet/cli.py:101 msgid "Stop playback" msgstr "Pysäytä toisto" #: quodlibet/cli.py:102 msgid "Turn up volume" msgstr "Lisää äänenvoimakkuutta" #: quodlibet/cli.py:103 msgid "Turn down volume" msgstr "Vähennä äänenvoimakkuutta" #: quodlibet/cli.py:104 msgid "Increase rating of playing song by one star" msgstr "Nosta soivan kappaleen arvosanaa yhdellä tähdellä" #: quodlibet/cli.py:105 msgid "Decrease rating of playing song by one star" msgstr "Laske soivan kappaleen arvosanaa yhdellä tähdellä" #: quodlibet/cli.py:106 msgid "Print player status" msgstr "Tulosta toistimen tila" #: quodlibet/cli.py:107 msgid "Hide main window" msgstr "Piilota pääikkuna" #: quodlibet/cli.py:108 msgid "Show main window" msgstr "Näytä pääikkuna" #: quodlibet/cli.py:109 msgid "Toggle main window visibility" msgstr "Piilota tai näytä pääikkuna" #: quodlibet/cli.py:110 msgid "Focus the running player" msgstr "Kohdista käynnissä olevaan toistimeen" #: quodlibet/cli.py:111 msgid "Remove active browser filters" msgstr "Poista aktiiviset selainsuodattimet" #: quodlibet/cli.py:112 msgid "Refresh and rescan library" msgstr "_Päivitä kirjasto" #: quodlibet/cli.py:113 msgid "List available browsers" msgstr "Listaa käytettävissä olevat selaimet" #: quodlibet/cli.py:114 msgid "Print the current playlist" msgstr "Tulosta nykyinen soittolista" #: quodlibet/cli.py:115 msgid "Print the contents of the queue" msgstr "Tulosta jonon sisältö" #: quodlibet/cli.py:116 msgid "Print the active text query" msgstr "Tulosta aktiivinen hakukysely" #: quodlibet/cli.py:117 msgid "Start without plugins" msgstr "Käynnistä ilman liitännäisiä" #: quodlibet/cli.py:118 msgid "Start Quod Libet if it isn't running" msgstr "Käynnistä Quod Libet jos se ei ole jo käynnissä" #: quodlibet/cli.py:119 msgid "Exit Quod Libet" msgstr "Poistu Quod Libetistä" #: quodlibet/cli.py:124 msgid "Seek within the playing song" msgstr "Siirry toistettavassa kappaleessa" #: quodlibet/cli.py:124 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: quodlibet/cli.py:125 msgid "Set or toggle shuffle mode" msgstr "Aseta sekoitustila tai vaihda sen tilaa" #: quodlibet/cli.py:126 msgid "Set shuffle mode type" msgstr "Aseta sekoituksen tyyppi" #: quodlibet/cli.py:127 msgid "Turn repeat off, on, or toggle it" msgstr "Aseta kertaus päälle, pois, tai vaihda sen tilaa" #: quodlibet/cli.py:128 msgid "Set repeat mode type" msgstr "Aseta kertauksen tyyppi" #: quodlibet/cli.py:129 msgid "Set the volume" msgstr "Aseta äänenvoimakkuus" #: quodlibet/cli.py:130 msgid "Search your audio library" msgstr "Hae äänikirjastosta" #: quodlibet/cli.py:130 quodlibet/cli.py:140 quodlibet/cli.py:144 #: quodlibet/cli.py:146 msgid "query" msgstr "kysely" #: quodlibet/cli.py:131 msgid "Play a file" msgstr "Toista tiedosto" #: quodlibet/cli.py:131 quodlibet/cli.py:140 quodlibet/cli.py:146 msgctxt "command" msgid "filename" msgstr "tiedostonimi" #: quodlibet/cli.py:132 msgid "Set rating of playing song" msgstr "Aseta toistettavan kappaleen arvosana" #: quodlibet/cli.py:133 msgid "Set the current browser" msgstr "Valitse nykyinen selain" #: quodlibet/cli.py:134 msgid "Stop after the playing song" msgstr "Pysäytä soivan kappaleen jälkeen" #: quodlibet/cli.py:135 msgid "Open a new browser" msgstr "Avaa uusi selain" #: quodlibet/cli.py:136 msgid "Show or hide the queue" msgstr "Näytä tai piilota jono" #: quodlibet/cli.py:137 msgid "Filter on a random value" msgstr "Suodata satunnaisen arvon perusteella" #: quodlibet/cli.py:137 msgctxt "command" msgid "tag" msgstr "tunniste" #: quodlibet/cli.py:138 msgid "Filter on a tag value" msgstr "Suodata tunnisteen arvon perusteella" #: quodlibet/cli.py:138 msgid "tag=value" msgstr "tunniste=arvo" #: quodlibet/cli.py:139 msgid "Enqueue a file or query" msgstr "Lisää tiedosto tai kysely jonoon" #: quodlibet/cli.py:141 msgid "Enqueue comma-separated files" msgstr "Lisää jonoon pilkulla erotellut tiedostot" #: quodlibet/cli.py:142 quodlibet/util/tags.py:157 msgid "filename" msgstr "tiedostonimi" #: quodlibet/cli.py:143 msgid "Print filenames of results of query to stdout" msgstr "Tulosta kyselyn tulosten tiedostonimet stdout:iin" #: quodlibet/cli.py:145 msgid "Unqueue a file or query" msgstr "Poista tiedosto tai kysely jonosta" #: quodlibet/cli.py:147 msgid "Add a file or directory to the library" msgstr "Lisää tiedosto tai kansio kirjastoon" #: quodlibet/cli.py:148 quodlibet/util/tags.py:100 msgid "location" msgstr "sijainti" #: quodlibet/cli.py:213 #, python-format msgid "Invalid argument for '%s'." msgstr "Virheellinen argumentti valitsimelle %s." #: quodlibet/cli.py:214 quodlibet/util/__init__.py:173 #, 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 "Quit Program" msgstr "Poistu ohjelmasta" #: 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:34 msgid "an audio tag editor" msgstr "äänitiedostojen tunniste-editori" #: quodlibet/exfalso.py:34 quodlibet/util/tags.py:158 msgid "directory" msgstr "kansio" #: quodlibet/exfalso.py:41 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:20 msgid "" "Downloads covers linked to by the artwork_url tag. This works with the " "Soundcloud browser." msgstr "" "Lataa kansikuva kappaleen artwork_url-tunnisteessa määritetystä osoitteesta. " "Toimii Soundcloud-selaimen 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:20 msgid "MusicBrainz Cover Source" msgstr "MusicBrainz-kansikuvalähde" #: quodlibet/ext/covers/musicbrainz.py:21 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:19 msgid "" "Allows arbitrary regex substitutions (s///) when tagging or renaming files." msgstr "" "Mahdollistaa säännöllisten lausekkeiden korvausoperaation (s///) 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:68 msgid "Advanced Preferences" msgstr "Lisäasetukset" #: quodlibet/ext/events/advanced_preferences.py:69 msgid "Allow editing of advanced config settings." msgstr "Muokkaa lisäasetuksia." #: quodlibet/ext/events/advanced_preferences.py:187 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/ext/events/weblyrics.py:318 quodlibet/qltk/prefs.py:266 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:66 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:172 msgid "Effects" msgstr "Tehosteet" #: quodlibet/ext/events/animosd/prefs.py:288 msgid "Ed_it Display Pattern…" msgstr "_Muokkaa näkymää…" #: quodlibet/ext/events/animosd/prefs.py:292 #: 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_library_update.py:138 msgid "Automatic Library Update" msgstr "Automaattinen kirjaston päivitys" #: quodlibet/ext/events/auto_library_update.py:139 #, 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." #: 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 by Brian Nelson." msgstr "" "Arvostelee kappaleita automaattisesti kun ne toistetaan tai ohitetaan. " "Käyttää accelerated-algoritmia ohjelmasta vux, jonka on kehittänyt Brian " "Nelson." #: quodlibet/ext/events/bansheeimport.py:106 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:111 #: quodlibet/ext/events/rbimport.py:114 msgid "Import Failed" msgstr "Tuonti epäonnistui" #: quodlibet/ext/events/bansheeimport.py:117 #, 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:126 msgid "Banshee Import" msgstr "Banshee-tuonti" #: quodlibet/ext/events/bansheeimport.py:127 msgid "Imports ratings and song statistics from Banshee." msgstr "Tuo arvosanat ja kappaletilastot Banshee-ohjelmasta." #: quodlibet/ext/events/bansheeimport.py:136 msgid "_Database path:" msgstr "_Tietokannan polku:" #: quodlibet/ext/events/bansheeimport.py:164 #: quodlibet/ext/events/rbimport.py:132 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/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:93 #: quodlibet/ext/gstreamer/karaoke.py:95 #, python-format msgid "%d Hz" msgstr "%d Hz" #: quodlibet/ext/events/equalizer.py:198 #: quodlibet/ext/gstreamer/crossfeed.py:112 #, 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/playlist/export_to_squeezebox.py:80 #: quodlibet/ext/songsmenu/albumart.py:324 #: quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/cover_download.py:309 #: quodlibet/ext/songsmenu/fingerprint/search.py:278 #: quodlibet/ext/songsmenu/html.py:75 quodlibet/ext/songsmenu/lastfmsync.py:219 #: quodlibet/ext/songsmenu/playlist.py:51 #: quodlibet/ext/songsmenu/replaygain.py:354 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/_editutils.py:40 #: quodlibet/qltk/lyrics.py:34 quodlibet/qltk/msg.py:52 #: quodlibet/qltk/renamefiles.py:216 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 "away" #: 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 "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:42 msgid "Inhibit Screensaver" msgstr "Estä näytönsäästäjä" #: quodlibet/ext/events/inhibit.py:43 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ä." #: quodlibet/ext/events/inhibit.py:52 msgid "Music is playing" msgstr "Musiikin toisto käynnissä" #: quodlibet/ext/events/iradiolog.py:16 msgid "Internet Radio Log" msgstr "Internet-radioloki" #: quodlibet/ext/events/iradiolog.py:17 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:31 msgid "Outputs a Jabber User Tunes file to ~/.quodlibet/jabber." msgstr "Kirjoittaa Jabber User Tunes -tiedoston polkuun ~/.quodlibet/jabber." #: 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 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:37 msgid "MPRIS D-Bus Support" msgstr "MPRIS D-Bus -tuki" #: quodlibet/ext/events/mpris/__init__.py:38 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ä." #: quodlibet/ext/events/mpris/__init__.py:44 #: quodlibet/ext/events/trayicon/prefs.py:36 msgid "Hide main window on close" msgstr "Piilota pääikkuna kun se suljetaan" #: quodlibet/ext/events/mpris/__init__.py:47 #: quodlibet/ext/events/themeswitcher.py:84 #: quodlibet/ext/gstreamer/compressor.py:99 #: quodlibet/ext/gstreamer/crossfeed.py:136 #: quodlibet/ext/gstreamer/karaoke.py:99 quodlibet/ext/gstreamer/pitch.py:89 #: quodlibet/qltk/prefs.py:741 msgid "Preferences" msgstr "Asetukset" #: quodlibet/ext/events/mqtt.py:54 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "Hyväksyy QL-kaavat, esim. %s" #: quodlibet/ext/events/mqtt.py:60 msgid "MQTT Publisher" msgstr "MQTT-julkaisija" #: quodlibet/ext/events/mqtt.py:61 msgid "Publishes status messages to an MQTT topic." msgstr "Julkaisee tilaviestejä MQTT-aiheeseen." #: quodlibet/ext/events/mqtt.py:128 msgid "Broker hostname" msgstr "Välittäjän verkko-osoite" #: quodlibet/ext/events/mqtt.py:129 msgid "broker hostname / IP (defaults to localhost)" msgstr "välittäjän verkko-osoite / IP (oletuksena localhost)" #: quodlibet/ext/events/mqtt.py:131 msgid "Broker port" msgstr "Välittäjän portti" #: quodlibet/ext/events/mqtt.py:131 msgid "broker port (defaults to 1883)" msgstr "välittäjän portti (oletus: 1883)" #: quodlibet/ext/events/mqtt.py:133 msgid "Topic" msgstr "Aihe" #: quodlibet/ext/events/mqtt.py:135 msgid "Playing Pattern" msgstr "Toiston tilaviestikaava" #: quodlibet/ext/events/mqtt.py:137 msgid "Status text when a song is started." msgstr "Tilaviesti, kun kappaleen toisto alkaa." #: quodlibet/ext/events/mqtt.py:139 msgid "Paused Pattern" msgstr "Keskeytyksen tilaviestikaava" #: quodlibet/ext/events/mqtt.py:141 msgid "Text when a song is paused." msgstr "Tilaviesti, kun kappaleen toisto keskeytetään." #: quodlibet/ext/events/mqtt.py:143 msgid "No-song Text" msgstr "Ei kappaletta -teksti" #: quodlibet/ext/events/mqtt.py:145 msgid "Plain text for when there is no current song" msgstr "Teksti, kun toistettavaa kappaletta ei ole" #: quodlibet/ext/events/mqtt.py:156 msgid "MQTT Configuration" msgstr "MQTT-asetukset" #: quodlibet/ext/events/mqtt.py:160 msgid "Status Text" msgstr "Tilaviestit" #: quodlibet/ext/events/mqtt.py:192 #, 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:196 #, 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:199 msgid "Connection error" msgstr "Yhteysvirhe" #: 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 "Aina 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/qlscrobbler.py:175 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:252 #, python-format msgid "Could not contact service '%s'." msgstr "Palveluun %s ei saatu yhteyttä." #: quodlibet/ext/events/qlscrobbler.py:258 msgid "Authentication failed: invalid URL." msgstr "Todennus epäonnistui: virheellinen URL." #: quodlibet/ext/events/qlscrobbler.py:275 #, 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:280 msgid "Client is banned. Contact the author." msgstr "Asiakasohjelma on estetty. Ota yhteyttä tämän ohjelman tekijään." #: quodlibet/ext/events/qlscrobbler.py:284 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:349 msgid "AudioScrobbler Submission" msgstr "AudioScrobbler-lähetys" #: quodlibet/ext/events/qlscrobbler.py:350 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:455 msgid "Authentication successful." msgstr "Todennus onnistui." #: quodlibet/ext/events/qlscrobbler.py:467 msgid "_Service:" msgstr "_Palvelu:" #: quodlibet/ext/events/qlscrobbler.py:467 msgid "_URL:" msgstr "_URL:" #: quodlibet/ext/events/qlscrobbler.py:467 msgid "User_name:" msgstr "_Käyttäjänimi:" #: quodlibet/ext/events/qlscrobbler.py:468 msgid "_Password:" msgstr "_Salasana:" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:484 msgid "Other…" msgstr "Muu…" #. verify data #: quodlibet/ext/events/qlscrobbler.py:522 msgid "_Verify account data" msgstr "_Testaa tilitiedot" #: quodlibet/ext/events/qlscrobbler.py:527 #: quodlibet/ext/songsmenu/lastfmsync.py:312 msgid "Account" msgstr "Tili" #: quodlibet/ext/events/qlscrobbler.py:535 msgid "_Artist pattern:" msgstr "Kaava _artistille:" #: quodlibet/ext/events/qlscrobbler.py:535 msgid "_Title pattern:" msgstr "Kaava kappale_nimelle:" #: quodlibet/ext/events/qlscrobbler.py:536 msgid "Exclude _filter:" msgstr "Poissulkeva _suodatin:" #: quodlibet/ext/events/qlscrobbler.py:554 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:564 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:573 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:581 msgid "_Offline mode (don't submit anything)" msgstr "_Yhteydetön tila (älä lähetä mitään)" #: quodlibet/ext/events/qlscrobbler.py:585 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:28 msgid "Random Album Playback" msgstr "Satunnaisen albumin toisto" #: quodlibet/ext/events/randomalbum.py:29 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:39 msgid "Rated higher" msgstr "Parempi arvosana" #: quodlibet/ext/events/randomalbum.py:40 msgid "Played more often" msgstr "Toistettu useammin" #: quodlibet/ext/events/randomalbum.py:41 msgid "Skipped more often" msgstr "Ohitettu useammin" #: quodlibet/ext/events/randomalbum.py:42 msgid "Played more recently" msgstr "Toistettu äskettäin" #: quodlibet/ext/events/randomalbum.py:43 msgid "Started more recently" msgstr "Toisto aloitettu äskettäin" #: quodlibet/ext/events/randomalbum.py:44 msgid "Added more recently" msgstr "Lisätty äskettäin" #: quodlibet/ext/events/randomalbum.py:45 msgid "Longer albums" msgstr "Pidemmät albumit" #: quodlibet/ext/events/randomalbum.py:84 msgid "seconds before starting next album" msgstr "sekuntia ennen seuraavan albumin aloittamista" #: quodlibet/ext/events/randomalbum.py:88 msgid "Weights" msgstr "Painoarvot" #: quodlibet/ext/events/randomalbum.py:90 msgid "Play some albums more than others" msgstr "Toista joitakin albumeita toisia useammin" #: quodlibet/ext/events/randomalbum.py:104 msgid "avoid" msgstr "vältä" #: quodlibet/ext/events/randomalbum.py:115 msgid "prefer" msgstr "suosi" #: quodlibet/ext/events/randomalbum.py:219 msgid "Random Album" msgstr "Satunnainen alb_umi" #: quodlibet/ext/events/randomalbum.py:220 #, python-format msgid "Waiting to start %s" msgstr "Odotetaan albumin %s toiston alkamista" #: quodlibet/ext/events/rbimport.py:119 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "Arvosanat ja tilastot tuotiin onnistuneesti %d kappaleelle" #: quodlibet/ext/events/rbimport.py:127 msgid "Rhythmbox Import" msgstr "Rhythmbox-tuonti" #: quodlibet/ext/events/rbimport.py:128 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:73 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "Ei asennettua GNOME Shell -hakupalveluntarjoajaa Quod Libetille." #: quodlibet/ext/events/searchprovider.py:79 msgid "GNOME Search Provider" msgstr "GNOME-hakupalveluntarjoaja" #: quodlibet/ext/events/searchprovider.py:80 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" "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" "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:29 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:57 #: quodlibet/ext/playlist/export_to_squeezebox.py:89 msgid "Error finding Squeezebox server" msgstr "Virhe Squeezebox-palvelimen löytämisessä" #: quodlibet/ext/events/squeezebox_sync.py:58 #: quodlibet/ext/playlist/export_to_squeezebox.py:90 #, python-format msgid "Error finding %s. Please check settings" msgstr "Virhe kohteen %s löytämisessä. Tarkista asetukset." #: quodlibet/ext/events/synchronizedlyrics.py:34 msgid "Synchronized Lyrics" msgstr "Tahdistetut sanoitukset" #: quodlibet/ext/events/synchronizedlyrics.py:35 msgid "Shows synchronized lyrics from .lrc file with same name as the track." msgstr "" "Näyttää tahdistetut sanoitukset .lrc-tiedostosta, jonka nimi vastaa " "kappaleen tiedostonimeä." #: quodlibet/ext/events/synchronizedlyrics.py:69 msgid "Text:" msgstr "Teksti:" #: quodlibet/ext/events/synchronizedlyrics.py:79 msgid "Background:" msgstr "Tausta:" #: quodlibet/ext/events/synchronizedlyrics.py:90 msgid "Font" msgstr "Fontti" #: quodlibet/ext/events/synchronizedlyrics.py:93 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:145 msgid "Paused:" msgstr "Keskeytetty:" #: quodlibet/ext/events/telepathy_status.py:146 #, 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:162 msgid "Plain text for status when there is no current song" msgstr "Tilateksti, kun toistettavaa kappaletta ei ole" #: quodlibet/ext/events/telepathy_status.py:163 msgid "No song:" msgstr "Ei kappaletta:" #. Frame #: quodlibet/ext/events/telepathy_status.py:170 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:91 msgid "Thumb Rating" msgstr "Peukkuarvostelu" #: quodlibet/ext/events/thumbrating.py:92 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 '~#score'." 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 '~#score'-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:47 msgid "Not playing" msgstr "Toisto pysäytetty" #: quodlibet/ext/events/trayicon/__init__.py:53 msgid "Tray Icon" msgstr "Ilmaisinalueen kuvake" #: quodlibet/ext/events/trayicon/__init__.py:54 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:183 quodlibet/qltk/quodlibetwindow.py:936 #: quodlibet/qltk/quodlibetwindow.py:1142 msgid "_Play" msgstr "_Toista" #: quodlibet/ext/events/trayicon/menu.py:63 #: quodlibet/qltk/quodlibetwindow.py:185 quodlibet/qltk/quodlibetwindow.py:1144 #: quodlibet/qltk/wlw.py:50 msgid "P_ause" msgstr "_Keskeytä" #: quodlibet/ext/events/trayicon/menu.py:68 #: quodlibet/qltk/quodlibetwindow.py:190 quodlibet/qltk/quodlibetwindow.py:931 msgid "Pre_vious" msgstr "_Edellinen" #: quodlibet/ext/events/trayicon/menu.py:71 #: quodlibet/qltk/quodlibetwindow.py:194 quodlibet/qltk/quodlibetwindow.py:941 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:902 msgid "Open _Browser" msgstr "Avaa _selain" #: quodlibet/ext/events/trayicon/menu.py:103 #: quodlibet/qltk/quodlibetwindow.py:921 quodlibet/qltk/songsmenu.py:383 msgid "Edit _Tags" msgstr "Muokkaa t_unnisteita" #: quodlibet/ext/events/trayicon/menu.py:112 #: quodlibet/qltk/quodlibetwindow.py:864 quodlibet/qltk/songsmenu.py:396 msgid "_Information" msgstr "T_iedot" #: quodlibet/ext/events/trayicon/menu.py:114 quodlibet/qltk/songsmenu.py:324 msgid "Play_lists" msgstr "Soitto_listat" #: quodlibet/ext/events/trayicon/menu.py:132 #: quodlibet/qltk/quodlibetwindow.py:916 msgid "_Quit" msgstr "_Lopeta" #: quodlibet/ext/events/trayicon/prefs.py:38 quodlibet/qltk/prefs.py:69 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 "Kappaleelle %s ei löydy sanoja" #: quodlibet/ext/events/viewlyrics.py:117 quodlibet/ext/events/weblyrics.py:193 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:603 msgid "Waveform Seek Bar" msgstr "Aaltomuoto-aikasiirtymäpalkki" #: quodlibet/ext/events/waveformseekbar.py:607 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:676 msgid "Override foreground color:" msgstr "Edustaväri:" #: quodlibet/ext/events/waveformseekbar.py:680 msgid "Override hover color:" msgstr "Väri osoitettaessa:" #: quodlibet/ext/events/waveformseekbar.py:684 msgid "Override remaining color:" msgstr "Jäljellä olevan osan väri:" #: quodlibet/ext/events/waveformseekbar.py:688 msgid "Show current position" msgstr "Näytä nykyinen sijainti" #: quodlibet/ext/events/waveformseekbar.py:693 msgid "Show time labels" msgstr "Näytä aikatiedot" #: quodlibet/ext/events/waveformseekbar.py:701 msgid "Seek amount when scrolling (milliseconds):" msgstr "Aikasiirtymä vieritettäessä (millisekunteina):" #: quodlibet/ext/events/weblyrics.py:208 msgid "No lyrics found" msgstr "Kappaleelle ei löydy sanoja" #: quodlibet/ext/events/weblyrics.py:268 msgid "_Zoom level:" msgstr "_Suurennuksen taso:" #: quodlibet/ext/events/weblyrics.py:286 msgid "URL:" msgstr "URL:" #: quodlibet/ext/events/weblyrics.py:291 msgid "Revert to default" msgstr "Palauta oletus" #: quodlibet/ext/events/weblyrics.py:306 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." #: quodlibet/ext/events/weblyrics.py:323 msgid "Alternate search" msgstr "Vaihtoehtoinen haku" #: quodlibet/ext/events/weblyrics.py:332 msgid "Web Lyrics" msgstr "Kappaleen sanat verkosta" #: quodlibet/ext/events/weblyrics.py:333 msgid "Shows a sidebar containing online lyrics of the playing song." msgstr "" "Näyttää sivupalkin, jossa on verkosta haetut toistettavan kappaleen sanat." #: 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:20 msgid "_Threshold:" msgstr "_Kompressointikynnys:" #: quodlibet/ext/gstreamer/compressor.py:21 msgid "Threshold until the filter is activated" msgstr "Kynnysarvo, jonka kohdalla suodatin otetaan käyttöön" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "R_atio:" msgstr "_Kompressointisuhde:" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "Compression ratio" msgstr "Kompressointisuhde" #: quodlibet/ext/gstreamer/compressor.py:74 #: quodlibet/ext/gstreamer/karaoke.py:91 #, python-format msgid "%d %%" msgstr "%d %%" #: quodlibet/ext/gstreamer/compressor.py:105 msgid "Audio Compressor" msgstr "Äänikompressori" #: quodlibet/ext/gstreamer/compressor.py:106 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:19 msgid "_Preset:" msgstr "_Esiasetus:" #: quodlibet/ext/gstreamer/crossfeed.py:19 msgid "Filter preset" msgstr "Suodattimen esiasetus" #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Frequency cut:" msgstr "_Rajataajuus:" #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Low-pass filter cut frequency" msgstr "Alipäästösuodattimen rajataajuus" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed _level:" msgstr "Syötön _taso:" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed level" msgstr "Syötön taso" #: quodlibet/ext/gstreamer/crossfeed.py:25 msgid "Default" msgstr "Oletus" #: quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "Lähimpänä virtuaalista kaiutinasettelua (30°, 3 metriä)" #: quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Chu Moy" msgstr "Chu Moy" #: quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "Muistuttaa Chu Moyn crossfeederiä (suosittu)" #: quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Jan Meier" msgstr "Jan Meier" #: quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "Muistuttaa Jan Meierin CORDA-vahtistimia (pieni muutos)" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Custom" msgstr "Mukautettu" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Custom settings" msgstr "Mukautettu" #: quodlibet/ext/gstreamer/crossfeed.py:152 msgid "Crossfeed" msgstr "Crossfeed" #: quodlibet/ext/gstreamer/crossfeed.py:153 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:20 msgid "Filter _band:" msgstr "Taajuuskaista:" #: quodlibet/ext/gstreamer/karaoke.py:21 msgid "The Frequency band of the filter" msgstr "Suodattimen taajuuskaista" #: quodlibet/ext/gstreamer/karaoke.py:22 msgid "Filter _width:" msgstr "Kaistanleveys:" #: quodlibet/ext/gstreamer/karaoke.py:23 msgid "The Frequency width of the filter" msgstr "Suodattimen kaistanleveys" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "_Level:" msgstr "_Taso:" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "Level of the effect" msgstr "Tehosteen taso" #: quodlibet/ext/gstreamer/karaoke.py:105 msgid "Karaoke" msgstr "Karaoke" #: quodlibet/ext/gstreamer/karaoke.py:106 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:21 msgid "R_ate:" msgstr "_Näytenopeus:" #: quodlibet/ext/gstreamer/pitch.py:22 msgid "_Tempo:" msgstr "_Tempo:" #: quodlibet/ext/gstreamer/pitch.py:23 msgid "_Pitch:" msgstr "_Sävelkorkeus:" #: quodlibet/ext/gstreamer/pitch.py:95 msgid "Audio Pitch / Speed" msgstr "Äänenkorkeus / toistonopeus" #: quodlibet/ext/gstreamer/pitch.py:96 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:147 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:100 msgid "Exports a playlist by copying files to a folder." msgstr "Vie soittolistan kopioimalla tiedostot kansioon." #: quodlibet/ext/playlist/export_to_folder.py:121 #: quodlibet/ext/songsmenu/playlist.py:132 msgid "Unable to export playlist" msgstr "Soittolistan vienti ei onnistu" #: quodlibet/ext/playlist/export_to_folder.py:122 msgid "Ensure you have write access to the destination." msgstr "Varmista, että kohteeseen on kirjoitusoikeus." #: quodlibet/ext/playlist/export_to_folder.py:165 msgid "Default filename pattern:" msgstr "Tiedostonimen oletuskaava:" #: 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. 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." #: 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:96 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 "" "Playback follows your selection, or the next song in the list once exhausted." msgstr "" "Toisto seuraa valittuja kappaleita, tai listassa seuraavana olevaa " "kappaletta kun kaikki valitut on toistettu." #: quodlibet/ext/playorder/playcounteq.py:21 msgid "Playcount Equalizer" msgstr "Toistokertojen tasaaja" #: quodlibet/ext/playorder/playcounteq.py:22 msgid "Shuffle, preferring songs with fewer total plays." msgstr "" "Toista satunnaisessa järjestyksessä suosien vähemmän toistettuja kappaleita." #: quodlibet/ext/playorder/playcounteq.py:24 msgid "Prefer less played" msgstr "Suosi vähemmän toistettuja" #: quodlibet/ext/playorder/queue.py:19 msgid "Queue Only" msgstr "Vain jono" #: quodlibet/ext/playorder/queue.py:21 msgid "" "Limits playing of songs to the queue. 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. Kun tämä on valittuna " "pääikkunassa, niin kappaleen kaksoisklikkaus lisää sen jonoon toistamisen " "sijaan." #: quodlibet/ext/playorder/reverse.py:14 msgid "Reverse" msgstr "Käänteinen järjestys" #: quodlibet/ext/playorder/reverse.py:16 msgid "Reverses the play order of songs." msgstr "Kääntää kappaleiden toistojärjestyksen." #: quodlibet/ext/playorder/shufflebygrouping.py:31 #: quodlibet/ext/playorder/shufflebygrouping.py:93 msgid "Shuffle by Grouping" msgstr "Sekoita ryhmittäen" #: quodlibet/ext/playorder/shufflebygrouping.py:32 msgid "" "Shuffles by a grouping of songs defined by a common tag instead of by track, " "similar to album shuffle. This is useful for shuffling multi-movement " "classical works while making sure all movements play in order before " "shuffling to the next piece." msgstr "" "Sekoittaa toistettavat kappaleet ryhmittämällä yhteisen tunnisteen omaavat " "kappaleet soimaan peräkkäin (samalla periaatteella kuin albumisekoitus). " "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:38 msgid "Shuffle by grouping" msgstr "Sekoita ryhmittäen" #: quodlibet/ext/playorder/shufflebygrouping.py:94 msgid "Waiting to start new group…" msgstr "Odotetaan uuden ryhmän toiston alkamista…" #: quodlibet/ext/playorder/shufflebygrouping.py:144 msgid "Grouping tag:" msgstr "Ryhmittävä tunniste:" #: quodlibet/ext/playorder/shufflebygrouping.py:148 msgid "Tag to group songs by" msgstr "Tunniste, jonka perusteella kappaleet ryhmitellään" #: quodlibet/ext/playorder/shufflebygrouping.py:150 msgid "Filter tag:" msgstr "Suodattava tunniste:" #: quodlibet/ext/playorder/shufflebygrouping.py:155 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:160 msgid "Delay:" msgstr "Viive:" #: quodlibet/ext/playorder/shufflebygrouping.py:166 msgid "Time delay in seconds before starting next group" msgstr "Viive (sekunneissa) ennen seuraavan ryhmän aloittamista" #: quodlibet/ext/playorder/shufflebygrouping.py:182 msgid "Reset to defaults" msgstr "Palauta oletukset" #: quodlibet/ext/playorder/skip_songs.py:25 msgid "Skip Songs" msgstr "Ohita kappaleet" #: quodlibet/ext/playorder/skip_songs.py:27 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." #: quodlibet/ext/playorder/track_repeat.py:30 msgid "Repeat Each Track" msgstr "Kertaa jokainen kappale" #: quodlibet/ext/playorder/track_repeat.py:32 msgid "Shuffle songs, but repeat every track a set number of times." msgstr "" "Toista kappaleet satunnaisessa järjestyksessä, mutta kertaa jokainen kappale " "tietty määrä kertoja." #: quodlibet/ext/playorder/track_repeat.py:51 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. Syntax is '@(if: " "condition, then, else)'." msgstr "" "Valitsee käytettävän kyselyn ehdollisen kyselyn pohjalta. Syntaksi: @(if: " "ehtolauseke, sitten-lauseke, muutoin-lauseke)." #: quodlibet/ext/query/missing.py:15 msgid "Missing Query" msgstr "Puuttuvan tunnisteen kysely" #: quodlibet/ext/query/missing.py:16 msgid "Matches songs without the given tag." msgstr "Täsmää kappaleisiin, joilla ei ole annettua tunnistetta." #: quodlibet/ext/query/missing.py:27 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. Syntax is '@(python: expression)'. The " "variable 's' (or 'a') is the song / album being matched. '_ts' is a (real " "number) timestamp at start of query. Modules 'time' and 'random' are also " "available, and the class 'Random' (==random.Random) too." msgstr "" "Käytä Python-lausekkeita kyselyissä. Syntaksi: @(python: lauseke). Muuttujat " "”s” ja ”a” ovat täsmäytettävä kappale ja albumi. ”_ts” on aikaleima kyselyn " "suorituksen alkaessa (reaalilukuna). Moduulit ”time” ja ”random” sekä luokka " "”Random” (eli random.Random) ovat myös käytettävissä." #: quodlibet/ext/query/savedsearch.py:19 msgid "Include Saved Search" msgstr "Sisällytä tallennettu haku" #: quodlibet/ext/query/savedsearch.py:20 msgid "" "Include the results of a saved search as part of another query. Syntax is " "'@(saved: search name)'." msgstr "" "Sisällytä tallennetun haun tulokset toiseen hakuun. Syntaksi: @(saved: haun " "nimi)." #: 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:116 msgid "Port:" msgstr "Portti:" #: quodlibet/ext/_shared/squeezebox/base.py:121 msgid "Username:" msgstr "Käyttäjänimi:" #: quodlibet/ext/_shared/squeezebox/base.py:126 msgid "Password:" msgstr "Salasana:" #: quodlibet/ext/_shared/squeezebox/base.py:130 msgid "Library directory the server connects to" msgstr "Kirjastokansio, johon palvelin kytkeytyy" #: quodlibet/ext/_shared/squeezebox/base.py:132 msgid "Library path:" msgstr "Kirjaston polku:" #. Add verify button #: quodlibet/ext/_shared/squeezebox/base.py:141 msgid "_Verify settings" msgstr "_Tarkista asetukset" #. Server settings Frame #: quodlibet/ext/_shared/squeezebox/base.py:147 msgid "Squeezebox Server" msgstr "Squeezebox-palvelin" #: quodlibet/ext/_shared/squeezebox/base.py:150 msgid "Debug" msgstr "Virheenpaikannus" #: quodlibet/ext/_shared/squeezebox/server.py:26 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "Squeezebox-palvelin osoitteessa {hostname}:{port}" #: quodlibet/ext/_shared/squeezebox/server.py:28 msgid "unidentified Squeezebox server" msgstr "tunnistamaton Squeezebox-palvelin" #: quodlibet/ext/_shared/squeezebox/server.py:37 #, 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:20 #: quodlibet/ext/songsmenu/importexport.py:39 quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "_OK" #: 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:331 msgid "Fit image to _window" msgstr "Sovita kuva ikkunaan" #: quodlibet/ext/songsmenu/albumart.py:337 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:343 msgid "_Program:" msgstr "_Ohjelma:" #: quodlibet/ext/songsmenu/albumart.py:348 msgid "_Edit image after saving" msgstr "_Muokkaa kuvaa tallennuksen jälkeen" #: quodlibet/ext/songsmenu/albumart.py:350 msgid "File_name:" msgstr "_Tiedostonimi:" #: quodlibet/ext/songsmenu/albumart.py:466 msgid "Saving failed" msgstr "Tallennus epäonnistui" #: quodlibet/ext/songsmenu/albumart.py:467 #, python-format msgid "Unable to save \"%s\"." msgstr "Kohdetta ”%s” ei voitu tallentaa." #: quodlibet/ext/songsmenu/albumart.py:565 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "[albumart] HTTP-virhe: %s" #: quodlibet/ext/songsmenu/albumart.py:622 msgid "Album Art Downloader" msgstr "Albumin kansikuvien lataaja" #: quodlibet/ext/songsmenu/albumart.py:675 #, python-format msgid "from %(source)s" msgstr "lähteestä %(source)s" #: quodlibet/ext/songsmenu/albumart.py:678 #, python-format msgid "Resolution: %s" msgstr "Resoluutio: %s" #: quodlibet/ext/songsmenu/albumart.py:681 #, python-format msgid "Size: %s" msgstr "Koko: %s" #: quodlibet/ext/songsmenu/albumart.py:727 msgid "Per engine 'at best' results limit" msgstr "Palvelukohtainen parhaiden tulosten määrän rajoitus" #: quodlibet/ext/songsmenu/albumart.py:737 msgid "_Search" msgstr "_Hae" #: quodlibet/ext/songsmenu/albumart.py:819 #: quodlibet/ext/songsmenu/brainz/widgets.py:451 msgid "Searching…" msgstr "Haetaan…" #: quodlibet/ext/songsmenu/albumart.py:884 #: quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "Valmis" #: quodlibet/ext/songsmenu/albumart.py:1006 msgid "Download Album Art" msgstr "Lataa albumien kansikuvia" #: quodlibet/ext/songsmenu/albumart.py:1007 msgid "Downloads album covers from various websites." msgstr "Lataa albumien kansikuvia eri verkkosivuilta." #: quodlibet/ext/songsmenu/albumart.py:1020 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 msgid "Disc" msgstr "Levy" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 #: quodlibet/ext/songsmenu/replaygain.py:393 quodlibet/qltk/tracknumbers.py:91 msgid "Track" msgstr "Raita" #: quodlibet/ext/songsmenu/brainz/widgets.py:132 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:447 msgid "Please enter a query." msgstr "Anna haku." #: quodlibet/ext/songsmenu/brainz/widgets.py:465 #: quodlibet/ext/songsmenu/brainz/widgets.py:496 msgid "Error encountered. Please retry." msgstr "Virhetilanne, yritä uudelleen." #: quodlibet/ext/songsmenu/brainz/widgets.py:472 #: quodlibet/ext/songsmenu/brainz/widgets.py:488 msgid "Loading result…" msgstr "Ladataan tuloksia…" #: quodlibet/ext/songsmenu/brainz/widgets.py:475 msgid "No results found." msgstr "Tuloksia ei löytynyt." #: quodlibet/ext/songsmenu/console.py:40 msgid "Python Console" msgstr "Python-konsoli" #: quodlibet/ext/songsmenu/console.py:41 msgid "Interactive Python console. Opens a new window." msgstr "Interaktiivinen Python-konsoli. Avaa uuden ikkunan." #: quodlibet/ext/songsmenu/console.py:48 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "{plugin_name} - {songs} valittuna ({app})" #: quodlibet/ext/songsmenu/console.py:55 msgid "Python Console Sidebar" msgstr "Python-konsoli (sivupalkki)" #: quodlibet/ext/songsmenu/console.py:56 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:75 msgid "You can access the following objects by default:" msgstr "Seuraavat objektit ovat käytössä oletuksena:" #: quodlibet/ext/songsmenu/console.py:85 msgid "Your current working directory is:" msgstr "Nykyinen työhakemisto:" #: quodlibet/ext/songsmenu/cover_download.py:119 msgid "Classic" msgstr "Normaali" #: quodlibet/ext/songsmenu/cover_download.py:120 msgid "Large" msgstr "Suuri" #: quodlibet/ext/songsmenu/cover_download.py:121 msgid "HD" msgstr "HD" #: quodlibet/ext/songsmenu/cover_download.py:122 msgid "Full HD" msgstr "Full HD" #: quodlibet/ext/songsmenu/cover_download.py:123 msgid "WQXGA" msgstr "WQXGA" #: quodlibet/ext/songsmenu/cover_download.py:124 msgid "4K UHD" msgstr "4K UHD" #: quodlibet/ext/songsmenu/cover_download.py:129 msgid "Cover Art Download" msgstr "Kansikuvien lataaja" #: quodlibet/ext/songsmenu/cover_download.py:180 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "Ladataan %(source)s - %(dimensions)s…" #: quodlibet/ext/songsmenu/cover_download.py:231 #, python-format msgid "" "Nothing found for albums:\n" "<i>%(albums)s</i>.\n" "\n" "Providers used:\n" "<tt>%(providers)s</tt>" msgstr "" "Kansikuvia ei löytynyt albumeille:\n" "<i>%(albums)s</i>.\n" "\n" "Käytetyt lähteet:\n" "<tt>%(providers)s</tt>" #: quodlibet/ext/songsmenu/cover_download.py:234 msgid "No covers found" msgstr "Ei löydettyjä kansikuvia" #: quodlibet/ext/songsmenu/cover_download.py:254 #, python-format msgid "%(size)d ✕ %(size)d px" msgstr "%(size)d ✕ %(size)d px" #: quodlibet/ext/songsmenu/cover_download.py:267 msgid "Preview size" msgstr "Esikatselukuvan koko" #: quodlibet/ext/songsmenu/cover_download.py:276 msgid "Save destination" msgstr "Tallennuskohde" #: quodlibet/ext/songsmenu/cover_download.py:336 msgid "Download Cover Art" msgstr "Lataa kansikuvia" #: quodlibet/ext/songsmenu/cover_download.py:337 msgid "Downloads high-quality album covers using cover plugins." msgstr "Lataa korkealaatuisia albumikansikuvia kansikuvalisäosien avulla." #: 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:55 msgid "pattern" msgstr "kaava" #: 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:91 msgid "Input value" msgstr "Anna arvo" #: quodlibet/ext/songsmenu/custom_commands.py:92 #, python-format msgid "Value for %s?" msgstr "Arvo parametrille %s?" #: quodlibet/ext/songsmenu/custom_commands.py:137 msgid "Custom Commands" msgstr "Mukautetut komennot" #: quodlibet/ext/songsmenu/custom_commands.py:138 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:197 #: quodlibet/ext/songsmenu/custom_commands.py:207 #: quodlibet/ext/songsmenu/custom_commands.py:259 msgid "Edit Custom Commands" msgstr "Muokkaa mukautettuja komentoja" #: quodlibet/ext/songsmenu/custom_commands.py:290 #, 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:397 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:399 msgid "_Group duplicates by:" msgstr "_Kaksoiskappaleet ryhmittelevä ehto:" #: quodlibet/ext/songsmenu/duplicates.py:404 msgid "Duplicate Key" msgstr "Kaksoiskappaleavain" #: quodlibet/ext/songsmenu/duplicates.py:409 msgid "Remove _Whitespace" msgstr "Jätä tyhjämerkit huomioimatta" #: quodlibet/ext/songsmenu/duplicates.py:410 msgid "Remove _Diacritics" msgstr "Jätä tarkemerkit huomioimatta" #: quodlibet/ext/songsmenu/duplicates.py:411 msgid "Remove _Punctuation" msgstr "Jätä välimerkit huomioimatta" #: quodlibet/ext/songsmenu/duplicates.py:412 msgid "Case _Insensitive" msgstr "Jätä kirjainkoko huomioimatta" #: quodlibet/ext/songsmenu/duplicates.py:420 msgid "Matching options" msgstr "Täsmäytyksen säännöt" #. Create a dialog. #: quodlibet/ext/songsmenu/editplaycount.py:19 #: quodlibet/ext/songsmenu/editplaycount.py:41 msgid "Edit Playcount" msgstr "Toistomäärän muokkaus" #: quodlibet/ext/songsmenu/editplaycount.py:20 msgid "" "Edit a song's ~#playcount and ~#skipcount.\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's ~#playcount to 0, the ~#lastplayed and ~#laststarted " "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ää (~#playcount ja " "~#skipcount).\n" "\n" "Useamman kappaleen ollessa valittuna lukuja kasvatetaan / pienennetään " "asettamisen sijaan.\n" "\n" "Jos kappaleen toistokertamääräksi (~#playcount) asetetaan 0, ~#lastplayed " "(viimeksi toistettu) ja ~#laststarted (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:68 msgid "Play Count" msgstr "Toistokertojen määrä" #: quodlibet/ext/songsmenu/editplaycount.py:69 msgid "Skip Count" msgstr "Ohituskertojen määrä" #: quodlibet/ext/songsmenu/embedded.py:25 msgid "Edit Embedded Images" msgstr "Muokkaa upotettuja kuvia" #: quodlibet/ext/songsmenu/embedded.py:26 msgid "Removes or replaces embedded images." msgstr "Poistaa tai korvaa upotettuja kuvia." #: quodlibet/ext/songsmenu/embedded.py:81 msgid "_Remove all Images" msgstr "_Poista kaikki kuvat" #: quodlibet/ext/songsmenu/embedded.py:85 msgid "_Embed Current Image" msgstr "_Upota nykyinen 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/exact_rating.py:54 quodlibet/qltk/ratingsmenu.py:98 msgid "Change _Rating" msgstr "Muuta arvosanaa" #: 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" #: quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" msgstr "Tila" #. 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:65 quodlibet/ext/songsmenu/html.py:75 msgid "Export to HTML" msgstr "Vie HTML-muotoon" #: quodlibet/ext/songsmenu/html.py:66 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:62 msgid "Error uploading" msgstr "Virhe lähetyksessä" #: quodlibet/ext/songsmenu/ifp.py:63 #, python-format msgid "" "Unable to upload <b>%s</b>. The device may be out of space, or turned off." msgstr "" "Tiedostoa <b>%s</b> ei voitu lähettää. Laitteen tallennustila voi olla " "täynnä tai laite voi olla pois päältä." #: quodlibet/ext/songsmenu/importexport.py:60 msgid "Export Metadata" msgstr "Vie metatietoja" #: quodlibet/ext/songsmenu/importexport.py:61 msgid "Exports metadata of selected songs as a .tags file." msgstr "Vie valittujen kappaleiden metatiedot .tags-tiedostoon." #: quodlibet/ext/songsmenu/importexport.py:105 msgid "Import Metadata" msgstr "Tuo metatietoja" #: quodlibet/ext/songsmenu/importexport.py:106 msgid "Imports metadata for selected songs from a .tags file." msgstr "Tuo valituille kappaleille metatiedot .tags-tiedostosta." #: quodlibet/ext/songsmenu/k3b.py:23 msgid "Burn CD" msgstr "Polta CD" #: quodlibet/ext/songsmenu/k3b.py:24 msgid "Burns CDs with K3b, Brasero or xfburn." msgstr "Polttaa CD-levyjä K3b-, Brasero- tai xfburn-ohjelmalla." #: quodlibet/ext/songsmenu/lastfmsync.py:97 msgid "Updating chart list." msgstr "Päivitetään soitetuimpien listaa." #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:116 msgid "Already up-to-date." msgstr "Tiedot jo ajan tasalla." #: quodlibet/ext/songsmenu/lastfmsync.py:124 #, python-format msgid "Fetching chart for week of %s." msgstr "Haetaan listaa päivän %s viikolle." #: quodlibet/ext/songsmenu/lastfmsync.py:146 msgid "Sync complete." msgstr "Synkronointi valmis." #: quodlibet/ext/songsmenu/lastfmsync.py:152 msgid "Error during sync" msgstr "Virhe synkronoinnissa" #: quodlibet/ext/songsmenu/lastfmsync.py:217 #: quodlibet/ext/songsmenu/lastfmsync.py:247 msgid "Last.fm Sync" msgstr "Last.fm-synkronointi" #: quodlibet/ext/songsmenu/lastfmsync.py:248 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:301 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." #. Create a dialog. #: quodlibet/ext/songsmenu/migratemetadata.py:36 #: quodlibet/ext/songsmenu/migratemetadata.py:45 msgid "Migrate Metadata" msgstr "Siirrä metatietoja" #: quodlibet/ext/songsmenu/migratemetadata.py:39 msgid "Copies the quodlibet-specific metadata between songs." msgstr "Kopioi Quod Libet -metatietoja kappaleiden välillä." #: quodlibet/ext/songsmenu/migratemetadata.py:52 msgid "_Copy" msgstr "_Kopioi" #: quodlibet/ext/songsmenu/migratemetadata.py:54 msgid "_Paste" msgstr "_Liitä" #. Create the tag table. #: quodlibet/ext/songsmenu/migratemetadata.py:64 msgid "Information to copy/paste" msgstr "Kopioitavat/liitettävät tiedot" #. Create the indexing box. #: quodlibet/ext/songsmenu/migratemetadata.py:86 msgid "Map tracks by disc and track number" msgstr "Yhdistä kappaleet levy- ja raitanumeron perusteella" #: quodlibet/ext/songsmenu/migratemetadata.py:87 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." #: quodlibet/ext/songsmenu/migratemetadata.py:103 #, python-format msgid "There is %d stored track." msgid_plural "There are %d stored tracks." msgstr[0] "%d tallennettu kappale." msgstr[1] "%d tallennettua kappaletta." #: quodlibet/ext/songsmenu/playlist.py:31 msgid "Export as Playlist" msgstr "Vie soittolistaksi" #: quodlibet/ext/songsmenu/playlist.py:32 msgid "Exports songs to an M3U or PLS playlist." msgstr "Vie kappaleet M3U- tai PLS-soittolistaksi." #: quodlibet/ext/songsmenu/playlist.py:77 msgid "Use relative paths" msgstr "Käytä suhteellisia polkuja" #: quodlibet/ext/songsmenu/playlist.py:77 msgid "Use absolute paths" msgstr "Käytä absoluuttisia polkuja" #: quodlibet/ext/songsmenu/playlist.py:133 #, python-format msgid "Writing to <b>%s</b> failed." msgstr "Kirjoittaminen kohteeseen <b>%s</b> 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" #: quodlibet/ext/songsmenu/replaygain.py:407 msgid "Progress" msgstr "Edistyminen" #: quodlibet/ext/songsmenu/replaygain.py:422 msgid "Gain" msgstr "Vahvistus" #: quodlibet/ext/songsmenu/replaygain.py:437 msgid "Peak" msgstr "Huippu" #: quodlibet/ext/songsmenu/replaygain.py:452 #, python-format msgid "There is <b>%(to-process)s</b> album to update (of %(all)s)" msgid_plural "There are <b>%(to-process)s</b> albums to update (of %(all)s)" msgstr[0] "<b>%(to-process)s</b> albumi päivitettäväksi (yhteensä %(all)s)" msgstr[1] "<b>%(to-process)s</b> albumia päivitettäväksi (yhteensä %(all)s)" #: quodlibet/ext/songsmenu/replaygain.py:568 msgid "Replay Gain" msgstr "Replay Gain" #: quodlibet/ext/songsmenu/replaygain.py:569 msgid "" "Analyzes and updates ReplayGain information, using GStreamer. Results are " "grouped by album." msgstr "" "Analysoi ja päivittää ReplayGain-tiedot käyttäen GStreameriä. Tulokset " "ryhmitellään albumeittain." #: quodlibet/ext/songsmenu/replaygain.py:607 msgid "always" msgstr "aina" #: quodlibet/ext/songsmenu/replaygain.py:608 msgid "if <b>any</b> RG tags are missing" msgstr "jos <b>mikä tahansa</b> RG-tunniste puuttuu" #: quodlibet/ext/songsmenu/replaygain.py:610 msgid "if <b>album</b> RG tags are missing" msgstr "jos <b>albumi</b>-RG-tunnisteet puuttuvat" #: quodlibet/ext/songsmenu/replaygain.py:627 msgid "_Process albums:" msgstr "_Käy albumit läpi:" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:639 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:37 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-example)s." msgstr "" "Suorittaa haun haluamallasi verkkosivulla kappaleiden tunnisteiden " "perusteella.\n" "Tukee kaavoja, esim. %(pattern-example)s." #: quodlibet/ext/songsmenu/website_search.py:80 msgid "Search URL patterns" msgstr "URL-hakukaava" #: quodlibet/ext/songsmenu/website_search.py:90 msgid "Edit search URLs" msgstr "Muokkaa hakuosoitteita" #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:116 msgid "Configure Searches…" msgstr "Hakuasetukset…" #: quodlibet/ext/songsmenu/wikipedia.py:35 msgid "Search Tag in Wikipedia" msgstr "Hae tunnistetta Wikipediasta" #: quodlibet/ext/songsmenu/wikipedia.py:36 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:56 #, python-format msgid "Search at %(website)s" msgstr "Hae sivulta %(website)s" #: quodlibet/ext/songsmenu/wikipedia.py:70 #: quodlibet/ext/songsmenu/wikipedia.py:76 quodlibet/qltk/edittags.py:443 msgid "Edit Tags" msgstr "Muokkaa tunnisteita" #: quodlibet/ext/songsmenu/wikipedia.py:111 msgid "Search failed" msgstr "Haku epäonnistui" #: quodlibet/ext/songsmenu/wikipedia.py:112 #, python-format msgid "Tag \"%s\" not found." msgstr "Tunnistetta ”%s” ei löytynyt." #. then (try to) load all new files #: quodlibet/library/libraries.py:651 quodlibet/library/libraries.py:661 #: quodlibet/library/libraries.py:727 quodlibet/library/libraries.py:746 #: quodlibet/qltk/information.py:272 quodlibet/qltk/prefs.py:692 #: quodlibet/util/library.py:123 msgid "Library" msgstr "Kirjasto" #: quodlibet/library/libraries.py:651 msgid "Checking mount points" msgstr "Tarkistetaan liitoskohdat" #: quodlibet/library/libraries.py:661 msgid "Scanning library" msgstr "Luetaan musiikkikirjastoa" #: quodlibet/library/libraries.py:726 #, python-format msgid "Scanning %s" msgstr "Luetaan kohdetta %s" #: quodlibet/library/libraries.py:746 msgid "Loading files" msgstr "Ladataan tiedostoja" #: quodlibet/main.py:50 msgid "Music player and music library manager" msgstr "Musiikkisoitin ja musiikkikirjaston hallinnoija" #: quodlibet/operon/base.py:70 #, 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:462 msgid "Print terse output" msgstr "Tulosta lyhytsanaisesti" #: quodlibet/operon/commands.py:43 quodlibet/operon/commands.py:82 #: quodlibet/operon/commands.py:464 #, 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:336 quodlibet/operon/commands.py:340 #: quodlibet/operon/commands.py:392 quodlibet/operon/commands.py:395 #: quodlibet/operon/commands.py:434 quodlibet/operon/commands.py:469 #: quodlibet/operon/commands.py:509 quodlibet/operon/commands.py:544 #: quodlibet/operon/commands.py:586 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:471 msgid "Too many arguments" msgstr "Liikaa argumentteja" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:91 #: quodlibet/operon/commands.py:476 quodlibet/qltk/data_editors.py:352 msgid "Description" msgstr "Kuvaus" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:476 #: quodlibet/qltk/edittags.py:493 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:324 #: quodlibet/operon/commands.py:385 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:304 quodlibet/operon/commands.py:445 #: quodlibet/operon/commands.py:677 #, python-format msgid "Can not set %r" msgstr "Ei voi asettaa: %r" #: quodlibet/operon/commands.py:319 msgid "Remove tags" msgstr "Poista tunnisteita" #: quodlibet/operon/commands.py:326 quodlibet/operon/commands.py:387 msgid "Value is a regular expression" msgstr "Arvo on säännöllinen lauseke" #: quodlibet/operon/commands.py:328 msgid "Remove all tags" msgstr "Poista kaikki tunnisteet" #: quodlibet/operon/commands.py:332 msgid "Can't combine '--all' with '--regexp'" msgstr "Argumenttia --all ei voi yhdistää argumenttiin --regexp" #: quodlibet/operon/commands.py:366 #, python-brace-format msgid "Can't remove {tagname} from {filename}" msgstr "Tunnistetta {tagname} ei voi poistaa tiedostosta {filename}" #: quodlibet/operon/commands.py:380 msgid "Remove a tag value" msgstr "Poista tunnisteen arvo" #: quodlibet/operon/commands.py:429 msgid "Add a tag value" msgstr "Lisää tunnisteelle arvo" #: quodlibet/operon/commands.py:457 msgid "List file information" msgstr "Listaa tiedoston tiedot" #: quodlibet/operon/commands.py:503 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:516 #, python-format msgid "Failed to load image file: %r" msgstr "Kuvatiedoston lataaminen epäonnistui: %r" #: quodlibet/operon/commands.py:523 quodlibet/operon/commands.py:552 #, 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:539 msgid "Remove all embedded images" msgstr "Poista kaikki upotetut kuvat" #: quodlibet/operon/commands.py:569 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "Vie upotetut kuvat kansioon %(filepath)s" #: quodlibet/operon/commands.py:581 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:640 msgid "Rename files based on tags" msgstr "Nimeä tiedostoja uudelleen tunnisteisiin perustuen" #: quodlibet/operon/commands.py:655 msgid "Fill tags based on the file path" msgstr "Aseta tunnisteet tiedostopolun perusteella" #: quodlibet/operon/commands.py:705 quodlibet/qltk/information.py:309 #: quodlibet/qltk/properties.py:83 quodlibet/qltk/renamefiles.py:224 #: quodlibet/qltk/tagsfrompath.py:228 quodlibet/qltk/tracknumbers.py:78 msgid "File" msgstr "Tiedosto" #: quodlibet/operon/commands.py:713 msgid "Fill tracknumbers for all files" msgstr "Aseta raitanumerot kaikille tiedostoille" #: quodlibet/operon/commands.py:732 msgid "Print tags based on the given pattern" msgstr "Tulosta tunnisteita annetun kaavan mukaan" #: quodlibet/operon/commands.py:769 msgid "Display help information" msgstr "Näytä käyttöohje" #: quodlibet/operon/util.py:43 #, 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:30 msgid "_Unknown" msgstr "_Tuntematon" #: quodlibet/order/__init__.py:142 msgid "In Order" msgstr "Järjestyksessä" #: quodlibet/order/__init__.py:143 msgid "_In Order" msgstr "_Järjestyksessä" #: quodlibet/order/reorder.py:22 msgid "Random" msgstr "Satunnainen" #: quodlibet/order/reorder.py:23 quodlibet/qltk/queue.py:147 msgid "_Random" msgstr "_Satunnainen" #: quodlibet/order/reorder.py:40 quodlibet/order/reorder.py:41 msgid "Prefer higher rated" msgstr "Suosi parempia arvosanoja" #: quodlibet/order/repeat.py:43 quodlibet/order/repeat.py:44 msgid "Repeat this track" msgstr "Kertaa tämä kappale" #: quodlibet/order/repeat.py:57 quodlibet/order/repeat.py:58 msgid "Repeat all" msgstr "Kertaa kaikki" #: quodlibet/order/repeat.py:73 quodlibet/order/repeat.py:74 msgid "One Song" msgstr "Yksi kappale" #: quodlibet/player/gstbe/player.py:98 msgid "Stream" msgstr "Virta" #: quodlibet/player/gstbe/player.py:98 msgid "Buffering" msgstr "Puskuroidaan" #: quodlibet/player/gstbe/player.py:452 msgid "Could not create GStreamer pipeline" msgstr "GStreamer-liukuhihnan luominen epäonnistui" #: quodlibet/player/gstbe/player.py:651 msgid "No GStreamer element found to handle media format" msgstr "Mediamuodon käsittelyyn ei löytynyt sopivaa GStreamer-elementtiä" #: quodlibet/player/gstbe/player.py:652 #, 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:25 msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. In case 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:36 msgid "_Output pipeline:" msgstr "_Ulostuloliukuhihna:" #: quodlibet/player/gstbe/prefs.py:43 #, python-format msgid "%.1f seconds" msgstr "%.1f sekuntia" #: quodlibet/player/gstbe/prefs.py:57 msgid "_Buffer duration:" msgstr "Puskurin pituus:" #: quodlibet/player/gstbe/prefs.py:66 msgid "Disable _gapless playback" msgstr "Poista katkoton toisto käytöstä" #: quodlibet/player/gstbe/prefs.py:70 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/util.py:101 msgid "No GStreamer audio sink found" msgstr "Ei löydettyä GStreamer-ääninielua" #: quodlibet/player/gstbe/util.py:120 msgid "Invalid GStreamer output pipeline" msgstr "Virheellinen GStreamer-ulostuloliukuhihna (output pipeline)" #: quodlibet/player/xinebe/player.py:90 msgid "Unable to create audio output" msgstr "Ääniulostuloa ei voitu luoda" #: quodlibet/player/xinebe/player.py:91 #, 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:61 #, 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:70 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "GStreamer-elementtiä {element} ei löytynyt." #: 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:55 #: quodlibet/qltk/songsmenu.py:66 msgid "_Run Plugin" msgstr "_Suorita liitännäinen" #. 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:40 msgid "_Name:" msgstr "_Nimi:" #: quodlibet/qltk/cbes.py:48 quodlibet/qltk/edittags.py:350 msgid "_Value:" msgstr "_Arvo:" #: quodlibet/qltk/cbes.py:263 msgid "Saved Values" msgstr "Tallennetut arvot" #: quodlibet/qltk/cbes.py:264 msgid "Edit saved values…" msgstr "Muokkaa tallennettuja arvoja…" #: quodlibet/qltk/controls.py:111 msgid "Auto_matic" msgstr "Auto_maattinen" #: quodlibet/qltk/controls.py:112 msgid "_Track Mode" msgstr "_Raita" #: quodlibet/qltk/controls.py:113 msgid "_Album Mode" msgstr "_Albumi" #. Translators: player state, no action #: quodlibet/qltk/controls.py:122 msgid "_Mute" msgstr "_Vaimennus" #: quodlibet/qltk/controls.py:128 msgid "_Replay Gain Mode" msgstr "_Replay Gain -tila" #. Translators: New Command/Entry/Item/... #: quodlibet/qltk/data_editors.py:116 #, python-format msgid "New %s" msgstr "Uusi %s" #: quodlibet/qltk/data_editors.py:215 msgid "(unknown)" msgstr "(tuntematon)" #: quodlibet/qltk/data_editors.py:344 msgid "Tag expression" msgstr "Tunnistelauseke" #: quodlibet/qltk/data_editors.py:371 msgid "Tag expression e.g. people:real or ~album~year" msgstr "Tunnistelauseke, esim. people:real tai ~album~year" #: quodlibet/qltk/data_editors.py:372 msgid "Enter new tag" msgstr "Anna uusi tunniste" #: 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/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:197 msgid "Split into _Multiple Values" msgstr "Jaa _useammaksi arvoksi" #: quodlibet/qltk/edittags.py:219 msgid "Split Disc out of _Album" msgstr "Erota levyn numero _albumin nimestä" #: quodlibet/qltk/edittags.py:243 msgid "Split _Version out of Title" msgstr "Erota _versio kappaleen nimestä" #: quodlibet/qltk/edittags.py:298 msgid "Split Arranger out of Ar_tist" msgstr "Erota sovittaja ar_tistin nimestä" #: quodlibet/qltk/edittags.py:303 msgid "Split _Performer out of Artist" msgstr "Erota _esittäjä artistin nimestä" #: quodlibet/qltk/edittags.py:309 msgid "Split _Performer out of Title" msgstr "Erota _esittäjä kappaleen nimestä" #: quodlibet/qltk/edittags.py:315 msgid "Split _Originalartist out of Title" msgstr "Erota _alkuperäinen esittäjä kappaleen nimestä" #: quodlibet/qltk/edittags.py:322 msgid "Add a Tag" msgstr "Lisää tunniste" #: quodlibet/qltk/edittags.py:341 msgid "_Tag:" msgstr "_Tunniste:" #: quodlibet/qltk/edittags.py:516 msgid "Show _programmatic tags" msgstr "Näytä _ohjelmalliset tunnisteet" #: quodlibet/qltk/edittags.py:517 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" #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:547 msgctxt "edittags" msgid "_Revert" msgstr "_Palauta" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:552 msgctxt "edittags" msgid "_Save" msgstr "_Tallenna" #: quodlibet/qltk/edittags.py:681 msgid "_Configure" msgstr "_Asetukset" #: quodlibet/qltk/edittags.py:696 msgid "_Split Tag" msgstr "_Jaa tunniste" #: quodlibet/qltk/edittags.py:705 msgid "_Copy Value(s)" msgstr "_Kopioi arvo(t)" #: quodlibet/qltk/edittags.py:736 msgid "Unable to add tag" msgstr "Tunnistetta ei voi lisätä" #: quodlibet/qltk/edittags.py:737 #, python-format msgid "Unable to add <b>%s</b>" msgstr "Tunnistetta <b>%s</b> ei voi lisätä" #: quodlibet/qltk/edittags.py:739 #, python-format msgid "" "The files currently selected do not support multiple values for <b>%s</b>." msgstr "Valitut tiedostot eivät tue useaa arvoa tunnisteelle <b>%s</b>." #. Can't add the new tag. #: quodlibet/qltk/edittags.py:766 quodlibet/qltk/edittags.py:947 #: quodlibet/qltk/tagsfrompath.py:211 quodlibet/util/__init__.py:505 #: quodlibet/util/tags.py:243 msgid "Invalid tag" msgstr "Virheellinen tunniste" #: quodlibet/qltk/edittags.py:767 quodlibet/qltk/edittags.py:948 #: quodlibet/qltk/tagsfrompath.py:212 #, python-format msgid "" "Invalid tag <b>%s</b>\n" "\n" "The files currently selected do not support editing this tag." msgstr "" "Tunniste <b>%s</b> ei kelpaa\n" "\n" "Valitut tiedostot eivät tue tämän tunnisteen muokkaamista." #: quodlibet/qltk/edittags.py:918 quodlibet/qltk/edittags.py:959 msgid "Invalid value" msgstr "Virheellinen arvo" #: quodlibet/qltk/edittags.py:919 quodlibet/qltk/edittags.py:960 #, python-format msgid "" "Invalid value: <b>%(value)s</b>\n" "\n" "%(error)s" msgstr "" "Arvo ei kelpaa: <b>%(value)s</b>\n" "\n" "%(error)s" #: quodlibet/qltk/_editutils.py:29 msgid "Tag may not be accurate" msgstr "Tunniste saattaa olla epätarkka" #: quodlibet/qltk/_editutils.py:32 #, 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:48 msgid "Unable to save song" msgstr "Kappaletta ei voi tallentaa" #: quodlibet/qltk/_editutils.py:51 #, 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:143 msgid "_More options…" msgstr "_Lisäasetukset…" #: quodlibet/qltk/entry.py:78 msgid "_Undo" msgstr "_Kumoa" #: quodlibet/qltk/entry.py:80 msgid "_Redo" msgstr "_Tee uudelleen" #: quodlibet/qltk/exfalsowindow.py:94 quodlibet/qltk/quodlibetwindow.py:956 msgid "_About" msgstr "_Tietoja" #: quodlibet/qltk/exfalsowindow.py:98 quodlibet/qltk/quodlibetwindow.py:978 msgid "_Check for Updates…" msgstr "Tarkista _päivitykset…" #: quodlibet/qltk/exfalsowindow.py:104 quodlibet/qltk/quodlibetwindow.py:911 #: quodlibet/qltk/songsmenu.py:289 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:278 msgid "Ex Falso Preferences" msgstr "Ex Falson asetukset" #: quodlibet/qltk/exfalsowindow.py:284 quodlibet/qltk/prefs.py:666 msgid "Tag Editing" msgstr "Tunnisteiden muokkaus" #: 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:386 msgid "Unable to create folder" msgstr "Kansiota ei voi luoda" #: quodlibet/qltk/filesel.py:403 msgid "Unable to delete folder" msgstr "Kansiota ei voi poistaa" #: quodlibet/qltk/filesel.py:519 quodlibet/qltk/pluginwin.py:167 msgid "Songs" msgstr "Kappaleet" #. Translators: As in "by Artist Name" #: quodlibet/qltk/info.py:42 #, python-format msgid "by %s" msgstr "%s" #: quodlibet/qltk/info.py:43 quodlibet/qltk/information.py:171 #: quodlibet/qltk/information.py:452 #, python-format msgid "Disc %s" msgstr "Levy %s" #: quodlibet/qltk/info.py:44 quodlibet/qltk/information.py:176 #, python-format msgid "Track %s" msgstr "Raita %s" #: quodlibet/qltk/info.py:108 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:342 #: quodlibet/qltk/information.py:475 quodlibet/qltk/information.py:543 msgid "Information" msgstr "Tiedot" #: quodlibet/qltk/information.py:127 msgid "Lyrics" msgstr "Sanat" #: quodlibet/qltk/information.py:188 quodlibet/qltk/information.py:400 #, python-format msgid "Produced by %s" msgstr "Tuottanut %s" #: quodlibet/qltk/information.py:203 quodlibet/util/tags.py:85 msgid "artist" msgstr "artisti" #: quodlibet/qltk/information.py:204 quodlibet/qltk/information.py:573 #: quodlibet/util/tags.py:85 msgid "artists" msgstr "artistit" #. for backwards compat #: quodlibet/qltk/information.py:225 quodlibet/util/tags.py:96 #: quodlibet/util/tags.py:124 msgid "performers" msgstr "esittäjät" #: quodlibet/qltk/information.py:239 quodlibet/qltk/information.py:252 #: quodlibet/qltk/songlistcolumns.py:276 msgid "Never" msgstr "Ei koskaan" #: quodlibet/qltk/information.py:240 #, 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:258 quodlibet/util/tags.py:149 msgid "added" msgstr "lisätty" #: quodlibet/qltk/information.py:259 quodlibet/util/tags.py:150 msgid "last played" msgstr "viimeksi toistettu" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:160 msgid "plays" msgstr "toistokertoja" #: quodlibet/qltk/information.py:261 quodlibet/util/tags.py:161 msgid "skips" msgstr "ohituksia" #: quodlibet/qltk/information.py:262 quodlibet/util/tags.py:166 msgid "rating" msgstr "arvosana" #: quodlibet/qltk/information.py:291 msgid "path" msgstr "polku" #: quodlibet/qltk/information.py:292 quodlibet/util/tags.py:164 msgid "length" msgstr "kesto" #: quodlibet/qltk/information.py:293 msgid "format" msgstr "muoto" #: quodlibet/qltk/information.py:294 quodlibet/util/tags.py:174 msgid "codec" msgstr "koodekki" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:175 msgid "encoding" msgstr "enkoodaus" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:171 msgid "bitrate" msgstr "bittinopeus" #: quodlibet/qltk/information.py:297 quodlibet/util/tags.py:172 msgid "file size" msgstr "tiedostokoko" #: quodlibet/qltk/information.py:298 quodlibet/util/tags.py:159 msgid "modified" msgstr "muokattu" #: quodlibet/qltk/information.py:335 msgid "Additional" msgstr "Lisätiedot" #: quodlibet/qltk/information.py:387 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d valittu" msgstr[1] "%d valittu" #: quodlibet/qltk/information.py:462 msgid "Track unavailable" msgstr "Raita ei ole käytettävissä" #: quodlibet/qltk/information.py:468 msgid "Track List" msgstr "Kappaleet" #: quodlibet/qltk/information.py:500 quodlibet/qltk/information.py:590 #, 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:503 msgid "Selected Discography" msgstr "Valittu diskografia" #: quodlibet/qltk/information.py:570 #, 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:598 quodlibet/util/tags.py:83 msgid "albums" msgstr "albumit" #: quodlibet/qltk/information.py:611 msgid "Total length:" msgstr "Kesto yhteensä:" #: quodlibet/qltk/information.py:615 msgid "Total size:" msgstr "Koko yhteensä:" #: quodlibet/qltk/information.py:618 msgid "Files" msgstr "Tiedostot" #: quodlibet/qltk/lyrics.py:36 msgid "_View online" msgstr "_Näytä verkossa" #: quodlibet/qltk/lyrics.py:64 msgid "No lyrics found for this song." msgstr "Kappaleelle ei löydy sanoja." #: quodlibet/qltk/lyrics.py:75 msgid "Searching for lyrics…" msgstr "Etsitään laulun 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/msg.py:41 msgid "Discard tag changes?" msgstr "Hylkää muutokset tunnisteisiin?" #: quodlibet/qltk/msg.py:42 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:55 quodlibet/qltk/prefs.py:628 #: quodlibet/qltk/prefs.py:635 quodlibet/qltk/textedit.py:63 #: quodlibet/qltk/tracknumbers.py:116 msgid "_Revert" msgstr "_Palauta" #: quodlibet/qltk/msg.py:104 msgid "File exists" msgstr "Tiedosto on olemassa" #: quodlibet/qltk/msg.py:106 #, python-format msgid "Replace %(file-name)s?" msgstr "Korvaa %(file-name)s?" #: quodlibet/qltk/msg.py:112 msgid "_Replace File" msgstr "_Korvaa tiedosto" #: quodlibet/qltk/notif.py:182 msgid "Active tasks" msgstr "Aktiiviset tehtävät" #: quodlibet/qltk/notif.py:188 #, python-format msgid "%d tasks running" msgstr "%d tehtävää käynnissä" #: quodlibet/qltk/playorder.py:256 msgid "Toggle shuffle mode" msgstr "Sekoitus päälle/pois" #: quodlibet/qltk/playorder.py:272 msgid "Toggle repeat mode" msgstr "Kertaus päälle/pois" #: quodlibet/qltk/pluginwin.py:44 msgid "Plugin Errors" msgstr "Liitännäisten virheet" #: quodlibet/qltk/pluginwin.py:124 msgid "Enabled" msgstr "Käytössä olevat" #: quodlibet/qltk/pluginwin.py:125 msgid "Disabled" msgstr "Käytöstä poistetut" #: quodlibet/qltk/pluginwin.py:131 msgid "No category" msgstr "Ei kategoriaa" #: quodlibet/qltk/pluginwin.py:169 msgid "Events" msgstr "Tapahtumat" #: quodlibet/qltk/pluginwin.py:170 msgid "Play Order" msgstr "Toistojärjestys" #: quodlibet/qltk/pluginwin.py:171 msgid "Editing" msgstr "Muokkaus" #: quodlibet/qltk/pluginwin.py:173 msgid "Covers" msgstr "Kansikuvat" #: quodlibet/qltk/pluginwin.py:309 msgid "No plugins found." msgstr "Liitännäisiä ei löytynyt." #: quodlibet/qltk/pluginwin.py:358 msgid "Plugins" msgstr "Liitännäiset" #: quodlibet/qltk/pluginwin.py:382 msgid "Filter by plugin state / tag" msgstr "Suodata liitännäisen tilan / tunnisteen perusteella" #: quodlibet/qltk/pluginwin.py:388 msgid "Filter by plugin type" msgstr "Suodata liitännäisen tyypin perusteella" #: quodlibet/qltk/pluginwin.py:394 msgid "Filter by plugin name or description" msgstr "Suodata liitännäisen nimen tai kuvauksen perusteella" #: quodlibet/qltk/pluginwin.py:403 msgid "Show _Errors" msgstr "Näytä _virheet" #: quodlibet/qltk/prefs.py:45 msgid "_Disc" msgstr "_Levy" #: quodlibet/qltk/prefs.py:46 msgid "_Track" msgstr "_Raita" #: quodlibet/qltk/prefs.py:47 msgid "Grou_ping" msgstr "_Ryhmittely" #: quodlibet/qltk/prefs.py:50 msgid "Al_bum" msgstr "Al_bumi" #: quodlibet/qltk/prefs.py:55 msgid "_Filename" msgstr "Tie_dostonimi" #: quodlibet/qltk/prefs.py:57 msgid "_Length" msgstr "_Kesto" #: quodlibet/qltk/prefs.py:64 msgid "_Jump to playing song automatically" msgstr "_Hyppää toistettavaan kappaleeseen automaattisesti" #: quodlibet/qltk/prefs.py:66 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:82 msgid "_Others:" msgstr "M_uut:" #: quodlibet/qltk/prefs.py:88 msgid "_Edit…" msgstr "_Muokkaa…" #: quodlibet/qltk/prefs.py:91 msgid "Add or remove additional column headers" msgstr "Lisää tai poista sarakeotsakkeita" #: quodlibet/qltk/prefs.py:101 msgid "Visible Columns" msgstr "Näytettävät sarakkeet" #: quodlibet/qltk/prefs.py:104 msgid "Title includes _version" msgstr "Nimi sisältää v_ersion" #: quodlibet/qltk/prefs.py:106 msgid "Artist includes all _people" msgstr "Artisti sisältää kaikki tekijät" #: quodlibet/qltk/prefs.py:108 msgid "Album includes _disc subtitle" msgstr "Albumi sisältää _levyn alaotsikon" #: quodlibet/qltk/prefs.py:110 msgid "Filename includes _folder" msgstr "Tiedostonimi sisältää _kansion" #: quodlibet/qltk/prefs.py:123 msgid "Column Preferences" msgstr "Sarakeasetukset" #: quodlibet/qltk/prefs.py:129 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:142 quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Kappalelista" #: quodlibet/qltk/prefs.py:222 msgid "Edit Columns" msgstr "Muokkaa sarakkeita" #: quodlibet/qltk/prefs.py:259 msgid "Duration totals" msgstr "Yhteiskesto" #: quodlibet/qltk/prefs.py:271 msgid "_Global filter:" msgstr "_Yleissuodatin:" #: quodlibet/qltk/prefs.py:277 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:283 msgctxt "heading" msgid "Search" msgstr "Haku" #: quodlibet/qltk/prefs.py:287 quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Selaimet" #: quodlibet/qltk/prefs.py:293 msgid "Confirm _multiple ratings" msgstr "Kysy _varmistusta usealle arvosanalle" #: quodlibet/qltk/prefs.py:295 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:298 msgid "Enable _one-click ratings" msgstr "Salli yhden napsautuksen arvostelu" #: quodlibet/qltk/prefs.py:300 msgid "Enable rating by clicking on the rating column in the song list" msgstr "Salli arvostelu napsauttamalla arvosana-saraketta kappalelistassa" #: quodlibet/qltk/prefs.py:306 quodlibet/qltk/prefs.py:669 msgid "Ratings" msgstr "Arvosanat" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:312 msgid "Prefer _embedded art" msgstr "Suosi _upotettuja kansikuvia" #: quodlibet/qltk/prefs.py:314 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:319 msgid "_Fixed image filename:" msgstr "_Kiinteästi valittu kuvatiedostonimi:" #: quodlibet/qltk/prefs.py:321 msgid "The single image filename to use if selected" msgstr "Jos määritetty, vain tätä kuvatiedostonimeä käytetään" #: quodlibet/qltk/prefs.py:327 msgid "The album art image file to use when forced (supports wildcards)" msgstr "Kuvatiedostonimi, jota käytetään pakotetusti (tukee jokerimerkkejä)" #: quodlibet/qltk/prefs.py:337 msgid "Album Art" msgstr "Albumien kansikuvat" #: quodlibet/qltk/prefs.py:358 msgid "Playback" msgstr "Toisto" #: quodlibet/qltk/prefs.py:363 msgid "Output Configuration" msgstr "Ulostulon asetukset" #: quodlibet/qltk/prefs.py:374 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:377 msgid "_Fall-back gain (dB):" msgstr "_Oletusvahvistus (dB):" #: quodlibet/qltk/prefs.py:388 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:391 msgid "_Pre-amp gain (dB):" msgstr "_Esivahvistus (dB):" #: quodlibet/qltk/prefs.py:396 msgid "_Enable Replay Gain volume adjustment" msgstr "_Käytä Replay Gain -äänenvoimakkuuden säätöä" #: quodlibet/qltk/prefs.py:421 msgid "Replay Gain Volume Adjustment" msgstr "Replay Gain -äänenvoimakkuuden säätö" #: quodlibet/qltk/prefs.py:428 msgid "_Continue playback on startup" msgstr "_Jatka toistoa käynnistettäessä" #: quodlibet/qltk/prefs.py:430 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:434 msgid "Startup" msgstr "Käynnistys" #: quodlibet/qltk/prefs.py:461 msgid "_Default rating:" msgstr "_Oletusarvosana:" #: quodlibet/qltk/prefs.py:504 msgid "Rating _scale:" msgstr "A_rvosteluasteikko:" #: quodlibet/qltk/prefs.py:553 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:558 msgid "_Bayesian averaging amount:" msgstr "_Bayesin keskiarvotekijä:" #: quodlibet/qltk/prefs.py:567 msgid "Save ratings and play _counts in tags" msgstr "Tallenna arvosanat ja toisto_kerrat tunnisteisiin" #: quodlibet/qltk/prefs.py:575 msgid "_Email:" msgstr "_Sähköposti:" #: quodlibet/qltk/prefs.py:577 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:597 msgid "Auto-save tag changes" msgstr "Tallenna muutokset tunnisteisiin automaattisesti" #: quodlibet/qltk/prefs.py:599 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "" "Tallenna muutokset tunnisteisiin ilman varmistusta muokattaessa useampaa " "tiedostoa" #: quodlibet/qltk/prefs.py:608 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:618 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:631 msgid "Split _tag on:" msgstr "_Tunniste-erottimet:" #: quodlibet/qltk/prefs.py:638 msgid "Split _subtag on:" msgstr "_Alitunniste-erottimet:" #: quodlibet/qltk/prefs.py:663 msgid "Tags" msgstr "Tunnisteet" #: quodlibet/qltk/prefs.py:684 msgid "Updating for new ratings" msgstr "Päivitetään arvosanoja" #: quodlibet/qltk/prefs.py:694 msgid "Scan library _on start" msgstr "_Päivitä kirjasto käynnistyksen yhteydessä" #: quodlibet/qltk/prefs.py:704 quodlibet/qltk/quodlibetwindow.py:990 msgid "_Scan Library" msgstr "_Päivitä kirjasto" #: quodlibet/qltk/prefs.py:706 quodlibet/qltk/quodlibetwindow.py:1052 msgid "Check for changes in your library" msgstr "Etsi muutoksia kirjastosta" #: quodlibet/qltk/prefs.py:711 msgid "Re_build Library" msgstr "Rakenna kirjasto _uudelleen" #: quodlibet/qltk/prefs.py:714 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:724 msgid "Scan Directories" msgstr "Luettavat kansiot" #: quodlibet/qltk/prefs.py:730 msgid "Hidden Songs" msgstr "Piilotetut kappaleet" #: quodlibet/qltk/properties.py:157 quodlibet/util/collection.py:403 #, python-format 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" #: quodlibet/qltk/properties.py:161 quodlibet/qltk/properties.py:163 msgid "Properties" msgstr "Ominaisuudet" #: quodlibet/qltk/queue.py:104 msgid "_Queue" msgstr "J_ono" #: quodlibet/qltk/queue.py:124 msgid "Ephemeral" msgstr "Väliaikainen" #: quodlibet/qltk/queue.py:125 msgid "Remove songs from the queue after playing them" msgstr "Poista kappaleet jonosta kun ne on soitettu" #: quodlibet/qltk/queue.py:133 msgid "Persistent" msgstr "Pysyvä" #: quodlibet/qltk/queue.py:134 msgid "Keep songs in the queue after playing them" msgstr "Pidä kappaleet jonossa kun ne on soitettu" #: quodlibet/qltk/queue.py:142 msgid "Mode" msgstr "Tila" #: quodlibet/qltk/queue.py:153 msgid "Stop at End" msgstr "Pysäytä lopuksi" #: quodlibet/qltk/queue.py:157 msgid "_Clear Queue" msgstr "_Tyhjennä jono" #: quodlibet/qltk/queue.py:178 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:290 #, 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:198 msgid "_Browse Library" msgstr "_Selaa kirjastoa" #: quodlibet/qltk/quodlibetwindow.py:348 msgid "Toggle queue visibility" msgstr "Näytä / piilota jono" #: quodlibet/qltk/quodlibetwindow.py:376 msgid "Playback Error" msgstr "Toistovirhe" #: quodlibet/qltk/quodlibetwindow.py:384 msgid "Set up library directories?" msgstr "Määritä kirjaston kansiot" #: quodlibet/qltk/quodlibetwindow.py:385 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:391 msgid "_Not Now" msgstr "_Ei nyt" #: quodlibet/qltk/quodlibetwindow.py:392 msgid "_Set Up" msgstr "_Määritä" #: quodlibet/qltk/quodlibetwindow.py:845 msgid "Unable to add songs" msgstr "Kappaleita ei voi lisätä" #: quodlibet/qltk/quodlibetwindow.py:846 quodlibet/qltk/quodlibetwindow.py:1286 #, python-format msgid "%s uses an unsupported protocol." msgstr "Kohteen %s käyttämää protokollaa ei tueta." #: quodlibet/qltk/quodlibetwindow.py:869 msgid "_Jump to Playing Song" msgstr "_Hyppää toistettavaan kappaleeseen" #: quodlibet/qltk/quodlibetwindow.py:876 msgid "_File" msgstr "_Tiedosto" #: quodlibet/qltk/quodlibetwindow.py:877 msgid "_Song" msgstr "_Kappale" #: quodlibet/qltk/quodlibetwindow.py:878 msgid "_View" msgstr "_Näytä" #: quodlibet/qltk/quodlibetwindow.py:879 msgid "_Browse" msgstr "_Selaa" #: quodlibet/qltk/quodlibetwindow.py:880 msgid "_Control" msgstr "O_hjaus" #: quodlibet/qltk/quodlibetwindow.py:881 msgid "_Help" msgstr "_Ohje" #: quodlibet/qltk/quodlibetwindow.py:887 msgid "_Add a Folder…" msgstr "Lisää _kansio…" #: quodlibet/qltk/quodlibetwindow.py:892 msgid "_Add a File…" msgstr "Lisää _tiedosto…" #: quodlibet/qltk/quodlibetwindow.py:897 msgid "_Add a Location…" msgstr "Lisää _sijainti…" #: quodlibet/qltk/quodlibetwindow.py:926 msgid "Edit Bookmarks…" msgstr "Muokkaa kirjanmerkkejä…" #: quodlibet/qltk/quodlibetwindow.py:946 msgid "Stop After This Song" msgstr "Pysäytä tämän kappaleen jälkeen" #: quodlibet/qltk/quodlibetwindow.py:952 msgid "_Keyboard Shortcuts" msgstr "_Pikanäppäimet" #: quodlibet/qltk/quodlibetwindow.py:961 msgid "Online Help" msgstr "Ohje verkossa" #: quodlibet/qltk/quodlibetwindow.py:970 msgid "Search Help" msgstr "Ohje hakujen tekemiseen" #: quodlibet/qltk/quodlibetwindow.py:1274 msgid "Add a Location" msgstr "Lisää sijainti" #: quodlibet/qltk/quodlibetwindow.py:1275 msgid "Enter the location of an audio file:" msgstr "Anna äänitiedoston sijainti:" #: quodlibet/qltk/quodlibetwindow.py:1280 #: quodlibet/qltk/quodlibetwindow.py:1285 msgid "Unable to add location" msgstr "Sijaintia ei voi lisätä" #: quodlibet/qltk/quodlibetwindow.py:1281 #, python-format msgid "%s is not a valid location." msgstr "%s ei ole kelvollinen sijainti." #: quodlibet/qltk/quodlibetwindow.py:1294 #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "Add Music" msgstr "Lisää musiikkia" #: quodlibet/qltk/quodlibetwindow.py:1294 quodlibet/qltk/scanbox.py:99 msgid "_Add Folders" msgstr "Lisää _kansioita" #: quodlibet/qltk/quodlibetwindow.py:1301 msgid "Music Files" msgstr "Musiikkitiedostot" #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "_Add Files" msgstr "Lisää _tiedostoja" #: quodlibet/qltk/ratingsmenu.py:24 #, 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:26 msgid "The saved ratings will be removed" msgstr "Tallennetut arvosanat poistetaan" #: quodlibet/qltk/ratingsmenu.py:27 #, python-format msgid "The rating of all selected songs will be changed to '%s'" msgstr "Valittujen kappaleiden arvosanaksi asetetaan %s" #: quodlibet/qltk/ratingsmenu.py:57 quodlibet/qltk/ratingsmenu.py:111 msgid "_Remove Rating" msgstr "_Poista arvosana" #: quodlibet/qltk/renamefiles.py:51 msgid "Replace spaces with _underscores" msgstr "Korvaa _välilyönnit alaviivoilla" #: quodlibet/qltk/renamefiles.py:61 msgid "Strip _Windows-incompatible characters" msgstr "Poista _Windows-yhteensopimattomat merkit" #: quodlibet/qltk/renamefiles.py:79 msgid "Strip _diacritical marks" msgstr "Poista ta_rkkeet" #: quodlibet/qltk/renamefiles.py:90 msgid "Strip non-_ASCII characters" msgstr "Poista _ASCII:hin kuulumattomat merkit" #: quodlibet/qltk/renamefiles.py:100 msgid "Use only _lowercase characters" msgstr "Käytä vain pieniä kirjaimia" #: quodlibet/qltk/renamefiles.py:128 msgid "Rename Files" msgstr "Nimeä tiedostot" #: quodlibet/qltk/renamefiles.py:146 quodlibet/qltk/tagsfrompath.py:115 msgid "Path Patterns" msgstr "Kaavat tiedostopoluille" #: quodlibet/qltk/renamefiles.py:147 quodlibet/qltk/tagsfrompath.py:116 msgid "Edit saved patterns…" msgstr "Muokkaa tallennettuja kaavoja…" #: quodlibet/qltk/renamefiles.py:150 quodlibet/qltk/tagsfrompath.py:119 #: quodlibet/qltk/tracknumbers.py:57 msgid "_Preview" msgstr "_Esikatsele" #: quodlibet/qltk/renamefiles.py:177 msgid "File names" msgstr "Tiedostonimet" #: quodlibet/qltk/renamefiles.py:187 msgid "_Move album art" msgstr "_Siirrä kansikuvat" #: quodlibet/qltk/renamefiles.py:190 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:195 msgid "_Overwrite album art at target" msgstr "_Ylikirjoita kohdenimellä olevat kansikuvat" #: quodlibet/qltk/renamefiles.py:203 msgid "_Remove empty directories" msgstr "_Poista tyhjät kansiot" #: quodlibet/qltk/renamefiles.py:209 msgid "Album art" msgstr "Albumien kansikuvat" #: quodlibet/qltk/renamefiles.py:238 msgid "New Name" msgstr "Uusi nimi" #: quodlibet/qltk/renamefiles.py:315 msgid "Unable to rename file" msgstr "Tiedoston nimeäminen ei onnistu" #: quodlibet/qltk/renamefiles.py:316 #, python-format msgid "" "Renaming <b>%(old-name)s</b> to <b>%(new-name)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." msgstr "" "Nimeäminen lähteestä <b>%(old-name)s</b> kohteeseen <b>%(new-name)s</b> ei " "onnistu. Kohdetiedosto on mahdollisesti jo olemassa, tai sinulla ei ole " "oikeuksia uuden tiedoston luomiseen tai vanhan poistamiseen." #: quodlibet/qltk/renamefiles.py:324 msgid "Ignore _All Errors" msgstr "Ohita kaikki virheet" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: quodlibet/qltk/renamefiles.py:325 quodlibet/qltk/wlw.py:49 msgid "_Stop" msgstr "_Pysäytä" #: quodlibet/qltk/renamefiles.py:327 msgid "_Continue" msgstr "_Jatka" #: quodlibet/qltk/renamefiles.py:440 msgid "Path is not absolute" msgstr "Polku ei ole absoluuttinen" #: quodlibet/qltk/renamefiles.py:441 #, python-format msgid "" "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 ~/." msgstr "" "Kaava\n" "\t<b>%s</b>\n" "sisältää merkin /, mutta ei ala juurihakemistosta. Välttääksesi kansioiden " "nimeämisen väärin, aloita kaavasi merkeillä / tai ~/." #: quodlibet/qltk/scanbox.py:47 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:99 msgid "Select Directories" msgstr "Valitse kansiot" #: quodlibet/qltk/searchbar.py:57 msgid "Saved Searches" msgstr "Tallennetut haut" #: quodlibet/qltk/searchbar.py:58 msgid "Edit saved searches…" msgstr "Muokkaa tallennettuja hakuja…" #: quodlibet/qltk/searchbar.py:82 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:144 msgid "Search after _typing" msgstr "Päivitä hakutuloksia jatkuvasti" #: quodlibet/qltk/searchbar.py:147 msgid "Show search results after the user stops typing" msgstr "Päivitä haun tuloksia jatkuvasti kirjoituksen aikana" #: quodlibet/qltk/searchbar.py:215 msgid "_Limit:" msgstr "_Määrä:" #: quodlibet/qltk/searchbar.py:228 msgid "_Weight" msgstr "_Painota arvosanalla" #: quodlibet/qltk/searchbar.py:355 msgid "Add query" msgstr "Lisää kysely" #: quodlibet/qltk/searchbar.py:356 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:375 #, python-format msgid "_Filter on %s" msgstr "_Suodata sarakkeen %s perusteella" #: quodlibet/qltk/songlist.py:1093 msgid "All _Headers" msgstr "Kaikki _otsakkeet" #: quodlibet/qltk/songlist.py:1094 msgid "_Track Headers" msgstr "_Raitaotsakkeet" #: quodlibet/qltk/songlist.py:1095 msgid "_Album Headers" msgstr "_Albumiotsakkeet" #: quodlibet/qltk/songlist.py:1096 msgid "_People Headers" msgstr "_Tekijäotsakkeet" #: quodlibet/qltk/songlist.py:1097 msgid "_Date Headers" msgstr "Ai_kaotsakkeet" #: quodlibet/qltk/songlist.py:1098 msgid "_File Headers" msgstr "Tie_dosto-otsakkeet" #: quodlibet/qltk/songlist.py:1099 msgid "_Production Headers" msgstr "T_uotanto-otsakkeet" #: quodlibet/qltk/songlist.py:1114 msgid "_Customize Headers…" msgstr "_Mukauta otsakkeita…" #: quodlibet/qltk/songlist.py:1119 msgid "_Expand Column" msgstr "_Laajenna sarake" #: quodlibet/qltk/songsmenu.py:40 #, python-format msgid "Remove track: \"%%(title)s\" from library?" msgid_plural "Remove %(count)d tracks from library?" msgstr[0] "Poistetaanko kappale ”%%(title)s” kirjastosta?" msgstr[1] "Poistetaanko %(count)d kappaletta kirjastosta?" #: quodlibet/qltk/songsmenu.py:46 msgid "Remove from Library" msgstr "Poista kirjastosta" #: quodlibet/qltk/songsmenu.py:51 #, 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:62 #, 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:134 msgid "Configure Plugins…" msgstr "Liitännäisten asetukset…" #: quodlibet/qltk/songsmenu.py:329 msgid "Add to _Queue" msgstr "Lisää _jonoon" #: quodlibet/qltk/songsmenu.py:349 msgid "_Remove from Library…" msgstr "_Poista kirjastosta…" #: quodlibet/qltk/songsmenu.py:414 msgid "Unable to show files" msgstr "Tiedostojen näyttäminen epäonnistui" #: quodlibet/qltk/songsmenu.py:415 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:422 #, 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/tagsfrompath.py:46 msgid "Replace _underscores with spaces" msgstr "Korvaa alaviivat _välilyönneillä" #: quodlibet/qltk/tagsfrompath.py:56 msgid "_Title-case tags" msgstr "_Isot alkukirjaimet tunnisteisiin" #: quodlibet/qltk/tagsfrompath.py:66 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<b>%s</b>\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" "Kaava\n" "\t<b>%s</b>\n" "on virheellinen. Se saattaa sisältää saman tunnisteen kahdesti tai " "parittomia kulmasulkumerkkejä (< / >)." #: quodlibet/qltk/tagsfrompath.py:215 msgid "Invalid tags" msgstr "Tunnisteet eivät kelpaa" #: quodlibet/qltk/tagsfrompath.py:216 #, 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." #: 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:923 #, python-format msgid "and %d more…" msgstr "ja %d muuta…" #: quodlibet/qltk/wlw.py:199 msgid "Saving the songs you changed." msgstr "Tallennetaan muutettuja kappaleita." #: quodlibet/qltk/wlw.py:200 #, 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:233 #, 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:425 msgid "Playlists must have a name" msgstr "Soittolistoilla täytyy olla nimi" #: quodlibet/util/collection.py:608 #, python-format msgid "A playlist named %s already exists." msgstr "Soittolista on jo olemassa nimellä %s." #: quodlibet/util/cover/built_in.py:32 msgid "Embedded album covers" msgstr "Upotetut albumien _kannet" #: quodlibet/util/cover/built_in.py:33 msgid "Uses covers embedded into audio files." msgstr "Käyttää äänitiedostoihin upotettuja kansikuvia." #: quodlibet/util/cover/built_in.py:55 msgid "Filesystem cover" msgstr "Kansikuva tiedostojärjestelmästä" #: quodlibet/util/cover/built_in.py:56 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:76 msgid "Display brief usage information" msgstr "Näytä lyhyt käyttöohje" #: quodlibet/util/__init__.py:78 msgid "Display version and copyright" msgstr "Näytä versio ja tekijänoikeustiedot" #: quodlibet/util/__init__.py:79 msgid "Print debugging information" msgstr "Kirjoita virheenkorjaustiedot" #: quodlibet/util/__init__.py:118 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "Käyttö: %(program)s %(usage)s" #: quodlibet/util/__init__.py:120 msgid "[options]" msgstr "[valitsimet]" #: quodlibet/util/__init__.py:165 #, python-format msgid "Option %r not recognized." msgstr "Valitsin %r ei kelpaa." #: quodlibet/util/__init__.py:168 #, python-format msgid "Option %r requires an argument." msgstr "Valitsin %r vaatii argumentin." #: quodlibet/util/__init__.py:171 #, python-format msgid "%r is not a unique prefix." msgstr "%r ei ole yksikäsitteinen etuliite." #: quodlibet/util/__init__.py:347 #, python-format msgid "%d kbps" msgstr "%d kb/s" #: quodlibet/util/__init__.py:402 #, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%s sekunti" msgstr[1] "%s sekuntia" #: quodlibet/util/__init__.py:415 msgid "No time information" msgstr "Ei aikatietoa" #: quodlibet/util/__init__.py:418 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d sekunti" msgstr[1] "%d sekuntia" #: quodlibet/util/__init__.py:419 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d minuutti" msgstr[1] "%d minuuttia" #: quodlibet/util/__init__.py:420 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d tunti" msgstr[1] "%d tuntia" #: quodlibet/util/__init__.py:421 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d päivä" msgstr[1] "%d päivää" #: quodlibet/util/__init__.py:422 #, 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:514 msgctxt "check" msgid "titlecase?" msgstr "no" #: quodlibet/util/massagers.py:114 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:129 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:150 msgid "Replay Gain peaks must be entered in 'x.yy' format." msgstr "Replay Gain -huiput annetaan muodossa ”x.yy”." #: quodlibet/util/massagers.py:172 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:194 msgid "" "MusicBrainz release status must be 'official', 'promotional', or 'bootleg'." msgstr "" "MusicBrainz-julkaisun tilaksi kelpaa ”official”, ”promotional” tai ”bootleg”." #: quodlibet/util/massagers.py:207 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:116 msgid "Unable to edit song" msgstr "Kappaleen muokkaaminen epäonnistui" #: quodlibet/util/songwrapper.py:117 #, python-format msgid "" "Saving <b>%s</b> failed. The file may be read-only, corrupted, or you do not " "have permission to edit it." msgstr "" "Kappaleen <b>%s</b> 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:151 msgid "disc" msgstr "levy" #: quodlibet/util/tags.py:115 quodlibet/util/tags.py:153 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" #. 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:130 msgid "MusicBrainz recording ID" msgstr "MusicBrainzin äänitteen tunniste" #: quodlibet/util/tags.py:131 msgid "MusicBrainz release track ID" msgstr "MusicBrainzin julkaisukappaleen tunniste" #: quodlibet/util/tags.py:132 msgid "MusicBrainz release ID" msgstr "MusicBrainzin julkaisun tunniste" #: quodlibet/util/tags.py:133 msgid "MusicBrainz artist ID" msgstr "MusicBrainzin artistin tunniste" #: quodlibet/util/tags.py:134 msgid "MusicBrainz release artist ID" msgstr "MusicBrainzin julkaisuartistin tunniste" #: quodlibet/util/tags.py:135 msgid "MusicBrainz TRM ID" msgstr "MusicBrainzin TRM-tunniste" #: quodlibet/util/tags.py:136 msgid "MusicIP PUID" msgstr "MusicIP PUID" #: quodlibet/util/tags.py:137 msgid "MusicBrainz album status" msgstr "MusicBrainzin albumin tila" #: quodlibet/util/tags.py:138 msgid "MusicBrainz album type" msgstr "MusicBrainzin albumin tyyppi" #: quodlibet/util/tags.py:139 msgid "MusicBrainz release group ID" msgstr "MusicBrainzin julkaisuryhmän tunniste" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:142 msgid "track gain" msgstr "raidan vahvistus" #: quodlibet/util/tags.py:143 msgid "track peak" msgstr "raidan huippu" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:145 msgid "album gain" msgstr "albumin vahvistus" #: quodlibet/util/tags.py:146 msgid "album peak" msgstr "albumin huippu" #: quodlibet/util/tags.py:147 msgid "reference loudness" msgstr "voimakkuuden vertailuarvo" #: quodlibet/util/tags.py:152 msgid "discs" msgstr "levyjä" #: quodlibet/util/tags.py:154 msgid "tracks" msgstr "raitoja" #: quodlibet/util/tags.py:155 msgid "last started" msgstr "toisto viimeksi aloitettu" #: quodlibet/util/tags.py:156 msgid "full name" msgstr "Koko polku" #: quodlibet/util/tags.py:163 msgid "mount point" msgstr "liitoskohta" #: quodlibet/util/tags.py:165 msgid "people" msgstr "tekijät" #: quodlibet/util/tags.py:167 msgid "year" msgstr "vuosi" #: quodlibet/util/tags.py:168 msgid "original release year" msgstr "alkuperäinen julkaisuvuosi" #: quodlibet/util/tags.py:169 msgid "bookmark" msgstr "kirjanmerkki" #: quodlibet/util/tags.py:170 msgid "bitdepth" msgstr "bittisyvyys" #: quodlibet/util/tags.py:173 msgid "file format" msgstr "tiedostomuoto" #: quodlibet/util/tags.py:176 msgid "playlists" msgstr "soittolistat" #: quodlibet/util/tags.py:177 msgid "sample rate" msgstr "näytteenottotaajuus" #: quodlibet/util/tags.py:178 msgid "channel count" msgstr "kanavien lkm" #. Translators: e.g. "artist (sort)" #: quodlibet/util/tags.py:268 msgid "sort" msgstr "järjestys" #. Translators: e.g. "performer (roles)" #: quodlibet/util/tags.py:276 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 "" #~ "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 "broker port" #~ msgstr "välittäjän portti" #~ 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 "_Download…" #~ msgstr "_Lataa…" #~ msgid "Download Files" #~ msgstr "Lataa tiedostoja" #~ msgid "Download File" #~ msgstr "Lataa tiedosto" #~ 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 "_Edit" #~ msgstr "_Muokkaa" #~ 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 "Watch this folder for new songs" #~ msgstr "Tarkkaile tätä kansiota uusien kappaleitten varalta" #~ 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 "Removing orphaned iPod track" #~ msgstr "VAROITUS: poistetaan orvoksi jäänyt iPod-kappale" #, 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9591856 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/po/fr.po����������������������������������������������������������������������������0000644�0001750�0001750�00000662315�00000000000�014100� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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: 2019-06-01 19:57+0200\n" "PO-Revision-Date: 2017-02-17 10:45+0100\n" "Last-Translator: Bundy01, Jean-Michel Pouré <jm@poure.com>\n" "Language-Team: français <>\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: Gtranslator 2.91.7\n" #: quodlibet/browsers/albums/main.py:206 #: quodlibet/browsers/covergrid/main.py:54 msgid "_Title" msgstr "_Titre" #: quodlibet/browsers/albums/main.py:207 #: quodlibet/browsers/covergrid/main.py:55 quodlibet/qltk/prefs.py:49 msgid "_Artist" msgstr "_Artiste" #: quodlibet/browsers/albums/main.py:208 #: quodlibet/browsers/covergrid/main.py:56 quodlibet/qltk/prefs.py:54 msgid "_Date" msgstr "_Date" #: quodlibet/browsers/albums/main.py:209 msgid "_Original Date" msgstr "_Date d'origine" #: quodlibet/browsers/albums/main.py:210 #: quodlibet/browsers/covergrid/main.py:57 quodlibet/qltk/prefs.py:53 msgid "_Genre" msgstr "_Genre" #: quodlibet/browsers/albums/main.py:211 #: quodlibet/browsers/covergrid/main.py:58 quodlibet/qltk/prefs.py:58 #: quodlibet/qltk/ratingsmenu.py:39 msgid "_Rating" msgstr "Évaluation" #: quodlibet/browsers/albums/main.py:212 msgid "_Playcount" msgstr "_Nombre d'essais" #: quodlibet/browsers/albums/main.py:218 #: quodlibet/browsers/covergrid/main.py:64 msgid "Sort _by…" msgstr "_Trier par…" #: quodlibet/browsers/albums/main.py:239 #: quodlibet/browsers/covergrid/main.py:85 #: quodlibet/browsers/paned/prefs.py:203 #: quodlibet/browsers/playlists/main.py:667 quodlibet/qltk/exfalsowindow.py:108 #: quodlibet/qltk/pluginwin.py:341 quodlibet/qltk/quodlibetwindow.py:906 msgid "_Preferences" msgstr "_Préférences" #: quodlibet/browsers/albums/main.py:409 msgid "Album List" msgstr "Liste des albums" #: quodlibet/browsers/albums/main.py:410 msgid "_Album List" msgstr "Liste des _albums" #: quodlibet/browsers/albums/main.py:524 #: quodlibet/browsers/covergrid/main.py:285 #: quodlibet/browsers/covergrid/main.py:501 msgid "All Albums" msgstr "Tous les albums" #: quodlibet/browsers/albums/main.py:525 #: quodlibet/browsers/covergrid/main.py:286 #: quodlibet/browsers/covergrid/main.py:502 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d album" msgstr[1] "%d albums" #: quodlibet/browsers/albums/main.py:706 #: quodlibet/browsers/covergrid/main.py:480 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:16 #: 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:385 quodlibet/util/collection.py:247 #, 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:383 quodlibet/util/collection.py:251 #, 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:124 #: quodlibet/ext/songsmenu/cover_download.py:243 msgid "Options" msgstr "Options" #: quodlibet/browsers/albums/prefs.py:74 #: quodlibet/browsers/covergrid/prefs.py:127 msgid "Album Display" msgstr "Affichage des albums" #: quodlibet/browsers/albums/prefs.py:78 #: quodlibet/browsers/covergrid/prefs.py:131 #: quodlibet/browsers/playlists/prefs.py:56 #: quodlibet/ext/songsmenu/albumart.py:328 #: quodlibet/ext/songsmenu/duplicates.py:345 #: quodlibet/ext/songsmenu/filterall.py:48 quodlibet/qltk/bookmarks.py:101 #: quodlibet/qltk/cbes.py:93 quodlibet/qltk/data_editors.py:96 #: quodlibet/qltk/data_editors.py:321 quodlibet/qltk/exfalsowindow.py:286 #: quodlibet/qltk/pluginwin.py:79 quodlibet/qltk/pluginwin.py:428 #: quodlibet/qltk/prefs.py:764 quodlibet/qltk/textedit.py:163 #: quodlibet/update.py:149 msgid "_Close" msgstr "_Fermer" #: quodlibet/browsers/audiofeeds.py:52 quodlibet/browsers/audiofeeds.py:64 #: quodlibet/browsers/audiofeeds.py:66 quodlibet/browsers/audiofeeds.py:156 #: quodlibet/browsers/paned/models.py:85 #: quodlibet/ext/songsmenu/fingerprint/search.py:46 #: quodlibet/formats/_audio.py:488 quodlibet/order/__init__.py:27 #: quodlibet/qltk/information.py:244 quodlibet/qltk/information.py:251 #: quodlibet/qltk/information.py:277 quodlibet/qltk/wlw.py:69 msgid "Unknown" msgstr "Inconnu(e)" #: quodlibet/browsers/audiofeeds.py:247 msgid "New Feed" msgstr "Nouveau flux" #: quodlibet/browsers/audiofeeds.py:248 msgid "Enter the location of an audio feed:" msgstr "Saisir l'adresse d'un flux audio :" #: quodlibet/browsers/audiofeeds.py:249 #: quodlibet/browsers/collection/prefs.py:89 quodlibet/browsers/iradio.py:356 #: quodlibet/browsers/paned/prefs.py:120 #: quodlibet/browsers/playlists/menu.py:96 #: quodlibet/browsers/playlists/util.py:52 quodlibet/qltk/bookmarks.py:62 #: quodlibet/qltk/cbes.py:55 quodlibet/qltk/data_editors.py:308 #: quodlibet/qltk/edittags.py:327 quodlibet/qltk/edittags.py:527 #: quodlibet/qltk/quodlibetwindow.py:1276 quodlibet/qltk/scanbox.py:61 msgid "_Add" msgstr "_Ajouter" #: quodlibet/browsers/audiofeeds.py:303 msgid "Audio Feeds" msgstr "Flux audio" #: quodlibet/browsers/audiofeeds.py:304 msgid "_Audio Feeds" msgstr "_Flux audio" #: quodlibet/browsers/audiofeeds.py:407 quodlibet/qltk/data_editors.py:93 msgid "_New" msgstr "_Nouveau" #: quodlibet/browsers/audiofeeds.py:467 quodlibet/browsers/audiofeeds.py:526 msgid "Unable to add feed" msgstr "Impossible d'importer le flux" #: quodlibet/browsers/audiofeeds.py:468 quodlibet/browsers/audiofeeds.py:527 #, python-format msgid "" "%s could not be added. The server may be down, or the location may not be an " "audio feed." msgstr "" "%s n'a pas pu être ajouté. Le serveur est peut-être en dérangement ou la " "ressource n'est pas un flux audio." #: quodlibet/browsers/audiofeeds.py:475 quodlibet/qltk/filesel.py:260 #: quodlibet/qltk/pluginwin.py:414 msgid "_Refresh" msgstr "_Rafraîchir" #: quodlibet/browsers/audiofeeds.py:476 #: quodlibet/browsers/playlists/main.py:487 #: quodlibet/browsers/playlists/util.py:43 quodlibet/qltk/delete.py:143 #: quodlibet/qltk/filesel.py:257 quodlibet/qltk/lyrics.py:35 #: quodlibet/qltk/maskedbox.py:28 quodlibet/qltk/songsmenu.py:364 msgid "_Delete" msgstr "_Supprimer" #: quodlibet/browsers/audiofeeds.py:543 msgid "" "The current audio backend does not support URLs, Audio Feeds browser " "disabled." msgstr "" "Le système audio ne supporte pas les URLs. Les flux audio ont été désactivés." #: quodlibet/browsers/_base.py:146 quodlibet/browsers/_base.py:149 msgid "Library Browser" msgstr "Navigateur de bibliothèque" #: quodlibet/browsers/_base.py:273 quodlibet/ext/songsmenu/console.py:45 #: quodlibet/ext/songsmenu/refresh.py:30 quodlibet/qltk/exfalsowindow.py:240 #: quodlibet/qltk/information.py:554 quodlibet/qltk/maskedbox.py:68 #: quodlibet/util/collection.py:532 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d titre" msgstr[1] "%d titres" #: quodlibet/browsers/_base.py:401 quodlibet/browsers/_base.py:406 #: quodlibet/qltk/tagsfrompath.py:193 quodlibet/qltk/textedit.py:140 #: quodlibet/util/__init__.py:573 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:23 #, python-format msgid "Unknown %s" msgstr "Inconnu(e) %s" #: quodlibet/browsers/collection/models.py:24 #, python-format msgid "Multiple %s Values" msgstr "%s multiples valeurs" #: quodlibet/browsers/collection/prefs.py:65 #: quodlibet/browsers/paned/prefs.py:93 msgid "_Custom" msgstr "_Autre" #. Remove button #: quodlibet/browsers/collection/prefs.py:93 #: quodlibet/browsers/paned/prefs.py:124 #: quodlibet/browsers/playlists/menu.py:97 #: quodlibet/ext/playlist/remove_duplicates.py:60 #: quodlibet/qltk/bookmarks.py:97 quodlibet/qltk/bookmarks.py:127 #: quodlibet/qltk/cbes.py:82 quodlibet/qltk/cbes.py:89 #: quodlibet/qltk/data_editors.py:78 quodlibet/qltk/data_editors.py:91 #: quodlibet/qltk/data_editors.py:298 quodlibet/qltk/data_editors.py:311 #: quodlibet/qltk/data_editors.py:319 quodlibet/qltk/edittags.py:533 #: quodlibet/qltk/edittags.py:710 quodlibet/qltk/maskedbox.py:48 #: quodlibet/qltk/maskedbox.py:88 quodlibet/qltk/queue.py:427 #: quodlibet/qltk/scanbox.py:36 quodlibet/qltk/scanbox.py:63 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:470 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:247 #: quodlibet/ext/songsmenu/editplaycount.py:45 #: quodlibet/ext/songsmenu/exact_rating.py:38 #: quodlibet/player/gstbe/prefs.py:40 quodlibet/qltk/prefs.py:127 #: quodlibet/qltk/textedit.py:64 msgid "_Apply" msgstr "_Appliquer" #: quodlibet/browsers/collection/prefs.py:197 #: quodlibet/browsers/paned/prefs.py:251 #: quodlibet/browsers/playlists/menu.py:95 #: quodlibet/browsers/playlists/util.py:42 quodlibet/errorreport/ui.py:103 #: quodlibet/ext/playlist/export_to_folder.py:38 #: 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:44 #: quodlibet/ext/songsmenu/fingerprint/search.py:281 #: quodlibet/ext/songsmenu/fingerprint/submit.py:90 #: quodlibet/ext/songsmenu/importexport.py:40 #: quodlibet/ext/songsmenu/lastfmsync.py:218 #: quodlibet/ext/songsmenu/playlist.py:50 #: 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:326 #: quodlibet/qltk/_editutils.py:39 quodlibet/qltk/getstring.py:28 #: quodlibet/qltk/maskedbox.py:27 quodlibet/qltk/msg.py:54 #: quodlibet/qltk/msg.py:93 quodlibet/qltk/msg.py:111 #: quodlibet/qltk/ratingsmenu.py:33 quodlibet/update.py:95 msgid "_Cancel" msgstr "_Annuler" #: quodlibet/browsers/covergrid/main.py:126 msgid "Cover Grid" msgstr "Mur de pochettes" #: quodlibet/browsers/covergrid/main.py:127 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:71 msgid "Show \"All Albums\" Item" msgstr "Montrer l'élément \"Tous les albums\"" #: quodlibet/browsers/covergrid/prefs.py:82 msgid "Wide Mode" msgstr "Mode large" #: quodlibet/browsers/covergrid/prefs.py:114 #: quodlibet/browsers/covergrid/prefs.py:115 msgid "Cover Magnification" msgstr "Échelle de la pochette" #: quodlibet/browsers/filesystem.py:39 msgid "File System" msgstr "Système de fichiers" #: quodlibet/browsers/filesystem.py:40 msgid "_File System" msgstr "_Système de fichiers" #: quodlibet/browsers/filesystem.py:124 quodlibet/qltk/songlist.py:255 msgid "Unable to copy songs" msgstr "Impossible de copier les titres" #: quodlibet/browsers/filesystem.py:125 quodlibet/qltk/songlist.py:256 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:197 msgid "_Add to Library" msgstr "_Ajouter à la bibliothèque" #: quodlibet/browsers/iradio.py:181 msgid "Unsupported file type" msgstr "Type de fichier non supporté" #: quodlibet/browsers/iradio.py:182 #, 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:229 quodlibet/browsers/iradio.py:242 #: quodlibet/browsers/iradio.py:835 msgid "Unable to add station" msgstr "Impossible d'ajouter la radio" #: quodlibet/browsers/iradio.py:253 quodlibet/browsers/iradio.py:486 msgid "Internet Radio" msgstr "Radio Internet" #: quodlibet/browsers/iradio.py:253 msgid "Downloading station list" msgstr "Télécharger la liste des stations" #: quodlibet/browsers/iradio.py:354 msgid "New Station" msgstr "Nouvelle radio Internet" #: quodlibet/browsers/iradio.py:355 msgid "Enter the location of an Internet radio station:" msgstr "Saisissez l'adresse d'une radio Internet:" #: quodlibet/browsers/iradio.py:373 msgid "Electronic" msgstr "" #: quodlibet/browsers/iradio.py:376 msgid "Hip Hop / Rap" msgstr "" #: quodlibet/browsers/iradio.py:377 msgid "Oldies" msgstr "" #: quodlibet/browsers/iradio.py:378 msgid "R&B" msgstr "" #: quodlibet/browsers/iradio.py:379 msgid "Japanese" msgstr "" #: quodlibet/browsers/iradio.py:380 msgid "Indian" msgstr "" #: quodlibet/browsers/iradio.py:382 msgid "Religious" msgstr "Religieux" #: quodlibet/browsers/iradio.py:384 msgid "Charts" msgstr "" #: quodlibet/browsers/iradio.py:385 msgid "Turkish" msgstr "" #: quodlibet/browsers/iradio.py:386 msgid "Reggae / Dancehall" msgstr "" #: quodlibet/browsers/iradio.py:387 msgid "Latin" msgstr "" #: quodlibet/browsers/iradio.py:388 msgid "College Radio" msgstr "Radio Universitaire" #: quodlibet/browsers/iradio.py:389 msgid "Talk / News" msgstr "Discussions / Actualités" #: quodlibet/browsers/iradio.py:390 msgid "Ambient" msgstr "Ambiance" #: quodlibet/browsers/iradio.py:391 msgid "Jazz" msgstr "" #: quodlibet/browsers/iradio.py:392 quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "Classique" #: quodlibet/browsers/iradio.py:393 quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "" #: quodlibet/browsers/iradio.py:394 msgid "Alternative" msgstr "" #: quodlibet/browsers/iradio.py:395 msgid "Metal" msgstr "" #: quodlibet/browsers/iradio.py:396 msgid "Country" msgstr "" #: quodlibet/browsers/iradio.py:397 msgid "News" msgstr "Actualités" #: quodlibet/browsers/iradio.py:398 msgid "Schlager" msgstr "Chansons Populaires" #: quodlibet/browsers/iradio.py:399 msgid "Funk" msgstr "" #: quodlibet/browsers/iradio.py:400 msgid "Indie" msgstr "" #: quodlibet/browsers/iradio.py:401 msgid "Blues" msgstr "" #: quodlibet/browsers/iradio.py:402 msgid "Soul" msgstr "" #: quodlibet/browsers/iradio.py:403 msgid "Lounge" msgstr "" #: quodlibet/browsers/iradio.py:404 msgid "Punk" msgstr "" #: quodlibet/browsers/iradio.py:405 msgid "Reggaeton" msgstr "" #: quodlibet/browsers/iradio.py:407 msgid "Slavic" msgstr "Slave" #: quodlibet/browsers/iradio.py:409 msgid "Greek" msgstr "Grec" #: quodlibet/browsers/iradio.py:410 msgid "Gothic" msgstr "" #: quodlibet/browsers/iradio.py:411 quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "" #: quodlibet/browsers/iradio.py:464 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:470 msgid "_Load Stations" msgstr "_Charger les stations" #: quodlibet/browsers/iradio.py:487 msgid "_Internet Radio" msgstr "_Radio Internet" #: quodlibet/browsers/iradio.py:560 msgid "_New Station…" msgstr "_Nouvelle station…" #: quodlibet/browsers/iradio.py:563 msgid "_Update Stations" msgstr "_Mise à jour des stations" #: quodlibet/browsers/iradio.py:590 msgid "All Stations" msgstr "Toutes les stations" #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:594 quodlibet/browsers/soundcloud/main.py:65 msgid "Favorites" msgstr "Favoris" #: quodlibet/browsers/iradio.py:602 msgid "No Category" msgstr "Aucune catégorie" #: quodlibet/browsers/iradio.py:827 msgid "No stations found" msgstr "Aucune radio trouvée." #: quodlibet/browsers/iradio.py:828 #, python-format msgid "No Internet radio stations were found at %s." msgstr "Aucune station radio ne correspond à %s." #: quodlibet/browsers/iradio.py:836 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:853 msgid "Add to Favorites" msgstr "_Ajouter à la liste des favoris" #: quodlibet/browsers/iradio.py:857 msgid "Remove from Favorites" msgstr "Supprimer des Favoris" #: quodlibet/browsers/iradio.py:957 #, 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:103 quodlibet/qltk/pluginwin.py:122 #: quodlibet/qltk/pluginwin.py:164 msgid "All" msgstr "Tous" #: quodlibet/browsers/paned/prefs.py:41 #: quodlibet/ext/songsmenu/cover_download.py:118 msgid "Small" msgstr "" #: quodlibet/browsers/paned/prefs.py:42 msgid "Wide" msgstr "" #: 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" "<tt>%s</tt>" msgstr "" "Ajouter au motif une balise optionnelle, par exemple <tt>composer</tt> ou\n" "<tt>%s</tt>" #: quodlibet/browsers/paned/prefs.py:231 msgid "Paned Browser Preferences" msgstr "Préférences du navigateur à panneaux" #: quodlibet/browsers/paned/prefs.py:236 msgid "Column layout" msgstr "Disposition en colonne" #: quodlibet/browsers/paned/prefs.py:240 msgid "Column content" msgstr "Contenu de la colonne" #: quodlibet/browsers/paned/prefs.py:242 msgid "Equal pane width" msgstr "Largeur de volet égal" #: quodlibet/browsers/playlists/main.py:48 #: quodlibet/browsers/playlists/main.py:603 quodlibet/qltk/pluginwin.py:168 msgid "Playlists" msgstr "Listes de lecture" #: quodlibet/browsers/playlists/main.py:49 msgid "_Playlists" msgstr "_Listes de lecture" #: quodlibet/browsers/playlists/main.py:152 msgid "_Remove from Playlist" msgstr "Supp_rimer de la liste de lecture" #: quodlibet/browsers/playlists/main.py:217 msgid "New" msgstr "Nouveau" #: quodlibet/browsers/playlists/main.py:221 msgid "Import" msgstr "Importer" #: quodlibet/browsers/playlists/main.py:443 msgid "Unable to import playlist" msgstr "Impossible d'importer la liste de lecture" #: quodlibet/browsers/playlists/main.py:444 msgid "Quod Libet can only import playlists in the M3U/M3U8 and PLS formats." msgstr "" "Quod Libet ne peut importer que les playlists aux formats M3U/M3U8 et PLS." #: quodlibet/browsers/playlists/main.py:494 msgid "_Rename" msgstr "Re_nommer" #: quodlibet/browsers/playlists/main.py:592 msgid "Unable to rename playlist" msgstr "Impossible de renommer la liste de lecture" #: quodlibet/browsers/playlists/main.py:604 msgid "Import Playlist" msgstr "Importer une liste de lecture" #: quodlibet/browsers/playlists/main.py:604 msgid "_Import" msgstr "_Importer" #: quodlibet/browsers/playlists/menu.py:25 msgid "_New Playlist…" msgstr "_Nouvelle liste de lecture…" #: quodlibet/browsers/playlists/menu.py:86 #, 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:90 #, 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:33 #, 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:35 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:50 #: quodlibet/browsers/playlists/util.py:125 quodlibet/util/collection.py:575 msgid "New Playlist" msgstr "Créer une liste de lecture" #: quodlibet/browsers/playlists/util.py:51 msgid "Enter a name for the new playlist:" msgstr "Saisissez un nom pour la nouvelle liste de lecture:" #: quodlibet/browsers/playlists/util.py:89 #, 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/search.py:32 msgid "_Limit Results" msgstr "_Limiter les résultats" #: quodlibet/browsers/search.py:37 msgid "_Allow multiple queries" msgstr "_Permettre plusieurs requêtes" #: quodlibet/browsers/search.py:53 msgid "Search Library" msgstr "Rechercher dans la bibliothèque" #: quodlibet/browsers/search.py:54 msgid "_Search Library" msgstr "_Rechercher dans la bibliothèque" #: quodlibet/browsers/soundcloud/main.py:39 msgid "Soundcloud Browser" msgstr "Navigateur Soundcloud" #: quodlibet/browsers/soundcloud/main.py:40 msgid "Sound_cloud" msgstr "Sound_cloud" #: quodlibet/browsers/soundcloud/main.py:60 quodlibet/qltk/searchbar.py:81 msgid "Search" msgstr "Rechercher" #: quodlibet/browsers/soundcloud/main.py:69 msgid "My tracks" msgstr "Mes pistes" #: quodlibet/browsers/soundcloud/main.py:141 #, python-format msgid "Go to %s" msgstr "Aller à %s" #: quodlibet/browsers/soundcloud/main.py:443 msgid "Connected" msgstr "Connecté" #: quodlibet/browsers/soundcloud/main.py:444 #, python-format msgid "Quod Libet is now connected, <b>%s</b>!" msgstr "Quod Libet est maintenant connecté, <b>%s</b>!" #: quodlibet/browsers/soundcloud/main.py:456 #, python-format msgid "Log out of %s" msgstr "Se déconnecter de %s" #: quodlibet/browsers/soundcloud/main.py:458 msgid "Enter code…" msgstr "Saisir le code …" #: quodlibet/browsers/soundcloud/main.py:459 #, python-format msgid "Log in to %s" msgstr "Se connecter à %s" #: quodlibet/browsers/soundcloud/util.py:86 msgid "Soundcloud authorisation" msgstr "Autorisation Soundcloud" #: quodlibet/browsers/soundcloud/util.py:87 msgid "Enter Soundcloud auth code:" msgstr "Saisir le code d'authentification Soundcloud :" #: quodlibet/cli.py:50 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:86 msgid "a music library and player" msgstr "un lecteur et une bibliothèque de musique" #: quodlibet/cli.py:87 msgid "[option]" msgstr "[option]" #: quodlibet/cli.py:89 msgid "Print the playing song and exit" msgstr "Afficher le titre en cours de lecture et quitter" #: quodlibet/cli.py:90 msgid "Begin playing immediately" msgstr "Commencer la lecture immédiatement" #: quodlibet/cli.py:91 msgid "Don't show any windows on start" msgstr "Cacher toutes les fenêtres au démarrage" #: quodlibet/cli.py:94 msgid "Jump to next song" msgstr "Aller au titre suivant" #: quodlibet/cli.py:96 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:97 msgid "Jump to previous song" msgstr "Aller au titre précédent" #: quodlibet/cli.py:98 msgid "Start playback" msgstr "Commencer la lecture" #: quodlibet/cli.py:99 msgid "Pause playback" msgstr "Suspendre la lecture" #: quodlibet/cli.py:100 msgid "Toggle play/pause mode" msgstr "Basculer entre le mode lecture et pause" #: quodlibet/cli.py:101 msgid "Stop playback" msgstr "Arrêter la lecture" #: quodlibet/cli.py:102 msgid "Turn up volume" msgstr "Augmenter le volume" #: quodlibet/cli.py:103 msgid "Turn down volume" msgstr "Diminuer le volume" #: quodlibet/cli.py:104 msgid "Increase rating of playing song by one star" msgstr "Augmenter la note d'une étoile pour la lecture d'une chanson" #: quodlibet/cli.py:105 msgid "Decrease rating of playing song by one star" msgstr "Diminuer la note d'une étoile pour la lecture d'une chanson" #: quodlibet/cli.py:106 msgid "Print player status" msgstr "Afficher l'état du lecteur" #: quodlibet/cli.py:107 msgid "Hide main window" msgstr "Cacher la fenêtre principale" #: quodlibet/cli.py:108 msgid "Show main window" msgstr "Afficher la fenêtre principale" #: quodlibet/cli.py:109 msgid "Toggle main window visibility" msgstr "Basculer la visibilité de la fenêtre principale" #: quodlibet/cli.py:110 msgid "Focus the running player" msgstr "Focaliser le lecteur en fonction" #: quodlibet/cli.py:111 msgid "Remove active browser filters" msgstr "Enlever les filtres actifs du navigateur" #: quodlibet/cli.py:112 msgid "Refresh and rescan library" msgstr "Rafraîchir et rescanner la bibliothèque" #: quodlibet/cli.py:113 msgid "List available browsers" msgstr "Lister les navigateurs disponibles" #: quodlibet/cli.py:114 msgid "Print the current playlist" msgstr "Afficher la liste de lecture" #: quodlibet/cli.py:115 msgid "Print the contents of the queue" msgstr "Afficher le contenu de la file d'attente" #: quodlibet/cli.py:116 msgid "Print the active text query" msgstr "Afficher le texte de la recherche en cours" #: quodlibet/cli.py:117 msgid "Start without plugins" msgstr "Démarrer sans greffons" #: quodlibet/cli.py:118 msgid "Start Quod Libet if it isn't running" msgstr "Démarrer Quod Libet s'il n'est pas en fonctionnement." #: quodlibet/cli.py:119 msgid "Exit Quod Libet" msgstr "Quitter Quod Libet" #: quodlibet/cli.py:124 msgid "Seek within the playing song" msgstr "Se déplacer dans le titre en cours de lecture" #: quodlibet/cli.py:124 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: quodlibet/cli.py:125 msgid "Set or toggle shuffle mode" msgstr "Activer ou désactiver la lecture aléatoire" #: quodlibet/cli.py:126 msgid "Set shuffle mode type" msgstr "Définir le type de mode de lecture aléatoire" #: quodlibet/cli.py:127 msgid "Turn repeat off, on, or toggle it" msgstr "Activer, désactiver ou basculer le mode répétition" #: quodlibet/cli.py:128 msgid "Set repeat mode type" msgstr "Définir le type de mode de répétition" #: quodlibet/cli.py:129 msgid "Set the volume" msgstr "Régler le volume" #: quodlibet/cli.py:130 msgid "Search your audio library" msgstr "Rechercher dans votre bibliothèque de musique" #: quodlibet/cli.py:130 quodlibet/cli.py:140 quodlibet/cli.py:144 #: quodlibet/cli.py:146 msgid "query" msgstr "requête" #: quodlibet/cli.py:131 msgid "Play a file" msgstr "Lire un fichier" #: quodlibet/cli.py:131 quodlibet/cli.py:140 quodlibet/cli.py:146 msgctxt "command" msgid "filename" msgstr "nom de fichier" #: quodlibet/cli.py:132 msgid "Set rating of playing song" msgstr "Définir l'évaluation de la lecture d'un morceau" #: quodlibet/cli.py:133 msgid "Set the current browser" msgstr "Définir le navigateur courant" #: quodlibet/cli.py:134 msgid "Stop after the playing song" msgstr "Arrêter après ce titre" #: quodlibet/cli.py:135 msgid "Open a new browser" msgstr "Démarrer un nouveau navigateur" #: quodlibet/cli.py:136 msgid "Show or hide the queue" msgstr "Afficher ou cacher la file d'attente" #: quodlibet/cli.py:137 msgid "Filter on a random value" msgstr "Filtrer au hasard" #: quodlibet/cli.py:137 msgctxt "command" msgid "tag" msgstr "étiquette" #: quodlibet/cli.py:138 msgid "Filter on a tag value" msgstr "Filtrer sur la valeur d'une étiquette" #: quodlibet/cli.py:138 msgid "tag=value" msgstr "étiquette=valeur" #: quodlibet/cli.py:139 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:141 msgid "Enqueue comma-separated files" msgstr "" "Mettre des fichiers séparés par un point-virgule dans la file d'attente" #: quodlibet/cli.py:142 quodlibet/util/tags.py:157 msgid "filename" msgstr "nom de fichier" #: quodlibet/cli.py:143 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:145 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:147 msgid "Add a file or directory to the library" msgstr "Ajouter un fichier ou un répertoire à la bibliothèque" #: quodlibet/cli.py:148 quodlibet/util/tags.py:100 msgid "location" msgstr "endroit" #: quodlibet/cli.py:213 #, python-format msgid "Invalid argument for '%s'." msgstr "Argument non valide pour '%s'." #: quodlibet/cli.py:214 quodlibet/util/__init__.py:173 #, 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 "Quit Program" msgstr "Quitter le Programme" #: 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 "_Envoi" #: quodlibet/errorreport/ui.py:110 msgid "Short description…" msgstr "Courte description…" #: quodlibet/errorreport/ui.py:113 msgid "Data to be sent:" msgstr "Données à envoyer :" #: quodlibet/exfalso.py:34 msgid "an audio tag editor" msgstr "un éditeur d'étiquettes (tags) audio" #: quodlibet/exfalso.py:34 quodlibet/util/tags.py:158 msgid "directory" msgstr "répertoire" #: quodlibet/exfalso.py:41 msgid "Audio metadata editor" msgstr "Editeur 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:20 msgid "" "Downloads covers linked to by the artwork_url tag. This works with the " "Soundcloud browser." msgstr "" "Téléchargements des pochettes liées par le tag artwork_url. Cela fonctionne " "avec le navigateur Soundcloud." #: 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:20 msgid "MusicBrainz Cover Source" msgstr "Source d'illustrations MusicBrainz" #: quodlibet/ext/covers/musicbrainz.py:21 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 étiquettes 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 _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:19 msgid "" "Allows arbitrary regex substitutions (s///) when tagging or renaming files." msgstr "" "Autorise les substitutions regex (//s) durant l'étiquetage ou le renommage " "des fichiers." #: quodlibet/ext/editing/titlecase.py:20 msgid "Title Case" msgstr "Titre Version" #: quodlibet/ext/editing/titlecase.py:21 msgid "Title-cases tag values in the tag editor." msgstr "Valeurs du tag Titre-version dans l'éditeur de tags." #: quodlibet/ext/editing/titlecase.py:40 msgid "Title-_case Value" msgstr "Valeur Titre-_version" #: 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 "_Humain titre version" #: 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:67 msgid "Advanced Preferences" msgstr "Préférences avancées" #: quodlibet/ext/events/advanced_preferences.py:68 msgid "Allow editing of advanced config settings." msgstr "Permet d'éditer les paramètres de configurations avancées." #: quodlibet/ext/events/advanced_preferences.py:180 msgid "I know what I'm doing" msgstr "Je confirme comprendre 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 concernant un titre dès qu'il est modifié." #: 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/ext/events/weblyrics.py:318 quodlibet/qltk/prefs.py:266 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:66 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:172 msgid "Effects" msgstr "Effets" #: quodlibet/ext/events/animosd/prefs.py:288 msgid "Ed_it Display Pattern…" msgstr "Ed_it Modèle d'Affichage…" #: quodlibet/ext/events/animosd/prefs.py:292 #: 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 la demande" #: 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 "Backend Audio" #: quodlibet/ext/events/auto_library_update.py:138 msgid "Automatic Library Update" msgstr "Rafraîchir la bibliothèque automatiquement" #: quodlibet/ext/events/auto_library_update.py:139 #, python-format msgid "Keeps your library up to date with inotify. Requires %s." msgstr "Maintenir votre bibliothèque à jour avec inotify. Dépend de %s" #: 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 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." #: quodlibet/ext/events/bansheeimport.py:106 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:111 #: quodlibet/ext/events/rbimport.py:114 msgid "Import Failed" msgstr "L'importation a échoué" # python-format #: quodlibet/ext/events/bansheeimport.py:117 #, 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 la " "chanson %d" msgstr[1] "" "Succès de l'importation des classifications et des statistiques pour les " "chansons %d" #: quodlibet/ext/events/bansheeimport.py:126 msgid "Banshee Import" msgstr "Importation Banshee" #: quodlibet/ext/events/bansheeimport.py:127 msgid "Imports ratings and song statistics from Banshee." msgstr "" "IImporte les classifications et les statistiques des chansons de Banshee." #: quodlibet/ext/events/bansheeimport.py:136 msgid "_Database path:" msgstr "_Chemin de la base de données :" #: quodlibet/ext/events/bansheeimport.py:164 #: quodlibet/ext/events/rbimport.py:132 msgid "Start Import" msgstr "Démarrer l'_importation" #: quodlibet/ext/events/clock.py:24 msgid "Alarm Clock" msgstr "Réveille-matin" #: 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 "Fondus enchaînés et pauses de votre musique." #: quodlibet/ext/events/equalizer.py:26 msgid "Flat" msgstr "Plat" #: 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 "É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:93 #: quodlibet/ext/gstreamer/karaoke.py:95 #, python-format msgid "%d Hz" msgstr "%d Hz" #: quodlibet/ext/events/equalizer.py:198 #: quodlibet/ext/gstreamer/crossfeed.py:112 #, 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/playlist/export_to_squeezebox.py:80 #: quodlibet/ext/songsmenu/albumart.py:324 #: quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/cover_download.py:309 #: quodlibet/ext/songsmenu/fingerprint/search.py:278 #: quodlibet/ext/songsmenu/html.py:75 quodlibet/ext/songsmenu/lastfmsync.py:219 #: quodlibet/ext/songsmenu/playlist.py:51 #: quodlibet/ext/songsmenu/replaygain.py:354 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/_editutils.py:40 #: quodlibet/qltk/lyrics.py:34 quodlibet/qltk/msg.py:52 #: quodlibet/qltk/renamefiles.py:216 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 "" #: quodlibet/ext/events/gajim_status.py:31 msgid "away" msgstr "lointain" #: quodlibet/ext/events/gajim_status.py:32 msgid "xa" msgstr "" #: 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 "Compte:" #: 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:42 msgid "Inhibit Screensaver" msgstr "Désactiver l'économiseur d'écran" #: quodlibet/ext/events/inhibit.py:43 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." #: quodlibet/ext/events/inhibit.py:52 msgid "Music is playing" msgstr "La musique est en cours de lecture" #: quodlibet/ext/events/iradiolog.py:16 msgid "Internet Radio Log" msgstr "Logs radio Internet" #: quodlibet/ext/events/iradiolog.py:17 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 "" #: quodlibet/ext/events/jep118.py:31 msgid "Outputs a Jabber User Tunes file to ~/.quodlibet/jabber." msgstr "Sortie d'un fichier Jabber User Tunes vers ~/.quodlibet/jabber." #: 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 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 "Connection" #: quodlibet/ext/events/mpdserver/__init__.py:163 msgid "Tested Clients" msgstr "Clients testés" #: quodlibet/ext/events/mpris/__init__.py:37 msgid "MPRIS D-Bus Support" msgstr "Support D-Bus MPRIS" #: quodlibet/ext/events/mpris/__init__.py:38 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." #: quodlibet/ext/events/mpris/__init__.py:44 #: 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/mpris/__init__.py:47 #: quodlibet/ext/events/themeswitcher.py:84 #: quodlibet/ext/gstreamer/compressor.py:99 #: quodlibet/ext/gstreamer/crossfeed.py:136 #: quodlibet/ext/gstreamer/karaoke.py:99 quodlibet/ext/gstreamer/pitch.py:89 #: quodlibet/qltk/prefs.py:741 msgid "Preferences" msgstr "Préférences" #: quodlibet/ext/events/mqtt.py:54 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "Accepte les modèles de QL, p. ex. %s" #: quodlibet/ext/events/mqtt.py:60 msgid "MQTT Publisher" msgstr "Éditeur MQTT" #: quodlibet/ext/events/mqtt.py:61 msgid "Publishes status messages to an MQTT topic." msgstr "Publie des messages de statut à un thème MQTT." #: quodlibet/ext/events/mqtt.py:128 msgid "Broker hostname" msgstr "Nom d'hôte de l'intermédiaire" #: quodlibet/ext/events/mqtt.py:129 msgid "broker hostname / IP (defaults to localhost)" msgstr "nom d'hôte du mandataire / IP (par défaut : localhost)" #: quodlibet/ext/events/mqtt.py:131 msgid "Broker port" msgstr "Port de l'intermédiaire" #: quodlibet/ext/events/mqtt.py:131 msgid "broker port (defaults to 1883" msgstr "" #: quodlibet/ext/events/mqtt.py:133 msgid "Topic" msgstr "Sujet" #: quodlibet/ext/events/mqtt.py:135 msgid "Playing Pattern" msgstr "Motif de lecture" #: quodlibet/ext/events/mqtt.py:137 msgid "Status text when a song is started." msgstr "Texte de statut lorsqu'un morceau est lancé." #: quodlibet/ext/events/mqtt.py:139 msgid "Paused Pattern" msgstr "Modèle en Pause" #: quodlibet/ext/events/mqtt.py:141 msgid "Text when a song is paused." msgstr "Texte affiché quand un titre est en pause" #: quodlibet/ext/events/mqtt.py:143 msgid "No-song Text" msgstr "Texte sans chanson" #: quodlibet/ext/events/mqtt.py:145 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:156 msgid "MQTT Configuration" msgstr "Configuration MQTT" #: quodlibet/ext/events/mqtt.py:160 msgid "Status Text" msgstr "Texte indiquant le statut" #: quodlibet/ext/events/mqtt.py:192 #, 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:196 #, 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:199 msgid "Connection error" msgstr "Erreur de connexion" #: 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 modifié <i>_manuellement</i>" #: quodlibet/ext/events/notify.py:154 msgid "Only on <i>_automatic</i> song changes" msgstr "Si le titre est modifié <i>_automatiquement</i>" #: quodlibet/ext/events/notify.py:162 msgid "On <i>a_ll</i> song changes" msgstr "À partir de <i>i>a_ll</i> Changements de chanson" #: 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/qlscrobbler.py:175 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" "Veuillez visiter la fenêtre Plugins pour configurer QLScrobbler. D'ici là, " "les chansons ne seront pas soumises." #: quodlibet/ext/events/qlscrobbler.py:252 #, python-format msgid "Could not contact service '%s'." msgstr "Impossible de se connecter au service '%s'" #: quodlibet/ext/events/qlscrobbler.py:258 msgid "Authentication failed: invalid URL." msgstr "Authentification impossible: URL invalide" #: quodlibet/ext/events/qlscrobbler.py:275 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "" "Authentication failed: nom d'utilisateur invalide '%s' ou mauvais mot de " "passe." #: quodlibet/ext/events/qlscrobbler.py:280 msgid "Client is banned. Contact the author." msgstr "Le client a été banni. Veuillez contacter l'auteur." #: quodlibet/ext/events/qlscrobbler.py:284 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" "Mauvaise heure système. Les soumissions peuvent échouer jusqu'à ce qu'elles " "soient corrigées." #: quodlibet/ext/events/qlscrobbler.py:349 msgid "AudioScrobbler Submission" msgstr "Soumission à AudioScrobbler" #: quodlibet/ext/events/qlscrobbler.py:350 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:455 msgid "Authentication successful." msgstr "Authentification validée." #: quodlibet/ext/events/qlscrobbler.py:467 msgid "_Service:" msgstr "_Service :" #: quodlibet/ext/events/qlscrobbler.py:467 msgid "_URL:" msgstr "_URL :" #: quodlibet/ext/events/qlscrobbler.py:467 msgid "User_name:" msgstr "_Nom d'utilisateur :" #: quodlibet/ext/events/qlscrobbler.py:468 msgid "_Password:" msgstr "Mot de _passe :" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:484 msgid "Other…" msgstr "Autre ..." #. verify data #: quodlibet/ext/events/qlscrobbler.py:522 msgid "_Verify account data" msgstr "_Vérification des données du compte" #: quodlibet/ext/events/qlscrobbler.py:527 #: quodlibet/ext/songsmenu/lastfmsync.py:312 msgid "Account" msgstr "Compte" #: quodlibet/ext/events/qlscrobbler.py:535 msgid "_Artist pattern:" msgstr "Motif de l'_artiste :" #: quodlibet/ext/events/qlscrobbler.py:535 msgid "_Title pattern:" msgstr "Motif du _titre" #: quodlibet/ext/events/qlscrobbler.py:536 msgid "Exclude _filter:" msgstr "_Filtre d'exclusion :" #: quodlibet/ext/events/qlscrobbler.py:554 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:564 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:573 msgid "Songs matching this filter will not be submitted" msgstr "Les titres correspondant à cette recherche ne seront pas soumis" #: quodlibet/ext/events/qlscrobbler.py:581 msgid "_Offline mode (don't submit anything)" msgstr "M_ode non-connecté (ne rien soumettre)" #: quodlibet/ext/events/qlscrobbler.py:585 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:28 msgid "Random Album Playback" msgstr "Lecture aléatoire de l'album" #: quodlibet/ext/events/randomalbum.py:29 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:39 msgid "Rated higher" msgstr "Le mieux évalué" #: quodlibet/ext/events/randomalbum.py:40 msgid "Played more often" msgstr "Le plus joué" #: quodlibet/ext/events/randomalbum.py:41 msgid "Skipped more often" msgstr "Le plus sauté" #: quodlibet/ext/events/randomalbum.py:42 msgid "Played more recently" msgstr "Joué récemment" #: quodlibet/ext/events/randomalbum.py:43 msgid "Started more recently" msgstr "Lancé récemment" #: quodlibet/ext/events/randomalbum.py:44 msgid "Added more recently" msgstr "Ajouté récemment" #: quodlibet/ext/events/randomalbum.py:45 msgid "Longer albums" msgstr "Albums les plus longs" #: quodlibet/ext/events/randomalbum.py:84 msgid "seconds before starting next album" msgstr "secondes avant de lancer l'album suivant" #: quodlibet/ext/events/randomalbum.py:88 msgid "Weights" msgstr "Poids" #: quodlibet/ext/events/randomalbum.py:90 msgid "Play some albums more than others" msgstr "Lire des albums plus souvent que d'autres" #: quodlibet/ext/events/randomalbum.py:104 msgid "avoid" msgstr "éviter" #: quodlibet/ext/events/randomalbum.py:115 msgid "prefer" msgstr "préférer" #: quodlibet/ext/events/randomalbum.py:219 msgid "Random Album" msgstr "Album aléatoire" #: quodlibet/ext/events/randomalbum.py:220 #, python-format msgid "Waiting to start %s" msgstr "En attente de lancement de %s" #: quodlibet/ext/events/rbimport.py:119 #, 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:127 msgid "Rhythmbox Import" msgstr "Importation Rhythmbox" #: quodlibet/ext/events/rbimport.py:128 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:73 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:79 msgid "GNOME Search Provider" msgstr "Fournisseur de recherche Gnome" #: quodlibet/ext/events/searchprovider.py:80 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" "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 "" "Stockez les points de recherche A et/ou B pour les pistes. Passez à l'heure " "A et arrêtez-vous après l'heure B lorsque la piste est jouée.\n" "Notez que changer le nom des points ci-dessous ne met pas à jour les noms de " "signets réels, mais seulement les noms de signets que le plugin 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:29 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:57 #: quodlibet/ext/playlist/export_to_squeezebox.py:89 msgid "Error finding Squeezebox server" msgstr "Recherche d'erreurs serveur Squeezebox" #: quodlibet/ext/events/squeezebox_sync.py:58 #: quodlibet/ext/playlist/export_to_squeezebox.py:90 #, python-format msgid "Error finding %s. Please check settings" msgstr "Recherche d'erreurs %s. Veuillez vérifier les paramètres" #: quodlibet/ext/events/synchronizedlyrics.py:34 msgid "Synchronized Lyrics" msgstr "Paroles synchronisées" #: quodlibet/ext/events/synchronizedlyrics.py:35 msgid "Shows synchronized lyrics from .lrc file with same name as the track." msgstr "" "Afficher les paroles de manière synchronisée avec l'audio, en utilisant un " "fichier .lrc de même nom que la piste." #: quodlibet/ext/events/synchronizedlyrics.py:69 msgid "Text:" msgstr "Texte:" #: quodlibet/ext/events/synchronizedlyrics.py:79 msgid "Background:" msgstr "Fond :" #: quodlibet/ext/events/synchronizedlyrics.py:90 msgid "Font" msgstr "Police" #: quodlibet/ext/events/synchronizedlyrics.py:93 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 la chanson 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:145 msgid "Paused:" msgstr "En pause :" #: quodlibet/ext/events/telepathy_status.py:146 #, 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:162 msgid "Plain text for status when there is no current song" msgstr "Texte brut pour le statut lorsqu'il n'y a pas de chanson en cours" #: quodlibet/ext/events/telepathy_status.py:163 msgid "No song:" msgstr "Aucun titre :" #. Frame #: quodlibet/ext/events/telepathy_status.py:170 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 "Theme natif" #: 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:91 msgid "Thumb Rating" msgstr "Évaluation du pouce" #: quodlibet/ext/events/thumbrating.py:92 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 '~#score'." msgstr "" "Ajoute un système de notation pouce en haut/ pouce en bas qui est converti " "en une valeur de notation. Utile pour conserver les totaux des votes en " "cours d'exécution et trier par '~#score'." #: 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:47 msgid "Not playing" msgstr "Pas de lecture en cours" #: quodlibet/ext/events/trayicon/__init__.py:53 msgid "Tray Icon" msgstr "" #: quodlibet/ext/events/trayicon/__init__.py:54 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:183 quodlibet/qltk/quodlibetwindow.py:936 #: quodlibet/qltk/quodlibetwindow.py:1142 msgid "_Play" msgstr "_Lecture" #: quodlibet/ext/events/trayicon/menu.py:63 #: quodlibet/qltk/quodlibetwindow.py:185 quodlibet/qltk/quodlibetwindow.py:1144 #: quodlibet/qltk/wlw.py:50 msgid "P_ause" msgstr "P_ause" #: quodlibet/ext/events/trayicon/menu.py:68 #: quodlibet/qltk/quodlibetwindow.py:190 quodlibet/qltk/quodlibetwindow.py:931 msgid "Pre_vious" msgstr "Précédent" #: quodlibet/ext/events/trayicon/menu.py:71 #: quodlibet/qltk/quodlibetwindow.py:194 quodlibet/qltk/quodlibetwindow.py:941 msgid "_Next" msgstr "Suivant" #: quodlibet/ext/events/trayicon/menu.py:76 msgid "_Shuffle" msgstr "Lire aléatoirement" #: 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:902 msgid "Open _Browser" msgstr "Ouvrir le _Navigateur" #: quodlibet/ext/events/trayicon/menu.py:103 #: quodlibet/qltk/quodlibetwindow.py:921 quodlibet/qltk/songsmenu.py:383 msgid "Edit _Tags" msgstr "Éditer les étique_ttes" #: quodlibet/ext/events/trayicon/menu.py:112 #: quodlibet/qltk/quodlibetwindow.py:864 quodlibet/qltk/songsmenu.py:396 msgid "_Information" msgstr "_Informations" #: quodlibet/ext/events/trayicon/menu.py:114 quodlibet/qltk/songsmenu.py:324 msgid "Play_lists" msgstr "_Listes de lecture" #: quodlibet/ext/events/trayicon/menu.py:132 #: quodlibet/qltk/quodlibetwindow.py:916 msgid "_Quit" msgstr "_Quitter" #: quodlibet/ext/events/trayicon/prefs.py:38 quodlibet/qltk/prefs.py:69 msgid "Behavior" msgstr "Fonctionnement" #: 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 molete de la souris permet de passer d'une musique à l'autre" #: 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 "Suggestions Affichage" #: 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 du tag ou du 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 quodlibet/ext/events/weblyrics.py:193 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 "" #: quodlibet/ext/events/visualisations.py:91 msgid "Reload" msgstr "Recharger" #: quodlibet/ext/events/waveformseekbar.py:603 msgid "Waveform Seek Bar" msgstr "Barre de recherche Waveform" #: quodlibet/ext/events/waveformseekbar.py:607 msgid "A seekbar in the shape of the waveform of the current song." msgstr "Une barre de recherche en forme d'onde de la chanson actuelle." #: quodlibet/ext/events/waveformseekbar.py:676 msgid "Override foreground color:" msgstr "Remplacer la couleur d'avant-plan :" #: quodlibet/ext/events/waveformseekbar.py:680 msgid "Override hover color:" msgstr "Remplacer la couleur du survol :" #: quodlibet/ext/events/waveformseekbar.py:684 msgid "Override remaining color:" msgstr "Remplacer la couleur restante :" #: quodlibet/ext/events/waveformseekbar.py:688 msgid "Show current position" msgstr "Afficher la position actuelle" #: quodlibet/ext/events/waveformseekbar.py:693 msgid "Show time labels" msgstr "Afficher les vignettes de temps" #: quodlibet/ext/events/waveformseekbar.py:701 msgid "Seek amount when scrolling (milliseconds):" msgstr "Cherchez la quantité lors du défilement (millisecondes) :" #: quodlibet/ext/events/weblyrics.py:208 msgid "No lyrics found" msgstr "Les paroles n'ont pas été trouvées." #: quodlibet/ext/events/weblyrics.py:268 msgid "_Zoom level:" msgstr "Niveau de _Zoom :" #: quodlibet/ext/events/weblyrics.py:286 msgid "URL:" msgstr "URL :" #: quodlibet/ext/events/weblyrics.py:291 msgid "Revert to default" msgstr "Rétablir les valeurs par défaut" #: quodlibet/ext/events/weblyrics.py:306 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." #: quodlibet/ext/events/weblyrics.py:323 msgid "Alternate search" msgstr "Recherche alternative" #: quodlibet/ext/events/weblyrics.py:332 msgid "Web Lyrics" msgstr "Paroles sur le Web" #: quodlibet/ext/events/weblyrics.py:333 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." #: 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:20 msgid "_Threshold:" msgstr "Seuil :" #: quodlibet/ext/gstreamer/compressor.py:21 msgid "Threshold until the filter is activated" msgstr "Niveau en deçà duquel le filtre est activé" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "R_atio:" msgstr "Ratio :" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "Compression ratio" msgstr "Ratio de compression" #: quodlibet/ext/gstreamer/compressor.py:74 #: quodlibet/ext/gstreamer/karaoke.py:91 #, python-format msgid "%d %%" msgstr "" #: quodlibet/ext/gstreamer/compressor.py:105 msgid "Audio Compressor" msgstr "Compresseur audio" #: quodlibet/ext/gstreamer/compressor.py:106 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:19 msgid "_Preset:" msgstr "Présélection :" #: quodlibet/ext/gstreamer/crossfeed.py:19 msgid "Filter preset" msgstr "Préréglage du filtre" #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Frequency cut:" msgstr "Coupe de _Fréquence :" #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Low-pass filter cut frequency" msgstr "Coupe des fréquences en utilisant un filtre passe bas" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed _level:" msgstr "Niveau d'entrée :" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed level" msgstr "Niveau d'entrée" #: quodlibet/ext/gstreamer/crossfeed.py:25 msgid "Default" msgstr "Par défaut" #: quodlibet/ext/gstreamer/crossfeed.py:26 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:27 msgid "Chu Moy" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "Près de l'alimentateur transversal de Chu Moy (populaire)" #: quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Jan Meier" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:30 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:31 msgid "Custom" msgstr "Personnalisé" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Custom settings" msgstr "Configuration personnalisée" #: quodlibet/ext/gstreamer/crossfeed.py:152 msgid "Crossfeed" msgstr "Crossfeed" #: quodlibet/ext/gstreamer/crossfeed.py:153 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:20 msgid "Filter _band:" msgstr "Filtrer sur le groupe" #: quodlibet/ext/gstreamer/karaoke.py:21 msgid "The Frequency band of the filter" msgstr "La largeur de bande du filtre" #: quodlibet/ext/gstreamer/karaoke.py:22 msgid "Filter _width:" msgstr "Filtrer sur la taille" #: quodlibet/ext/gstreamer/karaoke.py:23 msgid "The Frequency width of the filter" msgstr "La largeur de fréquence du filtre" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "_Level:" msgstr "Niveau :" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "Level of the effect" msgstr "Niveau de l'effet" #: quodlibet/ext/gstreamer/karaoke.py:105 msgid "Karaoke" msgstr "" #: quodlibet/ext/gstreamer/karaoke.py:106 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:21 msgid "R_ate:" msgstr "T_aux :" #: quodlibet/ext/gstreamer/pitch.py:22 msgid "_Tempo:" msgstr "Tempo :" #: quodlibet/ext/gstreamer/pitch.py:23 msgid "_Pitch:" msgstr "_Tonalité :" #: quodlibet/ext/gstreamer/pitch.py:95 msgid "Audio Pitch / Speed" msgstr "Tonalité / Vitesse Audio" #: quodlibet/ext/gstreamer/pitch.py:96 msgid "Controls the pitch of an audio stream." msgstr "Contrôle la hauteur 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:147 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:100 msgid "Exports a playlist by copying files to a folder." msgstr "Exporte une liste de lecture en copiant des fichiers dans un dossier." #: quodlibet/ext/playlist/export_to_folder.py:121 #: quodlibet/ext/songsmenu/playlist.py:132 msgid "Unable to export playlist" msgstr "Impossible d'exporter la liste de lecture" #: quodlibet/ext/playlist/export_to_folder.py:122 msgid "Ensure you have write access to the destination." msgstr "Assurez-vous d'avoir un accès en écriture à la destination." #: quodlibet/ext/playlist/export_to_folder.py:165 msgid "Default filename pattern:" msgstr "Modèle de nom de fichier par défaut :" #: 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. 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>." #: 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:96 msgid "Export to Squeezebox playlist" msgstr "EXporter vers 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 chansons en double seront supprimées de la playlist'%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 "" "Playback follows your selection, or the next song in the list once exhausted." msgstr "" "La lecture suit votre sélection, ou la chanson suivante dans la liste une " "fois épuisée." #: quodlibet/ext/playorder/playcounteq.py:21 msgid "Playcount Equalizer" msgstr "Équalisateur de compte de lecture" #: quodlibet/ext/playorder/playcounteq.py:22 msgid "Shuffle, preferring songs with fewer total plays." msgstr "Lire aléatoirement, en préférant les titres les moins joués." #: quodlibet/ext/playorder/playcounteq.py:24 msgid "Prefer less played" msgstr "Préférer les moins lus" #: quodlibet/ext/playorder/queue.py:19 msgid "Queue Only" msgstr "Uniquement en file d'attente" #: quodlibet/ext/playorder/queue.py:21 msgid "" "Limits playing of songs to the queue. Select this play order in the main " "window, then double-clicking any song will enqueue it instead of playing." msgstr "" "Limite la lecture des chansons à la file d'attente. Sélectionnez cet ordre " "de lecture dans la fenêtre principale, puis double-cliquez sur n'importe " "quel morceau pour le mettre en file d'attente au lieu de le lire." #: quodlibet/ext/playorder/reverse.py:14 msgid "Reverse" msgstr "Inverser" #: quodlibet/ext/playorder/reverse.py:16 msgid "Reverses the play order of songs." msgstr "Inverser l'ordre dans lequel les titres sont joués." #: quodlibet/ext/playorder/shufflebygrouping.py:31 #: quodlibet/ext/playorder/shufflebygrouping.py:93 msgid "Shuffle by Grouping" msgstr "Lecture aléatoire par Regroupement" #: quodlibet/ext/playorder/shufflebygrouping.py:32 msgid "" "Shuffles by a grouping of songs defined by a common tag instead of by track, " "similar to album shuffle. This is useful for shuffling multi-movement " "classical works while making sure all movements play in order before " "shuffling to the next piece." msgstr "" "Mélange par un groupe de chansons défini par une étiquette commune au lieu " "d'une piste, comme pour la lecture aléatoire d'albums. Ceci est utile pour " "mélanger des œuvres classiques à mouvements multiples tout en s'assurant que " "tous les mouvements jouent dans l'ordre avant de passer au morceau suivant." #: quodlibet/ext/playorder/shufflebygrouping.py:38 msgid "Shuffle by grouping" msgstr "Lecture aléatoire par regroupement" #: quodlibet/ext/playorder/shufflebygrouping.py:94 msgid "Waiting to start new group…" msgstr "En attendant de commencer un nouveau groupe…" #: quodlibet/ext/playorder/shufflebygrouping.py:144 msgid "Grouping tag:" msgstr "Étiquette de regroupement :" #: quodlibet/ext/playorder/shufflebygrouping.py:148 msgid "Tag to group songs by" msgstr "Étiquette pour grouper les chansons par" #: quodlibet/ext/playorder/shufflebygrouping.py:150 msgid "Filter tag:" msgstr "Etiquette de filtre :" #: quodlibet/ext/playorder/shufflebygrouping.py:155 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:160 msgid "Delay:" msgstr "Délai" #: quodlibet/ext/playorder/shufflebygrouping.py:166 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:182 msgid "Reset to defaults" msgstr "Retour aux valeurs par défaut" #: quodlibet/ext/playorder/skip_songs.py:25 msgid "Skip Songs" msgstr "Sauter des chansons" #: quodlibet/ext/playorder/skip_songs.py:27 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é." #: quodlibet/ext/playorder/track_repeat.py:30 msgid "Repeat Each Track" msgstr "Répéter chaque piste" #: quodlibet/ext/playorder/track_repeat.py:32 msgid "Shuffle songs, but repeat every track a set number of times." msgstr "" "Lire aléatoirement, mais en répétant chaque piste un certain nombre de fois." #: quodlibet/ext/playorder/track_repeat.py:51 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. Syntax is '@(if: " "condition, then, else)'." msgstr "" "Sélectionne la requête à faire correspondre en fonction d'une requête de " "condition. La syntaxe est '@(if: condition, then, else)'." #: quodlibet/ext/query/missing.py:15 msgid "Missing Query" msgstr "Requête Manquante" #: quodlibet/ext/query/missing.py:16 msgid "Matches songs without the given tag." msgstr "Correspond aux chansons sans étiquette donnée." #: quodlibet/ext/query/missing.py:27 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. Syntax is '@(python: expression)'. The " "variable 's' (or 'a') is the song / album being matched. '_ts' is a (real " "number) timestamp at start of query. Modules 'time' and 'random' are also " "available, and the class 'Random' (==random.Random) too." msgstr "" "Utilisez des expressions Python dans les requêtes. La syntaxe est " "'@(python : expression)'. La variable 's' (ou 'a') est la chanson ou l'album " "en cours de correspondance. ' _ts' est un horodatage (en nombre réel) au " "début de la requête. Les modules 'time' et 'random' sont également " "disponibles, ainsi que la classe 'Random' (==random.Random)." #: quodlibet/ext/query/savedsearch.py:19 msgid "Include Saved Search" msgstr "Inclure les recherches sauvegardées" #: quodlibet/ext/query/savedsearch.py:20 msgid "" "Include the results of a saved search as part of another query. Syntax is " "'@(saved: search name)'." msgstr "" "Inclure les résultats d'une recherche sauvegardée dans une autre requête. La " "syntaxe est '@(saved: search name)'." #: 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:116 msgid "Port:" msgstr "Port :" #: quodlibet/ext/_shared/squeezebox/base.py:121 msgid "Username:" msgstr "Nom d'utilisateur :" #: quodlibet/ext/_shared/squeezebox/base.py:126 msgid "Password:" msgstr "Mot de passe :" #: quodlibet/ext/_shared/squeezebox/base.py:130 msgid "Library directory the server connects to" msgstr "Répertoire la bibliothèque auquel le serveur se connecte" #: quodlibet/ext/_shared/squeezebox/base.py:132 msgid "Library path:" msgstr "Chemin de la librairie :" #. Add verify button #: quodlibet/ext/_shared/squeezebox/base.py:141 msgid "_Verify settings" msgstr "_Vérifier la configuration" #. Server settings Frame #: quodlibet/ext/_shared/squeezebox/base.py:147 msgid "Squeezebox Server" msgstr "Serveur Squeezebox" #: quodlibet/ext/_shared/squeezebox/base.py:150 msgid "Debug" msgstr "Débug" #: quodlibet/ext/_shared/squeezebox/server.py:26 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "Serveur Sqeezebox à l'adresse {hostname}:{port}" #: quodlibet/ext/_shared/squeezebox/server.py:28 msgid "unidentified Squeezebox server" msgstr "Serveur Squeezebox inconnu" #: quodlibet/ext/_shared/squeezebox/server.py:37 #, 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:20 #: quodlibet/ext/songsmenu/importexport.py:39 quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "_OK" #: 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:331 msgid "Fit image to _window" msgstr "Ajuster l'image à la fenêtre" #: quodlibet/ext/songsmenu/albumart.py:337 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:343 msgid "_Program:" msgstr "_Programme :" #: quodlibet/ext/songsmenu/albumart.py:348 msgid "_Edit image after saving" msgstr "_Éditer l'image après enregistrement" #: quodlibet/ext/songsmenu/albumart.py:350 msgid "File_name:" msgstr "_Nom de fichier" #: quodlibet/ext/songsmenu/albumart.py:466 msgid "Saving failed" msgstr "Échec de l'enregistrement" #: quodlibet/ext/songsmenu/albumart.py:467 #, python-format msgid "Unable to save \"%s\"." msgstr "Impossible d'enregistrer \"%s\"." #: quodlibet/ext/songsmenu/albumart.py:565 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "[albumart] Erreur HTTP : %s" #: quodlibet/ext/songsmenu/albumart.py:622 msgid "Album Art Downloader" msgstr "Téléchargement de pochettes" #: quodlibet/ext/songsmenu/albumart.py:675 #, python-format msgid "from %(source)s" msgstr "depuis %(source)s" #: quodlibet/ext/songsmenu/albumart.py:678 #, python-format msgid "Resolution: %s" msgstr "Solution : %s" #: quodlibet/ext/songsmenu/albumart.py:681 #, python-format msgid "Size: %s" msgstr "Taille : %s" #: quodlibet/ext/songsmenu/albumart.py:727 msgid "Per engine 'at best' results limit" msgstr "Limite de résultats 'au mieux' par moteur" #: quodlibet/ext/songsmenu/albumart.py:737 msgid "_Search" msgstr "_Rechercher" #: quodlibet/ext/songsmenu/albumart.py:819 #: quodlibet/ext/songsmenu/brainz/widgets.py:451 msgid "Searching…" msgstr "Recherche en cours ..." #: quodlibet/ext/songsmenu/albumart.py:884 #: quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "Fait." #: quodlibet/ext/songsmenu/albumart.py:1006 msgid "Download Album Art" msgstr "Télécharger des illustrations" #: quodlibet/ext/songsmenu/albumart.py:1007 msgid "Downloads album covers from various websites." msgstr "Téléchargement de pochettes d'album depuis plusieurs sites Web." #: quodlibet/ext/songsmenu/albumart.py:1020 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 msgid "Disc" msgstr "Disque" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 #: quodlibet/ext/songsmenu/replaygain.py:393 quodlibet/qltk/tracknumbers.py:91 msgid "Track" msgstr "Piste" #: quodlibet/ext/songsmenu/brainz/widgets.py:132 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:447 msgid "Please enter a query." msgstr "Veuillez saisir une requête." #: quodlibet/ext/songsmenu/brainz/widgets.py:465 #: quodlibet/ext/songsmenu/brainz/widgets.py:496 msgid "Error encountered. Please retry." msgstr "Des erreurs ont été rencontrées. Veuillez recommencer." #: quodlibet/ext/songsmenu/brainz/widgets.py:472 #: quodlibet/ext/songsmenu/brainz/widgets.py:488 msgid "Loading result…" msgstr "Chargement des résultats" #: quodlibet/ext/songsmenu/brainz/widgets.py:475 msgid "No results found." msgstr "Aucun résultat" #: quodlibet/ext/songsmenu/console.py:40 msgid "Python Console" msgstr "Console Python" #: quodlibet/ext/songsmenu/console.py:41 msgid "Interactive Python console. Opens a new window." msgstr "Console Python interactive. Ouvre une nouvelle fenêtre." #: quodlibet/ext/songsmenu/console.py:48 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "{plugin_name} pour {songs} ({app})" #: quodlibet/ext/songsmenu/console.py:55 msgid "Python Console Sidebar" msgstr "Barre latérale de la console Python" #: quodlibet/ext/songsmenu/console.py:56 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 chansons " "sélectionnées dans la fenêtre principale." #: quodlibet/ext/songsmenu/console.py:75 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:85 msgid "Your current working directory is:" msgstr "Votre répertoire par défaut est :" #: quodlibet/ext/songsmenu/cover_download.py:119 msgid "Classic" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:120 msgid "Large" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:121 msgid "HD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:122 msgid "Full HD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:123 msgid "WQXGA" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:124 msgid "4K UHD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:129 msgid "Cover Art Download" msgstr "Téléchargement de la pochette" #: quodlibet/ext/songsmenu/cover_download.py:180 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "Chargement %(source)s - %(dimensions)s…" #: quodlibet/ext/songsmenu/cover_download.py:231 #, python-format msgid "" "Nothing found for albums:\n" "<i>%(albums)s</i>.\n" "\n" "Providers used:\n" "<tt>%(providers)s</tt>" msgstr "" "Rien trouvé pour les albums :\n" "<i>%(albums)s</i>.\n" "\n" "Fournisseurs utilisés :\n" "<tt>%(providers)s</tt>" #: quodlibet/ext/songsmenu/cover_download.py:234 msgid "No covers found" msgstr "Les pochettes n'ont pas été trouvées" #: quodlibet/ext/songsmenu/cover_download.py:254 #, python-format msgid "%(size)d ✕ %(size)d px" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:267 msgid "Preview size" msgstr "Taille de l'aperçu" #: quodlibet/ext/songsmenu/cover_download.py:276 msgid "Save destination" msgstr "Enregistrer la destination" #: quodlibet/ext/songsmenu/cover_download.py:336 msgid "Download Cover Art" msgstr "Télécharger l'illustration de la pochette" #: quodlibet/ext/songsmenu/cover_download.py:337 msgid "Downloads high-quality album covers using cover plugins." msgstr "" "Télécharge des pochettes d'album de haute qualité à l'aide du plugin de " "pochette." #: 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:55 msgid "pattern" msgstr "motif" #: 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:91 msgid "Input value" msgstr "Valeur en entrée" #: quodlibet/ext/songsmenu/custom_commands.py:92 #, python-format msgid "Value for %s?" msgstr "Valeurs pour %s ?" #: quodlibet/ext/songsmenu/custom_commands.py:136 msgid "Custom Commands" msgstr "Commandes personnalisée" #: quodlibet/ext/songsmenu/custom_commands.py:137 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:190 #: quodlibet/ext/songsmenu/custom_commands.py:200 #: quodlibet/ext/songsmenu/custom_commands.py:254 msgid "Edit Custom Commands" msgstr "Editer une commande personnalisée" #: quodlibet/ext/songsmenu/custom_commands.py:201 msgid "" "Supports QL patterns\n" "eg <tt><~artist~title></tt>" msgstr "" "Supporte les modèles QL\n" "par exemple <tt><~artist~title></tt>" #: quodlibet/ext/songsmenu/custom_commands.py:285 #, 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:397 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" "Accepte les expressions du tag QL comme <tt>~artist~title</tt> ou " "<tt>musicbrainz_track_id</tt>" #: quodlibet/ext/songsmenu/duplicates.py:399 msgid "_Group duplicates by:" msgstr "Regrouper les doublons par :" #: quodlibet/ext/songsmenu/duplicates.py:404 msgid "Duplicate Key" msgstr "Clé en double" #: quodlibet/ext/songsmenu/duplicates.py:409 msgid "Remove _Whitespace" msgstr "Supprimer les espaces" #: quodlibet/ext/songsmenu/duplicates.py:410 msgid "Remove _Diacritics" msgstr "Supprimer les caractères spéciaux" #: quodlibet/ext/songsmenu/duplicates.py:411 msgid "Remove _Punctuation" msgstr "Supprimer la ponctuation" #: quodlibet/ext/songsmenu/duplicates.py:412 msgid "Case _Insensitive" msgstr "Non-sensible à la casse" #: quodlibet/ext/songsmenu/duplicates.py:420 msgid "Matching options" msgstr "Options de correspondance" #. Create a dialog. #: quodlibet/ext/songsmenu/editplaycount.py:19 #: quodlibet/ext/songsmenu/editplaycount.py:41 msgid "Edit Playcount" msgstr "Modifier le compteur de lectures" #: quodlibet/ext/songsmenu/editplaycount.py:20 msgid "" "Edit a song's ~#playcount and ~#skipcount.\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's ~#playcount to 0, the ~#lastplayed and ~#laststarted " "entries will be cleared. However, when setting a 0-play song to a positive " "play count, no play times will be created." msgstr "" "Editez le ~#nombre de lecture et le ~#nombre de saut d'une chanson.\n" "\n" "Lorsque plusieurs chansons sont sélectionnées, les nombres seront " "incrémentés, plutôt que réglés.\n" "Lorsque vous réglez le ~#compte de lecture d'un morceau à 0, les entrées " "~#dernier joué et ~#dernier lancé seront effacées. Cependant, lorsque vous " "réglez un morceau 0-play sur un compte de lecture positif, aucun temps de " "lecture ne sera créé." #: quodlibet/ext/songsmenu/editplaycount.py:68 msgid "Play Count" msgstr "Nombre de lectures" #: quodlibet/ext/songsmenu/editplaycount.py:69 msgid "Skip Count" msgstr "Comptage du nombre de fois où un titre est sauté" #: quodlibet/ext/songsmenu/embedded.py:25 msgid "Edit Embedded Images" msgstr "Editer les images incorporées" #: quodlibet/ext/songsmenu/embedded.py:26 msgid "Removes or replaces embedded images." msgstr "Supprime ou remplace les images embarquées." #: quodlibet/ext/songsmenu/embedded.py:81 msgid "_Remove all Images" msgstr "Supp_rimer toutes les images" #: quodlibet/ext/songsmenu/embedded.py:85 msgid "_Embed Current Image" msgstr "Incorporer l'image actuelle" #: 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/exact_rating.py:54 quodlibet/qltk/ratingsmenu.py:98 msgid "Change _Rating" msgstr "Modifie_r l'évaluation" #: 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" #: quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" msgstr "Etat" #. 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:65 quodlibet/ext/songsmenu/html.py:75 msgid "Export to HTML" msgstr "Exporter vers HTML" #: quodlibet/ext/songsmenu/html.py:66 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:62 msgid "Error uploading" msgstr "Erreur de téléchargement" #: quodlibet/ext/songsmenu/ifp.py:63 #, python-format msgid "" "Unable to upload <b>%s</b>. The device may be out of space, or turned off." msgstr "" "Impossible de télécharger <b>%s</b>. L'appareil peut être hors de portée ou " "éteint." #: quodlibet/ext/songsmenu/importexport.py:60 msgid "Export Metadata" msgstr "Exporter les méta-données" #: quodlibet/ext/songsmenu/importexport.py:61 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." #: quodlibet/ext/songsmenu/importexport.py:105 msgid "Import Metadata" msgstr "Importer les méta-données" #: quodlibet/ext/songsmenu/importexport.py:106 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." #: quodlibet/ext/songsmenu/k3b.py:23 msgid "Burn CD" msgstr "Graver un CD" #: quodlibet/ext/songsmenu/k3b.py:24 msgid "Burns CDs with K3b, Brasero or xfburn." msgstr "Gaver des CD avec K3b, Brasero ou xfburn" #: quodlibet/ext/songsmenu/lastfmsync.py:97 msgid "Updating chart list." msgstr "Mise à jour de la liste du graphique." #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:116 msgid "Already up-to-date." msgstr "Bien à jour." #: quodlibet/ext/songsmenu/lastfmsync.py:124 #, python-format msgid "Fetching chart for week of %s." msgstr "Diagramme de récupération pour la semaine de %s." #: quodlibet/ext/songsmenu/lastfmsync.py:146 msgid "Sync complete." msgstr "Synchronisation terminée." #: quodlibet/ext/songsmenu/lastfmsync.py:152 msgid "Error during sync" msgstr "Erreur durant la synchronisation" #: quodlibet/ext/songsmenu/lastfmsync.py:217 #: quodlibet/ext/songsmenu/lastfmsync.py:247 msgid "Last.fm Sync" msgstr "Synchronisation Last.fm" #: quodlibet/ext/songsmenu/lastfmsync.py:248 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:301 msgid "_Username:" msgstr "Nom d'_utilisateur :" #: quodlibet/ext/songsmenu/makesorttags.py:36 msgid "Create Sort Tags" msgstr "Créé 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." #. Create a dialog. #: quodlibet/ext/songsmenu/migratemetadata.py:36 #: quodlibet/ext/songsmenu/migratemetadata.py:45 msgid "Migrate Metadata" msgstr "Migrer les méta-données" #: quodlibet/ext/songsmenu/migratemetadata.py:39 msgid "Copies the quodlibet-specific metadata between songs." msgstr "Ajoute les métadata propres à Quodlibet dans les fichiers des titres." #: quodlibet/ext/songsmenu/migratemetadata.py:52 msgid "_Copy" msgstr "_Copier" #: quodlibet/ext/songsmenu/migratemetadata.py:54 msgid "_Paste" msgstr "Coller" #. Create the tag table. #: quodlibet/ext/songsmenu/migratemetadata.py:64 msgid "Information to copy/paste" msgstr "Informations vers copier/coller" #. Create the indexing box. #: quodlibet/ext/songsmenu/migratemetadata.py:86 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" #: quodlibet/ext/songsmenu/migratemetadata.py:87 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." #: quodlibet/ext/songsmenu/migratemetadata.py:103 #, python-format 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." #: quodlibet/ext/songsmenu/playlist.py:31 msgid "Export as Playlist" msgstr "Exporter vers liste de lecture" #: quodlibet/ext/songsmenu/playlist.py:32 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:77 msgid "Use relative paths" msgstr "Utiliser des chemins relatifs" #: quodlibet/ext/songsmenu/playlist.py:77 msgid "Use absolute paths" msgstr "Utiliser des chemins absolus" #: quodlibet/ext/songsmenu/playlist.py:133 #, python-format msgid "Writing to <b>%s</b> failed." msgstr "L'écriture sur <b>%s</b> 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" #: quodlibet/ext/songsmenu/replaygain.py:407 msgid "Progress" msgstr "Progression" #: quodlibet/ext/songsmenu/replaygain.py:422 msgid "Gain" msgstr "Gain" #: quodlibet/ext/songsmenu/replaygain.py:437 msgid "Peak" msgstr "Peak" #: quodlibet/ext/songsmenu/replaygain.py:452 #, python-format msgid "There is <b>%(to-process)s</b> album to update (of %(all)s)" msgid_plural "There are <b>%(to-process)s</b> albums to update (of %(all)s)" msgstr[0] "Il y a <b>%(to-process)s</b> album à mettre à jour (of %(all)s)" msgstr[1] "Il y a <b>%(to-process)s</b> albums à mettre à jour (of %(all)s)" #: quodlibet/ext/songsmenu/replaygain.py:568 msgid "Replay Gain" msgstr "Replay Gain" #: quodlibet/ext/songsmenu/replaygain.py:569 msgid "" "Analyzes and updates ReplayGain information, using GStreamer. Results are " "grouped by album." msgstr "" "Analyse et met à jour les informations de ReplayGain, en utilisant " "GStreamer. Les résultats sont regroupés par album." #: quodlibet/ext/songsmenu/replaygain.py:607 msgid "always" msgstr "toujours" #: quodlibet/ext/songsmenu/replaygain.py:608 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:610 msgid "if <b>album</b> RG tags are missing" msgstr "si <b>toutes les étiquettes<b> RG sont absentes" #: quodlibet/ext/songsmenu/replaygain.py:627 msgid "_Process albums:" msgstr "Appliquer aux albums :" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:639 msgid "Existing Tags" msgstr "Etiquettes 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 "" #. TRANSLATORS: BPM mean "beats per minute" #: quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "" #: 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 "Appuyez sur BPM pour le morceau sélectionné." #: quodlibet/ext/songsmenu/website_search.py:37 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-example)s." msgstr "" "Rechercher sur les sites de votre choix, selon n'importe quelle étiquette.\n" "Supporte les motifs, par exemple %(pattern-example)s." #: quodlibet/ext/songsmenu/website_search.py:80 msgid "Search URL patterns" msgstr "Rechercher selon des motifs d'URL" #: quodlibet/ext/songsmenu/website_search.py:90 msgid "Edit search URLs" msgstr "Éditer les URLs sauvegardées" #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:116 msgid "Configure Searches…" msgstr "Configurer les recherches …" #: quodlibet/ext/songsmenu/wikipedia.py:35 msgid "Search Tag in Wikipedia" msgstr "Étiquette de recherche dans Wikipedia" #: quodlibet/ext/songsmenu/wikipedia.py:36 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 Wikipedia sur l'étiquette " "correspondante de la chanson sélectionnée." #: quodlibet/ext/songsmenu/wikipedia.py:56 #, python-format msgid "Search at %(website)s" msgstr "Rechercher dans %(website)s" #: quodlibet/ext/songsmenu/wikipedia.py:70 #: quodlibet/ext/songsmenu/wikipedia.py:76 quodlibet/qltk/edittags.py:443 msgid "Edit Tags" msgstr "Éditer les étiquettes" #: quodlibet/ext/songsmenu/wikipedia.py:111 msgid "Search failed" msgstr "Echec de la recherche" #: quodlibet/ext/songsmenu/wikipedia.py:112 #, python-format msgid "Tag \"%s\" not found." msgstr "Étiquette \"%s\" introuvable." #. then (try to) load all new files #: quodlibet/library/libraries.py:651 quodlibet/library/libraries.py:661 #: quodlibet/library/libraries.py:727 quodlibet/library/libraries.py:746 #: quodlibet/qltk/information.py:272 quodlibet/qltk/prefs.py:692 #: quodlibet/util/library.py:123 msgid "Library" msgstr "Bibliothèque" #: quodlibet/library/libraries.py:651 msgid "Checking mount points" msgstr "Vérification des points de montage" #: quodlibet/library/libraries.py:661 msgid "Scanning library" msgstr "Parcours de la bibliothèque" #: quodlibet/library/libraries.py:726 #, python-format msgid "Scanning %s" msgstr "Parcours de %s" #: quodlibet/library/libraries.py:746 msgid "Loading files" msgstr "Chargement des fichiers en cours" #: quodlibet/main.py:50 msgid "Music player and music library manager" msgstr "un Lecteur de musique et un gestionnaire de bibliothèque musicale" #: quodlibet/operon/base.py:70 #, 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:462 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:464 #, 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:336 quodlibet/operon/commands.py:340 #: quodlibet/operon/commands.py:392 quodlibet/operon/commands.py:395 #: quodlibet/operon/commands.py:434 quodlibet/operon/commands.py:469 #: quodlibet/operon/commands.py:509 quodlibet/operon/commands.py:544 #: quodlibet/operon/commands.py:586 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:471 msgid "Too many arguments" msgstr "Trop d'arguments" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:91 #: quodlibet/operon/commands.py:476 quodlibet/qltk/data_editors.py:352 msgid "Description" msgstr "Description" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:476 #: quodlibet/qltk/edittags.py:493 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:324 #: quodlibet/operon/commands.py:385 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 "Editer 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:304 quodlibet/operon/commands.py:445 #: quodlibet/operon/commands.py:677 #, python-format msgid "Can not set %r" msgstr "Impossible de définir %r" #: quodlibet/operon/commands.py:319 msgid "Remove tags" msgstr "Supprimer les étiquettes" #: quodlibet/operon/commands.py:326 quodlibet/operon/commands.py:387 msgid "Value is a regular expression" msgstr "La valeur est une expression régulière" #: quodlibet/operon/commands.py:328 msgid "Remove all tags" msgstr "Supprimer toutes les étiquettes" #: quodlibet/operon/commands.py:332 msgid "Can't combine '--all' with '--regexp'" msgstr "Impossible de combiner '--all' avec '--regexp'" #: quodlibet/operon/commands.py:366 #, python-brace-format msgid "Can't remove {tagname} from {filename}" msgstr "Impossible de supprimer {tagname} de {filename}" #: quodlibet/operon/commands.py:380 msgid "Remove a tag value" msgstr "Supprimer la valeur d'une étiquette" #: quodlibet/operon/commands.py:429 msgid "Add a tag value" msgstr "Ajouter une valeur d'étiquette" #: quodlibet/operon/commands.py:457 msgid "List file information" msgstr "Lister les informations du fichier" #: quodlibet/operon/commands.py:503 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:516 #, python-format msgid "Failed to load image file: %r" msgstr "Impossible de charger le fichier image : %r" #: quodlibet/operon/commands.py:523 quodlibet/operon/commands.py:552 #, 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:539 msgid "Remove all embedded images" msgstr "Supprimer toutes les images incorporées" #: quodlibet/operon/commands.py:569 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "Extraire les images embarquées dans %(filepath)s" #: quodlibet/operon/commands.py:581 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:640 msgid "Rename files based on tags" msgstr "Renommer les fichiers à partir des étiquettes" #: quodlibet/operon/commands.py:655 msgid "Fill tags based on the file path" msgstr "Étiqueter en se basant le chemin de fichier " #: quodlibet/operon/commands.py:705 quodlibet/qltk/information.py:309 #: quodlibet/qltk/properties.py:83 quodlibet/qltk/renamefiles.py:224 #: quodlibet/qltk/tagsfrompath.py:228 quodlibet/qltk/tracknumbers.py:78 msgid "File" msgstr "Fichier" #: quodlibet/operon/commands.py:713 msgid "Fill tracknumbers for all files" msgstr "Remplir les numéros de pistes pour tous les fichiers" #: quodlibet/operon/commands.py:732 msgid "Print tags based on the given pattern" msgstr "Afficher les étiquettes selon un motif donné" #: quodlibet/operon/commands.py:769 msgid "Display help information" msgstr "Afficher des informations d'aide" #: quodlibet/operon/util.py:42 #, 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:30 msgid "_Unknown" msgstr "_Inconnu(e)" #: quodlibet/order/__init__.py:142 msgid "In Order" msgstr "Dans l'ordre" #: quodlibet/order/__init__.py:143 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:147 msgid "_Random" msgstr "_Aléatoire" #: quodlibet/order/reorder.py:40 quodlibet/order/reorder.py:41 msgid "Prefer higher rated" msgstr "Préférer les meilleures évaluations" #: quodlibet/order/repeat.py:43 quodlibet/order/repeat.py:44 msgid "Repeat this track" msgstr "Répéter cette piste" #: quodlibet/order/repeat.py:57 quodlibet/order/repeat.py:58 msgid "Repeat all" msgstr "Tout répéter" #: quodlibet/order/repeat.py:73 quodlibet/order/repeat.py:74 msgid "One Song" msgstr "Un titre" #: quodlibet/player/gstbe/player.py:98 msgid "Stream" msgstr "Flux" #: quodlibet/player/gstbe/player.py:98 msgid "Buffering" msgstr "Mise en mémoire tampon" #: quodlibet/player/gstbe/player.py:452 msgid "Could not create GStreamer pipeline" msgstr "Impossible de créer une association GStreamer" #: quodlibet/player/gstbe/player.py:651 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:652 #, 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:25 msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. In case the pipeline contains a sink, it will be used instead of " "the default one." msgstr "" "Le pipeline de sortie GStreamer utilisé pour la lecture. Laisser vide pour " "le pipeline par défaut. Dans le cas où le pipeline contient un puits, il " "sera utilisé à la place de celui par défaut." #: quodlibet/player/gstbe/prefs.py:36 msgid "_Output pipeline:" msgstr "Pipeline de s_ortie" #: quodlibet/player/gstbe/prefs.py:43 #, python-format msgid "%.1f seconds" msgstr "%.1f secondes" #: quodlibet/player/gstbe/prefs.py:57 msgid "_Buffer duration:" msgstr "Mémoire tampon :" #: quodlibet/player/gstbe/prefs.py:66 msgid "Disable _gapless playback" msgstr "Désactiver la _lecture sans blanc" #: quodlibet/player/gstbe/prefs.py:70 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/util.py:101 msgid "No GStreamer audio sink found" msgstr "Aucune sortie GStreamer audio n'est disponible" #: quodlibet/player/gstbe/util.py:120 msgid "Invalid GStreamer output pipeline" msgstr "Pipeline de sortie GStreamer invalide" #: quodlibet/player/xinebe/player.py:90 msgid "Unable to create audio output" msgstr "Impossible de créer la sortie audio" #: quodlibet/player/xinebe/player.py:91 #, 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:61 #, 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:70 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "Impossible de trouver l'élément GStreamer '{element}'." #: 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:55 #: quodlibet/qltk/songsmenu.py:66 msgid "_Run Plugin" msgstr "Lancer un greffons" #. 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:40 msgid "_Name:" msgstr "_Nom :" #: quodlibet/qltk/cbes.py:48 quodlibet/qltk/edittags.py:350 msgid "_Value:" msgstr "_Valeur :" #: quodlibet/qltk/cbes.py:263 msgid "Saved Values" msgstr "Entrées sauvegardées" #: quodlibet/qltk/cbes.py:264 msgid "Edit saved values…" msgstr "Éditer les entrées sauvegardées …" #: quodlibet/qltk/controls.py:111 msgid "Auto_matic" msgstr "Auto_matique" #: quodlibet/qltk/controls.py:112 msgid "_Track Mode" msgstr "Mode Piste" #: quodlibet/qltk/controls.py:113 msgid "_Album Mode" msgstr "Mode _Album" #. Translators: player state, no action #: quodlibet/qltk/controls.py:122 msgid "_Mute" msgstr "_Met" #: quodlibet/qltk/controls.py:128 msgid "_Replay Gain Mode" msgstr "Mode Replay Gain" #. Translators: New Command/Entry/Item/... #: quodlibet/qltk/data_editors.py:116 #, python-format msgid "New %s" msgstr "Nouveau %s" #: quodlibet/qltk/data_editors.py:215 msgid "(unknown)" msgstr "(Inconnu)" #: quodlibet/qltk/data_editors.py:344 msgid "Tag expression" msgstr "Motif d'étiquette" #: quodlibet/qltk/data_editors.py:371 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:372 msgid "Enter new tag" msgstr "Saisir une nouvelle étiquette" #: 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/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:197 msgid "Split into _Multiple Values" msgstr "Séparer en _plusieurs valeurs" #: quodlibet/qltk/edittags.py:219 msgid "Split Disc out of _Album" msgstr "Séparer le disque de l'_album" #: quodlibet/qltk/edittags.py:243 msgid "Split _Version out of Title" msgstr "Séparer la _version du titre" #: quodlibet/qltk/edittags.py:298 msgid "Split Arranger out of Ar_tist" msgstr "Séparer l'arrangeur de l'ar_tiste" #: quodlibet/qltk/edittags.py:303 msgid "Split _Performer out of Artist" msgstr "Séparer l'intér_prète de l'artiste" #: quodlibet/qltk/edittags.py:309 msgid "Split _Performer out of Title" msgstr "Séparer l'intér_prète du titre" #: quodlibet/qltk/edittags.py:315 msgid "Split _Originalartist out of Title" msgstr "Séparer l'artiste d'origine (Originalartist) du titre" #: quodlibet/qltk/edittags.py:322 msgid "Add a Tag" msgstr "Ajouter une étiquette" #: quodlibet/qltk/edittags.py:341 msgid "_Tag:" msgstr "É_tiquette :" #: quodlibet/qltk/edittags.py:516 msgid "Show _programmatic tags" msgstr "Afficher les étiquettes _programmables" #: quodlibet/qltk/edittags.py:517 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 automatiquement, " "comme par exemple les étiquettes MusicBrainz ou Replay Gain." #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:547 msgctxt "edittags" msgid "_Revert" msgstr "_Rétablir" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:552 msgctxt "edittags" msgid "_Save" msgstr "Enregi_strer" #: quodlibet/qltk/edittags.py:681 msgid "_Configure" msgstr "_Configurer" #: quodlibet/qltk/edittags.py:696 msgid "_Split Tag" msgstr "_Étiquette partagée" #: quodlibet/qltk/edittags.py:705 msgid "_Copy Value(s)" msgstr "_Valeur(s) de la ou des copie(s)" #: quodlibet/qltk/edittags.py:736 msgid "Unable to add tag" msgstr "Impossible d'ajouter l'étiquette" #: quodlibet/qltk/edittags.py:737 #, python-format msgid "Unable to add <b>%s</b>" msgstr "Impossible d'ajouter <b>%s</b>" #: quodlibet/qltk/edittags.py:739 #, python-format msgid "" "The files currently selected do not support multiple values for <b>%s</b>." msgstr "" "Les fichiers actuellement sélectionnés ne supportent pas les valeurs " "multiples pour <b>%s</b>." #. Can't add the new tag. #: quodlibet/qltk/edittags.py:766 quodlibet/qltk/edittags.py:947 #: quodlibet/qltk/tagsfrompath.py:211 quodlibet/util/__init__.py:505 #: quodlibet/util/tags.py:243 msgid "Invalid tag" msgstr "Étiquette non valide" #: quodlibet/qltk/edittags.py:767 quodlibet/qltk/edittags.py:948 #: quodlibet/qltk/tagsfrompath.py:212 #, python-format msgid "" "Invalid tag <b>%s</b>\n" "\n" "The files currently selected do not support editing this tag." msgstr "" "Étiquette invalide <b>%s</b>\n" "\n" "Les fichiers sélectionnés actuellement ne permettent pas l'édition de cette " "étiquette." #: quodlibet/qltk/edittags.py:918 quodlibet/qltk/edittags.py:959 msgid "Invalid value" msgstr "Valeur non valide" #: quodlibet/qltk/edittags.py:919 quodlibet/qltk/edittags.py:960 #, python-format msgid "" "Invalid value: <b>%(value)s</b>\n" "\n" "%(error)s" msgstr "" "Valeur invalide: <b>%(value)s</b>\n" "\n" "%(error)s" #: quodlibet/qltk/_editutils.py:29 msgid "Tag may not be accurate" msgstr "L'étiquette peut ne pas être correcte" #: quodlibet/qltk/_editutils.py:32 #, 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:48 msgid "Unable to save song" msgstr "Impossible d'enregistrer le titre" #: quodlibet/qltk/_editutils.py:51 #, 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 de l'éditer." #: quodlibet/qltk/_editutils.py:143 msgid "_More options…" msgstr "_Plus d'options …" #: quodlibet/qltk/entry.py:78 msgid "_Undo" msgstr "Ann_uler" #: quodlibet/qltk/entry.py:80 msgid "_Redo" msgstr "_Rétablir" #: quodlibet/qltk/exfalsowindow.py:94 quodlibet/qltk/quodlibetwindow.py:956 msgid "_About" msgstr "_A propos" #: quodlibet/qltk/exfalsowindow.py:98 quodlibet/qltk/quodlibetwindow.py:978 msgid "_Check for Updates…" msgstr "Vérifier les mises à jour …" #: quodlibet/qltk/exfalsowindow.py:104 quodlibet/qltk/quodlibetwindow.py:911 #: quodlibet/qltk/songsmenu.py:289 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:278 msgid "Ex Falso Preferences" msgstr "Préférences d'Ex Falso" #: quodlibet/qltk/exfalsowindow.py:284 quodlibet/qltk/prefs.py:666 msgid "Tag Editing" msgstr "Édition d'étiquettes" #: 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:386 msgid "Unable to create folder" msgstr "Impossible de créer le dossier" #: quodlibet/qltk/filesel.py:403 msgid "Unable to delete folder" msgstr "Impossible de supprimer le dossier" #: quodlibet/qltk/filesel.py:519 quodlibet/qltk/pluginwin.py:167 msgid "Songs" msgstr "Titres" #. Translators: As in "by Artist Name" #: quodlibet/qltk/info.py:42 #, python-format msgid "by %s" msgstr "par %s" #: quodlibet/qltk/info.py:43 quodlibet/qltk/information.py:171 #: quodlibet/qltk/information.py:452 #, python-format msgid "Disc %s" msgstr "Disque %s" #: quodlibet/qltk/info.py:44 quodlibet/qltk/information.py:176 #, python-format msgid "Track %s" msgstr "Piste %s" #: quodlibet/qltk/info.py:108 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:342 #: quodlibet/qltk/information.py:475 quodlibet/qltk/information.py:543 msgid "Information" msgstr "Informations" #: quodlibet/qltk/information.py:127 msgid "Lyrics" msgstr "Paroles" #: quodlibet/qltk/information.py:188 quodlibet/qltk/information.py:400 #, python-format msgid "Produced by %s" msgstr "Produit par %s" #: quodlibet/qltk/information.py:203 quodlibet/util/tags.py:85 msgid "artist" msgstr "artiste" #: quodlibet/qltk/information.py:204 quodlibet/qltk/information.py:573 #: quodlibet/util/tags.py:85 msgid "artists" msgstr "artistes" #. for backwards compat #: quodlibet/qltk/information.py:225 quodlibet/util/tags.py:96 #: quodlibet/util/tags.py:124 msgid "performers" msgstr "interprètes" #: quodlibet/qltk/information.py:239 quodlibet/qltk/information.py:252 #: quodlibet/qltk/songlistcolumns.py:276 msgid "Never" msgstr "Jamais" #: quodlibet/qltk/information.py:240 #, 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:258 quodlibet/util/tags.py:149 msgid "added" msgstr "ajoutée" #: quodlibet/qltk/information.py:259 quodlibet/util/tags.py:150 msgid "last played" msgstr "dernière écoute" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:160 msgid "plays" msgstr "joué" #: quodlibet/qltk/information.py:261 quodlibet/util/tags.py:161 msgid "skips" msgstr "sauts" #: quodlibet/qltk/information.py:262 quodlibet/util/tags.py:166 msgid "rating" msgstr "évaluation" #: quodlibet/qltk/information.py:291 msgid "path" msgstr "chemin" #: quodlibet/qltk/information.py:292 quodlibet/util/tags.py:164 msgid "length" msgstr "durée" #: quodlibet/qltk/information.py:293 msgid "format" msgstr "format" #: quodlibet/qltk/information.py:294 quodlibet/util/tags.py:174 msgid "codec" msgstr "codec" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:175 msgid "encoding" msgstr "encodage" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:171 msgid "bitrate" msgstr "débit des données" #: quodlibet/qltk/information.py:297 quodlibet/util/tags.py:172 msgid "file size" msgstr "taille du fichier" #: quodlibet/qltk/information.py:298 quodlibet/util/tags.py:159 msgid "modified" msgstr "modifiée" #: quodlibet/qltk/information.py:335 msgid "Additional" msgstr "Additionnel" #: quodlibet/qltk/information.py:387 #, 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:462 msgid "Track unavailable" msgstr "Piste indisponible" #: quodlibet/qltk/information.py:468 msgid "Track List" msgstr "Liste de pistes" #: quodlibet/qltk/information.py:500 quodlibet/qltk/information.py:590 #, 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:503 msgid "Selected Discography" msgstr "Discographie sélectionnée" #: quodlibet/qltk/information.py:570 #, 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:598 quodlibet/util/tags.py:83 msgid "albums" msgstr "albums" #: quodlibet/qltk/information.py:611 msgid "Total length:" msgstr "Durée totale :" #: quodlibet/qltk/information.py:615 msgid "Total size:" msgstr "Taille totale :" #: quodlibet/qltk/information.py:618 msgid "Files" msgstr "Fichiers" #: quodlibet/qltk/lyrics.py:36 msgid "_View online" msgstr "_Voir en ligne" #: quodlibet/qltk/lyrics.py:64 msgid "No lyrics found for this song." msgstr "Ce titre ne contient aucune parole." #: quodlibet/qltk/lyrics.py:75 msgid "Searching for lyrics…" msgstr "Recherche de paroles ..." #: 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/msg.py:41 msgid "Discard tag changes?" msgstr "Abandonner les modifications apportées aux étiquettes ?" #: quodlibet/qltk/msg.py:42 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:55 quodlibet/qltk/prefs.py:628 #: quodlibet/qltk/prefs.py:635 quodlibet/qltk/textedit.py:63 #: quodlibet/qltk/tracknumbers.py:116 msgid "_Revert" msgstr "_Rétablir" #: quodlibet/qltk/msg.py:104 msgid "File exists" msgstr "Le fichier existe" #: quodlibet/qltk/msg.py:106 #, python-format msgid "Replace %(file-name)s?" msgstr "Remplacer %(file-name)s ?" #: quodlibet/qltk/msg.py:112 msgid "_Replace File" msgstr "_Remplacer le fichier" #: quodlibet/qltk/notif.py:182 msgid "Active tasks" msgstr "Tâches actives" #: quodlibet/qltk/notif.py:188 #, python-format msgid "%d tasks running" msgstr "%d tâches en cours" #: quodlibet/qltk/playorder.py:256 msgid "Toggle shuffle mode" msgstr "Basculer le mode lecture aléatoire" #: quodlibet/qltk/playorder.py:272 msgid "Toggle repeat mode" msgstr "Basculer le mode Répétition" #: quodlibet/qltk/pluginwin.py:44 msgid "Plugin Errors" msgstr "Erreurs de greffon" #: quodlibet/qltk/pluginwin.py:124 msgid "Enabled" msgstr "Activé" #: quodlibet/qltk/pluginwin.py:125 msgid "Disabled" msgstr "Désactivé" #: quodlibet/qltk/pluginwin.py:131 msgid "No category" msgstr "Aucune catégorie" #: quodlibet/qltk/pluginwin.py:169 msgid "Events" msgstr "Événements" #: quodlibet/qltk/pluginwin.py:170 msgid "Play Order" msgstr "Ordre de lecture" #: quodlibet/qltk/pluginwin.py:171 msgid "Editing" msgstr "Édition" #: quodlibet/qltk/pluginwin.py:173 msgid "Covers" msgstr "" #: quodlibet/qltk/pluginwin.py:309 msgid "No plugins found." msgstr "Aucun greffon trouvé." #: quodlibet/qltk/pluginwin.py:358 msgid "Plugins" msgstr "Greffons" #: quodlibet/qltk/pluginwin.py:382 msgid "Filter by plugin state / tag" msgstr "Filtrer sur l'état du plugin / étiquette" #: quodlibet/qltk/pluginwin.py:388 msgid "Filter by plugin type" msgstr "Filtrer par type de plugin" #: quodlibet/qltk/pluginwin.py:394 msgid "Filter by plugin name or description" msgstr "Filtrer par nom ou description du plugin" #: quodlibet/qltk/pluginwin.py:403 msgid "Show _Errors" msgstr "Montrer les _erreurs" #: quodlibet/qltk/prefs.py:45 msgid "_Disc" msgstr "_Disque" #: quodlibet/qltk/prefs.py:46 msgid "_Track" msgstr "Pis_te" #: quodlibet/qltk/prefs.py:47 msgid "Grou_ping" msgstr "regrou_per" #: quodlibet/qltk/prefs.py:50 msgid "Al_bum" msgstr "Al_bum" #: quodlibet/qltk/prefs.py:55 msgid "_Filename" msgstr "Nom de _fichier" #: quodlibet/qltk/prefs.py:57 msgid "_Length" msgstr "D_urée" #: quodlibet/qltk/prefs.py:64 msgid "_Jump to playing song automatically" msgstr "_Aller automatiquement au titre en cours de lecture" #: quodlibet/qltk/prefs.py:66 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:82 msgid "_Others:" msgstr "Au_tres :" #: quodlibet/qltk/prefs.py:88 msgid "_Edit…" msgstr "_Éditer …" #: quodlibet/qltk/prefs.py:91 msgid "Add or remove additional column headers" msgstr "Ajouter ou supprimer des colonnes supplémentaires" #: quodlibet/qltk/prefs.py:101 msgid "Visible Columns" msgstr "Colonnes visibles" #: quodlibet/qltk/prefs.py:104 msgid "Title includes _version" msgstr "Le titre contient la _version" #: quodlibet/qltk/prefs.py:106 msgid "Artist includes all _people" msgstr "L'artiste contient toutes les personnes" #: quodlibet/qltk/prefs.py:108 msgid "Album includes _disc subtitle" msgstr "L'album contient le sous-titre du _disque" #: quodlibet/qltk/prefs.py:110 msgid "Filename includes _folder" msgstr "Le nom de _fichier contient le répertoire" #: quodlibet/qltk/prefs.py:123 msgid "Column Preferences" msgstr "Préférences des colonnes" #: quodlibet/qltk/prefs.py:129 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:142 quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Liste des titres" #: quodlibet/qltk/prefs.py:222 msgid "Edit Columns" msgstr "Modifier les colonnes" #: quodlibet/qltk/prefs.py:259 msgid "Duration totals" msgstr "Durée totale" #: quodlibet/qltk/prefs.py:271 msgid "_Global filter:" msgstr "Filtre _global :" #: quodlibet/qltk/prefs.py:277 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:283 msgctxt "heading" msgid "Search" msgstr "Rechercher" #: quodlibet/qltk/prefs.py:287 quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Navigateurs" #: quodlibet/qltk/prefs.py:293 msgid "Confirm _multiple ratings" msgstr "Confirmer les évaluations _multiples" #: quodlibet/qltk/prefs.py:295 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:298 msgid "Enable _one-click ratings" msgstr "Activer les n_otations en un clic" #: quodlibet/qltk/prefs.py:300 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:306 quodlibet/qltk/prefs.py:669 msgid "Ratings" msgstr "Evaluations" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:312 msgid "Prefer _embedded art" msgstr "Préférer les illustrations incorporées aux fichiers" #: quodlibet/qltk/prefs.py:314 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:319 msgid "_Fixed image filename:" msgstr "Nom de l'image fixe :" #: quodlibet/qltk/prefs.py:321 msgid "The single image filename to use if selected" msgstr "Le nom de fichier de l'image à utiliser si sélectionné" #: quodlibet/qltk/prefs.py:327 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)" #: quodlibet/qltk/prefs.py:337 msgid "Album Art" msgstr "Pochette d'Album" #: quodlibet/qltk/prefs.py:358 msgid "Playback" msgstr "Lecture" #: quodlibet/qltk/prefs.py:363 msgid "Output Configuration" msgstr "Afficher la configuration" #: quodlibet/qltk/prefs.py:374 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:377 msgid "_Fall-back gain (dB):" msgstr "Gain par _défaut (dB) :" #: quodlibet/qltk/prefs.py:388 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:391 msgid "_Pre-amp gain (dB):" msgstr "Gain _global (dB) :" #: quodlibet/qltk/prefs.py:396 msgid "_Enable Replay Gain volume adjustment" msgstr "_Activer l'ajustement de volume par les valeurs Replay Gain" #: quodlibet/qltk/prefs.py:421 msgid "Replay Gain Volume Adjustment" msgstr "Ajustement du volume par Replay Gain" #: quodlibet/qltk/prefs.py:428 msgid "_Continue playback on startup" msgstr "_Poursuivre la lecture au démarrage" #: quodlibet/qltk/prefs.py:430 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:434 msgid "Startup" msgstr "Démarrage" #: quodlibet/qltk/prefs.py:461 msgid "_Default rating:" msgstr "Évaluation par _défaut :" #: quodlibet/qltk/prefs.py:504 msgid "Rating _scale:" msgstr "Échelle d'évaluation :" #: quodlibet/qltk/prefs.py:553 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:558 msgid "_Bayesian averaging amount:" msgstr "_Montant moyen bayésien :" #: quodlibet/qltk/prefs.py:567 msgid "Save ratings and play _counts in tags" msgstr "" "Sauvegarder les évaluations et le _nombre de lecture dans les étiquettes" #: quodlibet/qltk/prefs.py:575 msgid "_Email:" msgstr "Courri_el :" #: quodlibet/qltk/prefs.py:577 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:597 msgid "Auto-save tag changes" msgstr "Enregistrer automatiquement les changements " #: quodlibet/qltk/prefs.py:599 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:608 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:618 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:631 msgid "Split _tag on:" msgstr "Partager l' _étiquette sur :" #: quodlibet/qltk/prefs.py:638 msgid "Split _subtag on:" msgstr "Partager la _sous-étiquette sur :" #: quodlibet/qltk/prefs.py:663 msgid "Tags" msgstr "Étiquettes" #: quodlibet/qltk/prefs.py:684 msgid "Updating for new ratings" msgstr "Mise à jour pour de nouvelles notations" #: quodlibet/qltk/prefs.py:694 msgid "Scan library _on start" msgstr "Rafraîchir la bibliothèque au démarrage" #: quodlibet/qltk/prefs.py:704 quodlibet/qltk/quodlibetwindow.py:990 msgid "_Scan Library" msgstr "_Rechercher dans la bibliothèque" #: quodlibet/qltk/prefs.py:706 quodlibet/qltk/quodlibetwindow.py:1052 msgid "Check for changes in your library" msgstr "Chercher les changements dans la bibliothèque" #: quodlibet/qltk/prefs.py:711 msgid "Re_build Library" msgstr "Re_charger la bibliothèque" #: quodlibet/qltk/prefs.py:714 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:724 msgid "Scan Directories" msgstr " _Répertoires à scanner" #: quodlibet/qltk/prefs.py:730 msgid "Hidden Songs" msgstr "Titre cachés" #: quodlibet/qltk/properties.py:157 quodlibet/util/collection.py:403 #, 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:104 msgid "_Queue" msgstr "_file d'attente" #: quodlibet/qltk/queue.py:124 msgid "Ephemeral" msgstr "Éphémère" #: quodlibet/qltk/queue.py:125 msgid "Remove songs from the queue after playing them" msgstr "Supprimer des chansons de la file d'attente après les avoir lues" #: quodlibet/qltk/queue.py:133 msgid "Persistent" msgstr "Persistant" #: quodlibet/qltk/queue.py:134 msgid "Keep songs in the queue after playing them" msgstr "Garder les chansons dans la file d'attente après les avoir jouées" #: quodlibet/qltk/queue.py:142 msgid "Mode" msgstr "Modèle" #: quodlibet/qltk/queue.py:153 msgid "Stop at End" msgstr "Arrêter à la Fin" #: quodlibet/qltk/queue.py:157 msgid "_Clear Queue" msgstr "_Effacer la file d'attente" #: quodlibet/qltk/queue.py:178 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:290 #, 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:198 msgid "_Browse Library" msgstr "_Parcourir la bibliothèque" #: quodlibet/qltk/quodlibetwindow.py:348 msgid "Toggle queue visibility" msgstr "Basculer la visibilité de la file d'attente" #: quodlibet/qltk/quodlibetwindow.py:376 msgid "Playback Error" msgstr "Erreur de lecture" #: quodlibet/qltk/quodlibetwindow.py:384 msgid "Set up library directories?" msgstr "Choisir des répertoires contenant les librairies" #: quodlibet/qltk/quodlibetwindow.py:385 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:391 msgid "_Not Now" msgstr "Pas mai_ntenant" #: quodlibet/qltk/quodlibetwindow.py:392 msgid "_Set Up" msgstr "Configurer" #: quodlibet/qltk/quodlibetwindow.py:845 msgid "Unable to add songs" msgstr "Impossible d'ajouter les titres" #: quodlibet/qltk/quodlibetwindow.py:846 quodlibet/qltk/quodlibetwindow.py:1286 #, python-format msgid "%s uses an unsupported protocol." msgstr "%s utilise un protocole non supporté." #: quodlibet/qltk/quodlibetwindow.py:869 msgid "_Jump to Playing Song" msgstr "_Aller au titre en cours de lecture" #: quodlibet/qltk/quodlibetwindow.py:876 msgid "_File" msgstr "_Fichier" #: quodlibet/qltk/quodlibetwindow.py:877 msgid "_Song" msgstr "Titre_s" #: quodlibet/qltk/quodlibetwindow.py:878 msgid "_View" msgstr "Afficha_ge" #: quodlibet/qltk/quodlibetwindow.py:879 msgid "_Browse" msgstr "Navigation" #: quodlibet/qltk/quodlibetwindow.py:880 msgid "_Control" msgstr "Lecture" #: quodlibet/qltk/quodlibetwindow.py:881 msgid "_Help" msgstr "_Aide" #: quodlibet/qltk/quodlibetwindow.py:887 msgid "_Add a Folder…" msgstr "_Ajouter un dossier ..." #: quodlibet/qltk/quodlibetwindow.py:892 msgid "_Add a File…" msgstr "_Ajouter un fichier ..." #: quodlibet/qltk/quodlibetwindow.py:897 msgid "_Add a Location…" msgstr "Ajouter un chemin ..." #: quodlibet/qltk/quodlibetwindow.py:926 msgid "Edit Bookmarks…" msgstr "Modifier les signets" #: quodlibet/qltk/quodlibetwindow.py:946 msgid "Stop After This Song" msgstr "Arrêter après ce titre" #: quodlibet/qltk/quodlibetwindow.py:952 msgid "_Keyboard Shortcuts" msgstr "Raccourcis clavier" #: quodlibet/qltk/quodlibetwindow.py:961 msgid "Online Help" msgstr "Aide en ligne" #: quodlibet/qltk/quodlibetwindow.py:970 msgid "Search Help" msgstr "Aide à la recherche" #: quodlibet/qltk/quodlibetwindow.py:1274 msgid "Add a Location" msgstr "Ajouter un chemin" #: quodlibet/qltk/quodlibetwindow.py:1275 msgid "Enter the location of an audio file:" msgstr "Saisir le chemin vers un fichier audio :" #: quodlibet/qltk/quodlibetwindow.py:1280 #: quodlibet/qltk/quodlibetwindow.py:1285 msgid "Unable to add location" msgstr "Impossible d'ajouter le chemin" #: quodlibet/qltk/quodlibetwindow.py:1281 #, python-format msgid "%s is not a valid location." msgstr "%s n'est pas un chemin valide." #: quodlibet/qltk/quodlibetwindow.py:1294 #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "Add Music" msgstr "Ajouter de la musique" #: quodlibet/qltk/quodlibetwindow.py:1294 quodlibet/qltk/scanbox.py:99 msgid "_Add Folders" msgstr "_Ajouter des dossiers" #: quodlibet/qltk/quodlibetwindow.py:1301 msgid "Music Files" msgstr "Fichiers de musique" #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "_Add Files" msgstr "_Ajouter des fichiers" #: quodlibet/qltk/ratingsmenu.py:24 #, 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:26 msgid "The saved ratings will be removed" msgstr "Les évaluations enregistrées seront supprimées" #: quodlibet/qltk/ratingsmenu.py:27 #, python-format msgid "The rating of all selected songs will be changed to '%s'" msgstr "L'évaluation des titres sélectionnés sera transformée en '%s'" #: quodlibet/qltk/ratingsmenu.py:57 quodlibet/qltk/ratingsmenu.py:111 msgid "_Remove Rating" msgstr "Supprime_r les évaluations" #: quodlibet/qltk/renamefiles.py:51 msgid "Replace spaces with _underscores" msgstr "Remplacer les espaces par des _soulignés" #: quodlibet/qltk/renamefiles.py:61 msgid "Strip _Windows-incompatible characters" msgstr "Remplacer les caractères incompatibles avec _Windows" #: quodlibet/qltk/renamefiles.py:79 msgid "Strip _diacritical marks" msgstr "Enlever les signes _diacritiques" #: quodlibet/qltk/renamefiles.py:90 msgid "Strip non-_ASCII characters" msgstr "Remplacer les caractères non-_ASCII" #: quodlibet/qltk/renamefiles.py:100 msgid "Use only _lowercase characters" msgstr "Utiliser uniquement des caractères minuscules" #: quodlibet/qltk/renamefiles.py:128 msgid "Rename Files" msgstr "Renommer les fichiers" #: quodlibet/qltk/renamefiles.py:146 quodlibet/qltk/tagsfrompath.py:115 msgid "Path Patterns" msgstr "Chemin des motifs" #: quodlibet/qltk/renamefiles.py:147 quodlibet/qltk/tagsfrompath.py:116 msgid "Edit saved patterns…" msgstr "Éditer les motifs enregistrés..." #: quodlibet/qltk/renamefiles.py:150 quodlibet/qltk/tagsfrompath.py:119 #: quodlibet/qltk/tracknumbers.py:57 msgid "_Preview" msgstr "A_perçu" #: quodlibet/qltk/renamefiles.py:177 msgid "File names" msgstr "Noms du fichier" #: quodlibet/qltk/renamefiles.py:187 msgid "_Move album art" msgstr "_Déplacer la pochette de l'album" #: quodlibet/qltk/renamefiles.py:190 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:195 msgid "_Overwrite album art at target" msgstr "_Réécrire la pochette de l'album vers la cible" #: quodlibet/qltk/renamefiles.py:203 msgid "_Remove empty directories" msgstr "_Supprimer les répertoires vides" #: quodlibet/qltk/renamefiles.py:209 msgid "Album art" msgstr "Pochette d'Album" #: quodlibet/qltk/renamefiles.py:238 msgid "New Name" msgstr "Nouveau nom" #: quodlibet/qltk/renamefiles.py:315 msgid "Unable to rename file" msgstr "Impossible de renommer le fichier" #: quodlibet/qltk/renamefiles.py:316 #, python-format msgid "" "Renaming <b>%(old-name)s</b> to <b>%(new-name)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." msgstr "" "Le renommage de <b>%(old-name)s</b> en <b>%(new-name)s</b> a échoué. Il se " "peut que le fichier destination existe déjà, ou que vous n'ayez pas la " "permission de créer le nouveau fichier ou de supprimer l'ancien." #: quodlibet/qltk/renamefiles.py:324 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:325 quodlibet/qltk/wlw.py:49 msgid "_Stop" msgstr "Arrêter" #: quodlibet/qltk/renamefiles.py:327 msgid "_Continue" msgstr "_Continuer" #: quodlibet/qltk/renamefiles.py:440 msgid "Path is not absolute" msgstr "Le chemin n'est pas absolu" #: quodlibet/qltk/renamefiles.py:441 #, python-format msgid "" "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 ~/." msgstr "" "Le motif\n" "\t<b>%s</b>\n" "contient / mais ne commence pas à la racine. Pour éviter des répertoires mal " "nommés, enracinez votre motif en le commençant par le répertoire / ou le " "répertoire ~/." #: quodlibet/qltk/scanbox.py:47 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:99 msgid "Select Directories" msgstr "Choisir des répertoires" #: quodlibet/qltk/searchbar.py:57 msgid "Saved Searches" msgstr "Recherches sauvegardées" #: quodlibet/qltk/searchbar.py:58 msgid "Edit saved searches…" msgstr "Éditer les recherches sauvegardées..." #: quodlibet/qltk/searchbar.py:82 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:144 msgid "Search after _typing" msgstr "Rechercher après avoir _tapé au clavier" #: quodlibet/qltk/searchbar.py:147 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:215 msgid "_Limit:" msgstr "_Limite :" #: quodlibet/qltk/searchbar.py:228 msgid "_Weight" msgstr "_Pondéré" #: quodlibet/qltk/searchbar.py:355 msgid "Add query" msgstr "Ajouter une requête" #: quodlibet/qltk/searchbar.py:356 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:375 #, python-format msgid "_Filter on %s" msgstr "_Filtrer sur %s" #: quodlibet/qltk/songlist.py:1093 msgid "All _Headers" msgstr "Toutes les entêtes" #: quodlibet/qltk/songlist.py:1094 msgid "_Track Headers" msgstr "Colonnes « _Piste »" #: quodlibet/qltk/songlist.py:1095 msgid "_Album Headers" msgstr "Colonnes « _Album »" #: quodlibet/qltk/songlist.py:1096 msgid "_People Headers" msgstr "Colonnes « Ar_tistes »" #: quodlibet/qltk/songlist.py:1097 msgid "_Date Headers" msgstr "Colonnes « _Date »" #: quodlibet/qltk/songlist.py:1098 msgid "_File Headers" msgstr "Colonnes « _Fichier »" #: quodlibet/qltk/songlist.py:1099 msgid "_Production Headers" msgstr "Colonnes « _Production »" #: quodlibet/qltk/songlist.py:1114 msgid "_Customize Headers…" msgstr "Colonnes « _Personnalisées »" #: quodlibet/qltk/songlist.py:1119 msgid "_Expand Column" msgstr "Déplier la colonne" #: quodlibet/qltk/songsmenu.py:40 #, python-format msgid "Remove track: \"%%(title)s\" from library?" msgid_plural "Remove %(count)d tracks from library?" msgstr[0] "Retirer la piste : \"%%(title)s\" de la bibliothèque ?" msgstr[1] "Supprimer les pistes %(count)d de la bibliothèque ?" #: quodlibet/qltk/songsmenu.py:46 msgid "Remove from Library" msgstr "Supprimer de la bibliothèque" #: quodlibet/qltk/songsmenu.py:51 #, 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:62 #, 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:134 msgid "Configure Plugins…" msgstr "Configurer les greffons …" #: quodlibet/qltk/songsmenu.py:329 msgid "Add to _Queue" msgstr "A_jouter à la file d'attente" #: quodlibet/qltk/songsmenu.py:349 msgid "_Remove from Library…" msgstr "_Supprimer de la bibliothèque…" #: quodlibet/qltk/songsmenu.py:414 msgid "Unable to show files" msgstr "Impossible d'afficher les fichiers" #: quodlibet/qltk/songsmenu.py:415 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:422 #, 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/tagsfrompath.py:46 msgid "Replace _underscores with spaces" msgstr "Remplacer les so_ulignés par des espaces" #: quodlibet/qltk/tagsfrompath.py:56 msgid "_Title-case tags" msgstr "Mettre une _majuscule aux valeurs résultantes" #: quodlibet/qltk/tagsfrompath.py:66 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<b>%s</b>\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" "Le motif\n" "\t<b>%s</b>\n" "n'est pas valide. Il peut contenir deux fois la même étiquette ou des " "parenthèses sans correspondance (< / >)." #: quodlibet/qltk/tagsfrompath.py:215 msgid "Invalid tags" msgstr "Étiquettes non valides" #: quodlibet/qltk/tagsfrompath.py:216 #, 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." #: 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:923 #, python-format msgid "and %d more…" msgstr "et %d de plus …" #: quodlibet/qltk/wlw.py:199 msgid "Saving the songs you changed." msgstr "Enregistrement en cours des titres modifés." #: quodlibet/qltk/wlw.py:200 #, 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:233 #, 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:425 msgid "Playlists must have a name" msgstr "Les listes de lectures doivent être nommées" #: quodlibet/util/collection.py:608 #, python-format msgid "A playlist named %s already exists." msgstr "Une liste de lecture appelée %s existe déjà." #: quodlibet/util/cover/built_in.py:32 msgid "Embedded album covers" msgstr "Pochettes embarquées dans les étiquettes/titres" #: quodlibet/util/cover/built_in.py:33 msgid "Uses covers embedded into audio files." msgstr "Utilise les pochettes inclues dans les fichiers audio." #: quodlibet/util/cover/built_in.py:55 msgid "Filesystem cover" msgstr "Pochette du système de fichiers" #: quodlibet/util/cover/built_in.py:56 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:76 msgid "Display brief usage information" msgstr "Afficher des informations d'utilisation succinctes " #: quodlibet/util/__init__.py:78 msgid "Display version and copyright" msgstr "Afficher la version et le copyright" #: quodlibet/util/__init__.py:79 msgid "Print debugging information" msgstr "Imprimer les informations de débogage" #: quodlibet/util/__init__.py:118 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "Utilisation : %(program)s %(usage)s" #: quodlibet/util/__init__.py:120 msgid "[options]" msgstr "[options]" #: quodlibet/util/__init__.py:165 #, python-format msgid "Option %r not recognized." msgstr "L'option %r n'est pas reconnue." #: quodlibet/util/__init__.py:168 #, python-format msgid "Option %r requires an argument." msgstr "L'option %r nécessite un argument" #: quodlibet/util/__init__.py:171 #, python-format msgid "%r is not a unique prefix." msgstr "%r n'est pas un préfixe unique." #: quodlibet/util/__init__.py:347 #, python-format msgid "%d kbps" msgstr "%d kbps" #: quodlibet/util/__init__.py:402 #, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%s secondes" msgstr[1] "%s secondes" #: quodlibet/util/__init__.py:415 msgid "No time information" msgstr "Aucun renseignement de durée" #: quodlibet/util/__init__.py:418 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d seconde" msgstr[1] "%d secondes" #: quodlibet/util/__init__.py:419 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d minute" msgstr[1] "%d minutes" #: quodlibet/util/__init__.py:420 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d heure" msgstr[1] "%d heures" #: quodlibet/util/__init__.py:421 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d jour" msgstr[1] "%d jours" #: quodlibet/util/__init__.py:422 #, 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:514 msgctxt "check" msgid "titlecase?" msgstr "" #: quodlibet/util/massagers.py:114 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:129 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:150 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:172 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:194 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:207 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:116 msgid "Unable to edit song" msgstr "Impossible d'éditer le titre" #: quodlibet/util/songwrapper.py:117 #, python-format msgid "" "Saving <b>%s</b> failed. The file may be read-only, corrupted, or you do not " "have permission to edit it." msgstr "" "La sauvegarde de <b>%s</b> a échoué. Le fichier peut être en lecture seule, " "corrompu, ou vous n'avez pas la permission de l'éditer." #: 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 "" #: 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:151 msgid "disc" msgstr "disque" #: quodlibet/util/tags.py:115 quodlibet/util/tags.py:153 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 "Nom de la première édition " #: 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" #. 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:130 msgid "MusicBrainz recording ID" msgstr "Identifiant MusicBrainz d'enregistrement" #: quodlibet/util/tags.py:131 msgid "MusicBrainz release track ID" msgstr "Identifiant MusicBrainz de piste" #: quodlibet/util/tags.py:132 msgid "MusicBrainz release ID" msgstr "Identifiant MusicBrainz de parution " #: quodlibet/util/tags.py:133 msgid "MusicBrainz artist ID" msgstr "Identifiant MusicBrainz d'artiste" #: quodlibet/util/tags.py:134 msgid "MusicBrainz release artist ID" msgstr "Identifiant MusicBrainz d'artiste dans la parution" #: quodlibet/util/tags.py:135 msgid "MusicBrainz TRM ID" msgstr "Identifiant MusicBrainz de TRM" #: quodlibet/util/tags.py:136 msgid "MusicIP PUID" msgstr "MusicIP PUID" #: quodlibet/util/tags.py:137 msgid "MusicBrainz album status" msgstr "Statut MusicBrainz de l'album" #: quodlibet/util/tags.py:138 msgid "MusicBrainz album type" msgstr "Type MusicBrainz de l'album" #: quodlibet/util/tags.py:139 msgid "MusicBrainz release group ID" msgstr "Identifiant MusicBrainz groupe de parutions " #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:142 msgid "track gain" msgstr "gain pour la piste" #: quodlibet/util/tags.py:143 msgid "track peak" msgstr "pic de la piste" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:145 msgid "album gain" msgstr "gain pour l'album" #: quodlibet/util/tags.py:146 msgid "album peak" msgstr "pic de l'album" #: quodlibet/util/tags.py:147 msgid "reference loudness" msgstr "volume sonore de référence" #: quodlibet/util/tags.py:152 msgid "discs" msgstr "disques" #: quodlibet/util/tags.py:154 msgid "tracks" msgstr "pistes" #: quodlibet/util/tags.py:155 msgid "last started" msgstr "dernier lancement" #: quodlibet/util/tags.py:156 msgid "full name" msgstr "chemin complet" #: quodlibet/util/tags.py:163 msgid "mount point" msgstr "point de montage" #: quodlibet/util/tags.py:165 msgid "people" msgstr "personnes" #: quodlibet/util/tags.py:167 msgid "year" msgstr "année" #: quodlibet/util/tags.py:168 msgid "original release year" msgstr "année de première publication " #: quodlibet/util/tags.py:169 msgid "bookmark" msgstr "signet" #: quodlibet/util/tags.py:170 msgid "bitdepth" msgstr "résolution en bits" #: quodlibet/util/tags.py:173 msgid "file format" msgstr "format de fichier" #: quodlibet/util/tags.py:176 msgid "playlists" msgstr "listes de lecture" #: quodlibet/util/tags.py:177 msgid "sample rate" msgstr "fréquence d'échantillonnage" #: quodlibet/util/tags.py:178 msgid "channel count" msgstr "Nombre de canaux" #. Translators: e.g. "artist (sort)" #: quodlibet/util/tags.py:268 msgid "sort" msgstr "trier" #. Translators: e.g. "performer (roles)" #: quodlibet/util/tags.py:276 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 "" #: 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" #: 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 "" "Gère les formats de fichier 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 gestionnaire de musique, qui permet de gérer votre " "bibliothèque audio avec beaucoup de souplesse, et offre un accès aux radio " "Internet et aux flux audio. En outre, il offre des fonctions étendues de " "gestion des méta-étiquettes et permet de puissantes recherches." #~ msgid "_Download…" #~ msgstr "_Télécharger…" #~ msgid "Download Files" #~ msgstr "Télécharger les fichiers" #~ msgid "Download File" #~ msgstr "Télécharger le fichier" #~ 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 "Could not find '%s'." #~ msgstr "Impossible de trouver '%s'." #~ 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 "broker port" #~ msgstr "Port de l'intermédiaire" #~ 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 "_Edit" #~ msgstr "_Éditer" #~ 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 "Watch this folder for new songs" #~ msgstr "Surveiller les modifications sur ce dossier" #~ 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 "Removing orphaned iPod track" #~ msgstr "W: suppression d'une piste orpheline de l'iPod" #, 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9591856 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/po/gl.po����������������������������������������������������������������������������0000644�0001750�0001750�00000600157�00000000000�014067� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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: 2017-05-17 18:58+0200\n" "PO-Revision-Date: 2013-07-20 22:34+0100\n" "Last-Translator: Johám-Luís Miguéns Vila <galiza.ceive@gmail.com>\n" "Language-Team: GALICIAN\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: Poedit 1.5.4\n" #: ../data/exfalso.appdata.xml.in.h:1 ../data/exfalso.desktop.in.h:2 msgid "Edit tags in your audio files" msgstr "Editar as etiquetas dos arquivos de áudio" #: ../data/exfalso.appdata.xml.in.h:2 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/exfalso.appdata.xml.in.h:3 ../data/quodlibet.appdata.xml.in.h:3 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/exfalso.desktop.in.h:1 msgid "Audio tag editor" msgstr "Editor de etiquetas de áudio" #: ../data/quodlibet.appdata.xml.in.h:1 ../data/quodlibet.desktop.in.h:2 msgid "Listen to, browse, or edit your audio collection" msgstr "Escoite, explore ou edite a sua colecçom de música" #: ../data/quodlibet.appdata.xml.in.h:2 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 "" #: ../data/quodlibet.desktop.in.h:1 msgid "Music Player" msgstr "Reprodutor de música" #: ../quodlibet/browsers/albums/main.py:168 #: ../quodlibet/browsers/covergrid/main.py:54 #, fuzzy msgid "_Title" msgstr "Título" #: ../quodlibet/browsers/albums/main.py:169 #: ../quodlibet/browsers/covergrid/main.py:55 ../quodlibet/qltk/prefs.py:49 msgid "_Artist" msgstr "_Artista" #: ../quodlibet/browsers/albums/main.py:170 #: ../quodlibet/browsers/covergrid/main.py:56 ../quodlibet/qltk/prefs.py:54 msgid "_Date" msgstr "_Data" #: ../quodlibet/browsers/albums/main.py:171 #: ../quodlibet/browsers/covergrid/main.py:57 ../quodlibet/qltk/prefs.py:53 #, fuzzy msgid "_Genre" msgstr "Estilo" #: ../quodlibet/browsers/albums/main.py:172 #: ../quodlibet/browsers/covergrid/main.py:58 ../quodlibet/qltk/prefs.py:58 #: ../quodlibet/qltk/ratingsmenu.py:39 msgid "_Rating" msgstr "_Qualificaçom" #: ../quodlibet/browsers/albums/main.py:178 #: ../quodlibet/browsers/covergrid/main.py:64 #, fuzzy msgid "Sort _by…" msgstr "Ordenar _por:" #: ../quodlibet/browsers/albums/main.py:199 #: ../quodlibet/browsers/covergrid/main.py:85 #: ../quodlibet/browsers/paned/prefs.py:166 #: ../quodlibet/browsers/playlists/main.py:629 #: ../quodlibet/qltk/exfalsowindow.py:109 ../quodlibet/qltk/pluginwin.py:341 #: ../quodlibet/qltk/quodlibetwindow.py:1016 #, fuzzy msgid "_Preferences" msgstr "Preferências" #: ../quodlibet/browsers/albums/main.py:361 msgid "Album List" msgstr "Lista de Álbuns" #: ../quodlibet/browsers/albums/main.py:362 msgid "_Album List" msgstr "Lista de _Álbuns" #: ../quodlibet/browsers/albums/main.py:472 #: ../quodlibet/browsers/covergrid/main.py:279 #: ../quodlibet/browsers/covergrid/main.py:488 msgid "All Albums" msgstr "Todos os Álbuns" #: ../quodlibet/browsers/albums/main.py:473 #: ../quodlibet/browsers/covergrid/main.py:280 #: ../quodlibet/browsers/covergrid/main.py:489 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d álbum" msgstr[1] "%d álbuns" #: ../quodlibet/browsers/albums/main.py:650 #: ../quodlibet/browsers/covergrid/main.py:467 #, 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 "Canções sem á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:381 ../quodlibet/util/collection.py:245 #, 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:379 ../quodlibet/util/collection.py:249 #, 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 "Preferências da Lista de Álbuns" #: ../quodlibet/browsers/albums/prefs.py:61 msgid "Show album _covers" msgstr "Mostrar _cobertas dos discos" #: ../quodlibet/browsers/albums/prefs.py:67 msgid "Inline _search includes people" msgstr "A procura _inclúi \"componentes\"" #: ../quodlibet/browsers/albums/prefs.py:71 #: ../quodlibet/browsers/covergrid/prefs.py:120 #, fuzzy msgid "Options" msgstr "[opções]" #: ../quodlibet/browsers/albums/prefs.py:74 #: ../quodlibet/browsers/covergrid/prefs.py:123 msgid "Album Display" msgstr "Vista de álbuns" #: ../quodlibet/browsers/albums/prefs.py:78 #: ../quodlibet/browsers/covergrid/prefs.py:127 #: ../quodlibet/browsers/media.py:39 #: ../quodlibet/browsers/playlists/prefs.py:56 #: ../quodlibet/ext/songsmenu/albumart.py:326 #: ../quodlibet/ext/songsmenu/duplicates.py:350 #: ../quodlibet/ext/songsmenu/filterall.py:48 #: ../quodlibet/qltk/bookmarks.py:101 ../quodlibet/qltk/cbes.py:93 #: ../quodlibet/qltk/data_editors.py:99 ../quodlibet/qltk/data_editors.py:324 #: ../quodlibet/qltk/exfalsowindow.py:297 ../quodlibet/qltk/pluginwin.py:79 #: ../quodlibet/qltk/pluginwin.py:427 ../quodlibet/qltk/prefs.py:707 #: ../quodlibet/qltk/textedit.py:164 ../quodlibet/update.py:148 msgid "_Close" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:55 #: ../quodlibet/browsers/audiofeeds.py:67 #: ../quodlibet/browsers/audiofeeds.py:69 #: ../quodlibet/browsers/audiofeeds.py:159 #: ../quodlibet/browsers/paned/models.py:86 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:46 #: ../quodlibet/formats/_audio.py:495 ../quodlibet/order/__init__.py:27 #: ../quodlibet/qltk/information.py:240 ../quodlibet/qltk/information.py:247 #: ../quodlibet/qltk/information.py:273 ../quodlibet/qltk/wlw.py:70 msgid "Unknown" msgstr "Desconhecido" #: ../quodlibet/browsers/audiofeeds.py:246 msgid "New Feed" msgstr "Nova Fonte" #: ../quodlibet/browsers/audiofeeds.py:247 msgid "Enter the location of an audio feed:" msgstr "Por favor, introduça a localizaçom da fonte (feed):" #: ../quodlibet/browsers/audiofeeds.py:248 #: ../quodlibet/browsers/collection/prefs.py:90 #: ../quodlibet/browsers/iradio.py:341 ../quodlibet/browsers/paned/prefs.py:78 #: ../quodlibet/browsers/playlists/menu.py:96 #: ../quodlibet/browsers/playlists/util.py:52 ../quodlibet/qltk/bookmarks.py:62 #: ../quodlibet/qltk/cbes.py:55 ../quodlibet/qltk/data_editors.py:311 #: ../quodlibet/qltk/edittags.py:288 ../quodlibet/qltk/edittags.py:488 #: ../quodlibet/qltk/quodlibetwindow.py:1354 ../quodlibet/qltk/scanbox.py:61 msgid "_Add" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:265 msgid "Audio Feeds" msgstr "Fontes de Áudio (feeds)" #: ../quodlibet/browsers/audiofeeds.py:266 msgid "_Audio Feeds" msgstr "Fontes de _Áudio (feeds)" #: ../quodlibet/browsers/audiofeeds.py:345 #: ../quodlibet/browsers/audiofeeds.py:350 #, fuzzy msgid "_Download…" msgstr "_Baixar" #: ../quodlibet/browsers/audiofeeds.py:359 msgid "Download Files" msgstr "Baixar os arquivos" #. Save button #: ../quodlibet/browsers/audiofeeds.py:359 #: ../quodlibet/browsers/audiofeeds.py:371 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:81 #: ../quodlibet/ext/songsmenu/albumart.py:322 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:355 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:278 #: ../quodlibet/ext/songsmenu/html.py:76 #: ../quodlibet/ext/songsmenu/lastfmsync.py:216 #: ../quodlibet/ext/songsmenu/playlist.py:51 #: ../quodlibet/ext/songsmenu/replaygain.py:365 #: ../quodlibet/ext/songsmenu/tapbpm.py:182 ../quodlibet/qltk/_editutils.py:39 #: ../quodlibet/qltk/lyrics.py:38 ../quodlibet/qltk/msg.py:52 #: ../quodlibet/qltk/renamefiles.py:168 ../quodlibet/qltk/tracknumbers.py:113 msgid "_Save" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:371 msgid "Download File" msgstr "Baixar o arquivo" #: ../quodlibet/browsers/audiofeeds.py:394 #: ../quodlibet/browsers/playlists/main.py:213 #: ../quodlibet/qltk/data_editors.py:96 msgid "_New" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:454 #: ../quodlibet/browsers/audiofeeds.py:513 msgid "Unable to add feed" msgstr "Non foi possível engadir a fonte" #: ../quodlibet/browsers/audiofeeds.py:455 #: ../quodlibet/browsers/audiofeeds.py:514 #, fuzzy, python-format msgid "" "%s could not be added. The server may be down, or the location may not be an " "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)." #. refresh button #: ../quodlibet/browsers/audiofeeds.py:462 ../quodlibet/browsers/media.py:217 #: ../quodlibet/browsers/media.py:386 ../quodlibet/qltk/filesel.py:259 #: ../quodlibet/qltk/pluginwin.py:413 #, fuzzy msgid "_Refresh" msgstr "Ac_tualizar a colecçom" #: ../quodlibet/browsers/audiofeeds.py:463 #: ../quodlibet/browsers/playlists/main.py:457 #: ../quodlibet/browsers/playlists/util.py:43 ../quodlibet/qltk/delete.py:143 #: ../quodlibet/qltk/filesel.py:256 ../quodlibet/qltk/lyrics.py:39 #: ../quodlibet/qltk/maskedbox.py:28 ../quodlibet/qltk/songsmenu.py:392 #, fuzzy msgid "_Delete" msgstr "Eliminar os ficheiros" #: ../quodlibet/browsers/audiofeeds.py:530 msgid "" "The current audio backend does not support URLs, Audio Feeds browser " "disabled." msgstr "" "A infraestrutura de áudio activa nom admite URLs. \n" "Desactivou-se o navegador de fontes (feeds)." #: ../quodlibet/browsers/_base.py:147 ../quodlibet/browsers/_base.py:150 msgid "Library Browser" msgstr "Navegador da Colecçom" #: ../quodlibet/browsers/_base.py:274 ../quodlibet/ext/songsmenu/refresh.py:30 #: ../quodlibet/qltk/exfalsowindow.py:241 ../quodlibet/qltk/information.py:542 #: ../quodlibet/qltk/maskedbox.py:68 ../quodlibet/util/collection.py:527 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d cançom" msgstr[1] "%d canções" #: ../quodlibet/browsers/_base.py:402 ../quodlibet/browsers/_base.py:407 #: ../quodlibet/qltk/tagsfrompath.py:194 ../quodlibet/qltk/textedit.py:141 #: ../quodlibet/util/__init__.py:622 msgid "Invalid pattern" msgstr "Padrom inválido" #: ../quodlibet/browsers/collection/main.py:78 msgid "Album Collection" msgstr "Colecçom de álbuns" #: ../quodlibet/browsers/collection/main.py:79 msgid "Album _Collection" msgstr "_Colecçom 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:66 #: ../quodlibet/browsers/paned/prefs.py:51 msgid "_Custom" msgstr "_Personalizada" #. Remove button #: ../quodlibet/browsers/collection/prefs.py:94 #: ../quodlibet/browsers/paned/prefs.py:82 #: ../quodlibet/browsers/playlists/menu.py:97 #: ../quodlibet/ext/playlist/remove_duplicates.py:60 #: ../quodlibet/qltk/bookmarks.py:97 ../quodlibet/qltk/bookmarks.py:127 #: ../quodlibet/qltk/cbes.py:82 ../quodlibet/qltk/cbes.py:89 #: ../quodlibet/qltk/data_editors.py:81 ../quodlibet/qltk/data_editors.py:94 #: ../quodlibet/qltk/data_editors.py:301 ../quodlibet/qltk/data_editors.py:314 #: ../quodlibet/qltk/data_editors.py:322 ../quodlibet/qltk/edittags.py:494 #: ../quodlibet/qltk/edittags.py:634 ../quodlibet/qltk/maskedbox.py:48 #: ../quodlibet/qltk/maskedbox.py:88 ../quodlibet/qltk/queue.py:350 #: ../quodlibet/qltk/scanbox.py:36 ../quodlibet/qltk/scanbox.py:63 #, fuzzy msgid "_Remove" msgstr "_Eliminar Emisora" #: ../quodlibet/browsers/collection/prefs.py:122 #: ../quodlibet/ext/songsmenu/filterall.py:34 #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:92 #: ../quodlibet/qltk/edittags.py:431 msgid "Tag" msgstr "Etiqueta" #: ../quodlibet/browsers/collection/prefs.py:128 msgid "Merge" msgstr "Juntar" #: ../quodlibet/browsers/collection/prefs.py:188 #, fuzzy msgid "Album Collection Preferences" msgstr "Preferências da Lista de Álbuns" #: ../quodlibet/browsers/collection/prefs.py:195 #: ../quodlibet/browsers/paned/prefs.py:209 #: ../quodlibet/ext/songsmenu/editplaycount.py:45 #: ../quodlibet/ext/songsmenu/exact_rating.py:38 #: ../quodlibet/player/gstbe/prefs.py:40 ../quodlibet/qltk/prefs.py:127 #: ../quodlibet/qltk/textedit.py:65 msgid "_Apply" msgstr "" #: ../quodlibet/browsers/collection/prefs.py:198 #: ../quodlibet/browsers/paned/prefs.py:213 #: ../quodlibet/browsers/playlists/menu.py:95 #: ../quodlibet/browsers/playlists/util.py:42 #: ../quodlibet/errorreport/ui.py:108 #: ../quodlibet/ext/playlist/export_to_folder.py:37 #: ../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:44 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:281 #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:88 #: ../quodlibet/ext/songsmenu/importexport.py:35 #: ../quodlibet/ext/songsmenu/lastfmsync.py:215 #: ../quodlibet/ext/songsmenu/playlist.py:50 #: ../quodlibet/ext/songsmenu/replaygain.py:364 #: ../quodlibet/ext/songsmenu/tapbpm.py:181 ../quodlibet/plugins/playlist.py:39 #: ../quodlibet/qltk/chooser.py:184 ../quodlibet/qltk/chooser.py:205 #: ../quodlibet/qltk/chooser.py:229 ../quodlibet/qltk/chooser.py:253 #: ../quodlibet/qltk/delete.py:90 ../quodlibet/qltk/delete.py:133 #: ../quodlibet/qltk/edittags.py:287 ../quodlibet/qltk/_editutils.py:38 #: ../quodlibet/qltk/getstring.py:28 ../quodlibet/qltk/maskedbox.py:27 #: ../quodlibet/qltk/msg.py:54 ../quodlibet/qltk/msg.py:93 #: ../quodlibet/qltk/ratingsmenu.py:33 ../quodlibet/qltk/songsmenu.py:45 #: ../quodlibet/qltk/songsmenu.py:73 ../quodlibet/update.py:94 msgid "_Cancel" msgstr "" #: ../quodlibet/browsers/covergrid/main.py:125 #, fuzzy msgid "Cover Grid" msgstr "Tamanho total:" #: ../quodlibet/browsers/covergrid/main.py:126 #, 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:71 #, fuzzy msgid "Show \"All Albums\" Item" msgstr "Todos os Álbuns" #: ../quodlibet/browsers/covergrid/prefs.py:78 msgid "Vertical Split" msgstr "" #: ../quodlibet/browsers/covergrid/prefs.py:110 #: ../quodlibet/browsers/covergrid/prefs.py:111 #, fuzzy msgid "Cover Magnification" msgstr "Nom há novas emisoras" #: ../quodlibet/browsers/filesystem.py:40 msgid "File System" msgstr "Sistema de arquivos" #: ../quodlibet/browsers/filesystem.py:41 msgid "_File System" msgstr "Sistema de _arquivos" #: ../quodlibet/browsers/filesystem.py:113 ../quodlibet/browsers/media.py:491 #: ../quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "Nom foi possível copiar as canções" #: ../quodlibet/browsers/filesystem.py:114 ../quodlibet/qltk/songlist.py:268 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "" "Os arquivos seleccionados nom se puiderom copiar a outras listas de " "reproduçom ou à fileira" #: ../quodlibet/browsers/filesystem.py:189 msgid "_Add to Library" msgstr "_Engadir à Colecçom" #: ../quodlibet/browsers/iradio.py:178 msgid "Unsupported file type" msgstr "Tipo de arquivo nom admitido" #: ../quodlibet/browsers/iradio.py:179 #, 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ó podem conter endereços de emisoras, nom outras " "listas de emisoras NEM listas de reproduçom. Os seguintes endereços nom " "puiderom ser carregados:\n" "%s" #: ../quodlibet/browsers/iradio.py:219 ../quodlibet/browsers/iradio.py:232 #: ../quodlibet/browsers/iradio.py:810 msgid "Unable to add station" msgstr "Nom foi possível engadir a emisora" #: ../quodlibet/browsers/iradio.py:243 ../quodlibet/browsers/iradio.py:471 msgid "Internet Radio" msgstr "Radio por Internet" #: ../quodlibet/browsers/iradio.py:243 #, fuzzy msgid "Downloading station list" msgstr "Baixar os arquivos" #: ../quodlibet/browsers/iradio.py:339 msgid "New Station" msgstr "Nova Emisora" #: ../quodlibet/browsers/iradio.py:340 msgid "Enter the location of an Internet radio station:" msgstr "Por favor, introduz o endereço dumha emisora por Internet" #: ../quodlibet/browsers/iradio.py:358 msgid "Electronic" msgstr "Electrónica" #: ../quodlibet/browsers/iradio.py:361 msgid "Hip Hop / Rap" msgstr "Hip Hop / Rap" #: ../quodlibet/browsers/iradio.py:362 msgid "Oldies" msgstr "Velhos sucessos" #: ../quodlibet/browsers/iradio.py:363 msgid "R&B" msgstr "R&B" #: ../quodlibet/browsers/iradio.py:364 msgid "Japanese" msgstr "Japonesa" #: ../quodlibet/browsers/iradio.py:365 msgid "Indian" msgstr "Índio" #: ../quodlibet/browsers/iradio.py:367 msgid "Religious" msgstr "Religioso" #: ../quodlibet/browsers/iradio.py:369 msgid "Charts" msgstr "Charts" #: ../quodlibet/browsers/iradio.py:370 msgid "Turkish" msgstr "Turca" #: ../quodlibet/browsers/iradio.py:371 msgid "Reggae / Dancehall" msgstr "Reggae / Baile" #: ../quodlibet/browsers/iradio.py:372 #, fuzzy msgid "Latin" msgstr "qualificaçom" #: ../quodlibet/browsers/iradio.py:373 msgid "College Radio" msgstr "Rádio universitária" #: ../quodlibet/browsers/iradio.py:374 msgid "Talk / News" msgstr "Faladoiro / Notícias" #: ../quodlibet/browsers/iradio.py:375 msgid "Ambient" msgstr "Ambiente" #: ../quodlibet/browsers/iradio.py:376 msgid "Jazz" msgstr "Jazz" #: ../quodlibet/browsers/iradio.py:377 ../quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "Clássica" #: ../quodlibet/browsers/iradio.py:378 ../quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "Pop" #: ../quodlibet/browsers/iradio.py:379 msgid "Alternative" msgstr "Alternativa" #: ../quodlibet/browsers/iradio.py:380 msgid "Metal" msgstr "Metal" #: ../quodlibet/browsers/iradio.py:381 msgid "Country" msgstr "Country" #: ../quodlibet/browsers/iradio.py:382 msgid "News" msgstr "Notícias" #: ../quodlibet/browsers/iradio.py:383 msgid "Schlager" msgstr "Schlager" #: ../quodlibet/browsers/iradio.py:384 msgid "Funk" msgstr "Funk" #: ../quodlibet/browsers/iradio.py:385 msgid "Indie" msgstr "Indie" #: ../quodlibet/browsers/iradio.py:386 msgid "Blues" msgstr "Blues" #: ../quodlibet/browsers/iradio.py:387 msgid "Soul" msgstr "Soul" #: ../quodlibet/browsers/iradio.py:388 msgid "Lounge" msgstr "Lounge" #: ../quodlibet/browsers/iradio.py:389 msgid "Punk" msgstr "Punk" #: ../quodlibet/browsers/iradio.py:390 msgid "Reggaeton" msgstr "Reggaeton" #: ../quodlibet/browsers/iradio.py:392 msgid "Slavic" msgstr "Eslava" #: ../quodlibet/browsers/iradio.py:394 msgid "Greek" msgstr "Grega" #: ../quodlibet/browsers/iradio.py:395 msgid "Gothic" msgstr "Gótica" #: ../quodlibet/browsers/iradio.py:396 ../quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "Rock" #: ../quodlibet/browsers/iradio.py:449 msgid "Would you like to load a list of popular radio stations?" msgstr "" #: ../quodlibet/browsers/iradio.py:455 #, fuzzy msgid "_Load Stations" msgstr "_Nova Emisora" #: ../quodlibet/browsers/iradio.py:472 msgid "_Internet Radio" msgstr "Radio por _Internet" #: ../quodlibet/browsers/iradio.py:538 #, fuzzy msgid "_New Station…" msgstr "Nova Emisora" #: ../quodlibet/browsers/iradio.py:541 #, fuzzy msgid "_Update Stations" msgstr "_Nova Emisora" #: ../quodlibet/browsers/iradio.py:568 #, fuzzy msgid "All Stations" msgstr "Nova Emisora" #. TODO: support for ~#rating=!None etc (#1940) #: ../quodlibet/browsers/iradio.py:572 #: ../quodlibet/browsers/soundcloud/main.py:64 msgid "Favorites" msgstr "Prediletos" #: ../quodlibet/browsers/iradio.py:580 #, fuzzy msgid "No Category" msgstr "Sem categoria" #: ../quodlibet/browsers/iradio.py:802 msgid "No stations found" msgstr "Nom se atopárom emisoras" #: ../quodlibet/browsers/iradio.py:803 #, python-format msgid "No Internet radio stations were found at %s." msgstr "Nom se atopárom emisoras de radio por internet em %s" #: ../quodlibet/browsers/iradio.py:811 msgid "All stations listed are already in your library." msgstr "Todas as emisoras relacionadas já estám na sua colecçom" #: ../quodlibet/browsers/iradio.py:828 #, fuzzy msgid "Add to Favorites" msgstr "_Engadir à lista" #: ../quodlibet/browsers/iradio.py:832 #, fuzzy msgid "Remove from Favorites" msgstr "Elimina_r da Lista" #: ../quodlibet/browsers/iradio.py:932 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "%(count)d emisora" msgstr[1] "%(count)d emisoras" #: ../quodlibet/browsers/media.py:36 msgid "Device Properties" msgstr "Propriedades do dispositivo" #: ../quodlibet/browsers/media.py:52 msgid "Device:" msgstr "Dispositivo:" #: ../quodlibet/browsers/media.py:54 msgid "Not mounted" msgstr "Nom está montado" #: ../quodlibet/browsers/media.py:55 #, fuzzy msgid "Mount point:" msgstr "Ponto de montagem:" #: ../quodlibet/browsers/media.py:61 ../quodlibet/qltk/cbes.py:40 msgid "_Name:" msgstr "_Nome:" #: ../quodlibet/browsers/media.py:135 msgid "Media Devices" msgstr "Dispositivos externos" #: ../quodlibet/browsers/media.py:136 msgid "_Media Devices" msgstr "Dispositivos _externos" #. eject button #: ../quodlibet/browsers/media.py:224 ../quodlibet/browsers/media.py:378 msgid "_Eject" msgstr "_Expulsar" #: ../quodlibet/browsers/media.py:360 #, fuzzy msgid "_Properties" msgstr "Propriedades" #: ../quodlibet/browsers/media.py:365 #: ../quodlibet/browsers/playlists/main.py:464 msgid "_Rename" msgstr "_Mudar o nome" #: ../quodlibet/browsers/media.py:461 #, fuzzy, python-format msgid "%(used-size)s used, %(free-size)s available" msgstr "<b>%s</b> utilizado, <b>%s</b> disponível" #: ../quodlibet/browsers/media.py:479 #, fuzzy, python-format msgid "%s is not connected." msgstr "<b>%s</b> nom está conectado." #: ../quodlibet/browsers/media.py:499 #, fuzzy, python-format msgid "Copying %(song)s" msgstr "A copiar <b>%(song)s</b>" #: ../quodlibet/browsers/media.py:513 ../quodlibet/browsers/media.py:529 msgid "Unable to copy song" msgstr "Non foi possível copiar a cançom" #: ../quodlibet/browsers/media.py:514 msgid "There is not enough free space for this song." msgstr "Nom há espaço livre de abondo para essa cançom." #: ../quodlibet/browsers/media.py:526 #, fuzzy, python-format msgid "%s could not be copied." msgstr "<b>%s</b> nom puido ser copiada." #: ../quodlibet/browsers/media.py:545 msgid "Unable to delete songs" msgstr "Nom se puidérom eliminar as canções" #: ../quodlibet/browsers/media.py:557 #, fuzzy, python-format msgid "Deleting %(song)s" msgstr "A eliminar <b>%(song)s</b>" #: ../quodlibet/browsers/media.py:575 #, fuzzy, python-format msgid "%s could not be deleted." msgstr "<b>%s</b> nom se puido eliminar." #: ../quodlibet/browsers/media.py:579 msgid "Unable to delete song" msgstr "Non foi possível eliminar a cançom" #: ../quodlibet/browsers/media.py:594 #, fuzzy, python-format msgid "Ejecting %s failed." msgstr "Erro ao expulsar <b>%s</b>." #: ../quodlibet/browsers/media.py:597 msgid "Unable to eject device" msgstr "Nom foi possível expulsar o dispositivo" #: ../quodlibet/browsers/media.py:603 msgid "No device backend, Media Devices browser disabled." msgstr "" "Sem sistema de infraestrutura de dispositivos, desactivou-se o navegador de " "dispositivos" #: ../quodlibet/browsers/paned/main.py:40 ../quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "Vista em paneis" #: ../quodlibet/browsers/paned/main.py:41 msgid "_Paned Browser" msgstr "_Vista em paneis" #: ../quodlibet/browsers/paned/main.py:90 msgid "Select _All" msgstr "Seleccionar _tudo" #: ../quodlibet/browsers/paned/models.py:104 ../quodlibet/qltk/pluginwin.py:122 #: ../quodlibet/qltk/pluginwin.py:164 msgid "All" msgstr "Tudo" #: ../quodlibet/browsers/paned/prefs.py:67 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "<tt>%s</tt>" msgstr "" #: ../quodlibet/browsers/paned/prefs.py:162 msgid "_Wide Mode" msgstr "" #: ../quodlibet/browsers/paned/prefs.py:197 msgid "Paned Browser Preferences" msgstr "Preferências do Navegador em paneis" #: ../quodlibet/browsers/paned/prefs.py:204 msgid "Equal pane width" msgstr "" #: ../quodlibet/browsers/playlists/main.py:48 #: ../quodlibet/browsers/playlists/main.py:575 #: ../quodlibet/qltk/pluginwin.py:168 msgid "Playlists" msgstr "Listas" #: ../quodlibet/browsers/playlists/main.py:49 msgid "_Playlists" msgstr "_Listas" #: ../quodlibet/browsers/playlists/main.py:152 msgid "_Remove from Playlist" msgstr "Elimina_r da Lista" #: ../quodlibet/browsers/playlists/main.py:215 #: ../quodlibet/browsers/playlists/main.py:576 msgid "_Import" msgstr "_Importar" #: ../quodlibet/browsers/playlists/main.py:391 #: ../quodlibet/browsers/playlists/util.py:50 #: ../quodlibet/util/collection.py:570 msgid "New Playlist" msgstr "Nova Lista" #: ../quodlibet/browsers/playlists/main.py:413 msgid "Unable to import playlist" msgstr "Non foi possível importar a lista" #: ../quodlibet/browsers/playlists/main.py:414 msgid "Quod Libet can only import playlists in the M3U and PLS formats." msgstr "O Quod Libet só pode importar listas nos formatos M3U ou PLS." #: ../quodlibet/browsers/playlists/main.py:565 msgid "Unable to rename playlist" msgstr "Non foi possível mudar o nome da lista" #: ../quodlibet/browsers/playlists/main.py:576 msgid "Import Playlist" msgstr "Importar lista" #: ../quodlibet/browsers/playlists/menu.py:25 #, fuzzy msgid "_New Playlist…" msgstr "_Nova Lista" #: ../quodlibet/browsers/playlists/menu.py:86 #, 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:90 #, 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:33 #, 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:35 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" "Toda a informaçom sobre a lista selecionada vai ser eliminada e nom se " "poderá repor" #: ../quodlibet/browsers/playlists/util.py:51 #, fuzzy msgid "Enter a name for the new playlist:" msgstr "Introduz um nome para o novo cartafol:" #: ../quodlibet/browsers/playlists/util.py:102 #, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" "A importar a lista de reproduçom\\n\n" "\n" "%(current)d/%(total)d canções engadidas." #: ../quodlibet/browsers/search.py:33 msgid "_Limit Results" msgstr "_Limitar os resultados" #: ../quodlibet/browsers/search.py:48 msgid "Search Library" msgstr "Procurar na colecçom" #: ../quodlibet/browsers/search.py:49 msgid "_Search Library" msgstr "_Procurar na colecçom" #: ../quodlibet/browsers/soundcloud/main.py:38 #, fuzzy msgid "Soundcloud Browser" msgstr "Vista em paneis" #: ../quodlibet/browsers/soundcloud/main.py:39 msgid "Sound_cloud" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:59 #: ../quodlibet/qltk/searchbar.py:73 msgid "Search" msgstr "Procurar" #: ../quodlibet/browsers/soundcloud/main.py:136 #, python-format msgid "Go to %s" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:380 #, fuzzy msgid "Connected" msgstr "endereço" #: ../quodlibet/browsers/soundcloud/main.py:381 #, python-format msgid "Quod Libet is now connected, <b>%s</b>!" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:393 #, python-format msgid "Log out of %s" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:395 msgid "Enter code…" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:396 #, python-format msgid "Log in to %s" msgstr "" #: ../quodlibet/browsers/soundcloud/util.py:86 msgid "Soundcloud authorisation" msgstr "" #: ../quodlibet/browsers/soundcloud/util.py:87 msgid "Enter Soundcloud auth code:" msgstr "" #: ../quodlibet/cli.py:50 #, fuzzy msgid "Quod Libet is not running (add '--run' to start it)" msgstr "O Quod Libet nom está a ser executado." #: ../quodlibet/cli.py:85 msgid "a music library and player" msgstr "um gestor de música e reprodutor" #: ../quodlibet/cli.py:86 #, fuzzy msgid "[option]" msgstr "[opções]" #: ../quodlibet/cli.py:88 msgid "Print the playing song and exit" msgstr "Mostra a cançom que se está a reproduzir" #: ../quodlibet/cli.py:89 msgid "Begin playing immediately" msgstr "Começar a tocar imediatamente" #: ../quodlibet/cli.py:90 msgid "Don't show any windows on start" msgstr "" #: ../quodlibet/cli.py:93 msgid "Jump to next song" msgstr "Ir à cançom seguinte" #: ../quodlibet/cli.py:95 msgid "Jump to previous song or restart if near the beginning" msgstr "Saltar à cançom anterior ou, de estar próximo ao início, recomeçar" #: ../quodlibet/cli.py:96 msgid "Jump to previous song" msgstr "Ir à cançom anterior" #: ../quodlibet/cli.py:97 msgid "Start playback" msgstr "Começar a reproduçom" #: ../quodlibet/cli.py:98 msgid "Pause playback" msgstr "Parar a reproduçom" #: ../quodlibet/cli.py:99 msgid "Toggle play/pause mode" msgstr "Alternar entre reproduzir e parar" #: ../quodlibet/cli.py:100 #, fuzzy msgid "Stop playback" msgstr "Começar a reproduçom" #: ../quodlibet/cli.py:101 msgid "Turn up volume" msgstr "Aumentar o volume" #: ../quodlibet/cli.py:102 msgid "Turn down volume" msgstr "Diminuir o volume" #: ../quodlibet/cli.py:103 msgid "Print player status" msgstr "Mostrar o estado do reprodutor" #: ../quodlibet/cli.py:104 msgid "Hide main window" msgstr "Agochar a fiestra principal" #: ../quodlibet/cli.py:105 msgid "Show main window" msgstr "Mostrar a fiestra principal" #: ../quodlibet/cli.py:106 msgid "Toggle main window visibility" msgstr "Alternar entre mostrar e agochar a fiestra principal" #: ../quodlibet/cli.py:107 msgid "Focus the running player" msgstr "Centrar-se no reprodutor actual" #: ../quodlibet/cli.py:108 msgid "Remove active browser filters" msgstr "Eliminar os filtros de navegaçom activos" #: ../quodlibet/cli.py:109 msgid "Refresh and rescan library" msgstr "Reler e actualizar a colecçom" #: ../quodlibet/cli.py:110 #, fuzzy msgid "List available browsers" msgstr "Desactivar o Navegador" #: ../quodlibet/cli.py:111 msgid "Print the current playlist" msgstr "Mostrar a lista de reproduçom actual" #: ../quodlibet/cli.py:112 msgid "Print the contents of the queue" msgstr "Mostrar o conteúdo da fileira" #: ../quodlibet/cli.py:113 #, fuzzy msgid "Print the active text query" msgstr "Mostrar o conteúdo da fileira" #: ../quodlibet/cli.py:114 msgid "Start without plugins" msgstr "Começar sem extensões" #: ../quodlibet/cli.py:115 #, fuzzy msgid "Start Quod Libet if it isn't running" msgstr "O Quod Libet nom está a ser executado." #: ../quodlibet/cli.py:116 msgid "Exit Quod Libet" msgstr "Sair do Quod Libet" #: ../quodlibet/cli.py:121 msgid "Seek within the playing song" msgstr "Avançar na cançom reproduzida" #: ../quodlibet/cli.py:121 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: ../quodlibet/cli.py:122 #, fuzzy msgid "Set or toggle shuffle mode" msgstr "Alternar entre reproduzir e parar" #: ../quodlibet/cli.py:123 msgid "Turn repeat off, on, or toggle it" msgstr "Activar ou desactivar o modo repetiçom" #: ../quodlibet/cli.py:124 msgid "Set the volume" msgstr "Configurar o volume" #: ../quodlibet/cli.py:125 msgid "Search your audio library" msgstr "Procurar na colecçom" #: ../quodlibet/cli.py:125 ../quodlibet/cli.py:137 ../quodlibet/cli.py:141 #: ../quodlibet/cli.py:143 msgid "query" msgstr "procura" #: ../quodlibet/cli.py:126 msgid "Play a file" msgstr "Reproduzir um arquivo" #: ../quodlibet/cli.py:126 ../quodlibet/cli.py:137 ../quodlibet/cli.py:143 #, fuzzy msgctxt "command" msgid "filename" msgstr "nome do ficheiro" #: ../quodlibet/cli.py:127 msgid "Rate the playing song" msgstr "Qualificar a cançom activa" #: ../quodlibet/cli.py:128 msgid "Set the current browser" msgstr "Configurar o navegador activo" #: ../quodlibet/cli.py:129 #, fuzzy msgid "Stop after the playing song" msgstr "Qualificar a cançom activa" #: ../quodlibet/cli.py:130 msgid "Open a new browser" msgstr "Abrir um novo navegador" #: ../quodlibet/cli.py:131 msgid "Show or hide the queue" msgstr "Mostrar ou agochar a fileira" #: ../quodlibet/cli.py:133 #, fuzzy msgid "Show or hide the main song list (deprecated)" msgstr "Mostrar ou agochar a lista principal" #: ../quodlibet/cli.py:134 msgid "Filter on a random value" msgstr "Filtro num valor aleatório" #: ../quodlibet/cli.py:134 #, fuzzy msgctxt "command" msgid "tag" msgstr "etiqueta" #: ../quodlibet/cli.py:135 msgid "Filter on a tag value" msgstr "Filtrar num valor da etiqueta" #: ../quodlibet/cli.py:135 msgid "tag=value" msgstr "etiqueta=valor" #: ../quodlibet/cli.py:136 msgid "Enqueue a file or query" msgstr "Pôr na fileira un arquivo ou procura" #: ../quodlibet/cli.py:138 msgid "Enqueue comma-separated files" msgstr "Engadir à fileira nomes de arquivo separados por comas" #: ../quodlibet/cli.py:139 ../quodlibet/util/tags.py:147 msgid "filename" msgstr "nome do ficheiro" #: ../quodlibet/cli.py:140 msgid "Print filenames of results of query to stdout" msgstr "Mostrar na saída padrom os nomes de archivo dos resultados da procura" #: ../quodlibet/cli.py:142 msgid "Unqueue a file or query" msgstr "Eliminar da fileira um arquivo ou procura" #: ../quodlibet/cli.py:203 #, python-format msgid "Invalid argument for '%s'." msgstr "Argumento inválido para '%s'." #: ../quodlibet/cli.py:204 ../quodlibet/util/__init__.py:190 #, python-format msgid "Try %s --help." msgstr "Tenta %s --help." #: ../quodlibet/devices/_base.py:65 msgid "Unknown Device" msgstr "Dispositivo desconhecido" #: ../quodlibet/devices/__init__.py:32 #, fuzzy, python-format 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." #: ../quodlibet/devices/__init__.py:153 #, python-format msgid "%r is not a supported device." msgstr "%r nom é um dispositivo admitido." #: ../quodlibet/devices/__init__.py:245 ../quodlibet/devices/__init__.py:251 #, fuzzy, python-format msgid "Could not find '%s'." msgstr "%s: Nom se puido achar media-player-info." #: ../quodlibet/devices/__init__.py:450 msgid "Initializing device backend." msgstr "A iniciar a infraestrutura de dispositivos." #: ../quodlibet/devices/__init__.py:451 #, python-format msgid "Trying '%s'" msgstr "A tentar '%s'" #: ../quodlibet/devices/__init__.py:461 msgid "Couldn't connect to a device backend." msgstr "Nom se puido conectar a unha infraestrutura gestora de dispositivos." #: ../quodlibet/devices/__init__.py:463 msgid "Device backend initialized." msgstr "Iniciou-se a infraestrutura de dispositivos." #: ../quodlibet/devices/storage.py:57 #, fuzzy msgid "_Filename pattern:" msgstr "Padrom para o _nome:" #: ../quodlibet/devices/storage.py:61 msgid "Copy _album covers" msgstr "Copiar as _cobertas dos discos" #: ../quodlibet/devices/storage.py:65 msgid "_Remove unused covers and directories" msgstr "_Eliminar cobertas e cartafoles nom utilizados" #: ../quodlibet/errorreport/ui.py:60 #, fuzzy msgid "An Error Occurred" msgstr "Ocorreu un erro" #: ../quodlibet/errorreport/ui.py:62 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:72 msgid "File Bug Report" msgstr "" #: ../quodlibet/errorreport/ui.py:74 ../quodlibet/errorreport/ui.py:90 msgid "Submit Error Report" msgstr "" #: ../quodlibet/errorreport/ui.py:75 msgid "Quit Program" msgstr "" #: ../quodlibet/errorreport/ui.py:76 #, fuzzy msgid "Ignore Error" msgstr "Ignorar todos os _erros" #: ../quodlibet/errorreport/ui.py:80 msgid "Error details:" msgstr "" #: ../quodlibet/errorreport/ui.py:92 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:100 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "" #: ../quodlibet/errorreport/ui.py:109 msgid "_Send" msgstr "" #: ../quodlibet/errorreport/ui.py:115 #, fuzzy msgid "Short description…" msgstr "descriçom" #: ../quodlibet/errorreport/ui.py:118 msgid "Data to be sent:" msgstr "" #: ../quodlibet/exfalso.py:34 msgid "an audio tag editor" msgstr "um editor de etiquetas de música" #: ../quodlibet/exfalso.py:34 ../quodlibet/util/tags.py:148 msgid "directory" msgstr "cartafol" #: ../quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "" #: ../quodlibet/ext/covers/artwork_url.py:20 msgid "" "Downloads covers linked to by the artwork_url tag.This works with the " "Soundcloud browser." msgstr "" #: ../quodlibet/ext/covers/discogs.py:25 #, fuzzy msgid "Discogs Cover Source" msgstr "ID do MusicBraniz da pista" #: ../quodlibet/ext/covers/discogs.py:26 msgid "Downloads covers from Discogs." msgstr "" #: ../quodlibet/ext/covers/lastfm.py:22 msgid "Last.fm Cover Source" msgstr "" #: ../quodlibet/ext/covers/lastfm.py:23 msgid "Downloads covers from Last.fm's cover art archive." msgstr "" #: ../quodlibet/ext/covers/musicbrainz.py:19 #, fuzzy msgid "MusicBrainz Cover Source" msgstr "ID do MusicBraniz da pista" #: ../quodlibet/ext/covers/musicbrainz.py:20 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:25 msgid "Kana/Kanji Simple Inverter" msgstr "" #: ../quodlibet/ext/editing/kakasi.py:26 msgid "Converts kana/kanji to romaji before renaming." msgstr "" #: ../quodlibet/ext/editing/kakasi.py:35 msgid "Romanize _Japanese text" msgstr "" #: ../quodlibet/ext/editing/kakasi.py:63 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:19 msgid "" "Allows arbitrary regex substitutions (s///) 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:69 #, fuzzy msgid "Advanced Preferences" msgstr "Preferências do Navegador em paneis" #: ../quodlibet/ext/events/advanced_preferences.py:70 msgid "Allow editing of advanced config settings." msgstr "" #: ../quodlibet/ext/events/advanced_preferences.py:162 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:153 msgid "Top of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:154 msgid "Middle of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:155 msgid "Bottom of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:158 msgid "_Position:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:171 #, fuzzy msgid "_Cover size:" msgstr "Tamanho total:" #: ../quodlibet/ext/events/animosd/prefs.py:177 #: ../quodlibet/ext/events/lyricswindow.py:334 ../quodlibet/qltk/prefs.py:266 #, fuzzy msgid "Display" msgstr "Editar a vista" #: ../quodlibet/ext/events/animosd/prefs.py:190 msgid "_Font:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:195 msgid "Left" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:196 msgid "Center" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:197 #, fuzzy msgid "Right" msgstr "_Importância" #: ../quodlibet/ext/events/animosd/prefs.py:200 msgid "_Align text:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:206 msgid "Text" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:217 msgid "_Text:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:227 msgid "_Fill:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:232 #: ../quodlibet/ext/events/synchronizedlyrics.py:63 msgid "Colors" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:240 msgid "_Shadows" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:241 #, fuzzy msgid "_Outline" msgstr "Infraestrutura de _saída:" #: ../quodlibet/ext/events/animosd/prefs.py:242 msgid "Rou_nded Corners" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:258 msgid "_Delay:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:264 #: ../quodlibet/qltk/pluginwin.py:172 msgid "Effects" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:270 #, fuzzy msgid "Ed_it Display Pattern…" msgstr "Editar a vista" #: ../quodlibet/ext/events/animosd/prefs.py:274 #: ../quodlibet/ext/events/trayicon/prefs.py:78 #, fuzzy msgid "Preview" msgstr "_Antever" #: ../quodlibet/ext/events/auto_library_update.py:136 msgid "Automatic Library Update" msgstr "" #: ../quodlibet/ext/events/auto_library_update.py:137 #, python-format msgid "Keeps your library up to date with inotify. Requires %s." msgstr "" #: ../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 by Brian Nelson." 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/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:97 msgid "Equalizer" msgstr "" #: ../quodlibet/ext/events/equalizer.py:98 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:132 #, 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:138 #, python-format msgid "%.1f kHz" msgstr "" #: ../quodlibet/ext/events/equalizer.py:139 #: ../quodlibet/ext/gstreamer/crossfeed.py:93 #: ../quodlibet/ext/gstreamer/karaoke.py:95 #, python-format msgid "%d Hz" msgstr "" #: ../quodlibet/ext/events/equalizer.py:173 #: ../quodlibet/ext/gstreamer/crossfeed.py:112 #, fuzzy, python-format msgid "%.1f dB" msgstr "%d segundo" #: ../quodlibet/ext/events/equalizer.py:192 #: ../quodlibet/ext/gstreamer/crossfeed.py:31 #, fuzzy msgid "Custom" msgstr "_Personalizada" #: ../quodlibet/ext/events/equalizer.py:199 #, fuzzy msgid "_Clear" msgstr "_Eliminar os erros" #. Translators: statuses relating to Instant Messenger apps #: ../quodlibet/ext/events/gajim_status.py:27 msgid "online" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:28 msgid "offline" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:29 msgid "chat" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:30 msgid "away" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:31 msgid "xa" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:32 msgid "invisible" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:37 msgid "Gajim Status Message" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:38 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:45 #: ../quodlibet/ext/events/telepathy_status.py:69 msgid "paused" 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:160 msgid "Add '[paused]'" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:163 msgid "If checked, '[paused]' will be added to status message on pause." msgstr "" #: ../quodlibet/ext/events/gajim_status.py:187 msgid "Statuses for which message will be changed" msgstr "" #: ../quodlibet/ext/events/headphonemon.py:156 msgid "Pause on Headphone Unplug" msgstr "" #: ../quodlibet/ext/events/headphonemon.py:157 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" #: ../quodlibet/ext/events/inhibit.py:41 msgid "Inhibit Screensaver" msgstr "" #: ../quodlibet/ext/events/inhibit.py:42 msgid "Prevents the GNOME screensaver from activating while a song is playing." msgstr "" #: ../quodlibet/ext/events/inhibit.py:51 #, fuzzy msgid "Music is playing" msgstr "Reprodutor de música" #: ../quodlibet/ext/events/iradiolog.py:16 #, fuzzy msgid "Internet Radio Log" msgstr "Radio por Internet" #: ../quodlibet/ext/events/iradiolog.py:17 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" #: ../quodlibet/ext/events/jep118.py:29 msgid "JEP-118" msgstr "" #: ../quodlibet/ext/events/jep118.py:30 msgid "Outputs a Jabber User Tunes file to ~/.quodlibet/jabber." 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 msgid "A restart is required for any changes to take effect" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:199 #, fuzzy msgid "No active song" msgstr "Nom foi possível guardar a cançom" #: ../quodlibet/ext/events/lyricswindow.py:215 #, fuzzy msgid "No lyrics found" msgstr "Nom se atopárom extensões." #: ../quodlibet/ext/events/lyricswindow.py:227 #, fuzzy msgid "Lyrics:" msgstr "Letra" #: ../quodlibet/ext/events/lyricswindow.py:284 msgid "_Zoom level:" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:302 msgid "URL:" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:307 msgid "Revert to default" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:322 msgid "Search via above URL if the lyrics couldn't be found in LyricsWikia." msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:339 #, fuzzy msgid "Alternate search" msgstr "Limpar a procura" #: ../quodlibet/ext/events/lyricswindow.py:347 #, fuzzy msgid "Lyrics Window" msgstr "Letra" #: ../quodlibet/ext/events/lyricswindow.py:348 #, fuzzy msgid "Shows a window containing lyrics of the playing song." msgstr "Ver e editar as tags da cançom reproduzida" #: ../quodlibet/ext/events/mediaserver.py:38 msgid "UPnP AV Media Server" msgstr "" #: ../quodlibet/ext/events/mediaserver.py:39 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." 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:39 msgid "" "Allows control of Quod Libet using the MPRIS 1.0/2.0 D-Bus Interface " "Specification." msgstr "" #: ../quodlibet/ext/events/mpris/__init__.py:45 #: ../quodlibet/ext/events/trayicon/prefs.py:30 #, fuzzy msgid "Hide main window on close" msgstr "Agochar a fiestra principal" #: ../quodlibet/ext/events/mpris/__init__.py:48 #: ../quodlibet/ext/events/themeswitcher.py:84 #: ../quodlibet/ext/gstreamer/compressor.py:99 #: ../quodlibet/ext/gstreamer/crossfeed.py:136 #: ../quodlibet/ext/gstreamer/karaoke.py:99 #: ../quodlibet/ext/gstreamer/pitch.py:83 ../quodlibet/qltk/prefs.py:688 #, fuzzy msgid "Preferences" msgstr "Preferências" #: ../quodlibet/ext/events/mqtt.py:50 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/mqtt.py:56 msgid "MQTT Publisher" msgstr "" #: ../quodlibet/ext/events/mqtt.py:57 msgid "Publishes status messages to an MQTT topic." msgstr "" #: ../quodlibet/ext/events/mqtt.py:122 msgid "Broker hostname" msgstr "" #: ../quodlibet/ext/events/mqtt.py:122 msgid "broker hostname / IP" msgstr "" #: ../quodlibet/ext/events/mqtt.py:124 msgid "Broker port" msgstr "" #: ../quodlibet/ext/events/mqtt.py:124 msgid "broker port" msgstr "" #: ../quodlibet/ext/events/mqtt.py:126 msgid "Topic" msgstr "" #: ../quodlibet/ext/events/mqtt.py:128 #, fuzzy msgid "Playing Pattern" msgstr "padrom" #: ../quodlibet/ext/events/mqtt.py:130 msgid "Status text when a song is started." msgstr "" #: ../quodlibet/ext/events/mqtt.py:132 #, fuzzy msgid "Paused Pattern" msgstr "padrom" #: ../quodlibet/ext/events/mqtt.py:134 msgid "Text when a song is paused." msgstr "" #: ../quodlibet/ext/events/mqtt.py:136 #, fuzzy msgid "No-song Text" msgstr "%d cançom" #: ../quodlibet/ext/events/mqtt.py:138 msgid "Plain text for when there is no current song" msgstr "" #: ../quodlibet/ext/events/mqtt.py:149 #, fuzzy msgid "MQTT Configuration" msgstr "Saída do registro" #: ../quodlibet/ext/events/mqtt.py:153 #, fuzzy msgid "Status Text" msgstr "padrom" #: ../quodlibet/ext/events/mqtt.py:185 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "" #: ../quodlibet/ext/events/mqtt.py:189 #, 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:192 #, fuzzy msgid "Connection error" msgstr "endereço" #: ../quodlibet/ext/events/notify.py:80 msgid "Notification text" msgstr "" #: ../quodlibet/ext/events/notify.py:88 #, fuzzy msgid "_Title:" msgstr "Título" #: ../quodlibet/ext/events/notify.py:99 ../quodlibet/ext/events/notify.py:128 msgid "Revert to default pattern" msgstr "" #: ../quodlibet/ext/events/notify.py:118 msgid "_Body:" msgstr "" #: ../quodlibet/ext/events/notify.py:138 msgid "_Show notification" msgstr "" #: ../quodlibet/ext/events/notify.py:156 #, fuzzy msgid "Show notifications" msgstr "Nom há novas emisoras" #: ../quodlibet/ext/events/notify.py:162 msgid "Only on <i>_manual</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:170 msgid "Only on <i>_automatic</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:178 msgid "On <i>a_ll</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:196 msgid "Only when the main window is not _focused" msgstr "" #: ../quodlibet/ext/events/notify.py:204 msgid "Show \"_Next\" button" msgstr "" #: ../quodlibet/ext/events/notify.py:236 msgid "Connection Error" msgstr "" #: ../quodlibet/ext/events/notify.py:237 ../quodlibet/ext/events/notify.py:391 #: ../quodlibet/ext/events/notify.py:433 #, fuzzy msgid "Couldn't connect to notification daemon." msgstr "Nom se puido conectar a unha infraestrutura gestora de dispositivos." #: ../quodlibet/ext/events/notify.py:251 #, fuzzy msgid "Song Notifications" msgstr "Nom há novas emisoras" #: ../quodlibet/ext/events/notify.py:252 msgid "Displays a notification when the song changes." msgstr "" #: ../quodlibet/ext/events/notify.py:415 ../quodlibet/qltk/unity.py:65 msgid "Next" msgstr "Seguinte" #: ../quodlibet/ext/events/qlscrobbler.py:178 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:254 #, 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:260 msgid "Authentication failed: invalid URL." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:277 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:282 msgid "Client is banned. Contact the author." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:286 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:351 msgid "AudioScrobbler Submission" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:352 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:450 msgid "Authentication successful." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:462 #, fuzzy msgid "_Service:" msgstr "Dispositivo:" #: ../quodlibet/ext/events/qlscrobbler.py:462 msgid "_URL:" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:462 #, fuzzy msgid "User_name:" msgstr "_Nome:" #: ../quodlibet/ext/events/qlscrobbler.py:463 msgid "_Password:" msgstr "" #. Translators: Other service #: ../quodlibet/ext/events/qlscrobbler.py:479 #, fuzzy msgid "Other…" msgstr "_Outros:" #. verify data #: ../quodlibet/ext/events/qlscrobbler.py:517 msgid "_Verify account data" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:522 #: ../quodlibet/ext/songsmenu/lastfmsync.py:304 msgid "Account" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:530 #, fuzzy msgid "_Artist pattern:" msgstr "_Artista" #: ../quodlibet/ext/events/qlscrobbler.py:530 #, fuzzy msgid "_Title pattern:" msgstr "Padrom para o _nome:" #: ../quodlibet/ext/events/qlscrobbler.py:531 msgid "Exclude _filter:" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:549 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:559 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:568 msgid "Songs matching this filter will not be submitted." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:576 msgid "_Offline mode (don't submit anything)" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:580 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:27 #, fuzzy msgid "Random Album Playback" msgstr "Ál_bum aleatório" #: ../quodlibet/ext/events/randomalbum.py:28 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:38 msgid "Rated higher" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:39 msgid "Played more often" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:40 msgid "Skipped more often" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:41 msgid "Played more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:42 msgid "Started more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:43 msgid "Added more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:44 #, fuzzy msgid "Longer albums" msgstr "álbuns" #: ../quodlibet/ext/events/randomalbum.py:83 msgid "seconds before starting next album" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:87 #, fuzzy msgid "Weights" msgstr "_Importância" #: ../quodlibet/ext/events/randomalbum.py:89 msgid "Play some albums more than others" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:103 msgid "avoid" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:114 msgid "prefer" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:201 #, fuzzy msgid "Random Album" msgstr "Ál_bum aleatório" #: ../quodlibet/ext/events/randomalbum.py:202 #, python-format msgid "Waiting to start %s" msgstr "" #: ../quodlibet/ext/events/rbimport.py:114 #, fuzzy msgid "Import Failed" msgstr "Importar lista" #: ../quodlibet/ext/events/rbimport.py:119 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "" #: ../quodlibet/ext/events/rbimport.py:127 msgid "Rhythmbox Import" msgstr "" #: ../quodlibet/ext/events/rbimport.py:128 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "" #: ../quodlibet/ext/events/rbimport.py:132 #, fuzzy msgid "Start Import" msgstr "_Importar" #: ../quodlibet/ext/events/screensaver.py:25 msgid "Screensaver Pause" msgstr "" #: ../quodlibet/ext/events/screensaver.py:26 msgid "Pauses playback while the GNOME screensaver is active." msgstr "" #: ../quodlibet/ext/events/searchprovider.py:73 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "" #: ../quodlibet/ext/events/searchprovider.py:79 msgid "GNOME Search Provider" msgstr "" #: ../quodlibet/ext/events/searchprovider.py:80 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/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:29 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:57 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:58 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:34 #, fuzzy msgid "Synchronized Lyrics" msgstr "Letra" #: ../quodlibet/ext/events/synchronizedlyrics.py:35 msgid "Shows synchronized lyrics from .lrc file with same name as the track." msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:66 msgid "Text:" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:76 msgid "Background:" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:87 msgid "Font" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:90 msgid "Size (px):" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:62 msgid "Telepathy Status Messages" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:63 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:122 #, fuzzy msgid "Playing:" msgstr "Parado" #: ../quodlibet/ext/events/telepathy_status.py:123 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:139 msgid "Paused:" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:140 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:156 msgid "Plain text for status when there is no current song" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:157 #, fuzzy msgid "No song:" msgstr "%d cançom" #. Frame #: ../quodlibet/ext/events/telepathy_status.py:164 #, 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/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:77 #: ../quodlibet/ext/events/trayicon/prefs.py:98 #: ../quodlibet/ext/events/trayicon/systemtray.py:177 #: ../quodlibet/qltk/info.py:47 msgid "Not playing" msgstr "Parado" #: ../quodlibet/ext/events/trayicon/__init__.py:53 #, fuzzy msgid "Tray Icon" msgstr "Preferências da Ícona" #: ../quodlibet/ext/events/trayicon/__init__.py:54 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:183 #: ../quodlibet/qltk/quodlibetwindow.py:1046 #: ../quodlibet/qltk/quodlibetwindow.py:1238 #, fuzzy msgid "_Play" msgstr "Reprodutor" #: ../quodlibet/ext/events/trayicon/menu.py:63 #: ../quodlibet/qltk/quodlibetwindow.py:185 #: ../quodlibet/qltk/quodlibetwindow.py:1240 ../quodlibet/qltk/wlw.py:51 #, fuzzy msgid "P_ause" msgstr "_Parar" #: ../quodlibet/ext/events/trayicon/menu.py:68 #: ../quodlibet/qltk/quodlibetwindow.py:190 #: ../quodlibet/qltk/quodlibetwindow.py:1041 #, fuzzy msgid "Pre_vious" msgstr "_Antever" #: ../quodlibet/ext/events/trayicon/menu.py:71 #: ../quodlibet/qltk/quodlibetwindow.py:194 #: ../quodlibet/qltk/quodlibetwindow.py:1051 #, fuzzy msgid "_Next" msgstr "Seguinte" #: ../quodlibet/ext/events/trayicon/menu.py:76 msgid "_Shuffle" msgstr "_Aleatoriamente" #: ../quodlibet/ext/events/trayicon/menu.py:81 msgid "_Repeat" msgstr "_Repetir" #: ../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:1012 #, fuzzy msgid "Open _Browser" msgstr "Abrir um novo navegador" #: ../quodlibet/ext/events/trayicon/menu.py:103 #: ../quodlibet/qltk/quodlibetwindow.py:1031 ../quodlibet/qltk/songsmenu.py:411 msgid "Edit _Tags" msgstr "Editar as _etiquetas" #: ../quodlibet/ext/events/trayicon/menu.py:112 #: ../quodlibet/qltk/quodlibetwindow.py:975 ../quodlibet/qltk/songsmenu.py:424 msgid "_Information" msgstr "_Informaçom" #: ../quodlibet/ext/events/trayicon/menu.py:114 #: ../quodlibet/qltk/songsmenu.py:340 #, fuzzy msgid "Play_lists" msgstr "Listas" #: ../quodlibet/ext/events/trayicon/menu.py:132 #: ../quodlibet/qltk/quodlibetwindow.py:1026 msgid "_Quit" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:32 ../quodlibet/qltk/prefs.py:69 msgid "Behavior" msgstr "Comportamento" #: ../quodlibet/ext/events/trayicon/prefs.py:42 #, 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:48 msgid "Scroll wheel changes song" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll _Wheel" msgstr "Roda do _Rato" #: ../quodlibet/ext/events/trayicon/prefs.py:84 msgid "Tooltip Display" msgstr "Editar vista" #: ../quodlibet/ext/events/viewlyrics.py:23 #, fuzzy msgid "View Lyrics" msgstr "Letra" #: ../quodlibet/ext/events/viewlyrics.py:24 msgid "Automatically displays lyrics beneath the song list in the main window." msgstr "" #: ../quodlibet/ext/events/viewlyrics.py:29 #, fuzzy msgid "_Lyrics" msgstr "Letra" #: ../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:406 #, fuzzy msgid "Waveform Seek Bar" msgstr "Alternativa" #: ../quodlibet/ext/events/waveformseekbar.py:410 msgid "A seekbar in the shape of the waveform of the current song." msgstr "" #: ../quodlibet/ext/events/waveformseekbar.py:443 msgid "Override foreground color:" msgstr "" #: ../quodlibet/ext/events/write_cover.py:32 msgid "Picture Saver" msgstr "" #: ../quodlibet/ext/events/write_cover.py:33 msgid "Saves the cover image of the current song to a file." msgstr "" #: ../quodlibet/ext/events/write_cover.py:66 #, fuzzy msgid "File:" msgstr "Arquivos" #: ../quodlibet/ext/gstreamer/compressor.py:20 msgid "_Threshold:" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:21 msgid "Threshold until the filter is activated" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:22 msgid "R_atio:" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:22 msgid "Compression ratio" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:74 #: ../quodlibet/ext/gstreamer/karaoke.py:91 #, python-format msgid "%d %%" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:105 msgid "Audio Compressor" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:106 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:19 #, fuzzy msgid "_Preset:" msgstr "_Antever" #: ../quodlibet/ext/gstreamer/crossfeed.py:19 #, fuzzy msgid "Filter preset" msgstr "Filtrar no _artista" #: ../quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Frequency cut:" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Low-pass filter cut frequency" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed _level:" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed level" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:25 #, fuzzy msgid "Default" msgstr "Predefinido" #: ../quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Chu Moy" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Jan Meier" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:31 #, fuzzy msgid "Custom settings" msgstr "_Personalizada" #: ../quodlibet/ext/gstreamer/crossfeed.py:152 msgid "Crossfeed" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:153 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:20 #, fuzzy msgid "Filter _band:" msgstr "Filtrar no e_stilo" #: ../quodlibet/ext/gstreamer/karaoke.py:21 msgid "The Frequency band of the filter" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:22 #, fuzzy msgid "Filter _width:" msgstr "Filtrar no _artista" #: ../quodlibet/ext/gstreamer/karaoke.py:23 msgid "The Frequency width of the filter" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:24 msgid "_Level:" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:24 msgid "Level of the effect" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:105 msgid "Karaoke" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:106 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:20 msgid "R_ate:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:21 msgid "_Tempo:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:22 msgid "_Pitch:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:89 #, fuzzy msgid "Audio Pitch / Speed" msgstr "Fontes de Áudio (feeds)" #: ../quodlibet/ext/gstreamer/pitch.py:90 #, 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:29 #: ../quodlibet/ext/playlist/export_to_folder.py:97 #: ../quodlibet/ext/playlist/export_to_folder.py:138 #, fuzzy msgid "Export Playlist to Folder" msgstr "Importar lista" #: ../quodlibet/ext/playlist/export_to_folder.py:38 #, fuzzy msgid "_Export" msgstr "_Importar" #: ../quodlibet/ext/playlist/export_to_folder.py:43 #, fuzzy msgid "Destination folder:" msgstr "Nom se atopárom emisoras" #: ../quodlibet/ext/playlist/export_to_folder.py:58 #, 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:156 #, fuzzy msgid "Default filename pattern:" msgstr "Padrom para o _nome:" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:23 msgid "Export to Squeezebox" msgstr "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:25 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 "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Export playlist to Squeezebox" msgstr "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:80 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 canções duplicadas serám 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 "" "Playback follows your selection, or the next song in the list once exhausted." msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:22 msgid "Playcount Equalizer" msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:23 msgid "Shuffle, preferring songs with fewer total plays." msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:25 #, fuzzy msgid "Prefer less played" msgstr "última vez tocada" #: ../quodlibet/ext/playorder/queue.py:19 #, fuzzy msgid "Queue Only" msgstr "Na fileira" #: ../quodlibet/ext/playorder/queue.py:21 msgid "" "Limits playing of songs to the queue. Select this play order in the main " "window, then double-clicking any song will enqueue it instead of playing." msgstr "" #: ../quodlibet/ext/playorder/reverse.py:14 #, fuzzy msgid "Reverse" msgstr "Nunca" #: ../quodlibet/ext/playorder/reverse.py:16 msgid "Reverses the play order of songs." msgstr "" #: ../quodlibet/ext/playorder/skip_songs.py:25 #, fuzzy msgid "Skip Songs" msgstr "saltar contador" #: ../quodlibet/ext/playorder/skip_songs.py:27 msgid "" "Playback skips over songs with a rating equal or below a given threshold." msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:30 msgid "Repeat Each Track" msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:32 msgid "Shuffle songs, but repeat every track a set number of times." msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:51 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. Syntax is '@(if: " "condition, then, else)'." msgstr "" #: ../quodlibet/ext/query/pythonexpression.py:14 msgid "Python Query" msgstr "" #: ../quodlibet/ext/query/pythonexpression.py:15 msgid "" "Use Python expressions in queries. Syntax is '@(python: expression)'. The " "variable 's' is the song being matched." msgstr "" #: ../quodlibet/ext/query/savedsearch.py:19 #, fuzzy msgid "Include Saved Search" msgstr "Valores guardados" #: ../quodlibet/ext/query/savedsearch.py:20 msgid "" "Include the results of a saved search as part of another query. Syntax is " "'@(saved: search name)'." 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:116 msgid "Port:" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:121 #, fuzzy msgid "Username:" msgstr "_Mudar o nome" #: ../quodlibet/ext/_shared/squeezebox/base.py:126 msgid "Password:" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:130 msgid "Library directory the server connects to." msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:132 #, fuzzy msgid "Library path:" msgstr "Colecçom" #. Add verify button #: ../quodlibet/ext/_shared/squeezebox/base.py:141 msgid "_Verify settings" msgstr "" #. Server settings Frame #: ../quodlibet/ext/_shared/squeezebox/base.py:147 msgid "Squeezebox Server" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:150 msgid "Debug" msgstr "Debug" #: ../quodlibet/ext/_shared/squeezebox/server.py:26 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:28 msgid "unidentified Squeezebox server" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:37 #, 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:20 #: ../quodlibet/ext/songsmenu/importexport.py:34 #: ../quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:329 #, fuzzy msgid "Fit image to _window" msgstr "Agochar a fiestra principal" #. Both labels #: ../quodlibet/ext/songsmenu/albumart.py:338 msgid "_Program:" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:343 msgid "_Edit image after saving" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:345 #, fuzzy msgid "File_name:" msgstr "Nome do ficheiro" #: ../quodlibet/ext/songsmenu/albumart.py:457 msgid "Saving failed" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:458 #, fuzzy, python-format msgid "Unable to save \"%s\"." msgstr "Nom foi possível guardar a cançom" #: ../quodlibet/ext/songsmenu/albumart.py:556 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:613 #, fuzzy msgid "Album Art Downloader" msgstr "Lista de Álbuns" #: ../quodlibet/ext/songsmenu/albumart.py:666 #, python-format msgid "from %(source)s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:669 #, python-format msgid "Resolution: %s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:672 #, fuzzy, python-format msgid "Size: %s" msgstr "Tamanho" #: ../quodlibet/ext/songsmenu/albumart.py:690 #, fuzzy msgid "_Search" msgstr "_Procurar:" #: ../quodlibet/ext/songsmenu/albumart.py:741 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:451 #, fuzzy msgid "Searching…" msgstr "Procurar" #: ../quodlibet/ext/songsmenu/albumart.py:804 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:922 #, fuzzy msgid "Download Album Art" msgstr "Lista de Álbuns" #: ../quodlibet/ext/songsmenu/albumart.py:923 msgid "Downloads album covers from various websites." msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:936 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 #: ../quodlibet/qltk/downloader.py:52 msgid "Filename" msgstr "Nome do ficheiro" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:130 #, fuzzy msgid "Disc" msgstr "_Disco" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:131 #: ../quodlibet/ext/songsmenu/replaygain.py:404 #: ../quodlibet/qltk/tracknumbers.py:92 msgid "Track" msgstr "Pista" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:132 #, 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:447 msgid "Please enter a query." msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:465 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:496 msgid "Error encountered. Please retry." msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:472 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:488 msgid "Loading result…" msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:475 #, fuzzy msgid "No results found." msgstr "Nom se atopárom extensões." #: ../quodlibet/ext/songsmenu/browsefolders.py:159 #, fuzzy msgid "Browse Folders" msgstr "Navegadores" #: ../quodlibet/ext/songsmenu/browsefolders.py:160 msgid "Opens the songs' folders in a file manager." msgstr "" #: ../quodlibet/ext/songsmenu/browsefolders.py:172 #, fuzzy msgid "Unable to open folders" msgstr "Nom foi possível criar o cartafol" #: ../quodlibet/ext/songsmenu/browsefolders.py:173 msgid "No program available to open folders." msgstr "" #: ../quodlibet/ext/songsmenu/console.py:40 msgid "Python Console" msgstr "" #: ../quodlibet/ext/songsmenu/console.py:41 msgid "Interactive Python console." msgstr "" #: ../quodlibet/ext/songsmenu/console.py:72 msgid "You can access the following objects by default:" msgstr "" #: ../quodlibet/ext/songsmenu/console.py:82 msgid "Your current working directory is:" 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:55 #, fuzzy msgid "pattern" msgstr "Padrom inválido" #: ../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:91 #, fuzzy msgid "Input value" msgstr "Valor inválido" #: ../quodlibet/ext/songsmenu/custom_commands.py:92 #, python-format msgid "Value for %s?" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:136 #, fuzzy msgid "Custom Commands" msgstr "_Personalizada" #: ../quodlibet/ext/songsmenu/custom_commands.py:137 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:188 #: ../quodlibet/ext/songsmenu/custom_commands.py:198 #: ../quodlibet/ext/songsmenu/custom_commands.py:252 msgid "Edit Custom Commands" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:199 msgid "" "Supports QL patterns\n" "eg <tt><~artist~title></tt>" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:283 #, fuzzy, python-format msgid "Unable to run custom command %s" msgstr "Nom foi possível copiar as canções" #: ../quodlibet/ext/songsmenu/duplicates.py:290 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "" msgstr[1] "" #: ../quodlibet/ext/songsmenu/duplicates.py:343 msgid "Collapse / Expand all" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:347 #, python-format msgid "Duplicate key expression is '%s'" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:363 #, fuzzy msgid "Duplicates Browser" msgstr "Desactivar o Navegador" #: ../quodlibet/ext/songsmenu/duplicates.py:364 msgid "Finds and displays similarly tagged versions of songs." msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:407 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:409 msgid "_Group duplicates by:" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:414 #, fuzzy msgid "Duplicate Key" msgstr "Eliminar a tag seleccionada" #: ../quodlibet/ext/songsmenu/duplicates.py:419 #, fuzzy msgid "Remove _Whitespace" msgstr "Eliminar a tag seleccionada" #: ../quodlibet/ext/songsmenu/duplicates.py:420 #, fuzzy msgid "Remove _Diacritics" msgstr "Eliminar a tag seleccionada" #: ../quodlibet/ext/songsmenu/duplicates.py:421 #, fuzzy msgid "Remove _Punctuation" msgstr "_Eliminar Emisora" #: ../quodlibet/ext/songsmenu/duplicates.py:422 msgid "Case _Insensitive" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:430 msgid "Matching options" msgstr "" #. Create a dialog. #: ../quodlibet/ext/songsmenu/editplaycount.py:19 #: ../quodlibet/ext/songsmenu/editplaycount.py:41 #, fuzzy msgid "Edit Playcount" msgstr "Editar a vista" #: ../quodlibet/ext/songsmenu/editplaycount.py:20 msgid "" "Edit a song's ~#playcount and ~#skipcount.\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's ~#playcount to 0, the ~#lastplayed and ~#laststarted " "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:68 msgid "Play Count" msgstr "" #: ../quodlibet/ext/songsmenu/editplaycount.py:69 #, fuzzy msgid "Skip Count" msgstr "saltar contador" #: ../quodlibet/ext/songsmenu/embedded.py:24 #, fuzzy msgid "Edit Embedded Images" msgstr "Extrair as imagens incrustadas" #: ../quodlibet/ext/songsmenu/embedded.py:25 #, fuzzy msgid "Removes or replaces embedded images." msgstr "Extrair as imagens incrustadas" #: ../quodlibet/ext/songsmenu/embedded.py:78 #, fuzzy msgid "_Remove all Images" msgstr "Eliminar a tag seleccionada" #: ../quodlibet/ext/songsmenu/embedded.py:82 #, fuzzy msgid "_Embed Current Image" msgstr "Extrair as imagens incrustadas" #: ../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:41 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 #: ../quodlibet/qltk/downloader.py:67 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 "Guardar" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" 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 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:49 msgid "Generating fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:63 msgid "_Details" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:85 msgid "_Submit" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:115 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:118 msgid "Fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Songs with MBIDs:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with sufficient tags:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs to submit:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:162 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:178 msgid "Submitting fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:186 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/id3tlen.py:21 msgid "Fix MP3 Duration" msgstr "" #: ../quodlibet/ext/songsmenu/id3tlen.py:22 msgid "" "Removes TLEN frames from ID3 tags which can be the cause for invalid song " "durations." msgstr "" #: ../quodlibet/ext/songsmenu/ifp.py:20 msgid "Send to iFP" msgstr "" #: ../quodlibet/ext/songsmenu/ifp.py:21 msgid "Uploads songs to an iRiver iFP device." msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:51 msgid "Export Metadata" msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:52 msgid "Exports metadata of selected songs as a .tags file." msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:92 #, fuzzy msgid "Import Metadata" msgstr "Importar lista" #: ../quodlibet/ext/songsmenu/importexport.py:93 msgid "Imports metadata for selected songs from a .tags file." msgstr "" #: ../quodlibet/ext/songsmenu/k3b.py:23 msgid "Burn CD" msgstr "" #: ../quodlibet/ext/songsmenu/k3b.py:24 msgid "Burns CDs with K3b, Brasero or xfburn." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:96 msgid "Updating chart list." msgstr "" #. No charts to fetch, no update scheduled. #: ../quodlibet/ext/songsmenu/lastfmsync.py:114 msgid "Already up-to-date." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:121 #, python-format msgid "Fetching chart for week of %s." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:143 msgid "Sync complete." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:149 #, fuzzy msgid "Error during sync" msgstr "Erro ao carregar %r" #: ../quodlibet/ext/songsmenu/lastfmsync.py:214 #: ../quodlibet/ext/songsmenu/lastfmsync.py:244 msgid "Last.fm Sync" msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:245 msgid "Updates your library's statistics from your Last.fm profile." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:293 #, 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 "" #. Create a dialog. #: ../quodlibet/ext/songsmenu/migratemetadata.py:29 #: ../quodlibet/ext/songsmenu/migratemetadata.py:38 #, fuzzy msgid "Migrate Metadata" msgstr "Importar lista" #: ../quodlibet/ext/songsmenu/migratemetadata.py:32 msgid "Copies the quodlibet-specific metadata between songs." msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:45 msgid "_Copy" msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:47 msgid "_Paste" msgstr "" #. Create the tag table. #: ../quodlibet/ext/songsmenu/migratemetadata.py:57 #, fuzzy msgid "Information to copy/paste" msgstr "Informaçom" #. Create the indexing box. #: ../quodlibet/ext/songsmenu/migratemetadata.py:79 msgid "Map tracks by disc and track number" msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:80 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 "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:96 #, python-format msgid "There is %d stored track." msgid_plural "There are %d stored tracks." msgstr[0] "" msgstr[1] "" #: ../quodlibet/ext/songsmenu/playlist.py:31 #, fuzzy msgid "Export as Playlist" msgstr "Importar lista" #: ../quodlibet/ext/songsmenu/playlist.py:32 msgid "Exports songs to an M3U or PLS playlist." msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:77 msgid "Use relative paths" msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:77 msgid "Use absolute paths" msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:132 #, fuzzy msgid "Unable to export playlist" msgstr "Non foi possível importar a lista" #: ../quodlibet/ext/songsmenu/playlist.py:133 #, fuzzy, python-format msgid "Writing to <b>%s</b> 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:362 msgid "ReplayGain Analyzer" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:418 msgid "Progress" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:433 msgid "Gain" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:448 msgid "Peak" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:463 #, python-format msgid "There is <b>%(to-process)s</b> album to update (of %(all)s)" msgid_plural "There are <b>%(to-process)s</b> albums to update (of %(all)s)" msgstr[0] "" msgstr[1] "" #: ../quodlibet/ext/songsmenu/replaygain.py:578 msgid "Replay Gain" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:579 msgid "" "Analyzes and updates ReplayGain information, using GStreamer. Results are " "grouped by album." msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:617 msgid "always" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:618 msgid "if <b>any</b> RG tags are missing" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:620 msgid "if <b>album</b> RG tags are missing" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:637 msgid "_Process albums:" msgstr "" #. Server settings Frame #: ../quodlibet/ext/songsmenu/replaygain.py:649 #, 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 "" #. TRANSLATORS: BPM mean "beats per minute" #: ../quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "" #: ../quodlibet/ext/songsmenu/tapbpm.py:32 #: ../quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" 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:172 #: ../quodlibet/ext/songsmenu/tapbpm.py:179 msgid "Tap BPM" msgstr "" #: ../quodlibet/ext/songsmenu/tapbpm.py:173 #, fuzzy msgid "Tap BPM for the selected song." msgstr "Nom se puidérom eliminar as canções" #: ../quodlibet/ext/songsmenu/website_search.py:35 #, fuzzy msgid "Website Search" msgstr "Procurar" #: ../quodlibet/ext/songsmenu/website_search.py:36 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern-example)s." msgstr "" #: ../quodlibet/ext/songsmenu/website_search.py:78 #, fuzzy msgid "Search URL patterns" msgstr "padrom" #: ../quodlibet/ext/songsmenu/website_search.py:88 #, fuzzy msgid "Edit search URLs" msgstr "Editar os valores guardados..." #. Add link to editor #: ../quodlibet/ext/songsmenu/website_search.py:114 #, fuzzy msgid "Configure Searches…" msgstr "Cores nos termos da _procura" #: ../quodlibet/ext/songsmenu/wikipedia.py:46 #, python-format msgid "Search at %(website)s" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:63 msgid "Search Artist in Wikipedia" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:64 msgid "" "Opens a browser window with Wikipedia article on the playing song artist." msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:71 msgid "Search Album in Wikipedia" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:72 msgid "" "Opens a browser window with Wikipedia article on the playing song album." msgstr "" #. then (try to) load all new files #: ../quodlibet/library/libraries.py:650 ../quodlibet/library/libraries.py:660 #: ../quodlibet/library/libraries.py:726 ../quodlibet/library/libraries.py:745 #: ../quodlibet/qltk/information.py:268 ../quodlibet/qltk/prefs.py:639 #: ../quodlibet/util/library.py:124 msgid "Library" msgstr "Colecçom" #: ../quodlibet/library/libraries.py:650 msgid "Checking mount points" msgstr "A comprovar os pontos de montagem" #: ../quodlibet/library/libraries.py:660 msgid "Scanning library" msgstr "A analisar a colecçom" #: ../quodlibet/library/libraries.py:725 #, python-format msgid "Scanning %s" msgstr "A analisar %s" #: ../quodlibet/library/libraries.py:745 msgid "Loading files" msgstr "" #: ../quodlibet/operon/base.py:70 #, python-format msgid "Failed to load file: %r" msgstr "Erro ao carregar o arquivo: %r" #: ../quodlibet/operon/commands.py:37 msgid "List tags" msgstr "Mostrar as etiquetas" #: ../quodlibet/operon/commands.py:42 ../quodlibet/operon/commands.py:81 #: ../quodlibet/operon/commands.py:461 msgid "Print terse output" msgstr "Mostrar saída de depuraçom" #: ../quodlibet/operon/commands.py:44 ../quodlibet/operon/commands.py:83 #: ../quodlibet/operon/commands.py:463 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "Colunas para serem mostradas e a sua orde no modo de depuraçom (%s)" #: ../quodlibet/operon/commands.py:47 ../quodlibet/operon/commands.py:86 #, fuzzy msgid "Also list programmatic tags" msgstr "Mostrar informaçom para de_puraçom" #: ../quodlibet/operon/commands.py:51 ../quodlibet/operon/commands.py:129 #: ../quodlibet/operon/commands.py:220 ../quodlibet/operon/commands.py:293 #: ../quodlibet/operon/commands.py:336 ../quodlibet/operon/commands.py:340 #: ../quodlibet/operon/commands.py:391 ../quodlibet/operon/commands.py:394 #: ../quodlibet/operon/commands.py:433 ../quodlibet/operon/commands.py:468 #: ../quodlibet/operon/commands.py:508 ../quodlibet/operon/commands.py:543 #: ../quodlibet/operon/commands.py:585 msgid "Not enough arguments" msgstr "Sem argumentos dabondo" #: ../quodlibet/operon/commands.py:53 ../quodlibet/operon/commands.py:90 #: ../quodlibet/operon/commands.py:131 ../quodlibet/operon/commands.py:222 #: ../quodlibet/operon/commands.py:470 #, fuzzy msgid "Too many arguments" msgstr "Demasiados erros" #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:92 #: ../quodlibet/operon/commands.py:475 ../quodlibet/qltk/data_editors.py:363 #, fuzzy msgid "Description" msgstr "descriçom" #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:475 #: ../quodlibet/qltk/edittags.py:454 msgid "Value" msgstr "Valor" #: ../quodlibet/operon/commands.py:76 msgid "List all common tags" msgstr "Mostrar todas as etiquetas habituais" #: ../quodlibet/operon/commands.py:118 msgid "Copy tags from one file to another" msgstr "Copiar as etiquetas dum arquivo para outro" #: ../quodlibet/operon/commands.py:123 ../quodlibet/operon/commands.py:164 #: ../quodlibet/operon/commands.py:289 ../quodlibet/operon/commands.py:324 #: ../quodlibet/operon/commands.py:384 msgid "Show changes, don't apply them" msgstr "Mostrar as mudanças, sem aplica-las" #: ../quodlibet/operon/commands.py:125 msgid "Skip tags that can't be written" msgstr "Saltar as etiquetas que nom se podem escrever" #: ../quodlibet/operon/commands.py:145 #, python-format msgid "Can't copy tag %r to file: %r" 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 "Estabelecer umha etiqueta e eliminar os valores anteriores" #: ../quodlibet/operon/commands.py:304 ../quodlibet/operon/commands.py:444 #: ../quodlibet/operon/commands.py:676 #, python-format msgid "Can not set %r" msgstr "Nom se puido estabelecer %r" #: ../quodlibet/operon/commands.py:319 #, fuzzy msgid "Remove tags" msgstr "_Eliminar Emisora" #: ../quodlibet/operon/commands.py:326 ../quodlibet/operon/commands.py:386 msgid "Value is a regular expression" msgstr "O valor é umha expressom regular" #: ../quodlibet/operon/commands.py:328 #, fuzzy msgid "Remove all tags" msgstr "Eliminar a tag seleccionada" #: ../quodlibet/operon/commands.py:332 msgid "Can't combine '--all' with '--regexp'" msgstr "Impossível combinar '--all' com '--regexp'" #: ../quodlibet/operon/commands.py:366 #, python-format msgid "Can't remove %r from %r" msgstr "Impossível eliminar %r de %r" #: ../quodlibet/operon/commands.py:379 #, fuzzy msgid "Remove a tag value" msgstr "Filtrar num valor da etiqueta" #: ../quodlibet/operon/commands.py:428 #, fuzzy msgid "Add a tag value" msgstr "Filtrar num valor da etiqueta" #: ../quodlibet/operon/commands.py:456 #, fuzzy msgid "List file information" msgstr "Sem informaçom sobre a duraçom" #: ../quodlibet/operon/commands.py:502 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" #: ../quodlibet/operon/commands.py:515 #, fuzzy, python-format msgid "Failed to load image file: %r" msgstr "Erro ao carregar o arquivo: %r" #: ../quodlibet/operon/commands.py:522 ../quodlibet/operon/commands.py:551 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" #: ../quodlibet/operon/commands.py:538 #, fuzzy msgid "Remove all embedded images" msgstr "Extrair as imagens incrustadas" #: ../quodlibet/operon/commands.py:568 #, fuzzy, python-format msgid "Extract embedded images to %(filepath)s" msgstr "Extrair as imagens incrustadas" #: ../quodlibet/operon/commands.py:580 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" #: ../quodlibet/operon/commands.py:639 msgid "Rename files based on tags" msgstr "Mudar o nome dos arquivos a partires das etiquetas" #: ../quodlibet/operon/commands.py:654 msgid "Fill tags based on the file path" msgstr "Tirar as etiquetas da rota ao arquivo" #: ../quodlibet/operon/commands.py:704 ../quodlibet/qltk/information.py:305 #: ../quodlibet/qltk/properties.py:84 ../quodlibet/qltk/renamefiles.py:176 #: ../quodlibet/qltk/tagsfrompath.py:229 ../quodlibet/qltk/tracknumbers.py:79 msgid "File" msgstr "Arquivo" #: ../quodlibet/operon/commands.py:712 msgid "Fill tracknumbers for all files" msgstr "Criar os números de pista para todos os arquivos" #: ../quodlibet/operon/commands.py:731 msgid "Print tags based on the given pattern" msgstr "Mostrar as etiquetas baseadas no padrom indicado" #: ../quodlibet/operon/commands.py:768 #, fuzzy msgid "Display help information" msgstr "Mostra informaçom sumária sobre o modo de utilizaçom" #: ../quodlibet/operon/util.py:40 #, 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:30 msgid "_Unknown" msgstr "_Desconhecido" #: ../quodlibet/order/__init__.py:142 msgid "In Order" msgstr "Em Ordem" #: ../quodlibet/order/__init__.py:143 msgid "_In Order" msgstr "_Ordenadamente" #: ../quodlibet/order/reorder.py:23 #, fuzzy msgid "Random" msgstr "Aleató_rio" #: ../quodlibet/order/reorder.py:24 ../quodlibet/qltk/queue.py:119 msgid "_Random" msgstr "Aleató_rio" #: ../quodlibet/order/reorder.py:39 ../quodlibet/order/reorder.py:40 msgid "Prefer higher rated" msgstr "" #: ../quodlibet/order/repeat.py:43 ../quodlibet/order/repeat.py:44 msgid "Repeat this track" msgstr "" #: ../quodlibet/order/repeat.py:57 ../quodlibet/order/repeat.py:58 #, fuzzy msgid "Repeat all" msgstr "_Repetir" #: ../quodlibet/order/repeat.py:73 ../quodlibet/order/repeat.py:74 msgid "One Song" msgstr "Umha cançom" #: ../quodlibet/player/gstbe/player.py:98 msgid "Stream" msgstr "Stream" #: ../quodlibet/player/gstbe/player.py:98 msgid "Buffering" msgstr "A encher o buffer" #: ../quodlibet/player/gstbe/player.py:319 #, fuzzy msgid "Could not create GStreamer pipeline" msgstr "Nom se puido criar a pipeline GStreamer predefinida." #: ../quodlibet/player/gstbe/player.py:560 msgid "No GStreamer element found to handle media format" msgstr "" #: ../quodlibet/player/gstbe/player.py:561 #, 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:25 #, fuzzy msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. In case 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:36 msgid "_Output pipeline:" msgstr "Infraestrutura de _saída:" #: ../quodlibet/player/gstbe/prefs.py:43 #, fuzzy, python-format msgid "%.1f seconds" msgstr "%d segundo" #: ../quodlibet/player/gstbe/prefs.py:57 msgid "_Buffer duration:" msgstr "Duraçom do _buffer:" #: ../quodlibet/player/gstbe/prefs.py:66 msgid "Disable _gapless playback" msgstr "" #: ../quodlibet/player/gstbe/prefs.py:70 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions." msgstr "" #: ../quodlibet/player/gstbe/util.py:93 #, fuzzy msgid "No GStreamer audio sink found" msgstr "Nom foi atopado dispositivo de áudio" #: ../quodlibet/player/gstbe/util.py:112 #, fuzzy msgid "Invalid GStreamer output pipeline" msgstr "Saida de GStreamer inválida, tentará-se com a predeterminada." #: ../quodlibet/player/xinebe/player.py:90 msgid "Unable to create audio output" msgstr "Non foi possível criar a saída de som" #: ../quodlibet/player/xinebe/player.py:91 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "" "Nom se atopou o dispositivo de som %r. Verifica as configurações do Xine em " "~/.quodlibet/config." #: ../quodlibet/plugins/__init__.py:62 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" #: ../quodlibet/plugins/__init__.py:71 #, fuzzy, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "Nom puido ligar-se com a pipeline do GStreamer: '%s'" #: ../quodlibet/plugins/playlist.py:30 #, 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:41 ../quodlibet/qltk/songsmenu.py:46 #: ../quodlibet/qltk/songsmenu.py:74 #, fuzzy msgid "_Run Plugin" msgstr "_Extensões" #: ../quodlibet/qltk/about.py:40 #, python-format msgid "Supported formats: %s" msgstr "Formatos admitidos: %s" #: ../quodlibet/qltk/about.py:43 #, python-format msgid "Audio device: %s" msgstr "Dispositivo de áudio: %s" #. Translators: Refers to the beginning of the playing song. #: ../quodlibet/qltk/bookmarks.py:27 msgid "Beginning" msgstr "Começo" #: ../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:207 ../quodlibet/qltk/information.py:131 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 "_Top 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 "E_stilo 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 40 canções mais tocadas (podem resultar mais se houverem canções " "reproduzidas um mesmo número de vezes)" #: ../quodlibet/qltk/cbes.py:48 ../quodlibet/qltk/edittags.py:311 msgid "_Value:" msgstr "_Valor:" #: ../quodlibet/qltk/cbes.py:262 msgid "Saved Values" msgstr "Valores guardados" #: ../quodlibet/qltk/cbes.py:263 #, fuzzy msgid "Edit saved values…" msgstr "Editar os valores guardados..." #: ../quodlibet/qltk/controls.py:111 msgid "Auto_matic" msgstr "Auto_mática" #: ../quodlibet/qltk/controls.py:112 #, fuzzy msgid "_Track Mode" msgstr "Cabeceiras dos _números de pista" #: ../quodlibet/qltk/controls.py:113 #, fuzzy msgid "_Album Mode" msgstr "Cabeceiras dos _álbuns" #. Translators: player state, no action #: ../quodlibet/qltk/controls.py:122 msgid "_Mute" msgstr "" #: ../quodlibet/qltk/controls.py:128 #, fuzzy msgid "_Replay Gain Mode" msgstr "Ajuste de volume do _Replay Gain" #. Translators: New Command/Entry/Item/... #: ../quodlibet/qltk/data_editors.py:119 #, python-format msgid "New %s" msgstr "" #: ../quodlibet/qltk/data_editors.py:218 #, fuzzy msgid "(unknown)" msgstr "Desconhecido" #: ../quodlibet/qltk/data_editors.py:355 #, fuzzy msgid "Tag expression" msgstr "O valor é umha expressom regular" #: ../quodlibet/qltk/data_editors.py:382 msgid "Tag expression e.g. people:real or ~album~year." msgstr "" #: ../quodlibet/qltk/data_editors.py:383 #, fuzzy msgid "Enter new tag" msgstr "Filtrar num valor da etiqueta" #: ../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 à Lixeira" #: ../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/downloader.py:38 msgid "Downloads" msgstr "Descargas" #: ../quodlibet/qltk/downloader.py:62 msgid "Size" msgstr "Tamanho" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: ../quodlibet/qltk/downloader.py:94 ../quodlibet/qltk/renamefiles.py:265 #: ../quodlibet/qltk/wlw.py:50 msgid "_Stop" msgstr "" #: ../quodlibet/qltk/edittags.py:63 ../quodlibet/qltk/edittags.py:74 #, python-format msgid "missing from %d song" msgid_plural "missing from %d songs" msgstr[0] "nom se achou da cançom %d" msgstr[1] "nom se achou de %d canções" #: ../quodlibet/qltk/edittags.py:67 ../quodlibet/qltk/edittags.py:71 #, python-format msgid "different across %d song" msgid_plural "different across %d songs" msgstr[0] "diferente em %d cançom" msgstr[1] "diferente em %d cançõess" #: ../quodlibet/qltk/edittags.py:193 msgid "Split into _Multiple Values" msgstr "Extraer em valores _múltiplos" #: ../quodlibet/qltk/edittags.py:211 msgid "Split Disc out of _Album" msgstr "Extraer o disco do _Álbum" #: ../quodlibet/qltk/edittags.py:228 msgid "Split _Version out of Title" msgstr "Extraer a _Versom do Título" #: ../quodlibet/qltk/edittags.py:259 msgid "Split Arranger out of Ar_tist" msgstr "Extraer o Arrangista do Ar_tista" #: ../quodlibet/qltk/edittags.py:264 msgid "Split _Performer out of Artist" msgstr "Extraer o _Intérprete do Artista" #: ../quodlibet/qltk/edittags.py:270 #, fuzzy msgid "Split _Performer out of Title" msgstr "Extraer o _Intérprete do Artista" #: ../quodlibet/qltk/edittags.py:276 #, fuzzy msgid "Split _Originalartist out of Title" msgstr "Extraer a _Versom do Título" #: ../quodlibet/qltk/edittags.py:283 msgid "Add a Tag" msgstr "Engadir umha etiqueta" #: ../quodlibet/qltk/edittags.py:302 msgid "_Tag:" msgstr "E_tiqueta:" #: ../quodlibet/qltk/edittags.py:404 msgid "Edit Tags" msgstr "Editar as etiquetas" #: ../quodlibet/qltk/edittags.py:477 msgid "Show _programmatic tags" msgstr "Mostrar informaçom para de_puraçom" #: ../quodlibet/qltk/edittags.py:478 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" "Acesso a todas as etiquetas, mesmo as geradas automaticamente, p.ex. " "etiquetas da MusicBrainz ou Replay Gain" #. Translators: Revert button in the tag editor #: ../quodlibet/qltk/edittags.py:508 #, fuzzy msgctxt "edittags" msgid "_Revert" msgstr "Nunca" #. Translators: Save button in the tag editor #: ../quodlibet/qltk/edittags.py:513 msgctxt "edittags" msgid "_Save" msgstr "" #: ../quodlibet/qltk/edittags.py:659 msgid "Unable to add tag" msgstr "Nom foi possível engadir a etiqueta" #: ../quodlibet/qltk/edittags.py:660 #, fuzzy, python-format msgid "Unable to add <b>%s</b>" msgstr "Nom foi possível engadir a cançom" #: ../quodlibet/qltk/edittags.py:662 #, fuzzy, python-format msgid "" "The files currently selected do not support multiple values for <b>%s</b>." 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:689 ../quodlibet/qltk/edittags.py:856 #: ../quodlibet/qltk/tagsfrompath.py:212 ../quodlibet/util/__init__.py:554 #: ../quodlibet/util/tags.py:231 msgid "Invalid tag" msgstr "Etiqueta inválida" #: ../quodlibet/qltk/edittags.py:690 ../quodlibet/qltk/edittags.py:857 #: ../quodlibet/qltk/tagsfrompath.py:213 #, python-format msgid "" "Invalid tag <b>%s</b>\n" "\n" "The files currently selected do not support editing this tag." msgstr "" "Etiqueta inválida <b>%s</b>\n" "\n" "Os arquivos seleccionados nom permitem a ediçom das etiquetas." #: ../quodlibet/qltk/edittags.py:828 ../quodlibet/qltk/edittags.py:868 msgid "Invalid value" msgstr "Valor inválido" #: ../quodlibet/qltk/edittags.py:829 ../quodlibet/qltk/edittags.py:869 #, python-format msgid "" "Invalid value: <b>%(value)s</b>\n" "\n" "%(error)s" msgstr "" "Valor inválido: <b>%(value)s</b>\n" "\n" "%(error)s" #: ../quodlibet/qltk/_editutils.py:28 msgid "Tag may not be accurate" msgstr "A etiqueta pode nom ser correcta" #: ../quodlibet/qltk/_editutils.py:31 #, 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:47 msgid "Unable to save song" msgstr "Nom foi possível guardar a cançom" #: ../quodlibet/qltk/_editutils.py:50 #, 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:142 #, 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:95 #: ../quodlibet/qltk/quodlibetwindow.py:1066 msgid "_About" msgstr "" #: ../quodlibet/qltk/exfalsowindow.py:99 #: ../quodlibet/qltk/quodlibetwindow.py:1088 msgid "_Check for Updates…" msgstr "" #: ../quodlibet/qltk/exfalsowindow.py:105 #: ../quodlibet/qltk/quodlibetwindow.py:1021 ../quodlibet/qltk/songsmenu.py:304 msgid "_Plugins" msgstr "_Extensões" #: ../quodlibet/qltk/exfalsowindow.py:267 #, 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:279 msgid "Ex Falso Preferences" msgstr "Preferências do Ex Falso" #: ../quodlibet/qltk/exfalsowindow.py:289 ../quodlibet/qltk/prefs.py:598 msgid "Split _on:" msgstr "Extraer _de:" #: ../quodlibet/qltk/exfalsowindow.py:295 ../quodlibet/qltk/prefs.py:613 msgid "Tag Editing" msgstr "Ediçom das etiquetas" #: ../quodlibet/qltk/filesel.py:210 msgid "Folders" msgstr "Cartafoles" #: ../quodlibet/qltk/filesel.py:253 #, fuzzy msgid "_New Folder…" msgstr "Novo Cartafol" #: ../quodlibet/qltk/filesel.py:262 #, fuzzy msgid "_Select all Sub-Folders" msgstr "Seleccionar todos os _cartafoles subordinados" #: ../quodlibet/qltk/filesel.py:374 msgid "New Folder" msgstr "Novo Cartafol" #: ../quodlibet/qltk/filesel.py:374 msgid "Enter a name for the new folder:" msgstr "Introduz um nome para o novo cartafol:" #: ../quodlibet/qltk/filesel.py:387 msgid "Unable to create folder" msgstr "Nom foi possível criar o cartafol" #: ../quodlibet/qltk/filesel.py:404 msgid "Unable to delete folder" msgstr "Nom foi possível eliminar o cartafol" #: ../quodlibet/qltk/filesel.py:519 ../quodlibet/qltk/pluginwin.py:167 msgid "Songs" msgstr "Canções" #. Translators: As in "by Artist Name" #: ../quodlibet/qltk/info.py:42 #, python-format msgid "by %s" msgstr "por %s" #: ../quodlibet/qltk/info.py:43 ../quodlibet/qltk/information.py:167 #: ../quodlibet/qltk/information.py:448 #, python-format msgid "Disc %s" msgstr "Disco %s" #: ../quodlibet/qltk/info.py:44 ../quodlibet/qltk/information.py:172 #, python-format msgid "Track %s" msgstr "Pista %s" #: ../quodlibet/qltk/info.py:108 #, fuzzy msgid "_Edit Display…" msgstr "Editar a vista" #: ../quodlibet/qltk/information.py:105 msgid "No songs are selected." msgstr "Sem canções seleccionadas." #: ../quodlibet/qltk/information.py:106 msgid "No Songs" msgstr "Sem Canções" #: ../quodlibet/qltk/information.py:121 ../quodlibet/qltk/information.py:338 #: ../quodlibet/qltk/information.py:471 ../quodlibet/qltk/information.py:531 msgid "Information" msgstr "Informaçom" #: ../quodlibet/qltk/information.py:126 msgid "Lyrics" msgstr "Letra" #: ../quodlibet/qltk/information.py:184 ../quodlibet/qltk/information.py:396 #, python-format msgid "Produced by %s" msgstr "Produzido por %s" #: ../quodlibet/qltk/information.py:199 ../quodlibet/util/tags.py:76 msgid "artist" msgstr "artista" #: ../quodlibet/qltk/information.py:200 ../quodlibet/qltk/information.py:561 #: ../quodlibet/util/tags.py:76 msgid "artists" msgstr "artistas" #. for backwards compat #: ../quodlibet/qltk/information.py:221 ../quodlibet/util/tags.py:86 #: ../quodlibet/util/tags.py:114 msgid "performers" msgstr "intérpretes" #: ../quodlibet/qltk/information.py:235 ../quodlibet/qltk/information.py:248 #: ../quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "Nunca" #: ../quodlibet/qltk/information.py:236 #, fuzzy, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "%d vez" msgstr[1] "%d vezes" #: ../quodlibet/qltk/information.py:254 ../quodlibet/util/tags.py:139 msgid "added" msgstr "engadida" #: ../quodlibet/qltk/information.py:255 ../quodlibet/util/tags.py:140 msgid "last played" msgstr "última vez tocada" #: ../quodlibet/qltk/information.py:256 ../quodlibet/util/tags.py:150 msgid "plays" msgstr "contador" #: ../quodlibet/qltk/information.py:257 ../quodlibet/util/tags.py:151 msgid "skips" msgstr "saltada" #: ../quodlibet/qltk/information.py:258 ../quodlibet/util/tags.py:156 msgid "rating" msgstr "qualificaçom" #: ../quodlibet/qltk/information.py:287 msgid "path" msgstr "" #: ../quodlibet/qltk/information.py:288 ../quodlibet/util/tags.py:154 msgid "length" msgstr "duraçom" #: ../quodlibet/qltk/information.py:289 #, fuzzy msgid "format" msgstr "Informaçom" #: ../quodlibet/qltk/information.py:290 ../quodlibet/util/tags.py:163 msgid "codec" msgstr "" #: ../quodlibet/qltk/information.py:291 ../quodlibet/util/tags.py:164 #, fuzzy msgid "encoding" msgstr "Ascendente" #: ../quodlibet/qltk/information.py:292 ../quodlibet/util/tags.py:160 msgid "bitrate" msgstr "taxa de bits" #: ../quodlibet/qltk/information.py:293 ../quodlibet/util/tags.py:161 msgid "file size" msgstr "tamaño do ficheiro" #: ../quodlibet/qltk/information.py:294 ../quodlibet/util/tags.py:149 msgid "modified" msgstr "modificada" #: ../quodlibet/qltk/information.py:331 msgid "Additional" msgstr "" #: ../quodlibet/qltk/information.py:383 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d seleccionada" msgstr[1] "%d seleccionadas" #: ../quodlibet/qltk/information.py:458 msgid "Track unavailable" msgstr "Pista nom disponível" #: ../quodlibet/qltk/information.py:464 msgid "Track List" msgstr "Lista de pistas" #: ../quodlibet/qltk/information.py:505 ../quodlibet/qltk/information.py:578 #, python-format msgid "%d song with no album" msgid_plural "%d songs with no album" msgstr[0] "%d cançom sem album" msgstr[1] "%d canções sem album" #: ../quodlibet/qltk/information.py:508 msgid "Selected Discography" msgstr "Discografia seleccionada" #: ../quodlibet/qltk/information.py:558 #, python-format msgid "%d song with no artist" msgid_plural "%d songs with no artist" msgstr[0] "%d cançom sem artista" msgstr[1] "%d canções sem artista" #: ../quodlibet/qltk/information.py:586 ../quodlibet/util/tags.py:74 msgid "albums" msgstr "álbuns" #: ../quodlibet/qltk/information.py:599 msgid "Total length:" msgstr "Duraçom total:" #: ../quodlibet/qltk/information.py:603 msgid "Total size:" msgstr "Tamanho total:" #: ../quodlibet/qltk/information.py:606 msgid "Files" msgstr "Arquivos" #: ../quodlibet/qltk/lyrics.py:37 msgid "_Download" msgstr "_Baixar" #: ../quodlibet/qltk/lyrics.py:40 #, fuzzy msgid "_Edit" msgstr "_Editar a vista..." #. buffer.set_text(_("No lyrics found.\n\nYou can click the " #. "Download button to have Quod Libet search " #. "for lyrics online. You can also enter them " #. "yourself and click save.")) #: ../quodlibet/qltk/lyrics.py:73 ../quodlibet/qltk/lyrics.py:109 msgid "No lyrics found for this song." msgstr "Nom se atopou a letra desta cançom" #: ../quodlibet/qltk/lyrics.py:82 #, fuzzy msgid "Searching for lyrics…" msgstr "A procurar a letra..." #: ../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/msg.py:41 msgid "Discard tag changes?" msgstr "Descartar as mudanças na etiqueta?" #: ../quodlibet/qltk/msg.py:42 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "" "As etiquetas fôrom mudadas mais nom guardadas. Guardar os ficheiros, ou " "desfazer e descartar as mudanças?" #: ../quodlibet/qltk/msg.py:55 ../quodlibet/qltk/prefs.py:595 #: ../quodlibet/qltk/textedit.py:64 ../quodlibet/qltk/tracknumbers.py:117 #, fuzzy msgid "_Revert" msgstr "Nunca" #: ../quodlibet/qltk/msg.py:86 msgid "File exists" msgstr "O arquivo já existe" #: ../quodlibet/qltk/msg.py:88 #, python-format msgid "Replace %(file-name)s?" msgstr "" #: ../quodlibet/qltk/msg.py:94 #, fuzzy msgid "_Replace File" msgstr "Mudar o nome dos arquivos" #: ../quodlibet/qltk/notif.py:182 msgid "Active tasks" msgstr "Tarefas ativas" #: ../quodlibet/qltk/notif.py:188 #, fuzzy, python-format msgid "%d tasks running" msgstr "Quod Libet está a ser executado" #: ../quodlibet/qltk/playorder.py:254 #, fuzzy msgid "Toggle shuffle mode" msgstr "Alternar entre reproduzir e parar" #: ../quodlibet/qltk/playorder.py:270 #, fuzzy msgid "Toggle repeat mode" msgstr "Alternar entre reproduzir e parar" #: ../quodlibet/qltk/pluginwin.py:44 msgid "Plugin Errors" msgstr "Erros das extensões" #: ../quodlibet/qltk/pluginwin.py:124 msgid "Enabled" msgstr "Activado" #: ../quodlibet/qltk/pluginwin.py:125 msgid "Disabled" msgstr "Desactivado" #: ../quodlibet/qltk/pluginwin.py:131 msgid "No category" msgstr "Sem categoria" #: ../quodlibet/qltk/pluginwin.py:169 msgid "Events" msgstr "" #: ../quodlibet/qltk/pluginwin.py:170 #, fuzzy msgid "Play Order" msgstr "Ordem de Repr_oduçom" #: ../quodlibet/qltk/pluginwin.py:171 #, fuzzy msgid "Editing" msgstr "Ediçom das etiquetas" #: ../quodlibet/qltk/pluginwin.py:173 #, fuzzy msgid "Covers" msgstr "Tamanho total:" #: ../quodlibet/qltk/pluginwin.py:309 msgid "No plugins found." msgstr "Nom se atopárom extensões." #: ../quodlibet/qltk/pluginwin.py:358 #, fuzzy msgid "Plugins" msgstr "_Extensões" #: ../quodlibet/qltk/pluginwin.py:402 msgid "Show _Errors" msgstr "Mostrar os _erros" #: ../quodlibet/qltk/prefs.py:45 msgid "_Disc" msgstr "_Disco" #: ../quodlibet/qltk/prefs.py:46 msgid "_Track" msgstr "_Pista" #: ../quodlibet/qltk/prefs.py:47 #, fuzzy msgid "Grou_ping" msgstr "agrupaçom" #: ../quodlibet/qltk/prefs.py:50 msgid "Al_bum" msgstr "Ál_bum" #: ../quodlibet/qltk/prefs.py:55 msgid "_Filename" msgstr "_Nome" #: ../quodlibet/qltk/prefs.py:57 msgid "_Length" msgstr "D_uraçom" #: ../quodlibet/qltk/prefs.py:64 msgid "_Jump to playing song automatically" msgstr "_Ir à cançom reproduzida automaticamente" #: ../quodlibet/qltk/prefs.py:66 msgid "When the playing song changes, scroll to it in the song list" msgstr "Centrar a lista na cançom reproduzida quando esta mudar" #: ../quodlibet/qltk/prefs.py:82 msgid "_Others:" msgstr "_Outros:" #: ../quodlibet/qltk/prefs.py:88 #, fuzzy msgid "_Edit…" msgstr "_Editar a vista..." #: ../quodlibet/qltk/prefs.py:91 msgid "Add or remove additional column headers" msgstr "Engadir ou eliminar colunas de informaçom adicionais." #: ../quodlibet/qltk/prefs.py:101 msgid "Visible Columns" msgstr "Colunas visíveis" #: ../quodlibet/qltk/prefs.py:104 msgid "Title includes _version" msgstr "O título inclúi a _versom" #: ../quodlibet/qltk/prefs.py:106 #, fuzzy msgid "Artist includes all _people" msgstr "A procura _inclúi \"componentes\"" #: ../quodlibet/qltk/prefs.py:108 msgid "Album includes _disc subtitle" msgstr "O album inclúi o subtítulo do _disco / parte" #: ../quodlibet/qltk/prefs.py:110 msgid "Filename includes _folder" msgstr "O nome inclúi o _cartafol" #: ../quodlibet/qltk/prefs.py:123 #, fuzzy msgid "Column Preferences" msgstr "Preferências" #: ../quodlibet/qltk/prefs.py:129 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "" "Aplicar a configuraçom actual á lista, engadindo novas colunas ao final" #: ../quodlibet/qltk/prefs.py:142 ../quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Lista de canções" #: ../quodlibet/qltk/prefs.py:222 #, fuzzy msgid "Edit Columns" msgstr "Colunas adicionais" #: ../quodlibet/qltk/prefs.py:259 msgid "Duration totals" msgstr "" #: ../quodlibet/qltk/prefs.py:271 msgid "_Global filter:" msgstr "Filtro _global:" #: ../quodlibet/qltk/prefs.py:277 msgid "Apply this query in addition to all others" msgstr "Aplicar esta procura engadindo-a às demais" #. Translators: The heading of the preference group, no action #: ../quodlibet/qltk/prefs.py:283 #, fuzzy msgctxt "heading" msgid "Search" msgstr "Procurar" #: ../quodlibet/qltk/prefs.py:287 ../quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Navegadores" #: ../quodlibet/qltk/prefs.py:293 msgid "Confirm _multiple ratings" msgstr "Confirmar a _qualificaçom múltipla" #: ../quodlibet/qltk/prefs.py:295 #, 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:298 msgid "Enable _one-click ratings" msgstr "Activar as qualificações com _um click" #: ../quodlibet/qltk/prefs.py:300 #, 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:306 ../quodlibet/qltk/prefs.py:616 msgid "Ratings" msgstr "Qualificações" #. Filename choice algorithm config #: ../quodlibet/qltk/prefs.py:312 msgid "Prefer _embedded art" msgstr "Preferir as capas _integradas" #: ../quodlibet/qltk/prefs.py:314 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" "Escholhe utilizar as capas integradas no arquivo de áudio (quando estiverem " "disponíveis), com preferência sobre outras fontes" #: ../quodlibet/qltk/prefs.py:319 #, fuzzy msgid "_Fixed image filename:" msgstr "_Forçar o nome de arquivo da imagem:" #: ../quodlibet/qltk/prefs.py:321 #, fuzzy msgid "The single image filename to use if selected" msgstr "O nome do arquivo da capa que se pretender forçar" #: ../quodlibet/qltk/prefs.py:327 msgid "The album art image file to use when forced" msgstr "O nome do arquivo da capa que se pretender forçar" #: ../quodlibet/qltk/prefs.py:336 #, fuzzy msgid "Album Art" msgstr "Lista de Álbuns" #: ../quodlibet/qltk/prefs.py:357 #, fuzzy msgid "Playback" msgstr "Parar a reproduçom" #: ../quodlibet/qltk/prefs.py:362 #, fuzzy msgid "Output Configuration" msgstr "Saída do registro" #: ../quodlibet/qltk/prefs.py:373 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" "De nom existir informaçom sobre o axuste Replay Gain para a cançom, " "multiplicar o volume por este valor" #: ../quodlibet/qltk/prefs.py:376 #, fuzzy msgid "_Fall-back gain (dB):" msgstr "Ganância por defeito (dB):" #: ../quodlibet/qltk/prefs.py:387 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "" "Multiplicar o volume de todas as canções por este valor, sempre que nom se " "produçam cortes" #: ../quodlibet/qltk/prefs.py:390 #, fuzzy msgid "_Pre-amp gain (dB):" msgstr "Ganância do _volume (dB)" #: ../quodlibet/qltk/prefs.py:395 msgid "_Enable Replay Gain volume adjustment" msgstr "_Activar o ajuste de volume do _Replay Gain" #: ../quodlibet/qltk/prefs.py:420 msgid "Replay Gain Volume Adjustment" msgstr "Ajuste de volume do _Replay Gain" #: ../quodlibet/qltk/prefs.py:450 #, fuzzy msgid "_Default rating:" msgstr "Predefinido" #: ../quodlibet/qltk/prefs.py:493 #, fuzzy msgid "Rating _scale:" msgstr "Qualificações" #: ../quodlibet/qltk/prefs.py:542 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 Média Bayesiana (C) para as qualificações agregadas.\n" "0 significa umha média convencional, valores máis elevados significam que os " "álbuns\n" "com poucas pistas terám menores qualificações estremas. Modificar este valor " "fai que se inicie\n" "o recálculo para todos os álbuns." #: ../quodlibet/qltk/prefs.py:547 msgid "_Bayesian averaging amount:" msgstr "Quantidade da média _Bayesiana" #: ../quodlibet/qltk/prefs.py:556 msgid "Save ratings and play _counts" msgstr "Guardar qualificações e o _contador" #: ../quodlibet/qltk/prefs.py:560 msgid "_Email:" msgstr "_Endereço de correio-e" #: ../quodlibet/qltk/prefs.py:562 msgid "Ratings and play counts will be set 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:577 #, fuzzy msgid "Auto-save tag changes" msgstr "Descartar as mudanças na etiqueta?" #: ../quodlibet/qltk/prefs.py:579 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "" "Ao se editárem múltiplos arquivos, guardar as modificações às etiquetas sen " "solicitar confirmaçom individual" #: ../quodlibet/qltk/prefs.py:587 #, 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:610 #, fuzzy msgid "Tags" msgstr "Editar as etiquetas" #: ../quodlibet/qltk/prefs.py:631 #, fuzzy msgid "Updating for new ratings" msgstr "_Nova Emisora" #: ../quodlibet/qltk/prefs.py:641 #, fuzzy msgid "Scan library _on start" msgstr "Actualizar a colecçom ao iniciar" #: ../quodlibet/qltk/prefs.py:651 ../quodlibet/qltk/quodlibetwindow.py:1100 #, fuzzy msgid "_Scan Library" msgstr "_Procurar na colecçom" #: ../quodlibet/qltk/prefs.py:653 ../quodlibet/qltk/quodlibetwindow.py:1162 msgid "Check for changes in your library" msgstr "Procurar mudanças na colecçom" #: ../quodlibet/qltk/prefs.py:658 #, fuzzy msgid "Re_build Library" msgstr "Reler a colecçom" #: ../quodlibet/qltk/prefs.py:661 #, 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:671 #, fuzzy msgid "Scan Directories" msgstr "Analisar os _cartafoles" #: ../quodlibet/qltk/prefs.py:677 #, fuzzy msgid "Hidden Songs" msgstr "Sem Canções" #: ../quodlibet/qltk/properties.py:158 ../quodlibet/util/collection.py:398 #, 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:162 ../quodlibet/qltk/properties.py:164 msgid "Properties" msgstr "Propriedades" #: ../quodlibet/qltk/queue.py:101 msgid "_Queue" msgstr "_Fileira" #: ../quodlibet/qltk/queue.py:126 msgid "Stop Once Empty" msgstr "" #: ../quodlibet/qltk/queue.py:130 #, fuzzy msgid "_Clear Queue" msgstr "_Eliminar os erros" #: ../quodlibet/qltk/queue.py:242 #, python-format msgid "%(count)d song (%(time)s)" msgid_plural "%(count)d songs (%(time)s)" msgstr[0] "%(count)d cançom (%(time)s)" msgstr[1] "%(count)d canções (%(time)s)" #: ../quodlibet/qltk/quodlibetwindow.py:198 msgid "_Browse Library" msgstr "_Examinar a colecçom" #: ../quodlibet/qltk/quodlibetwindow.py:395 #, fuzzy msgid "Toggle queue visibility" msgstr "Alternar entre mostrar e agochar a fiestra principal" #: ../quodlibet/qltk/quodlibetwindow.py:516 #, fuzzy msgid "Playback Error" msgstr "Parar a reproduçom" #: ../quodlibet/qltk/quodlibetwindow.py:524 #, fuzzy msgid "Set up library directories?" msgstr "Seleccionar os cartafoles" #: ../quodlibet/qltk/quodlibetwindow.py:525 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:531 msgid "_Not Now" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:532 msgid "_Set Up" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:956 msgid "Unable to add songs" msgstr "Nom foi possível engadir as canções" #: ../quodlibet/qltk/quodlibetwindow.py:957 #: ../quodlibet/qltk/quodlibetwindow.py:1364 #, fuzzy, python-format msgid "%s uses an unsupported protocol." msgstr "<b>%s</b> emprega um protocolo nom admitido." #: ../quodlibet/qltk/quodlibetwindow.py:980 msgid "_Jump to Playing Song" msgstr "_Ir à cançom reproduzida" #: ../quodlibet/qltk/quodlibetwindow.py:986 #, fuzzy msgid "_File" msgstr "Arquivo" #: ../quodlibet/qltk/quodlibetwindow.py:987 msgid "_Song" msgstr "C_ançom" #: ../quodlibet/qltk/quodlibetwindow.py:988 msgid "_View" msgstr "_Ver" #: ../quodlibet/qltk/quodlibetwindow.py:989 #, fuzzy msgid "_Browse" msgstr "Navegadores" #: ../quodlibet/qltk/quodlibetwindow.py:990 msgid "_Control" msgstr "_Controis" #: ../quodlibet/qltk/quodlibetwindow.py:991 msgid "_Help" msgstr "_Ajuda" #: ../quodlibet/qltk/quodlibetwindow.py:997 #, fuzzy msgid "_Add a Folder…" msgstr "_Engadir um Cartafol..." #: ../quodlibet/qltk/quodlibetwindow.py:1002 #, fuzzy msgid "_Add a File…" msgstr "_Engadir um arquivo..." #: ../quodlibet/qltk/quodlibetwindow.py:1007 #, fuzzy msgid "_Add a Location…" msgstr "Engadir umha localizaçom" #: ../quodlibet/qltk/quodlibetwindow.py:1036 #, fuzzy msgid "Edit Bookmarks…" msgstr "_Editar os marcadores..." #: ../quodlibet/qltk/quodlibetwindow.py:1056 #, fuzzy msgid "Stop After This Song" msgstr "Parar despois desta cançom" #: ../quodlibet/qltk/quodlibetwindow.py:1062 msgid "_Keyboard Shortcuts" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:1071 msgid "Online Help" msgstr "Ajuda na Internet" #: ../quodlibet/qltk/quodlibetwindow.py:1080 #, fuzzy msgid "Search Help" msgstr "Procurar" #: ../quodlibet/qltk/quodlibetwindow.py:1352 msgid "Add a Location" msgstr "Engadir umha localizaçom" #: ../quodlibet/qltk/quodlibetwindow.py:1353 msgid "Enter the location of an audio file:" msgstr "Por favor, introduça a localizaçom dum arquivo de música:" #: ../quodlibet/qltk/quodlibetwindow.py:1358 #: ../quodlibet/qltk/quodlibetwindow.py:1363 msgid "Unable to add location" msgstr "Nom foi possívell engadir a localizaçom" #: ../quodlibet/qltk/quodlibetwindow.py:1359 #, fuzzy, python-format msgid "%s is not a valid location." msgstr "<b>%s</b> nom é umha localizaçom válida." #: ../quodlibet/qltk/quodlibetwindow.py:1372 #: ../quodlibet/qltk/quodlibetwindow.py:1381 msgid "Add Music" msgstr "Engadir música" #: ../quodlibet/qltk/quodlibetwindow.py:1372 ../quodlibet/qltk/scanbox.py:99 #, fuzzy msgid "_Add Folders" msgstr "_Engadir um Cartafol..." #: ../quodlibet/qltk/quodlibetwindow.py:1379 #, fuzzy msgid "Music Files" msgstr "Reprodutor de música" #: ../quodlibet/qltk/quodlibetwindow.py:1381 #, fuzzy msgid "_Add Files" msgstr "_Engadir um arquivo..." #: ../quodlibet/qltk/ratingsmenu.py:24 #, 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:26 #, fuzzy msgid "The saved ratings will be removed" msgstr "As canções duplicadas serám eliminadas da lista '%s'." #: ../quodlibet/qltk/ratingsmenu.py:27 #, 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:57 ../quodlibet/qltk/ratingsmenu.py:111 #, fuzzy msgid "_Remove Rating" msgstr "_Eliminar Emisora" #: ../quodlibet/qltk/ratingsmenu.py:98 #, fuzzy msgid "Change _Rating" msgstr "_Qualificaçom" #: ../quodlibet/qltk/renamefiles.py:46 msgid "Replace spaces with _underscores" msgstr "Reemprazar espaços com _guiões baixos" #: ../quodlibet/qltk/renamefiles.py:56 msgid "Strip _Windows-incompatible characters" msgstr "Eliminar os caracteres nom compatíveis com _Windows(tm)" #: ../quodlibet/qltk/renamefiles.py:74 msgid "Strip _diacritical marks" msgstr "Eliminar as marcas _diacríticas" #: ../quodlibet/qltk/renamefiles.py:85 msgid "Strip non-_ASCII characters" msgstr "Eliminar os caracteres nom-_ASCII" #: ../quodlibet/qltk/renamefiles.py:95 msgid "Use only _lowercase characters" msgstr "Utilizar unicamente caracteres de caixa-_baixa" #: ../quodlibet/qltk/renamefiles.py:123 msgid "Rename Files" msgstr "Mudar o nome dos arquivos" #: ../quodlibet/qltk/renamefiles.py:139 ../quodlibet/qltk/tagsfrompath.py:116 #, fuzzy msgid "Path Patterns" msgstr "padrom" #: ../quodlibet/qltk/renamefiles.py:140 ../quodlibet/qltk/tagsfrompath.py:117 #, fuzzy msgid "Edit saved patterns…" msgstr "Editar os valores guardados..." #: ../quodlibet/qltk/renamefiles.py:143 ../quodlibet/qltk/tagsfrompath.py:120 #: ../quodlibet/qltk/tracknumbers.py:58 msgid "_Preview" msgstr "_Antever" #: ../quodlibet/qltk/renamefiles.py:190 msgid "New Name" msgstr "Novo nome" #: ../quodlibet/qltk/renamefiles.py:255 msgid "Unable to rename file" msgstr "Nom foi possível mudar o nome do arquivo" #: ../quodlibet/qltk/renamefiles.py:256 #, fuzzy, python-format msgid "" "Renaming <b>%(old-name)s</b> to <b>%(new-name)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." 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:264 msgid "Ignore _All Errors" msgstr "Ignorar todos os _erros" #: ../quodlibet/qltk/renamefiles.py:267 msgid "_Continue" msgstr "_Continuar" #: ../quodlibet/qltk/renamefiles.py:296 msgid "Path is not absolute" msgstr "A rota nom é absoluta" #: ../quodlibet/qltk/renamefiles.py:297 #, python-format msgid "" "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 ~/." 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/qltk/scanbox.py:47 #, 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:99 msgid "Select Directories" msgstr "Seleccionar os cartafoles" #: ../quodlibet/qltk/searchbar.py:52 #, fuzzy msgid "Saved Searches" msgstr "Valores guardados" #: ../quodlibet/qltk/searchbar.py:53 #, fuzzy msgid "Edit saved searches…" msgstr "Editar os valores guardados..." #: ../quodlibet/qltk/searchbar.py:74 msgid "Search your library, using free text or QL queries" msgstr "Procura na tua colecçom, empregando texto ou procuras do QL" #: ../quodlibet/qltk/searchbar.py:129 msgid "Search after _typing" msgstr "Procurar despois de _escrever" #: ../quodlibet/qltk/searchbar.py:132 msgid "Show search results after the user stops typing" msgstr "Mostrar os resultados despois de rematar de escrever" #: ../quodlibet/qltk/searchbar.py:187 msgid "_Limit:" msgstr "_Limite:" #: ../quodlibet/qltk/searchbar.py:200 msgid "_Weight" msgstr "_Importância" #: ../quodlibet/qltk/seekbutton.py:238 msgid "Display remaining time" msgstr "Mostrar 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 ../quodlibet/qltk/shortcuts.py:41 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: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:377 #, python-format msgid "_Filter on %s" msgstr "_Filtrar por %s" #: ../quodlibet/qltk/songlist.py:1094 #, fuzzy msgid "All _Headers" msgstr "Cabeceiras dos _álbuns" #: ../quodlibet/qltk/songlist.py:1095 msgid "_Track Headers" msgstr "Cabeceiras dos _números de pista" #: ../quodlibet/qltk/songlist.py:1096 msgid "_Album Headers" msgstr "Cabeceiras dos _álbuns" #: ../quodlibet/qltk/songlist.py:1097 msgid "_People Headers" msgstr "_Cabeceiras dos _componentes" #: ../quodlibet/qltk/songlist.py:1098 msgid "_Date Headers" msgstr "Cabeçeiras de _data" #: ../quodlibet/qltk/songlist.py:1099 msgid "_File Headers" msgstr "Cabeceira dos _arquivos" #: ../quodlibet/qltk/songlist.py:1100 msgid "_Production Headers" msgstr "Cabeceiras da _produçom" #: ../quodlibet/qltk/songlist.py:1115 #, fuzzy msgid "_Customize Headers…" msgstr "_Personalizar as cabeceiras..." #: ../quodlibet/qltk/songlist.py:1120 #, fuzzy msgid "_Expand Column" msgstr "Colunas adicionais" #: ../quodlibet/qltk/songsmenu.py:36 #, 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:64 #, 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:149 #, fuzzy msgid "Configure Plugins…" msgstr "Cores nos termos da _procura" #: ../quodlibet/qltk/songsmenu.py:345 msgid "Add to _Queue" msgstr "En_gadir à fileira" #: ../quodlibet/qltk/songsmenu.py:368 msgid "_Copy to Device" msgstr "_Copiar ao dispositivo" #: ../quodlibet/qltk/songsmenu.py:379 #, fuzzy msgid "_Remove from Library" msgstr "_Eliminar da Colecçom" #: ../quodlibet/qltk/tagsfrompath.py:47 msgid "Replace _underscores with spaces" msgstr "Reemprazar _guiões baixos com espaços" #: ../quodlibet/qltk/tagsfrompath.py:57 msgid "_Title-case tags" msgstr "_Letras capitais nas etiquetas" #: ../quodlibet/qltk/tagsfrompath.py:67 msgid "Split into multiple _values" msgstr "Dividir em _valores múltiplos" #: ../quodlibet/qltk/tagsfrompath.py:101 msgid "Tags From Path" msgstr "Etiquetas a partires da rota" #: ../quodlibet/qltk/tagsfrompath.py:138 msgid "Tags replace existing ones" msgstr "As etiquetas substituem as já existentes" #: ../quodlibet/qltk/tagsfrompath.py:139 msgid "Tags are added to existing ones" msgstr "As etiquetas engadem-se às já existentes" #. Save button #: ../quodlibet/qltk/tagsfrompath.py:153 msgid "Save" msgstr "" #: ../quodlibet/qltk/tagsfrompath.py:195 #, python-format msgid "" "The pattern\n" "\t<b>%s</b>\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" "O padrom\n" "\t<b>%s</b>\n" "é inválido. Pode ser que contenha duas vezes a mesma etiqueta ou que tenha " "chaves dessajustadas(< / >)." #: ../quodlibet/qltk/tagsfrompath.py:216 msgid "Invalid tags" msgstr "Etiquetas inválidas" #: ../quodlibet/qltk/tagsfrompath.py:217 #, 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 nom permitem a ediçom das etiquetas." #: ../quodlibet/qltk/textedit.py:142 #, 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 padrom introduzido é inválido. Assegure-se de que pus < e > como " "\\< e \\> e que as etiquetas estám ajustadas.\n" "\n" "%s" #: ../quodlibet/qltk/textedit.py:158 msgid "Edit Display" msgstr "Editar a vista" #: ../quodlibet/qltk/tracknumbers.py:39 msgid "Track Numbers" msgstr "Números de pista" #: ../quodlibet/qltk/tracknumbers.py:42 msgid "Start fro_m:" msgstr "Começar de_nde:" #: ../quodlibet/qltk/tracknumbers.py:51 msgid "_Total tracks:" msgstr "_Pistas totais:" #: ../quodlibet/qltk/unity.py:52 #, fuzzy msgid "Play/Pause" msgstr "_Parar" #: ../quodlibet/qltk/unity.py:75 #, fuzzy msgid "Previous" msgstr "_Antever" #: ../quodlibet/qltk/views.py:923 #, fuzzy, python-format msgid "and %d more…" msgstr "e %d mais..." #: ../quodlibet/qltk/wlw.py:200 msgid "Saving the songs you changed." msgstr "A guardar as canções modificadas." #: ../quodlibet/qltk/wlw.py:201 #, python-format msgid "" "%(current)d/%(total)d songs saved\n" "(%(remaining)s remaining)" msgstr "" "%(current)d/%(total)d canções guardadas\\n\n" "(%(remaining)s restantes)" #: ../quodlibet/qltk/wlw.py:234 #, fuzzy, python-format msgid "%(current)s of %(all)s" msgstr "A mover %(current)d/%(total)d." #: ../quodlibet/update.py:89 #, fuzzy msgid "Checking for Updates" msgstr "A comprovar os pontos de montagem" #: ../quodlibet/update.py:124 #, fuzzy msgid "Connection failed" msgstr "endereço" #: ../quodlibet/update.py:133 #, python-format msgid "You are already using the newest version %(version)s" msgstr "" #: ../quodlibet/update.py:136 #, 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:420 msgid "Playlists must have a name" msgstr "" #: ../quodlibet/util/collection.py:603 #, python-format msgid "A playlist named %s already exists." msgstr "Xá existe umha lista co nome %s ." #: ../quodlibet/util/cover/built_in.py:26 #, fuzzy msgid "Embedded album covers" msgstr "Mostrar _cobertas dos discos" #: ../quodlibet/util/cover/built_in.py:27 msgid "Uses covers embedded into audio files." msgstr "" #: ../quodlibet/util/cover/built_in.py:49 #, fuzzy msgid "Filesystem cover" msgstr "Sistema de arquivos" #: ../quodlibet/util/cover/built_in.py:50 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "" #: ../quodlibet/util/__init__.py:93 msgid "Display brief usage information" msgstr "Mostra informaçom sumária sobre o modo de utilizaçom" #: ../quodlibet/util/__init__.py:95 msgid "Display version and copyright" msgstr "Mostrar a versão e o copyright" #: ../quodlibet/util/__init__.py:135 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "" #: ../quodlibet/util/__init__.py:137 msgid "[options]" msgstr "[opções]" #: ../quodlibet/util/__init__.py:182 #, python-format msgid "Option %r not recognized." msgstr "Nom se reconhece a opçom %r." #: ../quodlibet/util/__init__.py:185 #, python-format msgid "Option %r requires an argument." msgstr "A opçom %r requer um argumento." #: ../quodlibet/util/__init__.py:188 #, python-format msgid "%r is not a unique prefix." msgstr "%r nom é um prefixo único." #: ../quodlibet/util/__init__.py:364 #, python-format msgid "%d kbps" msgstr "%d kbps" #: ../quodlibet/util/__init__.py:419 #, fuzzy, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%d segundo" msgstr[1] "%d segundos" #: ../quodlibet/util/__init__.py:432 msgid "No time information" msgstr "Sem informaçom sobre a duraçom" #: ../quodlibet/util/__init__.py:435 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d segundo" msgstr[1] "%d segundos" #: ../quodlibet/util/__init__.py:436 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d minuto" msgstr[1] "%d minutos" #: ../quodlibet/util/__init__.py:437 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d hora" msgstr[1] "%d horas" #: ../quodlibet/util/__init__.py:438 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d dia" msgstr[1] "%d dias" #: ../quodlibet/util/__init__.py:439 #, 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:563 #, 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 introduzida no formato '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 ganâncias Replay Gain ham-de-ser introduzidas no formato 'x.yy dB'" #: ../quodlibet/util/massagers.py:151 msgid "Replay Gain peaks must be entered in 'x.yy' format." msgstr "Os picos ReplayGain ham-de-ser introduzidos no formato 'x.yy'" #: ../quodlibet/util/massagers.py:173 msgid "MusicBrainz IDs must be in UUID format." msgstr "As IDs das pistas MusicBrainz ham-de-ser 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 estado oficial da publicaçom no MusicBrainz há ser 'official', " "'promotional' ou 'bootleg'" #: ../quodlibet/util/massagers.py:208 msgid "Language must be an ISO 639-2 three-letter code" msgstr "O idioma tem de ser um código de três letras ISO 639-2" #: ../quodlibet/util/songwrapper.py:112 msgid "Unable to edit song" msgstr "Nom foi possível editar a etiqueta da cançom" #: ../quodlibet/util/songwrapper.py:113 #, python-format msgid "" "Saving <b>%s</b> 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/util/string/__init__.py:34 #: ../quodlibet/util/string/__init__.py:44 msgid "[Invalid Encoding]" msgstr "[Codificaçom inválida]" #: ../quodlibet/util/tags.py:74 msgid "album" msgstr "álbum" #: ../quodlibet/util/tags.py:75 msgid "arranger" msgstr "arrangista" #: ../quodlibet/util/tags.py:75 msgid "arrangers" msgstr "arrangistas" #: ../quodlibet/util/tags.py:75 #, fuzzy msgid "arrangement" msgstr "arrangista" #: ../quodlibet/util/tags.py:77 msgid "author" msgstr "autor/a" #: ../quodlibet/util/tags.py:77 msgid "authors" msgstr "autores/as" #: ../quodlibet/util/tags.py:78 msgid "composer" msgstr "compositor/a" #: ../quodlibet/util/tags.py:78 msgid "composers" msgstr "compositores/as" #: ../quodlibet/util/tags.py:78 #, fuzzy msgid "composition" msgstr "compositor/a" #. Translators: conducting as in conducting a musical performance #: ../quodlibet/util/tags.py:80 msgid "conductor" msgstr "director/a" #: ../quodlibet/util/tags.py:80 msgid "conductors" msgstr "directores/as" #: ../quodlibet/util/tags.py:80 #, fuzzy msgid "conducting" msgstr "director/a" #: ../quodlibet/util/tags.py:81 msgid "contact" msgstr "Contacto" #: ../quodlibet/util/tags.py:82 msgid "copyright" msgstr "copyright" #: ../quodlibet/util/tags.py:83 msgid "date" msgstr "data" #: ../quodlibet/util/tags.py:84 msgid "description" msgstr "descriçom" #: ../quodlibet/util/tags.py:85 msgid "genre" msgstr "estilo" #: ../quodlibet/util/tags.py:85 #, fuzzy msgid "genres" msgstr "estilo" #: ../quodlibet/util/tags.py:86 msgid "performer" msgstr "intérprete" #: ../quodlibet/util/tags.py:87 msgid "grouping" msgstr "agrupaçom" #: ../quodlibet/util/tags.py:88 msgid "language" msgstr "idioma" #: ../quodlibet/util/tags.py:89 msgid "license" msgstr "licença" #: ../quodlibet/util/tags.py:90 msgid "location" msgstr "endereço" #: ../quodlibet/util/tags.py:91 msgid "lyricist" msgstr "autor da letra" #: ../quodlibet/util/tags.py:91 msgid "lyricists" msgstr "Autores/as das letras" #: ../quodlibet/util/tags.py:91 #, fuzzy msgid "lyrics" msgstr "autor da letra" #. Translators: Also e.g. "record label", "publisher" #: ../quodlibet/util/tags.py:93 msgid "organization" msgstr "companhia" #: ../quodlibet/util/tags.py:94 msgid "title" msgstr "título" #: ../quodlibet/util/tags.py:95 msgid "version" msgstr "versom" #: ../quodlibet/util/tags.py:96 msgid "website" msgstr "Sítio de Internet" #: ../quodlibet/util/tags.py:98 msgid "album artist" msgstr "artista do álbum" #: ../quodlibet/util/tags.py:99 msgid "BPM" msgstr "BPM" #. Translators: This used to be called "part". #: ../quodlibet/util/tags.py:102 ../quodlibet/util/tags.py:103 msgid "disc subtitle" msgstr "parte" #: ../quodlibet/util/tags.py:104 ../quodlibet/util/tags.py:141 msgid "disc" msgstr "disco" #: ../quodlibet/util/tags.py:105 ../quodlibet/util/tags.py:143 msgid "track" msgstr "pista" # label ID #: ../quodlibet/util/tags.py:106 msgid "label ID" msgstr "Número de catálogo" #: ../quodlibet/util/tags.py:107 msgid "original release date" msgstr "data de publicaçom original" #: ../quodlibet/util/tags.py:108 msgid "original album" msgstr "álbum original" #: ../quodlibet/util/tags.py:109 msgid "original artist" msgstr "artista original" #: ../quodlibet/util/tags.py:110 msgid "recording date" msgstr "data da gravaçom" #: ../quodlibet/util/tags.py:111 msgid "release country" msgstr "país de publicaçom" #. 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:120 #, fuzzy msgid "MusicBrainz recording ID" msgstr "ID do MusicBraniz da pista" #: ../quodlibet/util/tags.py:121 #, fuzzy msgid "MusicBrainz release track ID" msgstr "ID do MusicBrainz do lançamento" #: ../quodlibet/util/tags.py:122 msgid "MusicBrainz release ID" msgstr "ID do MusicBrainz do lançamento" #: ../quodlibet/util/tags.py:123 #, fuzzy msgid "MusicBrainz artist ID" msgstr "ID do MusicBrainz do artista" #: ../quodlibet/util/tags.py:124 #, fuzzy msgid "MusicBrainz release artist ID" msgstr "ID do MusicBrainz do lançamento" #: ../quodlibet/util/tags.py:125 msgid "MusicBrainz TRM ID" msgstr "ID do MusicBraniz do TRM" #: ../quodlibet/util/tags.py:126 msgid "MusicIP PUID" msgstr "PUID do MUsicIP" #: ../quodlibet/util/tags.py:127 msgid "MusicBrainz album status" msgstr "Estado do álbum segundo MusicBrainz" #: ../quodlibet/util/tags.py:128 msgid "MusicBrainz album type" msgstr "Tipo de álbum segundo MusicBrainz" #: ../quodlibet/util/tags.py:129 #, 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:132 msgid "track gain" msgstr "ganância de volume da pista" #: ../quodlibet/util/tags.py:133 msgid "track peak" msgstr "pico de ganância da pista" #. Translators: "gain" means a volume adjustment, not "to acquire". #: ../quodlibet/util/tags.py:135 msgid "album gain" msgstr "ganância de volume do âlbum" #: ../quodlibet/util/tags.py:136 msgid "album peak" msgstr "pico de ganância do álbum" #: ../quodlibet/util/tags.py:137 #, fuzzy msgid "reference loudness" msgstr "Preferências" #: ../quodlibet/util/tags.py:142 msgid "discs" msgstr "discos" #: ../quodlibet/util/tags.py:144 msgid "tracks" msgstr "pistas" #: ../quodlibet/util/tags.py:145 msgid "last started" msgstr "última vez iniciada" #: ../quodlibet/util/tags.py:146 msgid "full name" msgstr "localizaçom" #: ../quodlibet/util/tags.py:153 msgid "mount point" msgstr "ponto de montagem" #: ../quodlibet/util/tags.py:155 msgid "people" msgstr "componentes" #: ../quodlibet/util/tags.py:157 msgid "year" msgstr "ano" #: ../quodlibet/util/tags.py:158 #, fuzzy msgid "original release year" msgstr "data de publicaçom original" #: ../quodlibet/util/tags.py:159 msgid "bookmark" msgstr "marcador" #: ../quodlibet/util/tags.py:162 #, fuzzy msgid "file format" msgstr "Formato" #: ../quodlibet/util/tags.py:165 #, fuzzy msgid "playlists" msgstr "Listas" #: ../quodlibet/util/tags.py:166 msgid "channel count" msgstr "" #. Translators: e.g. "artist (sort)" #: ../quodlibet/util/tags.py:256 msgid "sort" msgstr "" #. Translators: e.g. "performer (roles)" #: ../quodlibet/util/tags.py:264 msgid "roles" msgstr "" #, 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 "Remove all songs from the queue" #~ msgstr "Eliminar todas as canções da fileira" #~ msgid "Watch this folder for new songs" #~ msgstr "Verificar a existência de novas canções no cartafol" #~ 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 "Model:" #~ msgstr "Modelo:" #~ msgid "Capacity:" #~ msgstr "Capacidade:" #~ msgid "Firmware:" #~ msgstr "Firmware:" #~ msgid "Removing orphaned iPod track" #~ msgstr "A eliminar pista orfã do iPod" #, 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 "Unable to open input files" #~ msgstr "Nom se puiderom abrir os arquivos" #~ 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 "General" #~ msgstr "Geral" #~ 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 "_Select" #~ msgstr "_Seleccionar" #~ 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 "Choose New Stations" #~ msgstr "Escolher Novas Emisoras" #~ msgid "Add" #~ msgstr "Engadir" #~ msgid "Bitrate" #~ msgstr "Taxa de bits" #~ msgid "_Stations..." #~ msgstr "_Emisoras..." #~ msgid "Quod Libet" #~ msgstr "Quod Libet" #~ 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 "Recommend" #~ msgstr "Recomendada" #~ 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 "Tag by Filename" #~ msgstr "Tag a partires do Nome" #~ 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 "Search Bar" #~ msgstr "Barra de pesquisa" #~ 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9591856 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/po/he.po����������������������������������������������������������������������������0000644�0001750�0001750�00000616553�00000000000�014070� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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: 2019-10-27 19:37+0200\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:206 quodlibet/browsers/covergrid/main.py:54 msgid "_Title" msgstr "_כותרת" #: quodlibet/browsers/albums/main.py:207 quodlibet/browsers/covergrid/main.py:55 #: quodlibet/qltk/prefs.py:49 msgid "_Artist" msgstr "_אמן" #: quodlibet/browsers/albums/main.py:208 quodlibet/browsers/covergrid/main.py:56 #: quodlibet/qltk/prefs.py:54 msgid "_Date" msgstr "_תאריך" #: quodlibet/browsers/albums/main.py:209 msgid "_Original Date" msgstr "_תאריך מקורי" #: quodlibet/browsers/albums/main.py:210 quodlibet/browsers/covergrid/main.py:57 #: quodlibet/qltk/prefs.py:53 msgid "_Genre" msgstr "_סוגה" #: quodlibet/browsers/albums/main.py:211 quodlibet/browsers/covergrid/main.py:58 #: quodlibet/qltk/prefs.py:58 quodlibet/qltk/ratingsmenu.py:39 msgid "_Rating" msgstr "_דרוג" #: quodlibet/browsers/albums/main.py:212 msgid "_Playcount" msgstr "_מספר השמעות" #: quodlibet/browsers/albums/main.py:218 quodlibet/browsers/covergrid/main.py:64 msgid "Sort _by…" msgstr "מיון _לפי…" #: quodlibet/browsers/albums/main.py:239 quodlibet/browsers/covergrid/main.py:85 #: quodlibet/browsers/paned/prefs.py:203 quodlibet/browsers/playlists/main.py:667 #: quodlibet/qltk/exfalsowindow.py:108 quodlibet/qltk/pluginwin.py:341 #: quodlibet/qltk/quodlibetwindow.py:906 msgid "_Preferences" msgstr "_העדפות" #: quodlibet/browsers/albums/main.py:409 msgid "Album List" msgstr "רשימת אלבומים" #: quodlibet/browsers/albums/main.py:410 msgid "_Album List" msgstr "_רשימת אלבומים" #: quodlibet/browsers/albums/main.py:524 quodlibet/browsers/covergrid/main.py:285 #: quodlibet/browsers/covergrid/main.py:501 msgid "All Albums" msgstr "כל האלבומים" #: quodlibet/browsers/albums/main.py:525 quodlibet/browsers/covergrid/main.py:286 #: quodlibet/browsers/covergrid/main.py:502 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d אלבום" msgstr[1] "%d אלבומים" #: quodlibet/browsers/albums/main.py:706 quodlibet/browsers/covergrid/main.py:480 msgid "Reload album _cover" msgid_plural "Reload album _covers" msgstr[0] "טעינה חוזרת של עטיפת _אלבום" msgstr[1] "טעינה חוזרת של עטיפות _אלבומים" #: quodlibet/browsers/albums/prefs.py:28 quodlibet/browsers/collection/models.py:16 #: 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:385 quodlibet/util/collection.py:247 #, 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:383 #: quodlibet/util/collection.py:251 #, 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:124 #: quodlibet/ext/songsmenu/cover_download.py:243 msgid "Options" msgstr "אפשרויות" #: quodlibet/browsers/albums/prefs.py:74 quodlibet/browsers/covergrid/prefs.py:127 msgid "Album Display" msgstr "מַצָּג אלבום" #: quodlibet/browsers/albums/prefs.py:78 quodlibet/browsers/covergrid/prefs.py:131 #: quodlibet/browsers/playlists/prefs.py:56 quodlibet/ext/songsmenu/albumart.py:328 #: quodlibet/ext/songsmenu/duplicates.py:345 quodlibet/ext/songsmenu/filterall.py:48 #: quodlibet/qltk/bookmarks.py:101 quodlibet/qltk/cbes.py:93 quodlibet/qltk/data_editors.py:96 #: quodlibet/qltk/data_editors.py:321 quodlibet/qltk/exfalsowindow.py:286 #: quodlibet/qltk/pluginwin.py:79 quodlibet/qltk/pluginwin.py:428 quodlibet/qltk/prefs.py:764 #: quodlibet/qltk/textedit.py:163 quodlibet/update.py:149 msgid "_Close" msgstr "_סגירה" #: quodlibet/browsers/audiofeeds.py:52 quodlibet/browsers/audiofeeds.py:64 #: quodlibet/browsers/audiofeeds.py:66 quodlibet/browsers/audiofeeds.py:156 #: quodlibet/browsers/paned/models.py:85 quodlibet/ext/songsmenu/fingerprint/search.py:46 #: quodlibet/formats/_audio.py:488 quodlibet/order/__init__.py:27 quodlibet/qltk/information.py:244 #: quodlibet/qltk/information.py:251 quodlibet/qltk/information.py:277 quodlibet/qltk/wlw.py:69 msgid "Unknown" msgstr "לא ידוע" #: quodlibet/browsers/audiofeeds.py:247 msgid "New Feed" msgstr "ערוץ חדש" #: quodlibet/browsers/audiofeeds.py:248 msgid "Enter the location of an audio feed:" msgstr "הזנת מיקום ערוץ שמע:" #: quodlibet/browsers/audiofeeds.py:249 quodlibet/browsers/collection/prefs.py:89 #: quodlibet/browsers/iradio.py:357 quodlibet/browsers/paned/prefs.py:120 #: quodlibet/browsers/playlists/menu.py:96 quodlibet/browsers/playlists/util.py:52 #: quodlibet/qltk/bookmarks.py:62 quodlibet/qltk/cbes.py:55 quodlibet/qltk/data_editors.py:308 #: quodlibet/qltk/edittags.py:327 quodlibet/qltk/edittags.py:527 #: quodlibet/qltk/quodlibetwindow.py:1276 quodlibet/qltk/scanbox.py:61 msgid "_Add" msgstr "_הוספה" #: quodlibet/browsers/audiofeeds.py:303 msgid "Audio Feeds" msgstr "ערוצי שמע" #: quodlibet/browsers/audiofeeds.py:304 msgid "_Audio Feeds" msgstr "_הזנות שמע" #: quodlibet/browsers/audiofeeds.py:407 quodlibet/qltk/data_editors.py:93 msgid "_New" msgstr "_חדש" #: quodlibet/browsers/audiofeeds.py:467 quodlibet/browsers/audiofeeds.py:526 msgid "Unable to add feed" msgstr "לא ניתן להוסיף את הערוץ המבוקש" #: quodlibet/browsers/audiofeeds.py:468 quodlibet/browsers/audiofeeds.py:527 #, python-format msgid "%s could not be added. The server may be down, or the location may not be an audio feed." msgstr "לא ניתן להוסיף את %s. ייתכן שהשרת מושבת, או שהמיקום אינו הזנת שמע." #: quodlibet/browsers/audiofeeds.py:475 quodlibet/qltk/filesel.py:260 #: quodlibet/qltk/pluginwin.py:414 msgid "_Refresh" msgstr "_רענון" #: quodlibet/browsers/audiofeeds.py:476 quodlibet/browsers/playlists/main.py:487 #: quodlibet/browsers/playlists/util.py:43 quodlibet/qltk/delete.py:143 #: quodlibet/qltk/filesel.py:257 quodlibet/qltk/lyrics.py:35 quodlibet/qltk/maskedbox.py:28 #: quodlibet/qltk/songsmenu.py:364 msgid "_Delete" msgstr "_מחיקה" #: quodlibet/browsers/audiofeeds.py:543 msgid "The current audio backend does not support URLs, Audio Feeds browser disabled." msgstr "רכיב השרת הנוכחי אינו תומך ב URL, דפדפן הזנות שמע נוטרל." #: quodlibet/browsers/_base.py:146 quodlibet/browsers/_base.py:149 msgid "Library Browser" msgstr "דפדפן ספריה" #: quodlibet/browsers/_base.py:273 quodlibet/ext/songsmenu/console.py:45 #: quodlibet/ext/songsmenu/refresh.py:30 quodlibet/qltk/exfalsowindow.py:240 #: quodlibet/qltk/information.py:554 quodlibet/qltk/maskedbox.py:68 #: quodlibet/util/collection.py:532 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "שיר %d" msgstr[1] "%d שירים" #: quodlibet/browsers/_base.py:401 quodlibet/browsers/_base.py:406 #: quodlibet/qltk/tagsfrompath.py:193 quodlibet/qltk/textedit.py:140 quodlibet/util/__init__.py:573 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:23 #, python-format msgid "Unknown %s" msgstr "%s לא ידוע" #: quodlibet/browsers/collection/models.py:24 #, python-format msgid "Multiple %s Values" msgstr "ערכי %s מרובים" #: quodlibet/browsers/collection/prefs.py:65 quodlibet/browsers/paned/prefs.py:93 msgid "_Custom" msgstr "_מותאם אישית" #. Remove button #: quodlibet/browsers/collection/prefs.py:93 quodlibet/browsers/paned/prefs.py:124 #: quodlibet/browsers/playlists/menu.py:97 quodlibet/ext/playlist/remove_duplicates.py:60 #: quodlibet/qltk/bookmarks.py:97 quodlibet/qltk/bookmarks.py:127 quodlibet/qltk/cbes.py:82 #: quodlibet/qltk/cbes.py:89 quodlibet/qltk/data_editors.py:78 quodlibet/qltk/data_editors.py:91 #: quodlibet/qltk/data_editors.py:298 quodlibet/qltk/data_editors.py:311 #: quodlibet/qltk/data_editors.py:319 quodlibet/qltk/edittags.py:533 quodlibet/qltk/edittags.py:710 #: quodlibet/qltk/maskedbox.py:48 quodlibet/qltk/maskedbox.py:88 quodlibet/qltk/queue.py:427 #: quodlibet/qltk/scanbox.py:36 quodlibet/qltk/scanbox.py:63 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:470 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:247 #: quodlibet/ext/songsmenu/editplaycount.py:45 quodlibet/ext/songsmenu/exact_rating.py:38 #: quodlibet/player/gstbe/prefs.py:40 quodlibet/qltk/prefs.py:127 quodlibet/qltk/textedit.py:64 msgid "_Apply" msgstr "_החלה" #: quodlibet/browsers/collection/prefs.py:197 quodlibet/browsers/paned/prefs.py:251 #: quodlibet/browsers/playlists/menu.py:95 quodlibet/browsers/playlists/util.py:42 #: quodlibet/errorreport/ui.py:103 quodlibet/ext/playlist/export_to_folder.py:38 #: 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:44 #: quodlibet/ext/songsmenu/fingerprint/search.py:281 #: quodlibet/ext/songsmenu/fingerprint/submit.py:90 quodlibet/ext/songsmenu/importexport.py:40 #: quodlibet/ext/songsmenu/lastfmsync.py:218 quodlibet/ext/songsmenu/playlist.py:50 #: 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:326 quodlibet/qltk/_editutils.py:39 quodlibet/qltk/getstring.py:28 #: quodlibet/qltk/maskedbox.py:27 quodlibet/qltk/msg.py:54 quodlibet/qltk/msg.py:93 #: quodlibet/qltk/msg.py:111 quodlibet/qltk/ratingsmenu.py:33 quodlibet/update.py:95 msgid "_Cancel" msgstr "_ביטול" #: quodlibet/browsers/covergrid/main.py:126 msgid "Cover Grid" msgstr "שבכת תמונות עטיפה" #: quodlibet/browsers/covergrid/main.py:127 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:71 msgid "Show \"All Albums\" Item" msgstr "הצגת כל האלבומים" #: quodlibet/browsers/covergrid/prefs.py:82 msgid "Wide Mode" msgstr "מצב רחב" #: quodlibet/browsers/covergrid/prefs.py:114 quodlibet/browsers/covergrid/prefs.py:115 msgid "Cover Magnification" msgstr "הגדלת תמונת עטיפה" #: quodlibet/browsers/filesystem.py:39 msgid "File System" msgstr "מערכת קבצים" #: quodlibet/browsers/filesystem.py:40 msgid "_File System" msgstr "_מערכת קבצים" #: quodlibet/browsers/filesystem.py:124 quodlibet/qltk/songlist.py:255 msgid "Unable to copy songs" msgstr "לא ניתן להעתיק את השיר" #: quodlibet/browsers/filesystem.py:125 quodlibet/qltk/songlist.py:256 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "לא ניתן להעתיק את הקבצים שנבחרו לרשימת השמעה אחרת או לתור." #: quodlibet/browsers/filesystem.py:197 msgid "_Add to Library" msgstr "_הוספה לספריה" #: quodlibet/browsers/iradio.py:182 msgid "Unsupported file type" msgstr "סוג קובץ אינו נתמך" #: quodlibet/browsers/iradio.py:183 #, 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:230 quodlibet/browsers/iradio.py:243 #: quodlibet/browsers/iradio.py:836 msgid "Unable to add station" msgstr "לא ניתן להוסיף תחנה" #: quodlibet/browsers/iradio.py:254 quodlibet/browsers/iradio.py:487 msgid "Internet Radio" msgstr "רדיו מרשתת" #: quodlibet/browsers/iradio.py:254 msgid "Downloading station list" msgstr "מוריד רשימת תחנות" #: quodlibet/browsers/iradio.py:355 msgid "New Station" msgstr "תחנה חדשה" #: quodlibet/browsers/iradio.py:356 msgid "Enter the location of an Internet radio station:" msgstr "הזנת הכתובת של תחנת רדיו מרשתת:" #: quodlibet/browsers/iradio.py:374 msgid "Electronic" msgstr "אלקטרוני" #: quodlibet/browsers/iradio.py:377 msgid "Hip Hop / Rap" msgstr "היפ הופ /ראפ" #: quodlibet/browsers/iradio.py:378 msgid "Oldies" msgstr "אולדיז" #: quodlibet/browsers/iradio.py:379 msgid "R&B" msgstr "R&B" #: quodlibet/browsers/iradio.py:380 msgid "Japanese" msgstr "יפנית" #: quodlibet/browsers/iradio.py:381 msgid "Indian" msgstr "הודית" #: quodlibet/browsers/iradio.py:383 msgid "Religious" msgstr "דתי" #: quodlibet/browsers/iradio.py:385 msgid "Charts" msgstr "רשימות" #: quodlibet/browsers/iradio.py:386 msgid "Turkish" msgstr "תורכית" #: quodlibet/browsers/iradio.py:387 msgid "Reggae / Dancehall" msgstr "רגאיי / אולם ריקודים" #: quodlibet/browsers/iradio.py:388 msgid "Latin" msgstr "לטינית" #: quodlibet/browsers/iradio.py:389 msgid "College Radio" msgstr "רדיו מכללות" #: quodlibet/browsers/iradio.py:390 msgid "Talk / News" msgstr "שיח / חדשות" #: quodlibet/browsers/iradio.py:391 msgid "Ambient" msgstr "אמביינט" #: quodlibet/browsers/iradio.py:392 msgid "Jazz" msgstr "ג'ז" #: quodlibet/browsers/iradio.py:393 quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "קלסי" #: quodlibet/browsers/iradio.py:394 quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "פופ" #: quodlibet/browsers/iradio.py:395 msgid "Alternative" msgstr "אלטרנטיב" #: quodlibet/browsers/iradio.py:396 msgid "Metal" msgstr "מטאל" #: quodlibet/browsers/iradio.py:397 msgid "Country" msgstr "קאונטרי" #: quodlibet/browsers/iradio.py:398 msgid "News" msgstr "חדשות" #: quodlibet/browsers/iradio.py:399 msgid "Schlager" msgstr "שלאגר" #: quodlibet/browsers/iradio.py:400 msgid "Funk" msgstr "פונק" #: quodlibet/browsers/iradio.py:401 msgid "Indie" msgstr "אינדי" #: quodlibet/browsers/iradio.py:402 msgid "Blues" msgstr "בלוז" #: quodlibet/browsers/iradio.py:403 msgid "Soul" msgstr "נשמה" #: quodlibet/browsers/iradio.py:404 msgid "Lounge" msgstr "לאונג'" #: quodlibet/browsers/iradio.py:405 msgid "Punk" msgstr "פאנק" #: quodlibet/browsers/iradio.py:406 msgid "Reggaeton" msgstr "רגאטון" #: quodlibet/browsers/iradio.py:408 msgid "Slavic" msgstr "סלבי" #: quodlibet/browsers/iradio.py:410 msgid "Greek" msgstr "יווני" #: quodlibet/browsers/iradio.py:411 msgid "Gothic" msgstr "גותי" #: quodlibet/browsers/iradio.py:412 quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "רוק" #: quodlibet/browsers/iradio.py:465 msgid "Would you like to load a list of popular radio stations?" msgstr "האם לטעון רשימת תחנות רדיו פופולריות?" #: quodlibet/browsers/iradio.py:471 msgid "_Load Stations" msgstr "_טעינת תחנות" #: quodlibet/browsers/iradio.py:488 msgid "_Internet Radio" msgstr "רדיו _מרשתת" #: quodlibet/browsers/iradio.py:561 msgid "_New Station…" msgstr "_תחנה חדשה…" #: quodlibet/browsers/iradio.py:564 msgid "_Update Stations" msgstr "_עדכון תחנות" #: quodlibet/browsers/iradio.py:591 msgid "All Stations" msgstr "כל התחנות" #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:595 quodlibet/browsers/soundcloud/main.py:65 msgid "Favorites" msgstr "מועדפים" #: quodlibet/browsers/iradio.py:603 msgid "No Category" msgstr "ללא קטגוריה" #: quodlibet/browsers/iradio.py:828 msgid "No stations found" msgstr "לא נמצאו תחנות" #: quodlibet/browsers/iradio.py:829 #, python-format msgid "No Internet radio stations were found at %s." msgstr "לא נמצאו תחנות רדיו מרשתת ב %s." #: quodlibet/browsers/iradio.py:837 msgid "All stations listed are already in your library." msgstr "כל התחנות שברשימה נמצאות כבר בספריה." #: quodlibet/browsers/iradio.py:854 msgid "Add to Favorites" msgstr "הוספה למועדפים" #: quodlibet/browsers/iradio.py:858 msgid "Remove from Favorites" msgstr "הסרה ממועדפים" #: quodlibet/browsers/iradio.py:958 #, 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:103 quodlibet/qltk/pluginwin.py:122 #: quodlibet/qltk/pluginwin.py:164 msgid "All" msgstr "הכל" #: quodlibet/browsers/paned/prefs.py:41 quodlibet/ext/songsmenu/cover_download.py:118 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" "<tt>%s</tt>" msgstr "" "דפוס תיוג עם סימון אופציונלי כמו <tt>composer</tt> או\n" "<tt>%s</tt>" #: quodlibet/browsers/paned/prefs.py:231 msgid "Paned Browser Preferences" msgstr "העדפות חלוניות דפדפן" #: quodlibet/browsers/paned/prefs.py:236 msgid "Column layout" msgstr "פריסת עמודה" #: quodlibet/browsers/paned/prefs.py:240 msgid "Column content" msgstr "תוכן עמודה" #: quodlibet/browsers/paned/prefs.py:242 msgid "Equal pane width" msgstr "רוחב חלונית שווה" #: quodlibet/browsers/playlists/main.py:48 quodlibet/browsers/playlists/main.py:603 #: quodlibet/qltk/pluginwin.py:168 msgid "Playlists" msgstr "רשימות השמעה" #: quodlibet/browsers/playlists/main.py:49 msgid "_Playlists" msgstr "_רשימות השמעה" #: quodlibet/browsers/playlists/main.py:152 msgid "_Remove from Playlist" msgstr "_הסרה מרשימת השמעה" #: quodlibet/browsers/playlists/main.py:217 msgid "New" msgstr "חדש" #: quodlibet/browsers/playlists/main.py:221 msgid "Import" msgstr "יבוא" #: quodlibet/browsers/playlists/main.py:443 msgid "Unable to import playlist" msgstr "לא ניתן לייבא את רשימת ההשמעה" #: quodlibet/browsers/playlists/main.py:444 msgid "Quod Libet can only import playlists in the M3U/M3U8 and PLS formats." msgstr "קְווֹדְלִיבֵּט יכולה לייבא רק רשימות השמעה בתבנית M3U או PLS." #: quodlibet/browsers/playlists/main.py:494 msgid "_Rename" msgstr "_שנוי שם" #: quodlibet/browsers/playlists/main.py:592 msgid "Unable to rename playlist" msgstr "לא ניתן לשנות שם רשימת ההשמעה" #: quodlibet/browsers/playlists/main.py:604 msgid "Import Playlist" msgstr "ייבא רשימת השמעה" #: quodlibet/browsers/playlists/main.py:604 msgid "_Import" msgstr "_יבוא" #: quodlibet/browsers/playlists/menu.py:25 msgid "_New Playlist…" msgstr "_רשימת השמעה חדשה…" #: quodlibet/browsers/playlists/menu.py:86 #, 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:90 #, 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:33 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "האם למחוק רשימת השמעה '%s'?" #: quodlibet/browsers/playlists/util.py:35 msgid "All information about the selected playlist will be deleted and can not be restored." msgstr "כל המידע לגבי רשימת ההשמעה שנבחרה ימחק ולא יהיה בר שחזור." #: quodlibet/browsers/playlists/util.py:50 quodlibet/browsers/playlists/util.py:125 #: quodlibet/util/collection.py:575 msgid "New Playlist" msgstr "רשימת השמעה חדשה" #: quodlibet/browsers/playlists/util.py:51 msgid "Enter a name for the new playlist:" msgstr "הזנת שם חדש לרשימת ההשמעה:" #: quodlibet/browsers/playlists/util.py:89 #, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" "מייבא רשימת השמעה\n" "%(current)d/%(total)d שירים נוספו." #: quodlibet/browsers/search.py:32 msgid "_Limit Results" msgstr "_הגבלת תוצאות" #: quodlibet/browsers/search.py:37 msgid "_Allow multiple queries" msgstr "_אפשור שאילתות מרובות" #: quodlibet/browsers/search.py:53 msgid "Search Library" msgstr "חיפוש בספרית השירים" #: quodlibet/browsers/search.py:54 msgid "_Search Library" msgstr "_חיפוש בספריה" #: quodlibet/browsers/soundcloud/main.py:39 msgid "Soundcloud Browser" msgstr "דפדפן סאונדקלאוד" #: quodlibet/browsers/soundcloud/main.py:40 msgid "Sound_cloud" msgstr "סאונד_קלאוד" #: quodlibet/browsers/soundcloud/main.py:60 quodlibet/qltk/searchbar.py:81 msgid "Search" msgstr "חיפוש" #: quodlibet/browsers/soundcloud/main.py:69 msgid "My tracks" msgstr "הרצועות שלי" #: quodlibet/browsers/soundcloud/main.py:141 #, python-format msgid "Go to %s" msgstr "מעבר ל %s" #: quodlibet/browsers/soundcloud/main.py:443 msgid "Connected" msgstr "מחובר" #: quodlibet/browsers/soundcloud/main.py:444 #, python-format msgid "Quod Libet is now connected, <b>%s</b>!" msgstr "קְווֹדְלִיבֵּט מחוברת כעת, <b>%s</b>!" #: quodlibet/browsers/soundcloud/main.py:456 #, python-format msgid "Log out of %s" msgstr "התנתקות מ %s" #: quodlibet/browsers/soundcloud/main.py:458 msgid "Enter code…" msgstr "הזנת קוד…" #: quodlibet/browsers/soundcloud/main.py:459 #, python-format msgid "Log in to %s" msgstr "התחברות ל %s" #: quodlibet/browsers/soundcloud/util.py:86 msgid "Soundcloud authorisation" msgstr "אימות סאונדקלאוד" #: quodlibet/browsers/soundcloud/util.py:87 msgid "Enter Soundcloud auth code:" msgstr "הזנת קוד אימות סאונדקלאוד:" #: quodlibet/cli.py:50 msgid "Quod Libet is not running (add '--run' to start it)" msgstr "קְווֹדְלִיבֵּט אינה פועלת (הוספת '--run' לאתחול)" #: quodlibet/cli.py:86 msgid "a music library and player" msgstr "ספרית מוזיקה ונגן" #: quodlibet/cli.py:87 msgid "[option]" msgstr "[אפשרות]" #: quodlibet/cli.py:89 msgid "Print the playing song and exit" msgstr "הדפסת השיר המושמע ויציאה" #: quodlibet/cli.py:90 msgid "Begin playing immediately" msgstr "השמעה מיידית" #: quodlibet/cli.py:91 msgid "Don't show any windows on start" msgstr "לא להציג כל חלון בהפעלה" #: quodlibet/cli.py:94 msgid "Jump to next song" msgstr "מעבר לשיר הבא" #: quodlibet/cli.py:96 msgid "Jump to previous song or restart if near the beginning" msgstr "מעבר לשיר הקודם או השמעה מבראשית במידה וסמוך לתחילת השיר" #: quodlibet/cli.py:97 msgid "Jump to previous song" msgstr "מעבר לשיר הקודם" #: quodlibet/cli.py:98 msgid "Start playback" msgstr "התחלת השמעה" #: quodlibet/cli.py:99 msgid "Pause playback" msgstr "השהיית השמעה" #: quodlibet/cli.py:100 msgid "Toggle play/pause mode" msgstr "החלפה בין מצב השמעה/השהייה" #: quodlibet/cli.py:101 msgid "Stop playback" msgstr "עצירת השמעה" #: quodlibet/cli.py:102 msgid "Turn up volume" msgstr "הגברת עצמה" #: quodlibet/cli.py:103 msgid "Turn down volume" msgstr "הנמכת עצמה" #: quodlibet/cli.py:104 msgid "Increase rating of playing song by one star" msgstr "הוספת כוכב אחד לדרוג השיר המושמע" #: quodlibet/cli.py:105 msgid "Decrease rating of playing song by one star" msgstr "הסרת כוכב אחד מדרוג השיר המושמע" #: quodlibet/cli.py:106 msgid "Print player status" msgstr "הדפסת מצב נגן" #: quodlibet/cli.py:107 msgid "Hide main window" msgstr "הסתרת חלון ראשי" #: quodlibet/cli.py:108 msgid "Show main window" msgstr "הצגת חלון ראשי" #: quodlibet/cli.py:109 msgid "Toggle main window visibility" msgstr "החלפת מצג חלון ראשי" #: quodlibet/cli.py:110 msgid "Focus the running player" msgstr "מיקוד על הנגן שבשימוש כעת" #: quodlibet/cli.py:111 msgid "Remove active browser filters" msgstr "הסרת מסנן דפדפן פעיל" #: quodlibet/cli.py:112 msgid "Refresh and rescan library" msgstr "רענון ספרית שירים" #: quodlibet/cli.py:113 msgid "List available browsers" msgstr "רשימת דפדפנים זמינים" #: quodlibet/cli.py:114 msgid "Print the current playlist" msgstr "הדפסת רשימת הדמעה נוכחית" #: quodlibet/cli.py:115 msgid "Print the contents of the queue" msgstr "הדפסת תוכן תור ההשמעה" #: quodlibet/cli.py:116 msgid "Print the active text query" msgstr "הדפסת מלל שאילתה נוכחית" #: quodlibet/cli.py:117 msgid "Start without plugins" msgstr "הפעלה ללא מתקעים" #: quodlibet/cli.py:118 msgid "Start Quod Libet if it isn't running" msgstr "אתחול קְווֹדְלִיבֵּט במידה ואינה פועלת" #: quodlibet/cli.py:119 msgid "Exit Quod Libet" msgstr "יציאה מקְווֹדְלִיבֵּט" #: quodlibet/cli.py:124 msgid "Seek within the playing song" msgstr "הזחה בתוך השיר המתנגן" #: quodlibet/cli.py:124 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: quodlibet/cli.py:125 msgid "Set or toggle shuffle mode" msgstr "הגדרת או החלפת מצב אקראי" #: quodlibet/cli.py:126 msgid "Set shuffle mode type" msgstr "הגדרת סוג מצב אקראי" #: quodlibet/cli.py:127 msgid "Turn repeat off, on, or toggle it" msgstr "כיבוי, הפעלת, או החלפת מצב חזרה" #: quodlibet/cli.py:128 msgid "Set repeat mode type" msgstr "הגדרת סוג מצב חזרה" #: quodlibet/cli.py:129 msgid "Set the volume" msgstr "קביעת העוצמה" #: quodlibet/cli.py:130 msgid "Search your audio library" msgstr "חיפוש בספרית השמע" #: quodlibet/cli.py:130 quodlibet/cli.py:140 quodlibet/cli.py:144 quodlibet/cli.py:146 msgid "query" msgstr "שאילתה" #: quodlibet/cli.py:131 msgid "Play a file" msgstr "השמעת קובץ" #: quodlibet/cli.py:131 quodlibet/cli.py:140 quodlibet/cli.py:146 msgctxt "command" msgid "filename" msgstr "שם קובץ" #: quodlibet/cli.py:132 msgid "Set rating of playing song" msgstr "דרוג השיר המתנגן" #: quodlibet/cli.py:133 msgid "Set the current browser" msgstr "קביעת הדפדפן הנוכחי" #: quodlibet/cli.py:134 msgid "Stop after the playing song" msgstr "עצירה לאחר השיר המושמע" #: quodlibet/cli.py:135 msgid "Open a new browser" msgstr "פתיחת דפדפן חדש" #: quodlibet/cli.py:136 msgid "Show or hide the queue" msgstr "הצגת או הסתרת התור" #: quodlibet/cli.py:137 msgid "Filter on a random value" msgstr "סינון לפי ערך אקראי" #: quodlibet/cli.py:137 msgctxt "command" msgid "tag" msgstr "תג" #: quodlibet/cli.py:138 msgid "Filter on a tag value" msgstr "סינון לפי ערך תג" #: quodlibet/cli.py:138 msgid "tag=value" msgstr "תג=ערך" #: quodlibet/cli.py:139 msgid "Enqueue a file or query" msgstr "הוספת קובץ או שאילתה לתור" #: quodlibet/cli.py:141 msgid "Enqueue comma-separated files" msgstr "הוספת קבצים לתור, מופרדים בפסיק" #: quodlibet/cli.py:142 quodlibet/util/tags.py:157 msgid "filename" msgstr "שם קובץ" #: quodlibet/cli.py:143 msgid "Print filenames of results of query to stdout" msgstr "הדפסת שמות קבצים של תוצאות שאילתה ל- stdout" #: quodlibet/cli.py:145 msgid "Unqueue a file or query" msgstr "הסרת קובץ או שאילתה מהתור" #: quodlibet/cli.py:147 msgid "Add a file or directory to the library" msgstr "הוספת קובץ או מחיצה לספריה" #: quodlibet/cli.py:148 quodlibet/util/tags.py:100 msgid "location" msgstr "מיקום" #: quodlibet/cli.py:213 #, python-format msgid "Invalid argument for '%s'." msgstr "ערך לא תקין עבור '%s'." #: quodlibet/cli.py:214 quodlibet/util/__init__.py:173 #, 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 "Quit Program" 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:34 msgid "an audio tag editor" msgstr "עורך תגי שמע" #: quodlibet/exfalso.py:34 quodlibet/util/tags.py:158 msgid "directory" msgstr "מחיצה" #: quodlibet/exfalso.py:41 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:20 msgid "Downloads covers linked to by the artwork_url tag. This works with the Soundcloud browser." 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:20 msgid "MusicBrainz Cover Source" msgstr "מקור תמונות עטיפה מוזיקבריינז" #: quodlibet/ext/covers/musicbrainz.py:21 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:19 msgid "Allows arbitrary regex substitutions (s///) 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:68 msgid "Advanced Preferences" msgstr "העדפות מתקדמות" #: quodlibet/ext/events/advanced_preferences.py:69 msgid "Allow editing of advanced config settings." msgstr "אפשור עריכת תצורה מתקדמות." #: quodlibet/ext/events/advanced_preferences.py:187 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/ext/events/weblyrics.py:318 #: quodlibet/qltk/prefs.py:266 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:66 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:172 msgid "Effects" msgstr "פַּעֲלוּלִים" #: quodlibet/ext/events/animosd/prefs.py:288 msgid "Ed_it Display Pattern…" msgstr "ער_יכת דפוס מַצָּג…" #: quodlibet/ext/events/animosd/prefs.py:292 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_library_update.py:138 msgid "Automatic Library Update" msgstr "עדכון ספריה אוטומטי" #: quodlibet/ext/events/auto_library_update.py:139 #, python-format msgid "Keeps your library up to date with inotify. Requires %s." msgstr "שמירה על עדכניות ספרית המוזיקה באמצעות אינוטיפיי. נדרש %s." #: 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 by Brian Nelson." msgstr "" "דרוג שירים אוטומטית במהלך השמעתם או דלוגום. המתקע משתמש באלוגריטם 'האצה' מאת vox שנכתב על ידי " "בריאן נלסון." #: quodlibet/ext/events/bansheeimport.py:106 msgid "Specified Banshee database is malformed or missing" msgstr "מסד הנתונים של בנשי שצוין פגום או חסר" #: quodlibet/ext/events/bansheeimport.py:111 quodlibet/ext/events/rbimport.py:114 msgid "Import Failed" msgstr "יבוא כשל" #: quodlibet/ext/events/bansheeimport.py:117 #, 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:126 msgid "Banshee Import" msgstr "יבוא בנשי" #: quodlibet/ext/events/bansheeimport.py:127 msgid "Imports ratings and song statistics from Banshee." msgstr "יבוא דרוג וסטטיסטיקת השמעות מבנשי." #: quodlibet/ext/events/bansheeimport.py:136 msgid "_Database path:" msgstr "_נתיב מסד נתונים:" #: quodlibet/ext/events/bansheeimport.py:164 quodlibet/ext/events/rbimport.py:132 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/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:93 #: quodlibet/ext/gstreamer/karaoke.py:95 #, python-format msgid "%d Hz" msgstr "%d Hz" #: quodlibet/ext/events/equalizer.py:198 quodlibet/ext/gstreamer/crossfeed.py:112 #, 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/playlist/export_to_squeezebox.py:80 #: quodlibet/ext/songsmenu/albumart.py:324 quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/cover_download.py:309 quodlibet/ext/songsmenu/fingerprint/search.py:278 #: quodlibet/ext/songsmenu/html.py:75 quodlibet/ext/songsmenu/lastfmsync.py:219 #: quodlibet/ext/songsmenu/playlist.py:51 quodlibet/ext/songsmenu/replaygain.py:354 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/_editutils.py:40 #: quodlibet/qltk/lyrics.py:34 quodlibet/qltk/msg.py:52 quodlibet/qltk/renamefiles.py:216 #: 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:42 msgid "Inhibit Screensaver" msgstr "עיכוב שומר צג" #: quodlibet/ext/events/inhibit.py:43 msgid "Prevents the GNOME screensaver from activating while a song is playing." msgstr "מניעת שומר צג גנום משיפעול בזמן ששיר מושמע." #: quodlibet/ext/events/inhibit.py:52 msgid "Music is playing" msgstr "מוזיקה מושמעת" #: quodlibet/ext/events/iradiolog.py:16 msgid "Internet Radio Log" msgstr "רישומי יומן רדיו מרשתת" #: quodlibet/ext/events/iradiolog.py:17 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:31 msgid "Outputs a Jabber User Tunes file to ~/.quodlibet/jabber." 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 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:37 msgid "MPRIS D-Bus Support" msgstr "תמיכת MPRIS D-Bus" #: quodlibet/ext/events/mpris/__init__.py:38 msgid "Allows control of Quod Libet using the MPRIS 2 D-Bus Interface Specification." msgstr "שליטה בקְווֹדְלִיבֵּט תוך שימוש בהגדרות ממשק 2 MPRIS D-Bus." #: quodlibet/ext/events/mpris/__init__.py:44 quodlibet/ext/events/trayicon/prefs.py:36 msgid "Hide main window on close" msgstr "הסתרת חלון ראשי בסגירה" #: quodlibet/ext/events/mpris/__init__.py:47 quodlibet/ext/events/themeswitcher.py:84 #: quodlibet/ext/gstreamer/compressor.py:99 quodlibet/ext/gstreamer/crossfeed.py:136 #: quodlibet/ext/gstreamer/karaoke.py:99 quodlibet/ext/gstreamer/pitch.py:89 #: quodlibet/qltk/prefs.py:741 msgid "Preferences" msgstr "העדפות" #: quodlibet/ext/events/mqtt.py:54 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "מתקבלים דפוסי קוודליבט, כלומר %s" #: quodlibet/ext/events/mqtt.py:60 msgid "MQTT Publisher" msgstr "מפרסם MQTT" #: quodlibet/ext/events/mqtt.py:61 msgid "Publishes status messages to an MQTT topic." msgstr "פרסום מצב הודעות לנושא MQTT." #: quodlibet/ext/events/mqtt.py:128 msgid "Broker hostname" msgstr "שם מתוך מארח" #: quodlibet/ext/events/mqtt.py:129 msgid "broker hostname / IP (defaults to localhost)" msgstr "שם מתוך מארח /IP (ברירת מחדל למחשב מקומי)" #: quodlibet/ext/events/mqtt.py:131 msgid "Broker port" msgstr "פִּתְחָת מתוך" #: quodlibet/ext/events/mqtt.py:131 msgid "broker port (defaults to 1883)" msgstr "פִּתְחָת מתוך (ברירת מחדל 1883)" #: quodlibet/ext/events/mqtt.py:133 msgid "Topic" msgstr "נושא" #: quodlibet/ext/events/mqtt.py:135 msgid "Playing Pattern" msgstr "דפוס השמעה" #: quodlibet/ext/events/mqtt.py:137 msgid "Status text when a song is started." msgstr "מלל מצב בעת השמעת שיר." #: quodlibet/ext/events/mqtt.py:139 msgid "Paused Pattern" msgstr "דפוס מושהה" #: quodlibet/ext/events/mqtt.py:141 msgid "Text when a song is paused." msgstr "מלל בעת השהיית שיר." #: quodlibet/ext/events/mqtt.py:143 msgid "No-song Text" msgstr "אין מלל שיר" #: quodlibet/ext/events/mqtt.py:145 msgid "Plain text for when there is no current song" msgstr "מלל פשוט כשלא מושמע שיר" #: quodlibet/ext/events/mqtt.py:156 msgid "MQTT Configuration" msgstr "תצור MQTT" #: quodlibet/ext/events/mqtt.py:160 msgid "Status Text" msgstr "מלל מצב" #: quodlibet/ext/events/mqtt.py:192 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "חיבור למתוך %(host)s:%(port)d" #: quodlibet/ext/events/mqtt.py:196 #, 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:199 msgid "Connection error" 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/qlscrobbler.py:175 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs will not be submitted." msgstr "נא להגדיר את QLScrobbler בחלון המתקעים. עד אז השירים לא ישוגרו." #: quodlibet/ext/events/qlscrobbler.py:252 #, python-format msgid "Could not contact service '%s'." msgstr "לא ניתן להתחבר לשרות '%s'." #: quodlibet/ext/events/qlscrobbler.py:258 msgid "Authentication failed: invalid URL." msgstr "ההזדהות כשלה: URL שגוי." #: quodlibet/ext/events/qlscrobbler.py:275 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "ההזדהות כשלה: שם משתמש '%s' או הססמה שגויים." #: quodlibet/ext/events/qlscrobbler.py:280 msgid "Client is banned. Contact the author." msgstr "חשבון לקוח מוחרם. נא ליצור קשר אם המחבר." #: quodlibet/ext/events/qlscrobbler.py:284 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "שעון מערכת שגוי. השגור עשוי להכשל עד שיתוקן." #: quodlibet/ext/events/qlscrobbler.py:349 msgid "AudioScrobbler Submission" msgstr "הגשת אודיוסקרובלר" #: quodlibet/ext/events/qlscrobbler.py:350 msgid "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler services." msgstr "לקוח אודיוסקרובלר עבור Last.fm ושרותי אודיוסקרובלר אחרים." #: quodlibet/ext/events/qlscrobbler.py:455 msgid "Authentication successful." msgstr "ההזדהות צלחה." #: quodlibet/ext/events/qlscrobbler.py:467 msgid "_Service:" msgstr "_שרות:" #: quodlibet/ext/events/qlscrobbler.py:467 msgid "_URL:" msgstr "_URL:" #: quodlibet/ext/events/qlscrobbler.py:467 msgid "User_name:" msgstr "שם _משתש:" #: quodlibet/ext/events/qlscrobbler.py:468 msgid "_Password:" msgstr "_ססמה:" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:484 msgid "Other…" msgstr "אחר…" #. verify data #: quodlibet/ext/events/qlscrobbler.py:522 msgid "_Verify account data" msgstr "_אימות נתוני חשבון" #: quodlibet/ext/events/qlscrobbler.py:527 quodlibet/ext/songsmenu/lastfmsync.py:312 msgid "Account" msgstr "חשבון" #: quodlibet/ext/events/qlscrobbler.py:535 msgid "_Artist pattern:" msgstr "_דפוס אמן:" #: quodlibet/ext/events/qlscrobbler.py:535 msgid "_Title pattern:" msgstr "_דפוס שם קובץ:" #: quodlibet/ext/events/qlscrobbler.py:536 msgid "Exclude _filter:" msgstr "_מסנן החרגה:" #: quodlibet/ext/events/qlscrobbler.py:554 msgid "The pattern used to format the artist name for submission. Leave blank for default." msgstr "הדפוס משמש תִּיבְנוּת שם האמן לשגור. להשאיר ריק לברירת המחדל." #: quodlibet/ext/events/qlscrobbler.py:564 msgid "The pattern used to format the title for submission. Leave blank for default." msgstr "הדפוס משמש לתִּיבְנוּת כותרת לשגור. להשאיר ריק לברירת המחדל." #: quodlibet/ext/events/qlscrobbler.py:573 msgid "Songs matching this filter will not be submitted" msgstr "שירים התואמים למסנן זה לא ישוגרו" #: quodlibet/ext/events/qlscrobbler.py:581 msgid "_Offline mode (don't submit anything)" msgstr "_מצב לא מקוון (לא לשגר דבר)" #: quodlibet/ext/events/qlscrobbler.py:585 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:28 msgid "Random Album Playback" msgstr "השמעת אלבום אקראי" #: quodlibet/ext/events/randomalbum.py:29 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:39 msgid "Rated higher" msgstr "דרוג גבוהה" #: quodlibet/ext/events/randomalbum.py:40 msgid "Played more often" msgstr "הושמעו בתכיפות" #: quodlibet/ext/events/randomalbum.py:41 msgid "Skipped more often" msgstr "דולגו יותר לאחרונה" #: quodlibet/ext/events/randomalbum.py:42 msgid "Played more recently" msgstr "הושמעו יותר לאחרונה" #: quodlibet/ext/events/randomalbum.py:43 msgid "Started more recently" msgstr "התחלו יותר לאחרונה" #: quodlibet/ext/events/randomalbum.py:44 msgid "Added more recently" msgstr "נוספו לאחרונה" #: quodlibet/ext/events/randomalbum.py:45 msgid "Longer albums" msgstr "אלבומים ארוכים יותר" #: quodlibet/ext/events/randomalbum.py:84 msgid "seconds before starting next album" msgstr "שניות לפני תחילת השמעת האלבום הבא" #: quodlibet/ext/events/randomalbum.py:88 msgid "Weights" msgstr "משקולות" #: quodlibet/ext/events/randomalbum.py:90 msgid "Play some albums more than others" msgstr "השמעת אלבומים מסוימים יותר מאחרים" #: quodlibet/ext/events/randomalbum.py:104 msgid "avoid" msgstr "להמנע" #: quodlibet/ext/events/randomalbum.py:115 msgid "prefer" msgstr "העדפה" #: quodlibet/ext/events/randomalbum.py:219 msgid "Random Album" msgstr "אלבום אקראי" #: quodlibet/ext/events/randomalbum.py:220 #, python-format msgid "Waiting to start %s" msgstr "בהמתנה ל %s" #: quodlibet/ext/events/rbimport.py:119 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "דרוג וסטטיסטיקה יובאו בהצלחה עבור %d שירים" #: quodlibet/ext/events/rbimport.py:127 msgid "Rhythmbox Import" msgstr "יבוא ריטמבוקס" #: quodlibet/ext/events/rbimport.py:128 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:73 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "לא מותקנת מעטפת ספק חיפוש גנום עבור קְווֹדְלִיבֵּט." #: quodlibet/ext/events/searchprovider.py:79 msgid "GNOME Search Provider" msgstr "ספק חיפוש גנום" #: quodlibet/ext/events/searchprovider.py:80 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" "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:29 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from an identical library." msgstr "הפיכת פלט לוג'טק סקוויזבוקס לתמונת מראה של קְווֹדְלִיבֵּט, בתנאי ששניהם קוראים מספריה זהה." #: quodlibet/ext/events/squeezebox_sync.py:57 quodlibet/ext/playlist/export_to_squeezebox.py:89 msgid "Error finding Squeezebox server" msgstr "אירעה שגיאה במציאת שרת סקוויזבוקס" #: quodlibet/ext/events/squeezebox_sync.py:58 quodlibet/ext/playlist/export_to_squeezebox.py:90 #, python-format msgid "Error finding %s. Please check settings" msgstr "אירעה שגיאה במציאת %s. נא לבדוק הגדרות" #: quodlibet/ext/events/synchronizedlyrics.py:34 msgid "Synchronized Lyrics" msgstr "סנכרון תַּמְלִיל" #: quodlibet/ext/events/synchronizedlyrics.py:35 msgid "Shows synchronized lyrics from .lrc file with same name as the track." msgstr "הצגת תַּמְלִיל מסונכרן בעל שם זהה לשם הרצועה מקובץ .lrc." #: quodlibet/ext/events/synchronizedlyrics.py:69 msgid "Text:" msgstr "מלל:" #: quodlibet/ext/events/synchronizedlyrics.py:79 msgid "Background:" msgstr "רקע:" #: quodlibet/ext/events/synchronizedlyrics.py:90 msgid "Font" msgstr "גופן" #: quodlibet/ext/events/synchronizedlyrics.py:93 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:145 msgid "Paused:" msgstr "מושהה:" #: quodlibet/ext/events/telepathy_status.py:146 #, 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:162 msgid "Plain text for status when there is no current song" msgstr "מלל פשוט כשלא מושמע שיר" #: quodlibet/ext/events/telepathy_status.py:163 msgid "No song:" msgstr "אין שיר:" #. Frame #: quodlibet/ext/events/telepathy_status.py:170 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:91 msgid "Thumb Rating" msgstr "דֵּרוּג אגודל" #: quodlibet/ext/events/thumbrating.py:92 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 '~#score'." 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:47 msgid "Not playing" msgstr "לא מנגן" #: quodlibet/ext/events/trayicon/__init__.py:53 msgid "Tray Icon" msgstr "צלמית מגש המערכת" #: quodlibet/ext/events/trayicon/__init__.py:54 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:183 #: quodlibet/qltk/quodlibetwindow.py:936 quodlibet/qltk/quodlibetwindow.py:1142 msgid "_Play" msgstr "_השמעה" #: quodlibet/ext/events/trayicon/menu.py:63 quodlibet/qltk/quodlibetwindow.py:185 #: quodlibet/qltk/quodlibetwindow.py:1144 quodlibet/qltk/wlw.py:50 msgid "P_ause" msgstr "ה_שהיה" #: quodlibet/ext/events/trayicon/menu.py:68 quodlibet/qltk/quodlibetwindow.py:190 #: quodlibet/qltk/quodlibetwindow.py:931 msgid "Pre_vious" msgstr "הקו_דם" #: quodlibet/ext/events/trayicon/menu.py:71 quodlibet/qltk/quodlibetwindow.py:194 #: quodlibet/qltk/quodlibetwindow.py:941 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:902 msgid "Open _Browser" msgstr "פתיחת _דפדפן" #: quodlibet/ext/events/trayicon/menu.py:103 quodlibet/qltk/quodlibetwindow.py:921 #: quodlibet/qltk/songsmenu.py:383 msgid "Edit _Tags" msgstr "עריכת _תגים" #: quodlibet/ext/events/trayicon/menu.py:112 quodlibet/qltk/quodlibetwindow.py:864 #: quodlibet/qltk/songsmenu.py:396 msgid "_Information" msgstr "_מידע" #: quodlibet/ext/events/trayicon/menu.py:114 quodlibet/qltk/songsmenu.py:324 msgid "Play_lists" msgstr "רשימות _השמעה" #: quodlibet/ext/events/trayicon/menu.py:132 quodlibet/qltk/quodlibetwindow.py:916 msgid "_Quit" msgstr "_יצאה" #: quodlibet/ext/events/trayicon/prefs.py:38 quodlibet/qltk/prefs.py:69 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 quodlibet/ext/events/weblyrics.py:193 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:603 msgid "Waveform Seek Bar" msgstr "סרגל הזחה בצורת גל" #: quodlibet/ext/events/waveformseekbar.py:607 msgid "A seekbar in the shape of the waveform of the current song." msgstr "סרגל הזחה בתצורת גל של השיר המושמע." #: quodlibet/ext/events/waveformseekbar.py:676 msgid "Override foreground color:" msgstr "עֲקִיפָת צבע קִדְמָה:" #: quodlibet/ext/events/waveformseekbar.py:680 msgid "Override hover color:" msgstr "עֲקִיפָת צבע רחוף:" #: quodlibet/ext/events/waveformseekbar.py:684 msgid "Override remaining color:" msgstr "עֲקִיפָת צבע נותר:" #: quodlibet/ext/events/waveformseekbar.py:688 msgid "Show current position" msgstr "הצגת מיקום נוכחי" #: quodlibet/ext/events/waveformseekbar.py:693 msgid "Show time labels" msgstr "הצגת תוויות זמן" #: quodlibet/ext/events/waveformseekbar.py:701 msgid "Seek amount when scrolling (milliseconds):" msgstr "משך הזחה בעת גלילה (מילי-שניות):" #: quodlibet/ext/events/weblyrics.py:208 msgid "No lyrics found" msgstr "לא נמצא תַּמְלִיל" #: quodlibet/ext/events/weblyrics.py:268 msgid "_Zoom level:" msgstr "_רמת מיקוד:" #: quodlibet/ext/events/weblyrics.py:286 msgid "URL:" msgstr "URL:" #: quodlibet/ext/events/weblyrics.py:291 msgid "Revert to default" msgstr "הסגה לברירת מחדל" #: quodlibet/ext/events/weblyrics.py:306 msgid "Search via above URL if the lyrics couldn't be found in LyricsWikia." msgstr "חיפוש ב URL שלעיל, אם התַּמְלִיל לא נמצא ב LyricsWikia." #: quodlibet/ext/events/weblyrics.py:323 msgid "Alternate search" msgstr "שינוי חיפוש" #: quodlibet/ext/events/weblyrics.py:332 msgid "Web Lyrics" msgstr "תַּמְלִיל מרשתת" #: quodlibet/ext/events/weblyrics.py:333 msgid "Shows a sidebar containing online lyrics of the playing song." 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:20 msgid "_Threshold:" msgstr "_סף:" #: quodlibet/ext/gstreamer/compressor.py:21 msgid "Threshold until the filter is activated" msgstr "סף שפעול המסנן" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "R_atio:" msgstr "י_חס:" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "Compression ratio" msgstr "יחס דחיסה" #: quodlibet/ext/gstreamer/compressor.py:74 quodlibet/ext/gstreamer/karaoke.py:91 #, python-format msgid "%d %%" msgstr "%d %%" #: quodlibet/ext/gstreamer/compressor.py:105 msgid "Audio Compressor" msgstr "דוחס שמע" #: quodlibet/ext/gstreamer/compressor.py:106 msgid "Changes the amplitude of all samples above a specific threshold with a specific ratio." msgstr "שינוי המִשְׂרַעַת של כל הדגימות מעל סף מסוים ביחס מסוים." #: quodlibet/ext/gstreamer/crossfeed.py:19 msgid "_Preset:" msgstr "_מוגדר מראש:" #: quodlibet/ext/gstreamer/crossfeed.py:19 msgid "Filter preset" msgstr "מסנן מוגדר מראש" #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Frequency cut:" msgstr "_קיצוץ תדר:" #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Low-pass filter cut frequency" msgstr "קיצוץ תדר מסנן מעבר נמוך" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed _level:" msgstr "_רמת הזנה:" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed level" msgstr "רמת הזנה" #: quodlibet/ext/gstreamer/crossfeed.py:25 msgid "Default" msgstr "ברירת מחדל" #: quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "הצבה קרובה ביותר לרמקול מדומה (30°, 3 מטר)" #: quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Chu Moy" msgstr "צ'ו מוי" #: quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "סגירת הצלבת ערוצים של Chu Moy (עממי)" #: quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Jan Meier" msgstr "יאן מאיר" #: quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "קרוב למגברי CORDA של ז'אן מאיר (שונה במקצת)" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Custom" msgstr "מותאם אישית" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Custom settings" msgstr "הגדרות מותאמות אישית" #: quodlibet/ext/gstreamer/crossfeed.py:152 msgid "Crossfeed" msgstr "הצלבת ערוצים" #: quodlibet/ext/gstreamer/crossfeed.py:153 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:20 msgid "Filter _band:" msgstr "סינון לפי _הרכב:" #: quodlibet/ext/gstreamer/karaoke.py:21 msgid "The Frequency band of the filter" msgstr "פס התדר של המסנן" #: quodlibet/ext/gstreamer/karaoke.py:22 msgid "Filter _width:" msgstr "רוחב _מסנן:" #: quodlibet/ext/gstreamer/karaoke.py:23 msgid "The Frequency width of the filter" msgstr "רוחב פס התדר של המסנן" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "_Level:" msgstr "_רמה:" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "Level of the effect" msgstr "רמת פעלול" #: quodlibet/ext/gstreamer/karaoke.py:105 msgid "Karaoke" msgstr "קאראוקי" #: quodlibet/ext/gstreamer/karaoke.py:106 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:21 msgid "R_ate:" msgstr "ד_רוג:" #: quodlibet/ext/gstreamer/pitch.py:22 msgid "_Tempo:" msgstr "_קצב:" #: quodlibet/ext/gstreamer/pitch.py:23 msgid "_Pitch:" msgstr "_שיא:" #: quodlibet/ext/gstreamer/pitch.py:95 msgid "Audio Pitch / Speed" msgstr "שיא / מהירות שמע" #: quodlibet/ext/gstreamer/pitch.py:96 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:147 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:100 msgid "Exports a playlist by copying files to a folder." msgstr "יצוא רשימת שמע תוך העתקת קבצים לתיקיה." #: quodlibet/ext/playlist/export_to_folder.py:121 quodlibet/ext/songsmenu/playlist.py:132 msgid "Unable to export playlist" msgstr "לא ניתן לייצא רשימת ההשמעה" #: quodlibet/ext/playlist/export_to_folder.py:122 msgid "Ensure you have write access to the destination." msgstr "נא לוודא כי קימות הרשאות כתיבה ליעד." #: quodlibet/ext/playlist/export_to_folder.py:165 msgid "Default filename pattern:" 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. Shares configuration with <a href=\"quodlibet:///prefs/plugins/Squeezebox Output" "\">Squeezebox Sync plugin</a>." msgstr "" "יצוא דִּינָמִי של רשימת השמעה לרשימת השמעה לוג'יטק סקוויזבוקס, בהנתן ששניהם שותפים לאותה מחיצה. תצור " "שיתוף באמצעות <a href=\"quodlibet:///prefs/plugins/Squeezebox Output\">Squeezebox Sync plugin</" "a>." #: 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:96 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 msgid "Playback follows your selection, or the next song in the list once exhausted." msgstr "השמעה עוקבת אחרי הבחירה או השיר הבא ברשימה עם סיום הנוכחי." #: quodlibet/ext/playorder/playcounteq.py:21 msgid "Playcount Equalizer" msgstr "שוין מספר השמעות" #: quodlibet/ext/playorder/playcounteq.py:22 msgid "Shuffle, preferring songs with fewer total plays." msgstr "אקראי, העדפת שירים בעלי סך כל השמעות מעטות יותר." #: quodlibet/ext/playorder/playcounteq.py:24 msgid "Prefer less played" msgstr "העדפת שירים שהושמעו פחות" #: quodlibet/ext/playorder/queue.py:19 msgid "Queue Only" msgstr "תור בלבד" #: quodlibet/ext/playorder/queue.py:21 msgid "" "Limits playing of songs to the queue. Select this play order in the main window, then double-" "clicking any song will enqueue it instead of playing." msgstr "" "הגבלת השמעת שיר לתור. בחירה בסדר השמעה זה מהחלון הראשי, הקשה כפולה על שיר כלשהו, יצרף אותו לתור " "במקום להשמיעו." #: quodlibet/ext/playorder/reverse.py:14 msgid "Reverse" msgstr "הסגה" #: quodlibet/ext/playorder/reverse.py:16 msgid "Reverses the play order of songs." msgstr "היפוך סדר השמעה של השירים." #: quodlibet/ext/playorder/shufflebygrouping.py:31 quodlibet/ext/playorder/shufflebygrouping.py:93 msgid "Shuffle by Grouping" msgstr "אקראי לפי קיבוץ" #: quodlibet/ext/playorder/shufflebygrouping.py:32 msgid "" "Shuffles by a grouping of songs defined by a common tag instead of by track, similar to album " "shuffle. This is useful for shuffling multi-movement classical works while making sure all " "movements play in order before shuffling to the next piece." msgstr "" "השמעה אקראית תוך קיבוץ שירים בעלי תג קיבוץ משותף במקום רצועה, בדומה להשמעה אקראית של אלבום. " "שימושי בעיקר בהשמעה אקראית של יצירות קלאסיות בעלות מקטעים מרובים תוך הקפדה שכל מקטע יושמע לפני " "שיתבצע דִּלּוּג אקראי לחלק הבא." #: quodlibet/ext/playorder/shufflebygrouping.py:38 msgid "Shuffle by grouping" msgstr "אקראי לפי קיבוץ" #: quodlibet/ext/playorder/shufflebygrouping.py:94 msgid "Waiting to start new group…" msgstr "המתנה להתחלת קבוצה חדשה…" #: quodlibet/ext/playorder/shufflebygrouping.py:144 msgid "Grouping tag:" msgstr "תג קיבוץ:" #: quodlibet/ext/playorder/shufflebygrouping.py:148 msgid "Tag to group songs by" msgstr "תג קיבוץ שירים" #: quodlibet/ext/playorder/shufflebygrouping.py:150 msgid "Filter tag:" msgstr "תג סינון:" #: quodlibet/ext/playorder/shufflebygrouping.py:155 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:160 msgid "Delay:" msgstr "השהיה:" #: quodlibet/ext/playorder/shufflebygrouping.py:166 msgid "Time delay in seconds before starting next group" msgstr "השהיה של שניות לפני תחילת השמעת הקבוצה הבאה" #: quodlibet/ext/playorder/shufflebygrouping.py:182 msgid "Reset to defaults" msgstr "איפוס לברירת מחדל" #: quodlibet/ext/playorder/skip_songs.py:25 msgid "Skip Songs" msgstr "דִּלּוּג על שירים" #: quodlibet/ext/playorder/skip_songs.py:27 msgid "Playback skips over songs with a rating equal or below a given threshold." msgstr "דלוג השמעה על שירים בעלי דֵּרוּג שווה או נמוך לסף הנתון." #: quodlibet/ext/playorder/track_repeat.py:30 msgid "Repeat Each Track" msgstr "חזרה על כל רצועה" #: quodlibet/ext/playorder/track_repeat.py:32 msgid "Shuffle songs, but repeat every track a set number of times." msgstr "השמעה אקראית של שירים, עם חזרה על כל רצועה מספר מוגדר של פעמים." #: quodlibet/ext/playorder/track_repeat.py:51 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. Syntax is '@(if: condition, then, else)'." msgstr "בחירת שאילתה כך שתתאים לשאילתת תנאי. התחביר הוא '@(if: condition, then, else)'." #: quodlibet/ext/query/missing.py:15 msgid "Missing Query" msgstr "שאילתה חסרה" #: quodlibet/ext/query/missing.py:16 msgid "Matches songs without the given tag." msgstr "התאמת שירים ללא התג הנתון." #: quodlibet/ext/query/missing.py:27 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. Syntax is '@(python: expression)'. The variable 's' (or 'a') " "is the song / album being matched. '_ts' is a (real number) timestamp at start of query. Modules " "'time' and 'random' are also available, and the class 'Random' (==random.Random) too." msgstr "" "שימוש בביטוי פייטון בשאילתות. התחביר הוא '@ (python: expression)'. המשתנה '(או' a ') הוא שיר / " "אלבום המותאם. '_ts' הוא חותמת זמן (מספר אמתי) בתחילת השאילתה. פִּרְקָן 'זמן' ו 'אקראי' זמינים, כמו " "גם 'אקראי' (== random.Random)." #: quodlibet/ext/query/savedsearch.py:19 msgid "Include Saved Search" msgstr "הכללת ערכי חיפוש שמורים" #: quodlibet/ext/query/savedsearch.py:20 msgid "" "Include the results of a saved search as part of another query. Syntax is '@(saved: search " "name)'." msgstr "מכליל תוצאות של חיפוש שמור כחלק משאילתה אחרת. התחביר הוא '@(saved: search name)'." #: 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:116 msgid "Port:" msgstr "פורט:" #: quodlibet/ext/_shared/squeezebox/base.py:121 msgid "Username:" msgstr "שם משתש:" #: quodlibet/ext/_shared/squeezebox/base.py:126 msgid "Password:" msgstr "סיסמה:" #: quodlibet/ext/_shared/squeezebox/base.py:130 msgid "Library directory the server connects to" msgstr "מחיצת הספריה אליה מתחבר השרת" #: quodlibet/ext/_shared/squeezebox/base.py:132 msgid "Library path:" msgstr "נתיב ספריה:" #. Add verify button #: quodlibet/ext/_shared/squeezebox/base.py:141 msgid "_Verify settings" msgstr "_אימות הגדרות" #. Server settings Frame #: quodlibet/ext/_shared/squeezebox/base.py:147 msgid "Squeezebox Server" msgstr "שרת סקוויזבוקס" #: quodlibet/ext/_shared/squeezebox/base.py:150 msgid "Debug" msgstr "ניפוי תקלים" #: quodlibet/ext/_shared/squeezebox/server.py:26 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "שרת סקוויזבוקס ב {hostname}:{port}" #: quodlibet/ext/_shared/squeezebox/server.py:28 msgid "unidentified Squeezebox server" msgstr "שרת סקוויזבוקס לא מוגדר" #: quodlibet/ext/_shared/squeezebox/server.py:37 #, 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:20 quodlibet/ext/songsmenu/importexport.py:39 #: quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "_אוקיי" #: quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" "נמצא שרת סקוויזבוקס.\n" "נא לבחור נגן" #: quodlibet/ext/songsmenu/albumart.py:331 msgid "Fit image to _window" msgstr "התאמת תמונה _לחלון" #: quodlibet/ext/songsmenu/albumart.py:337 msgid "See '[plugins] cover_filenames' config entry for image filename strings" msgstr "ראו תצורת '[plugins] cover_filenames'] עבור מחרוזות קובצי תמונות" #. Both labels #: quodlibet/ext/songsmenu/albumart.py:343 msgid "_Program:" msgstr "_תכנית:" #: quodlibet/ext/songsmenu/albumart.py:348 msgid "_Edit image after saving" msgstr "_עריכת תמונה לאחר שמירה" #: quodlibet/ext/songsmenu/albumart.py:350 msgid "File_name:" msgstr "שם _קובץ:" #: quodlibet/ext/songsmenu/albumart.py:466 msgid "Saving failed" msgstr "פעולת השמירה כשלה" #: quodlibet/ext/songsmenu/albumart.py:467 #, python-format msgid "Unable to save \"%s\"." msgstr "לא ניתן לשמור \"%s\"." #: quodlibet/ext/songsmenu/albumart.py:565 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "שגיאת [תמונת עטיפה] HTTP: %s" #: quodlibet/ext/songsmenu/albumart.py:622 msgid "Album Art Downloader" msgstr "מוריד עטיפות אלבום" #: quodlibet/ext/songsmenu/albumart.py:675 #, python-format msgid "from %(source)s" msgstr "מ %(source)s" #: quodlibet/ext/songsmenu/albumart.py:678 #, python-format msgid "Resolution: %s" msgstr "רָמַת הפרדה: %s" #: quodlibet/ext/songsmenu/albumart.py:681 #, python-format msgid "Size: %s" msgstr "גודל: %s" #: quodlibet/ext/songsmenu/albumart.py:727 msgid "Per engine 'at best' results limit" msgstr "הגבלת התוצאות לפי מנוע 'לכל היותר'" #: quodlibet/ext/songsmenu/albumart.py:737 msgid "_Search" msgstr "_חיפוש" #: quodlibet/ext/songsmenu/albumart.py:819 quodlibet/ext/songsmenu/brainz/widgets.py:451 msgid "Searching…" msgstr "חיפוש…" #: quodlibet/ext/songsmenu/albumart.py:884 quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "בוצע" #: quodlibet/ext/songsmenu/albumart.py:1006 msgid "Download Album Art" msgstr "הורדת עטיפות אלבום" #: quodlibet/ext/songsmenu/albumart.py:1007 msgid "Downloads album covers from various websites." msgstr "הורדת עטיפות אלבום מאתרים שונים." #: quodlibet/ext/songsmenu/albumart.py:1020 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 msgid "Disc" msgstr "תקליטור" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 quodlibet/ext/songsmenu/replaygain.py:393 #: quodlibet/qltk/tracknumbers.py:91 msgid "Track" msgstr "רצועה" #: quodlibet/ext/songsmenu/brainz/widgets.py:132 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:447 msgid "Please enter a query." msgstr "נא להזין שאילתה." #: quodlibet/ext/songsmenu/brainz/widgets.py:465 quodlibet/ext/songsmenu/brainz/widgets.py:496 msgid "Error encountered. Please retry." msgstr "אירעה שגיאה. נא לנסות שוב." #: quodlibet/ext/songsmenu/brainz/widgets.py:472 quodlibet/ext/songsmenu/brainz/widgets.py:488 msgid "Loading result…" msgstr "טעינת תוצאת…" #: quodlibet/ext/songsmenu/brainz/widgets.py:475 msgid "No results found." msgstr "לא נמצאו תוצאות." #: quodlibet/ext/songsmenu/console.py:40 msgid "Python Console" msgstr "מסוף פייטון" #: quodlibet/ext/songsmenu/console.py:41 msgid "Interactive Python console. Opens a new window." msgstr "מסוף פייטון הִדּוּדִי. פתיחה בחלון חדש." #: quodlibet/ext/songsmenu/console.py:48 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "{plugin_name} עבור {songs} ({app})" #: quodlibet/ext/songsmenu/console.py:55 msgid "Python Console Sidebar" msgstr "סרגל צד מסוף פייטון" #: quodlibet/ext/songsmenu/console.py:56 msgid "Interactive Python console sidebar, that follows the selected songs in the main window." msgstr "מסוף פייטון הידודי, שעוקב אחר השירים שנבחרו בחלון הראשי." #: quodlibet/ext/songsmenu/console.py:75 msgid "You can access the following objects by default:" msgstr "ניתן לגשת לאובייקטים הבאים כברירת מחדל:" #: quodlibet/ext/songsmenu/console.py:85 msgid "Your current working directory is:" msgstr "המחיצה הפעילה היא:" #: quodlibet/ext/songsmenu/cover_download.py:119 msgid "Classic" msgstr "קלאסי" #: quodlibet/ext/songsmenu/cover_download.py:120 msgid "Large" msgstr "גדול" #: quodlibet/ext/songsmenu/cover_download.py:121 msgid "HD" msgstr "HD" #: quodlibet/ext/songsmenu/cover_download.py:122 msgid "Full HD" msgstr "HD מלא" #: quodlibet/ext/songsmenu/cover_download.py:123 msgid "WQXGA" msgstr "WQXGA" #: quodlibet/ext/songsmenu/cover_download.py:124 msgid "4K UHD" msgstr "4K UHD" #: quodlibet/ext/songsmenu/cover_download.py:129 msgid "Cover Art Download" msgstr "הורדת תמונת עטיפות" #: quodlibet/ext/songsmenu/cover_download.py:180 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "טעינת %(source)s - %(dimensions)s…" #: quodlibet/ext/songsmenu/cover_download.py:231 #, python-format msgid "" "Nothing found for albums:\n" "<i>%(albums)s</i>.\n" "\n" "Providers used:\n" "<tt>%(providers)s</tt>" msgstr "" "לא נמצאו אלבומים:\n" "<i>%(albums)s</i>.\n" "\n" "על ידי ספקים:\n" "<tt>%(providers)s</tt>" #: quodlibet/ext/songsmenu/cover_download.py:234 msgid "No covers found" msgstr "לא נמצאו עטיפות" #: quodlibet/ext/songsmenu/cover_download.py:254 #, python-format msgid "%(size)d ✕ %(size)d px" msgstr "%(size)d ✕ %(size)d px" #: quodlibet/ext/songsmenu/cover_download.py:267 msgid "Preview size" msgstr "גודל תצוגה מקדימה" #: quodlibet/ext/songsmenu/cover_download.py:276 msgid "Save destination" msgstr "יעד לשמירה" #: quodlibet/ext/songsmenu/cover_download.py:336 msgid "Download Cover Art" msgstr "הורדת עטיפות אלבום" #: quodlibet/ext/songsmenu/cover_download.py:337 msgid "Downloads high-quality album covers using cover plugins." 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:55 msgid "pattern" 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 "" "דפוס ה 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:91 msgid "Input value" msgstr "הזנת ערך" #: quodlibet/ext/songsmenu/custom_commands.py:92 #, python-format msgid "Value for %s?" msgstr "ערך עבור %s?" #: quodlibet/ext/songsmenu/custom_commands.py:137 msgid "Custom Commands" msgstr "פקודות מותאמות אישית" #: quodlibet/ext/songsmenu/custom_commands.py:138 msgid "Runs custom commands (in batches if required) on songs using any of their tags." msgstr "הפעלת פקודות מותאמות אישית (באצווה אם נדרש) על שירים תוך שימוש תג כלשהו." #: quodlibet/ext/songsmenu/custom_commands.py:197 quodlibet/ext/songsmenu/custom_commands.py:207 #: quodlibet/ext/songsmenu/custom_commands.py:259 msgid "Edit Custom Commands" msgstr "עריכת פקודות מותאות אישית" #: quodlibet/ext/songsmenu/custom_commands.py:290 #, 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:397 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:399 msgid "_Group duplicates by:" msgstr "_קיבוץ כפולים לפי:" #: quodlibet/ext/songsmenu/duplicates.py:404 msgid "Duplicate Key" msgstr "מפתח כפול" #: quodlibet/ext/songsmenu/duplicates.py:409 msgid "Remove _Whitespace" msgstr "הסרת _רווח לבן" #: quodlibet/ext/songsmenu/duplicates.py:410 msgid "Remove _Diacritics" msgstr "הסרת _סִימָן דִּיאָקְרִיטִי" #: quodlibet/ext/songsmenu/duplicates.py:411 msgid "Remove _Punctuation" msgstr "הסרת _פיסוק" #: quodlibet/ext/songsmenu/duplicates.py:412 msgid "Case _Insensitive" msgstr "רגישות _לרישיות" #: quodlibet/ext/songsmenu/duplicates.py:420 msgid "Matching options" msgstr "אפשרויות התאמה" #. Create a dialog. #: quodlibet/ext/songsmenu/editplaycount.py:19 quodlibet/ext/songsmenu/editplaycount.py:41 msgid "Edit Playcount" msgstr "עריכת מספר השמעות" #: quodlibet/ext/songsmenu/editplaycount.py:20 msgid "" "Edit a song's ~#playcount and ~#skipcount.\n" "\n" "When multiple songs are selected, counts will be incremented, rather than set.\n" "\n" "When setting a song's ~#playcount to 0, the ~#lastplayed and ~#laststarted 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:68 msgid "Play Count" msgstr "מונה השמעות" #: quodlibet/ext/songsmenu/editplaycount.py:69 msgid "Skip Count" msgstr "דִּלּוּג ספירה" #: quodlibet/ext/songsmenu/embedded.py:25 msgid "Edit Embedded Images" msgstr "עריכת תמונות משובצות" #: quodlibet/ext/songsmenu/embedded.py:26 msgid "Removes or replaces embedded images." msgstr "הסרת או החלפת תמונות משובצות." #: quodlibet/ext/songsmenu/embedded.py:81 msgid "_Remove all Images" msgstr "_הסרת כל התמונות" #: quodlibet/ext/songsmenu/embedded.py:85 msgid "_Embed Current 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/exact_rating.py:54 quodlibet/qltk/ratingsmenu.py:98 msgid "Change _Rating" 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 "חלול טביעות אצבע שמע באמצעות כרומאפרינט ושיגורם ל 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 "כתיבה" #: quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" 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:65 quodlibet/ext/songsmenu/html.py:75 msgid "Export to HTML" msgstr "יצוא ל HTML" #: quodlibet/ext/songsmenu/html.py:66 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:62 msgid "Error uploading" msgstr "שגיאת ההעלאה" #: quodlibet/ext/songsmenu/ifp.py:63 #, python-format msgid "Unable to upload <b>%s</b>. The device may be out of space, or turned off." msgstr "לא ניתן לטעון את <b>% s </ b>. ייתכן שהמכשיר כבוי או הזיכרון מלא." #: quodlibet/ext/songsmenu/importexport.py:60 msgid "Export Metadata" msgstr "יצוא מטה-דטה" #: quodlibet/ext/songsmenu/importexport.py:61 msgid "Exports metadata of selected songs as a .tags file." msgstr "יצוא מטה-דטה לשירים שנבחרו לקובץ .tags." #: quodlibet/ext/songsmenu/importexport.py:105 msgid "Import Metadata" msgstr "יבוא מטה-דטה" #: quodlibet/ext/songsmenu/importexport.py:106 msgid "Imports metadata for selected songs from a .tags file." msgstr "יבוא מטה-דטה לשירים שנבחרו מקובץ .tags." #: quodlibet/ext/songsmenu/k3b.py:23 msgid "Burn CD" msgstr "צריבת תקליטור" #: quodlibet/ext/songsmenu/k3b.py:24 msgid "Burns CDs with K3b, Brasero or xfburn." msgstr "צריבת תקליטור באמצעות K3b, בראסרו או xfburn." #: quodlibet/ext/songsmenu/lastfmsync.py:97 msgid "Updating chart list." msgstr "עדכון רשימת לוח שידורים." #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:116 msgid "Already up-to-date." msgstr "מעודכן כבר." #: quodlibet/ext/songsmenu/lastfmsync.py:124 #, python-format msgid "Fetching chart for week of %s." msgstr "אחזור לוח שידורים לשבוע %s." #: quodlibet/ext/songsmenu/lastfmsync.py:146 msgid "Sync complete." msgstr "סנכרון הושלם." #: quodlibet/ext/songsmenu/lastfmsync.py:152 msgid "Error during sync" msgstr "אירעה שגיאה במהלך הסנכרון" #: quodlibet/ext/songsmenu/lastfmsync.py:217 quodlibet/ext/songsmenu/lastfmsync.py:247 msgid "Last.fm Sync" msgstr "סנכרון Last.fm" #: quodlibet/ext/songsmenu/lastfmsync.py:248 msgid "Updates your library's statistics from your Last.fm profile." msgstr "עדכון הנתונים הסטטיסטיים של הספרייה מפרופיל Last.fm." #: quodlibet/ext/songsmenu/lastfmsync.py:301 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 "המרת שמות אלבום ואמנים לשמות מיון, לא להיט." #. Create a dialog. #: quodlibet/ext/songsmenu/migratemetadata.py:36 quodlibet/ext/songsmenu/migratemetadata.py:45 msgid "Migrate Metadata" msgstr "מיזוג מטה-דטה" #: quodlibet/ext/songsmenu/migratemetadata.py:39 msgid "Copies the quodlibet-specific metadata between songs." msgstr "העתקת מטא-דטה ייחודיים לקוודליבט בין שירים." #: quodlibet/ext/songsmenu/migratemetadata.py:52 msgid "_Copy" msgstr "_העתקה" #: quodlibet/ext/songsmenu/migratemetadata.py:54 msgid "_Paste" msgstr "_הדבקה" #. Create the tag table. #: quodlibet/ext/songsmenu/migratemetadata.py:64 msgid "Information to copy/paste" msgstr "מידע להעתקה/הדבקה" #. Create the indexing box. #: quodlibet/ext/songsmenu/migratemetadata.py:86 msgid "Map tracks by disc and track number" msgstr "ממפה רצועות על פי מספר תקליטור ורצועה" #: quodlibet/ext/songsmenu/migratemetadata.py:87 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> יש לאפשר זאת בעת העתקת אחסון מטא-דטה לשמירת פרטי רצועה." #: quodlibet/ext/songsmenu/migratemetadata.py:103 #, python-format msgid "There is %d stored track." msgid_plural "There are %d stored tracks." msgstr[0] "קיימת %d רצועה שמורה." msgstr[1] "קיימות %d רצועות שמורות." #: quodlibet/ext/songsmenu/playlist.py:31 msgid "Export as Playlist" msgstr "יצוא כרשימת השמעה" #: quodlibet/ext/songsmenu/playlist.py:32 msgid "Exports songs to an M3U or PLS playlist." msgstr "יצוא שירים לרשימת השמעה M3U או PLS." #: quodlibet/ext/songsmenu/playlist.py:77 msgid "Use relative paths" msgstr "שימוש בנתיבים יחסיים" #: quodlibet/ext/songsmenu/playlist.py:77 msgid "Use absolute paths" msgstr "שימוש בנתיבים מוחלטים" #: quodlibet/ext/songsmenu/playlist.py:133 #, python-format msgid "Writing to <b>%s</b> 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" #: quodlibet/ext/songsmenu/replaygain.py:407 msgid "Progress" msgstr "התקדמות" #: quodlibet/ext/songsmenu/replaygain.py:422 msgid "Gain" msgstr "הגברה" #: quodlibet/ext/songsmenu/replaygain.py:437 msgid "Peak" msgstr "שיא" #: quodlibet/ext/songsmenu/replaygain.py:452 #, python-format msgid "There is <b>%(to-process)s</b> album to update (of %(all)s)" msgid_plural "There are <b>%(to-process)s</b> 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:568 msgid "Replay Gain" msgstr "ריפליי גאיין" #: quodlibet/ext/songsmenu/replaygain.py:569 msgid "Analyzes and updates ReplayGain information, using GStreamer. Results are grouped by album." msgstr "ניתוח ועדכן מידע ריפלייגאיין באמצעות ג'סטרימר. התוצאות מקובצות לפי אלבום." #: quodlibet/ext/songsmenu/replaygain.py:607 msgid "always" msgstr "תמיד" #: quodlibet/ext/songsmenu/replaygain.py:608 msgid "if <b>any</b> RG tags are missing" msgstr "כאשר חסר תג <b>כלשהו</b> RG" #: quodlibet/ext/songsmenu/replaygain.py:610 msgid "if <b>album</b> RG tags are missing" msgstr "כאשר חסר תג <b>אלבום</b> RG" #: quodlibet/ext/songsmenu/replaygain.py:627 msgid "_Process albums:" msgstr "_עיבוד אלבומים:" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:639 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 "הקשה על BPM לקבלת קצב סיביות לדקה." #: quodlibet/ext/songsmenu/website_search.py:37 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-example)s." msgstr "" "חיפוש באתר שנבחר על פי תגי שיר.\n" "תמיכה בדפוסים, לדוגמה %(pattern-example)s." #: quodlibet/ext/songsmenu/website_search.py:80 msgid "Search URL patterns" msgstr "חיפוש דפוסי URL" #: quodlibet/ext/songsmenu/website_search.py:90 msgid "Edit search URLs" msgstr "עריכת חיפוש URLים" #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:116 msgid "Configure Searches…" msgstr "תיצור חיפוש…" #: quodlibet/ext/songsmenu/wikipedia.py:35 msgid "Search Tag in Wikipedia" msgstr "חיפוש תג בויקיפדיה" #: quodlibet/ext/songsmenu/wikipedia.py:36 msgid "Opens a browser window with the Wikipedia article on the selected song's corresponding tag." msgstr "פתיחת חלון דפדפן, עם מאמרים מויקיפדיה, על פי תגי השיר שנבחר." #: quodlibet/ext/songsmenu/wikipedia.py:56 #, python-format msgid "Search at %(website)s" msgstr "חיפוש ב %(website)s" #: quodlibet/ext/songsmenu/wikipedia.py:70 quodlibet/ext/songsmenu/wikipedia.py:76 #: quodlibet/qltk/edittags.py:443 msgid "Edit Tags" msgstr "עריכת תגים" #: quodlibet/ext/songsmenu/wikipedia.py:111 msgid "Search failed" msgstr "פעולת חיפוש כשלה" #: quodlibet/ext/songsmenu/wikipedia.py:112 #, python-format msgid "Tag \"%s\" not found." msgstr "תג \"%s\" לא נמצא." #. then (try to) load all new files #: quodlibet/library/libraries.py:651 quodlibet/library/libraries.py:661 #: quodlibet/library/libraries.py:727 quodlibet/library/libraries.py:746 #: quodlibet/qltk/information.py:272 quodlibet/qltk/prefs.py:692 quodlibet/util/library.py:123 msgid "Library" msgstr "ספריה" #: quodlibet/library/libraries.py:651 msgid "Checking mount points" msgstr "בודק מחיצות מעוגנות" #: quodlibet/library/libraries.py:661 msgid "Scanning library" msgstr "ספרית השירים נסרקת" #: quodlibet/library/libraries.py:726 #, python-format msgid "Scanning %s" msgstr "סורק %s" #: quodlibet/library/libraries.py:746 msgid "Loading files" msgstr "טעינת קבצים" #: quodlibet/main.py:50 msgid "Music player and music library manager" msgstr "מנהל ספרית מוזיקה ונגן" #: quodlibet/operon/base.py:70 #, 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:462 msgid "Print terse output" msgstr "הדפסת פלט מצומצם" #: quodlibet/operon/commands.py:43 quodlibet/operon/commands.py:82 quodlibet/operon/commands.py:464 #, 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:336 quodlibet/operon/commands.py:340 #: quodlibet/operon/commands.py:392 quodlibet/operon/commands.py:395 #: quodlibet/operon/commands.py:434 quodlibet/operon/commands.py:469 #: quodlibet/operon/commands.py:509 quodlibet/operon/commands.py:544 #: quodlibet/operon/commands.py:586 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:471 msgid "Too many arguments" msgstr "יותר מדי ארגומנטים" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:91 quodlibet/operon/commands.py:476 #: quodlibet/qltk/data_editors.py:352 msgid "Description" msgstr "תיאור" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:476 quodlibet/qltk/edittags.py:493 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:324 #: quodlibet/operon/commands.py:385 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:304 quodlibet/operon/commands.py:445 #: quodlibet/operon/commands.py:677 #, python-format msgid "Can not set %r" msgstr "%r לא ניתן להגדרה" #: quodlibet/operon/commands.py:319 msgid "Remove tags" msgstr "_הסרת תגים" #: quodlibet/operon/commands.py:326 quodlibet/operon/commands.py:387 msgid "Value is a regular expression" msgstr "ערך הוא ביטוי סדיר" #: quodlibet/operon/commands.py:328 msgid "Remove all tags" msgstr "הסרת כל התגים" #: quodlibet/operon/commands.py:332 msgid "Can't combine '--all' with '--regexp'" msgstr "לא ניתן לאחד '--all' עם '--regexp'" #: quodlibet/operon/commands.py:366 #, python-brace-format msgid "Can't remove {tagname} from {filename}" msgstr "לא ניתן להסיר {tagname} מ {filename}" #: quodlibet/operon/commands.py:380 msgid "Remove a tag value" msgstr "הסרת ערך תג" #: quodlibet/operon/commands.py:429 msgid "Add a tag value" msgstr "הוספת ערך תג" #: quodlibet/operon/commands.py:457 msgid "List file information" msgstr "הצגת נתוני קובץ" #: quodlibet/operon/commands.py:503 msgid "Set the provided image as primary embedded image and remove all other embedded images" msgstr "קביעת התמונה שסופקה כתמונה משובצת עיקרית והסרת יתר התמונות המשובצות" #: quodlibet/operon/commands.py:516 #, python-format msgid "Failed to load image file: %r" msgstr "לא ניתן לטעון קובץ תמונה: %r" #: quodlibet/operon/commands.py:523 quodlibet/operon/commands.py:552 #, 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:539 msgid "Remove all embedded images" msgstr "הסרת כל התמונות המשובצות" #: quodlibet/operon/commands.py:569 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "חילוץ תמונות משובצות ל %(filepath)s" #: quodlibet/operon/commands.py:581 msgid "Path to where the images will be saved to (defaults to the working directory)" msgstr "הנתיב למיקום בו יישמרו התמונות (ברירות מחדל למחיצת העבודה)" #: quodlibet/operon/commands.py:640 msgid "Rename files based on tags" msgstr "שינוי שמות קבצים על פי תגים" #: quodlibet/operon/commands.py:655 msgid "Fill tags based on the file path" msgstr "הזנת תגים על פי נתיב הקובץ" #: quodlibet/operon/commands.py:705 quodlibet/qltk/information.py:309 #: quodlibet/qltk/properties.py:83 quodlibet/qltk/renamefiles.py:224 #: quodlibet/qltk/tagsfrompath.py:228 quodlibet/qltk/tracknumbers.py:78 msgid "File" msgstr "קובץ" #: quodlibet/operon/commands.py:713 msgid "Fill tracknumbers for all files" msgstr "הזנת מספר רצועה בכל הקבצים" #: quodlibet/operon/commands.py:732 msgid "Print tags based on the given pattern" msgstr "הדפסת תגים על פי דפוס נתון" #: quodlibet/operon/commands.py:769 msgid "Display help information" msgstr "מַצָּג עזרה" #: quodlibet/operon/util.py:43 #, 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:30 msgid "_Unknown" msgstr "_לא ידוע" #: quodlibet/order/__init__.py:142 msgid "In Order" msgstr "לפי הסדר" #: quodlibet/order/__init__.py:143 msgid "_In Order" msgstr "לפי _סדר" #: quodlibet/order/reorder.py:22 msgid "Random" msgstr "אקראי" #: quodlibet/order/reorder.py:23 quodlibet/qltk/queue.py:147 msgid "_Random" msgstr "_אקראי" #: quodlibet/order/reorder.py:40 quodlibet/order/reorder.py:41 msgid "Prefer higher rated" msgstr "העדפת דרוג גבוהה יותר" #: quodlibet/order/repeat.py:43 quodlibet/order/repeat.py:44 msgid "Repeat this track" msgstr "חזרה על הרצועה" #: quodlibet/order/repeat.py:57 quodlibet/order/repeat.py:58 msgid "Repeat all" msgstr "חזרה על הכל" #: quodlibet/order/repeat.py:73 quodlibet/order/repeat.py:74 msgid "One Song" msgstr "שיר בודד" #: quodlibet/player/gstbe/player.py:98 msgid "Stream" msgstr "הזרמה" #: quodlibet/player/gstbe/player.py:98 msgid "Buffering" msgstr "חציצה" #: quodlibet/player/gstbe/player.py:452 msgid "Could not create GStreamer pipeline" msgstr "לא ניתן ליצר צנרת ג'סטרימר" #: quodlibet/player/gstbe/player.py:651 msgid "No GStreamer element found to handle media format" msgstr "לא נמצא רכיב ג'סטרימר לטיפול בתבנית המדיה" #: quodlibet/player/gstbe/player.py:652 #, 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:25 msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default pipeline. In case " "the pipeline contains a sink, it will be used instead of the default one." msgstr "" "פלט צנרת ג'סטרימר המשמש להשמעה. נא להשאיר ריק עבור צנרת ברירת המחדל. במידה והצנרת מחוברת ליעד, " "יעשה בה שימוש במקום בברירת המחדל." #: quodlibet/player/gstbe/prefs.py:36 msgid "_Output pipeline:" msgstr "_פלט צנרת:" #: quodlibet/player/gstbe/prefs.py:43 #, python-format msgid "%.1f seconds" msgstr "%.1f שניות" #: quodlibet/player/gstbe/prefs.py:57 msgid "_Buffer duration:" msgstr "_משך חוצץ:" #: quodlibet/player/gstbe/prefs.py:66 msgid "Disable _gapless playback" msgstr "נטרול השמעת _נטול פערים" #: quodlibet/player/gstbe/prefs.py:70 msgid "Disabling gapless playback can avoid track changing problems with some GStreamer versions" msgstr "השבתת השמעת נטול פערים עשוי למנוע בעיות בהחלפת רצועה בעלת מספר גרסאות ג'סטרימר" #: quodlibet/player/gstbe/util.py:101 msgid "No GStreamer audio sink found" msgstr "לא נמצא יעד שמע ג'סטרימר" #: quodlibet/player/gstbe/util.py:120 msgid "Invalid GStreamer output pipeline" msgstr "פלט צנרת ג'סטרימר שגויה" #: quodlibet/player/xinebe/player.py:90 msgid "Unable to create audio output" msgstr "לא ניתן ליצור פלט שמע" #: quodlibet/player/xinebe/player.py:91 #, 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:61 #, python-brace-format msgid "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "לא נמצאה פִּרְקָן '{module}'. אולי צריך להתקין את החבילה?" #: quodlibet/plugins/__init__.py:70 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "לא ניתן למצוא רכיב ג'סטרימר '{element}'." #: 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:55 quodlibet/qltk/songsmenu.py:66 msgid "_Run Plugin" 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:40 msgid "_Name:" msgstr "_שם:" #: quodlibet/qltk/cbes.py:48 quodlibet/qltk/edittags.py:350 msgid "_Value:" msgstr "_ערך:" #: quodlibet/qltk/cbes.py:263 msgid "Saved Values" msgstr "ערכים שמורים" #: quodlibet/qltk/cbes.py:264 msgid "Edit saved values…" msgstr "עריכת ערכים שמורים…" #: quodlibet/qltk/controls.py:111 msgid "Auto_matic" msgstr "אוטו_מטי" #: quodlibet/qltk/controls.py:112 msgid "_Track Mode" msgstr "_מצב רצועה" #: quodlibet/qltk/controls.py:113 msgid "_Album Mode" msgstr "_מצב אלבום" #. Translators: player state, no action #: quodlibet/qltk/controls.py:122 msgid "_Mute" msgstr "_השתקה" #: quodlibet/qltk/controls.py:128 msgid "_Replay Gain Mode" msgstr "_מצב ריפליי גאיין" #. Translators: New Command/Entry/Item/... #: quodlibet/qltk/data_editors.py:116 #, python-format msgid "New %s" msgstr "חדש %s" #: quodlibet/qltk/data_editors.py:215 msgid "(unknown)" msgstr "(לא ידוע)" #: quodlibet/qltk/data_editors.py:344 msgid "Tag expression" msgstr "ביטוי תג" #: quodlibet/qltk/data_editors.py:371 msgid "Tag expression e.g. people:real or ~album~year" msgstr "ביטוי תג לדוגמה, אנשים: אמיתי או ~album~year" #: quodlibet/qltk/data_editors.py:372 msgid "Enter new tag" 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/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:197 msgid "Split into _Multiple Values" msgstr "פיצול לערכים _מרובים" #: quodlibet/qltk/edittags.py:219 msgid "Split Disc out of _Album" msgstr "פיצול תקליטור מתוך _אלבום" #: quodlibet/qltk/edittags.py:243 msgid "Split _Version out of Title" msgstr "פיצול _גרסה מתוך שם" #: quodlibet/qltk/edittags.py:298 msgid "Split Arranger out of Ar_tist" msgstr "פיצול _אמרגן מתוך אמן" #: quodlibet/qltk/edittags.py:303 msgid "Split _Performer out of Artist" msgstr "פיצול מ_בצע מתוך אמן" #: quodlibet/qltk/edittags.py:309 msgid "Split _Performer out of Title" msgstr "פיצול _מבצע מתוך כותרת" #: quodlibet/qltk/edittags.py:315 msgid "Split _Originalartist out of Title" msgstr "פיצול _אמרגן מתוך כותרת" #: quodlibet/qltk/edittags.py:322 msgid "Add a Tag" msgstr "הוספת תג" #: quodlibet/qltk/edittags.py:341 msgid "_Tag:" msgstr "_תג:" #: quodlibet/qltk/edittags.py:516 msgid "Show _programmatic tags" msgstr "הצגת _תגים תָכנותִיים" #: quodlibet/qltk/edittags.py:517 msgid "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay Gain tags" msgstr "גישה לכל התגים, לרבות תגי ממוכנים כגון מוזיקבריינז או ריפליי גאיין" #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:547 msgctxt "edittags" msgid "_Revert" msgstr "_הסגה" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:552 msgctxt "edittags" msgid "_Save" msgstr "_שמירה" #: quodlibet/qltk/edittags.py:681 msgid "_Configure" msgstr "_תצור" #: quodlibet/qltk/edittags.py:696 msgid "_Split Tag" msgstr "_פיצול תג" #: quodlibet/qltk/edittags.py:705 msgid "_Copy Value(s)" msgstr "_העתקת ערך(כים)" #: quodlibet/qltk/edittags.py:736 msgid "Unable to add tag" msgstr "לא ניתן להוסיף תג" #: quodlibet/qltk/edittags.py:737 #, python-format msgid "Unable to add <b>%s</b>" msgstr "לא ניתן להוסיף <b>%s</b>" #: quodlibet/qltk/edittags.py:739 #, python-format msgid "The files currently selected do not support multiple values for <b>%s</b>." msgstr "הקבצים שנבחרו אינם תומכים ערכים מרובים ב <b>%s</b>." #. Can't add the new tag. #: quodlibet/qltk/edittags.py:766 quodlibet/qltk/edittags.py:947 quodlibet/qltk/tagsfrompath.py:211 #: quodlibet/util/__init__.py:505 quodlibet/util/tags.py:243 msgid "Invalid tag" msgstr "תג שגוי" #: quodlibet/qltk/edittags.py:767 quodlibet/qltk/edittags.py:948 quodlibet/qltk/tagsfrompath.py:212 #, python-format msgid "" "Invalid tag <b>%s</b>\n" "\n" "The files currently selected do not support editing this tag." msgstr "" "תג שגוי <b>%s</b>\n" "\n" "הקבצים שנבחרו אינם תומכים בעריכת התג זה." #: quodlibet/qltk/edittags.py:918 quodlibet/qltk/edittags.py:959 msgid "Invalid value" msgstr "ערך שגוי" #: quodlibet/qltk/edittags.py:919 quodlibet/qltk/edittags.py:960 #, python-format msgid "" "Invalid value: <b>%(value)s</b>\n" "\n" "%(error)s" msgstr "" "ערך שגוי: <b>%(value)s</b>\n" "\n" "%(error)s" #: quodlibet/qltk/_editutils.py:29 msgid "Tag may not be accurate" msgstr "התג עשוי להיות לא מדוייק" #: quodlibet/qltk/_editutils.py:32 #, 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:48 msgid "Unable to save song" msgstr "לא ניתן לשמור שיר" #: quodlibet/qltk/_editutils.py:51 #, 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:143 msgid "_More options…" msgstr "_אפשרויות נוספות…" #: quodlibet/qltk/entry.py:78 msgid "_Undo" msgstr "_הסגה" #: quodlibet/qltk/entry.py:80 msgid "_Redo" msgstr "_מחדש" #: quodlibet/qltk/exfalsowindow.py:94 quodlibet/qltk/quodlibetwindow.py:956 msgid "_About" msgstr "_אודות" #: quodlibet/qltk/exfalsowindow.py:98 quodlibet/qltk/quodlibetwindow.py:978 msgid "_Check for Updates…" msgstr "_בדיקת זמינות עדכונים…" #: quodlibet/qltk/exfalsowindow.py:104 quodlibet/qltk/quodlibetwindow.py:911 #: quodlibet/qltk/songsmenu.py:289 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:278 msgid "Ex Falso Preferences" msgstr "מאפייני אקס פאלסו" #: quodlibet/qltk/exfalsowindow.py:284 quodlibet/qltk/prefs.py:666 msgid "Tag Editing" 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:386 msgid "Unable to create folder" msgstr "לא ניתן ליצור תיקיה חדשה" #: quodlibet/qltk/filesel.py:403 msgid "Unable to delete folder" msgstr "לא ניתן למחוק תיקיה" #: quodlibet/qltk/filesel.py:519 quodlibet/qltk/pluginwin.py:167 msgid "Songs" msgstr "שירים" #. Translators: As in "by Artist Name" #: quodlibet/qltk/info.py:42 #, python-format msgid "by %s" msgstr "בביצוע %s" #: quodlibet/qltk/info.py:43 quodlibet/qltk/information.py:171 quodlibet/qltk/information.py:452 #, python-format msgid "Disc %s" msgstr "תקליטור %s" #: quodlibet/qltk/info.py:44 quodlibet/qltk/information.py:176 #, python-format msgid "Track %s" msgstr "רצועה %s" #: quodlibet/qltk/info.py:108 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:342 #: quodlibet/qltk/information.py:475 quodlibet/qltk/information.py:543 msgid "Information" msgstr "מידע" #: quodlibet/qltk/information.py:127 msgid "Lyrics" msgstr "תַּמְלִיל" #: quodlibet/qltk/information.py:188 quodlibet/qltk/information.py:400 #, python-format msgid "Produced by %s" msgstr "הופק על ידי %s" #: quodlibet/qltk/information.py:203 quodlibet/util/tags.py:85 msgid "artist" msgstr "אמן" #: quodlibet/qltk/information.py:204 quodlibet/qltk/information.py:573 quodlibet/util/tags.py:85 msgid "artists" msgstr "אמנים" #. for backwards compat #: quodlibet/qltk/information.py:225 quodlibet/util/tags.py:96 quodlibet/util/tags.py:124 msgid "performers" msgstr "מבצעים" #: quodlibet/qltk/information.py:239 quodlibet/qltk/information.py:252 #: quodlibet/qltk/songlistcolumns.py:276 msgid "Never" msgstr "מעולם לא" #: quodlibet/qltk/information.py:240 #, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "פעם %(n)d" msgstr[1] "%(n)d פעמים" #: quodlibet/qltk/information.py:258 quodlibet/util/tags.py:149 msgid "added" msgstr "נוספו בתאריך" #: quodlibet/qltk/information.py:259 quodlibet/util/tags.py:150 msgid "last played" msgstr "הושמעו לאחרונה" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:160 msgid "plays" msgstr "השמעות" #: quodlibet/qltk/information.py:261 quodlibet/util/tags.py:161 msgid "skips" msgstr "דולג" #: quodlibet/qltk/information.py:262 quodlibet/util/tags.py:166 msgid "rating" msgstr "דֵּרוּג" #: quodlibet/qltk/information.py:291 msgid "path" msgstr "נתיב" #: quodlibet/qltk/information.py:292 quodlibet/util/tags.py:164 msgid "length" msgstr "משך" #: quodlibet/qltk/information.py:293 msgid "format" msgstr "תבנית" #: quodlibet/qltk/information.py:294 quodlibet/util/tags.py:174 msgid "codec" msgstr "מקודד" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:175 msgid "encoding" msgstr "קידוד" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:171 msgid "bitrate" msgstr "קצב סיביות" #: quodlibet/qltk/information.py:297 quodlibet/util/tags.py:172 msgid "file size" msgstr "גודל קובץ" #: quodlibet/qltk/information.py:298 quodlibet/util/tags.py:159 msgid "modified" msgstr "שונה לאחרונה" #: quodlibet/qltk/information.py:335 msgid "Additional" msgstr "נוסף" #: quodlibet/qltk/information.py:387 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d נבחר" msgstr[1] "%d נבחרו" #: quodlibet/qltk/information.py:462 msgid "Track unavailable" msgstr "רצועה לא זמינה" #: quodlibet/qltk/information.py:468 msgid "Track List" msgstr "רשימת רצועות" #: quodlibet/qltk/information.py:500 quodlibet/qltk/information.py:590 #, 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:503 msgid "Selected Discography" msgstr "דיסקוגרפיה נבחרת" #: quodlibet/qltk/information.py:570 #, 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:598 quodlibet/util/tags.py:83 msgid "albums" msgstr "אלבומים" #: quodlibet/qltk/information.py:611 msgid "Total length:" msgstr "משך כללי:" #: quodlibet/qltk/information.py:615 msgid "Total size:" msgstr "גודל כללי:" #: quodlibet/qltk/information.py:618 msgid "Files" msgstr "קבצים" #: quodlibet/qltk/lyrics.py:36 msgid "_View online" msgstr "_צפיה מקוונת" #: quodlibet/qltk/lyrics.py:64 msgid "No lyrics found for this song." msgstr "לא נמצא תַּמְלִיל לשיר." #: quodlibet/qltk/lyrics.py:75 msgid "Searching for lyrics…" 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/msg.py:41 msgid "Discard tag changes?" msgstr "שמיטת שינויים בתג?" #: quodlibet/qltk/msg.py:42 msgid "Tags have been changed but not saved. Save these files, or revert and discard changes?" msgstr "תגים שונו אך לא נשמרו. נא לשמור שינויים, או לחזור למקור ולשמוט שינויים?" #: quodlibet/qltk/msg.py:55 quodlibet/qltk/prefs.py:628 quodlibet/qltk/prefs.py:635 #: quodlibet/qltk/textedit.py:63 quodlibet/qltk/tracknumbers.py:116 msgid "_Revert" msgstr "_הסגה" #: quodlibet/qltk/msg.py:104 msgid "File exists" msgstr "הקובץ קיים" #: quodlibet/qltk/msg.py:106 #, python-format msgid "Replace %(file-name)s?" msgstr "החלפת %(file-name)s?" #: quodlibet/qltk/msg.py:112 msgid "_Replace File" msgstr "_החלפת קובץ" #: quodlibet/qltk/notif.py:182 msgid "Active tasks" msgstr "משימות פעילות" #: quodlibet/qltk/notif.py:188 #, python-format msgid "%d tasks running" msgstr "%d משימות רצות" #: quodlibet/qltk/playorder.py:256 msgid "Toggle shuffle mode" msgstr "החלפת מצב אקראי" #: quodlibet/qltk/playorder.py:272 msgid "Toggle repeat mode" msgstr "החלפת מצב חזרה" #: quodlibet/qltk/pluginwin.py:44 msgid "Plugin Errors" msgstr "שגיאות מתקע" #: quodlibet/qltk/pluginwin.py:124 msgid "Enabled" msgstr "מאופשר" #: quodlibet/qltk/pluginwin.py:125 msgid "Disabled" msgstr "מנוטרל" #: quodlibet/qltk/pluginwin.py:131 msgid "No category" msgstr "ללא קטגוריה" #: quodlibet/qltk/pluginwin.py:169 msgid "Events" msgstr "ארועים" #: quodlibet/qltk/pluginwin.py:170 msgid "Play Order" msgstr "סדר השמעה" #: quodlibet/qltk/pluginwin.py:171 msgid "Editing" msgstr "ערכיה" #: quodlibet/qltk/pluginwin.py:173 msgid "Covers" msgstr "תמונות עטיפה" #: quodlibet/qltk/pluginwin.py:309 msgid "No plugins found." msgstr "לא נמצאו מתקעים." #: quodlibet/qltk/pluginwin.py:358 msgid "Plugins" msgstr "מתקעים" #: quodlibet/qltk/pluginwin.py:382 msgid "Filter by plugin state / tag" msgstr "סינון לפי תג /מצב מתקע" #: quodlibet/qltk/pluginwin.py:388 msgid "Filter by plugin type" msgstr "סינון לפי סוג מתקע" #: quodlibet/qltk/pluginwin.py:394 msgid "Filter by plugin name or description" msgstr "סינון לפי שם או תאור מתקע" #: quodlibet/qltk/pluginwin.py:403 msgid "Show _Errors" msgstr "הצג שגיא_ות" #: quodlibet/qltk/prefs.py:45 msgid "_Disc" msgstr "_תקליטור" #: quodlibet/qltk/prefs.py:46 msgid "_Track" msgstr "_רצועה" #: quodlibet/qltk/prefs.py:47 msgid "Grou_ping" msgstr "קי_בוץ" #: quodlibet/qltk/prefs.py:50 msgid "Al_bum" msgstr "אל_בום" #: quodlibet/qltk/prefs.py:55 msgid "_Filename" msgstr "_שם קובץ" #: quodlibet/qltk/prefs.py:57 msgid "_Length" msgstr "_משך" #: quodlibet/qltk/prefs.py:64 msgid "_Jump to playing song automatically" msgstr "_דלוג לשיר המושמע באופן אוטומטי" #: quodlibet/qltk/prefs.py:66 msgid "When the playing song changes, scroll to it in the song list" msgstr "כאשר מתחלף שיר מושמע, להציג אותו ברשימת השירים" #: quodlibet/qltk/prefs.py:82 msgid "_Others:" msgstr "_אחרים:" #: quodlibet/qltk/prefs.py:88 msgid "_Edit…" msgstr "_עריכה…" #: quodlibet/qltk/prefs.py:91 msgid "Add or remove additional column headers" msgstr "הוספה או הסרה של עמודות" #: quodlibet/qltk/prefs.py:101 msgid "Visible Columns" msgstr "עמודות מוצגות" #: quodlibet/qltk/prefs.py:104 msgid "Title includes _version" msgstr "כותרת כלולת _גרסה" #: quodlibet/qltk/prefs.py:106 msgid "Artist includes all _people" msgstr "אמן כולל את כל _האנשים" #: quodlibet/qltk/prefs.py:108 msgid "Album includes _disc subtitle" msgstr "אלבום כולל כתוביות _תקליטור" #: quodlibet/qltk/prefs.py:110 msgid "Filename includes _folder" msgstr "שם קובץ כולל _תקיה" #: quodlibet/qltk/prefs.py:123 msgid "Column Preferences" msgstr "העדפות עמודות" #: quodlibet/qltk/prefs.py:129 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "החלת התצורה הנוכחית על רשימת שירים, הוספת עמודות חדשות לסוף" #: quodlibet/qltk/prefs.py:142 quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "רשימת שירים" #: quodlibet/qltk/prefs.py:222 msgid "Edit Columns" msgstr "עריכת עמודות" #: quodlibet/qltk/prefs.py:259 msgid "Duration totals" msgstr "סך כל משך" #: quodlibet/qltk/prefs.py:271 msgid "_Global filter:" msgstr "_מסנן כללי:" #: quodlibet/qltk/prefs.py:277 msgid "Apply this query in addition to all others" msgstr "החלת שאילתה זו בנוסף לכל האחרות" #. Translators: The heading of the preference group, no action #: quodlibet/qltk/prefs.py:283 msgctxt "heading" msgid "Search" msgstr "חיפוש" #: quodlibet/qltk/prefs.py:287 quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "דפדפנים" #: quodlibet/qltk/prefs.py:293 msgid "Confirm _multiple ratings" msgstr "אישור דֵּרוּג _מרובה" #: quodlibet/qltk/prefs.py:295 msgid "Ask for confirmation before changing the rating of multiple songs at once" msgstr "בקשת אישור לפני שינוי הדֵּרוּג של שירים מרובים בו-זמנית" #: quodlibet/qltk/prefs.py:298 msgid "Enable _one-click ratings" msgstr "אפשור דרוג בהקשה _אחת" #: quodlibet/qltk/prefs.py:300 msgid "Enable rating by clicking on the rating column in the song list" msgstr "אפשור דרוג על ידי לחיצה על עמודת הדרוג ברשימת השירים" #: quodlibet/qltk/prefs.py:306 quodlibet/qltk/prefs.py:669 msgid "Ratings" msgstr "דרוג" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:312 msgid "Prefer _embedded art" msgstr "העדפת _תמונה משובצת" #: quodlibet/qltk/prefs.py:314 msgid "Choose to use artwork embedded in the audio (where available) over other sources" msgstr "בחירה בשימוש בתמונות עטיפה משובצות (ככל שהן זמינות) על פני תמונות אחרות" #: quodlibet/qltk/prefs.py:319 msgid "_Fixed image filename:" msgstr "_שם קובץ תמונה קבוע:" #: quodlibet/qltk/prefs.py:321 msgid "The single image filename to use if selected" msgstr "שם קובץ תמונה היחיד, בו יעשה שימוש, אם נבחר" #: quodlibet/qltk/prefs.py:327 msgid "The album art image file to use when forced (supports wildcards)" msgstr "קובץ תמונת עטיפת האלבום, בו יעשה שימוש, אם אולץ (תומך תווים כלליים)" #: quodlibet/qltk/prefs.py:337 msgid "Album Art" msgstr "עטיפת אלבום" #: quodlibet/qltk/prefs.py:358 msgid "Playback" msgstr "השמעה" #: quodlibet/qltk/prefs.py:363 msgid "Output Configuration" msgstr "תְּצוּרָת פלט" #: quodlibet/qltk/prefs.py:374 msgid "If no Replay Gain information is available for a song, scale the volume by this value" msgstr "אם אין מידע ריפליי גאיין זמין להשמעה, עוצמת הקול תושווה לערך זה" #: quodlibet/qltk/prefs.py:377 msgid "_Fall-back gain (dB):" msgstr "_מרווח עצמה מוצא (dB):" #: quodlibet/qltk/prefs.py:388 msgid "Scale volume for all songs by this value, as long as the result will not clip" msgstr "סולם עצמה עבור כל השירים לפי ערך זה, כל עוד התוצאה לא מקוצצת" #: quodlibet/qltk/prefs.py:391 msgid "_Pre-amp gain (dB):" msgstr "_מרווח קדם-מגבר (dB):" #: quodlibet/qltk/prefs.py:396 msgid "_Enable Replay Gain volume adjustment" msgstr "_אפשור כיוונון עוצמת ריפליי גאיין" #: quodlibet/qltk/prefs.py:421 msgid "Replay Gain Volume Adjustment" msgstr "כיוונון עוצמת ריפליי גאיין" #: quodlibet/qltk/prefs.py:428 msgid "_Continue playback on startup" msgstr "_המשך השמעה לאחר אתחול" #: quodlibet/qltk/prefs.py:430 msgid "If music is playing on shutdown, automatically start playing on next startup" msgstr "אם מושמעת מוזיקה בעת כיבוי, היא תמשיך להתנגן מיד לאחר האתחול" #: quodlibet/qltk/prefs.py:434 msgid "Startup" msgstr "אתחול" #: quodlibet/qltk/prefs.py:461 msgid "_Default rating:" msgstr "_דֵּרוּג ברירת מחדל:" #: quodlibet/qltk/prefs.py:504 msgid "Rating _scale:" msgstr "סרגל _דרוג:" #: quodlibet/qltk/prefs.py:553 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:558 msgid "_Bayesian averaging amount:" msgstr "_סכום ממוצע בייסיאני:" #: quodlibet/qltk/prefs.py:567 msgid "Save ratings and play _counts in tags" msgstr "שמירת דֵּרוּג ומספר _השמעות בתגים" #: quodlibet/qltk/prefs.py:575 msgid "_Email:" msgstr "_דואר אלקטרוני:" #: quodlibet/qltk/prefs.py:577 msgid "Ratings and play counts will be saved in tags for this email address" msgstr "הדֵּרוּג ומספר ההשמעות ישמרו בתגים עבור כותבת דוא\"ל זו" #: quodlibet/qltk/prefs.py:597 msgid "Auto-save tag changes" msgstr "שמירת שינויים אוטומטית בתגים" #: quodlibet/qltk/prefs.py:599 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "שמירת שינויים בתגים ללא בקשת אישור בעת עריכת מספר קבצים" #: quodlibet/qltk/prefs.py:608 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:618 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:631 msgid "Split _tag on:" msgstr "פיצול _תג עם:" #: quodlibet/qltk/prefs.py:638 msgid "Split _subtag on:" msgstr "פיצול תג _משנה עם:" #: quodlibet/qltk/prefs.py:663 msgid "Tags" msgstr "תגים" #: quodlibet/qltk/prefs.py:684 msgid "Updating for new ratings" msgstr "עדכונים לדרוג חדש" #: quodlibet/qltk/prefs.py:694 msgid "Scan library _on start" msgstr "סריקת ספריה _באתחול" #: quodlibet/qltk/prefs.py:704 quodlibet/qltk/quodlibetwindow.py:990 msgid "_Scan Library" msgstr "_סריקת ספריה" #: quodlibet/qltk/prefs.py:706 quodlibet/qltk/quodlibetwindow.py:1052 msgid "Check for changes in your library" msgstr "בדיקת שינויים בספרית השירים" #: quodlibet/qltk/prefs.py:711 msgid "Re_build Library" msgstr "בנ_ית הספריה מחדש" #: quodlibet/qltk/prefs.py:714 msgid "Reload all songs in your library. This can take a long time." msgstr "טעינה חוזרת של כל השירים בספריה. הפעולה עשויה לארוך זמן ממושך." #: quodlibet/qltk/prefs.py:724 msgid "Scan Directories" msgstr "סריקת מחיצות" #: quodlibet/qltk/prefs.py:730 msgid "Hidden Songs" msgstr "שירים מוסתרים" #: quodlibet/qltk/properties.py:157 quodlibet/util/collection.py:403 #, 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:104 msgid "_Queue" msgstr "_סדר השמעה" #: quodlibet/qltk/queue.py:124 msgid "Ephemeral" msgstr "בר-חלוף" #: quodlibet/qltk/queue.py:125 msgid "Remove songs from the queue after playing them" msgstr "הסרת שירים מהתור לאחר השמעתם" #: quodlibet/qltk/queue.py:133 msgid "Persistent" msgstr "התמדה" #: quodlibet/qltk/queue.py:134 msgid "Keep songs in the queue after playing them" msgstr "השארת שירים בתור לאחר השמעתם" #: quodlibet/qltk/queue.py:142 msgid "Mode" msgstr "מצב" #: quodlibet/qltk/queue.py:153 msgid "Stop at End" msgstr "עצירה בסוף" #: quodlibet/qltk/queue.py:157 msgid "_Clear Queue" msgstr "_ניקוי תור" #: quodlibet/qltk/queue.py:178 msgid "Disable queue - the queue will be ignored when playing" msgstr "נטרול התור - הנגן יתעלם מהתור בזמן ההשמעה" #: quodlibet/qltk/queue.py:290 #, 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:198 msgid "_Browse Library" msgstr "_דפדוף בספריה" #: quodlibet/qltk/quodlibetwindow.py:348 msgid "Toggle queue visibility" msgstr "החלפת מצג תור" #: quodlibet/qltk/quodlibetwindow.py:376 msgid "Playback Error" msgstr "שגיאת השמעה" #: quodlibet/qltk/quodlibetwindow.py:384 msgid "Set up library directories?" msgstr "הגדרת מחיצות בספריה?" #: quodlibet/qltk/quodlibetwindow.py:385 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "לא הוגדרה ספרית מוזיקה. האם להגדירה כעת?" #: quodlibet/qltk/quodlibetwindow.py:391 msgid "_Not Now" msgstr "_לא כעת" #: quodlibet/qltk/quodlibetwindow.py:392 msgid "_Set Up" msgstr "_הגדרות" #: quodlibet/qltk/quodlibetwindow.py:845 msgid "Unable to add songs" msgstr "לא ניתן להוסיף שיר או שירים" #: quodlibet/qltk/quodlibetwindow.py:846 quodlibet/qltk/quodlibetwindow.py:1286 #, python-format msgid "%s uses an unsupported protocol." msgstr "%s משתמש בפרוטוקול שאינו נתמך." #: quodlibet/qltk/quodlibetwindow.py:869 msgid "_Jump to Playing Song" msgstr "_דלוג לשיר מושמע" #: quodlibet/qltk/quodlibetwindow.py:876 msgid "_File" msgstr "_קובץ" #: quodlibet/qltk/quodlibetwindow.py:877 msgid "_Song" msgstr "_שיר" #: quodlibet/qltk/quodlibetwindow.py:878 msgid "_View" msgstr "_תצוגה" #: quodlibet/qltk/quodlibetwindow.py:879 msgid "_Browse" msgstr "_דפדוף" #: quodlibet/qltk/quodlibetwindow.py:880 msgid "_Control" msgstr "_בקרה" #: quodlibet/qltk/quodlibetwindow.py:881 msgid "_Help" msgstr "_עזרה" #: quodlibet/qltk/quodlibetwindow.py:887 msgid "_Add a Folder…" msgstr "_הוספת תיקיה…" #: quodlibet/qltk/quodlibetwindow.py:892 msgid "_Add a File…" msgstr "_הוספת קובץ…" #: quodlibet/qltk/quodlibetwindow.py:897 msgid "_Add a Location…" msgstr "_הוספת מיקום…" #: quodlibet/qltk/quodlibetwindow.py:926 msgid "Edit Bookmarks…" msgstr "עריכת סימניות…" #: quodlibet/qltk/quodlibetwindow.py:946 msgid "Stop After This Song" msgstr "עצירה לאחר השיר זה" #: quodlibet/qltk/quodlibetwindow.py:952 msgid "_Keyboard Shortcuts" msgstr "_קיצורי מקלדת" #: quodlibet/qltk/quodlibetwindow.py:961 msgid "Online Help" msgstr "עזרה מקוונת" #: quodlibet/qltk/quodlibetwindow.py:970 msgid "Search Help" msgstr "חיפוש עזרה" #: quodlibet/qltk/quodlibetwindow.py:1274 msgid "Add a Location" msgstr "הוספת מיקום" #: quodlibet/qltk/quodlibetwindow.py:1275 msgid "Enter the location of an audio file:" msgstr "הזנת המיקום של קובץ שמע:" #: quodlibet/qltk/quodlibetwindow.py:1280 quodlibet/qltk/quodlibetwindow.py:1285 msgid "Unable to add location" msgstr "לא ניתן להוסיף את הנתיב שצוין" #: quodlibet/qltk/quodlibetwindow.py:1281 #, python-format msgid "%s is not a valid location." msgstr "%s אינו מיקום תָקֵף." #: quodlibet/qltk/quodlibetwindow.py:1294 quodlibet/qltk/quodlibetwindow.py:1303 msgid "Add Music" msgstr "הוספת מוזיקה" #: quodlibet/qltk/quodlibetwindow.py:1294 quodlibet/qltk/scanbox.py:99 msgid "_Add Folders" msgstr "_הוספת תיקיות" #: quodlibet/qltk/quodlibetwindow.py:1301 msgid "Music Files" msgstr "קובצי מוזיקה" #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "_Add Files" msgstr "_הוספת קבצים" #: quodlibet/qltk/ratingsmenu.py:24 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "האם לשנות דרוג לכל %d השירים?" #: quodlibet/qltk/ratingsmenu.py:26 msgid "The saved ratings will be removed" msgstr "הדרוג השמור יוסר" #: quodlibet/qltk/ratingsmenu.py:27 #, python-format msgid "The rating of all selected songs will be changed to '%s'" msgstr "הדרוג לכל השירים שנבחרו ישתנה ל '%s'" #: quodlibet/qltk/ratingsmenu.py:57 quodlibet/qltk/ratingsmenu.py:111 msgid "_Remove Rating" msgstr "_הסרת דרוג" #: quodlibet/qltk/renamefiles.py:51 msgid "Replace spaces with _underscores" msgstr "החלפת _רווחים בקווים תחתיים" #: quodlibet/qltk/renamefiles.py:61 msgid "Strip _Windows-incompatible characters" msgstr "הסרת _תווים שאינם נתמכים בחלונות" #: quodlibet/qltk/renamefiles.py:79 msgid "Strip _diacritical marks" msgstr "הסרת _סִימָים דִּיאָקְרִיטִיים" #: quodlibet/qltk/renamefiles.py:90 msgid "Strip non-_ASCII characters" msgstr "ה_סרת תווים שאינם תווי ASCII" #: quodlibet/qltk/renamefiles.py:100 msgid "Use only _lowercase characters" msgstr "שימוש _באותיות קטנות בלבד" #: quodlibet/qltk/renamefiles.py:128 msgid "Rename Files" msgstr "שינוי שמות קבצים" #: quodlibet/qltk/renamefiles.py:146 quodlibet/qltk/tagsfrompath.py:115 msgid "Path Patterns" msgstr "דפוס נתיב" #: quodlibet/qltk/renamefiles.py:147 quodlibet/qltk/tagsfrompath.py:116 msgid "Edit saved patterns…" msgstr "עריכת דפוסים שמורים…" #: quodlibet/qltk/renamefiles.py:150 quodlibet/qltk/tagsfrompath.py:119 #: quodlibet/qltk/tracknumbers.py:57 msgid "_Preview" msgstr "_תצוגה מקדימה" #: quodlibet/qltk/renamefiles.py:177 msgid "File names" msgstr "שמות קובצים" #: quodlibet/qltk/renamefiles.py:187 msgid "_Move album art" msgstr "_העברת עטיפות אלבום" #: quodlibet/qltk/renamefiles.py:190 msgid "See '[albumart] filenames' config entry for image search strings" msgstr "ראו הזנות תצור של שמות קובץ [albumart] למחרוזות חיפוש תמונה" #: quodlibet/qltk/renamefiles.py:195 msgid "_Overwrite album art at target" msgstr "_דריסת עטיפת אלבום ביעד" #: quodlibet/qltk/renamefiles.py:203 msgid "_Remove empty directories" msgstr "_הסרת תיקיות ריקות" #: quodlibet/qltk/renamefiles.py:209 msgid "Album art" msgstr "עטיפת אלבום" #: quodlibet/qltk/renamefiles.py:238 msgid "New Name" msgstr "שם חדש" #: quodlibet/qltk/renamefiles.py:315 msgid "Unable to rename file" msgstr "לא ניתן לשנות שם קובץ" #: quodlibet/qltk/renamefiles.py:316 #, python-format msgid "" "Renaming <b>%(old-name)s</b> to <b>%(new-name)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." msgstr "" "שינוי שם מ <b>%(old-name)s</b> ל <b>%(new-name)s</b> כשל. יתכן ששם היעד קיים כבר או שחסרה הרשאה " "מתאימה ליצור או למחוק קובץ קודם." #: quodlibet/qltk/renamefiles.py:324 msgid "Ignore _All Errors" msgstr "להתעלם _מכל השגיאות" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: quodlibet/qltk/renamefiles.py:325 quodlibet/qltk/wlw.py:49 msgid "_Stop" msgstr "_עצירה" #: quodlibet/qltk/renamefiles.py:327 msgid "_Continue" msgstr "_להמשיך" #: quodlibet/qltk/renamefiles.py:440 msgid "Path is not absolute" msgstr "הנתיב אינו מלא" #: quodlibet/qltk/renamefiles.py:441 #, python-format msgid "" "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 ~/." msgstr "" "הדפוס\n" "\t<b>%s</b>\n" "מכיל / אך אינה מתחיל מספרית השורש. על מנת למנוע שמות תיקיה שגויים על הדפוס להתחיל מ / או מ /~." #: quodlibet/qltk/scanbox.py:47 msgid "Songs in the listed folders will be added to the library during a library refresh" msgstr "שירים בתקיות המוצגות יתווספו לספריה בעת רענונה" #: quodlibet/qltk/scanbox.py:99 msgid "Select Directories" msgstr "בחר ספריות" #: quodlibet/qltk/searchbar.py:57 msgid "Saved Searches" msgstr "ערכי חיפוש שמורים" #: quodlibet/qltk/searchbar.py:58 msgid "Edit saved searches…" msgstr "עריכת חיפושים שמורים…" #: quodlibet/qltk/searchbar.py:82 msgid "Search your library, using free text or QL queries" msgstr "חיפוש בספריה תוך שימוש במלל חופשי או שאילתות QL" #: quodlibet/qltk/searchbar.py:144 msgid "Search after _typing" msgstr "חיפוש לאחר _הקלדה" #: quodlibet/qltk/searchbar.py:147 msgid "Show search results after the user stops typing" msgstr "הצגת תוצאות חיפוש מיד לאחר סיום הקלדה" #: quodlibet/qltk/searchbar.py:215 msgid "_Limit:" msgstr "_מגבלה:" #: quodlibet/qltk/searchbar.py:228 msgid "_Weight" msgstr "_משקל" #: quodlibet/qltk/searchbar.py:355 msgid "Add query" msgstr "הוספת שאילתה" #: quodlibet/qltk/searchbar.py:356 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:375 #, python-format msgid "_Filter on %s" msgstr "_מיין לפי %s" #: quodlibet/qltk/songlist.py:1093 msgid "All _Headers" msgstr "כל _הכותרות" #: quodlibet/qltk/songlist.py:1094 msgid "_Track Headers" msgstr "_כותרות רצועות" #: quodlibet/qltk/songlist.py:1095 msgid "_Album Headers" msgstr "כ_ותרות אלבומים" #: quodlibet/qltk/songlist.py:1096 msgid "_People Headers" msgstr "כותרות _מבצעים" #: quodlibet/qltk/songlist.py:1097 msgid "_Date Headers" msgstr "כותרות ת_אריך" #: quodlibet/qltk/songlist.py:1098 msgid "_File Headers" msgstr "_כותרות קבצים" #: quodlibet/qltk/songlist.py:1099 msgid "_Production Headers" msgstr "כות_רות הפקה" #: quodlibet/qltk/songlist.py:1114 msgid "_Customize Headers…" msgstr "_כותרות מותאמת אישית…" #: quodlibet/qltk/songlist.py:1119 msgid "_Expand Column" msgstr "_הרחבת עמודה" #: quodlibet/qltk/songsmenu.py:40 #, python-format msgid "Remove track: \"%%(title)s\" from library?" msgid_plural "Remove %(count)d tracks from library?" msgstr[0] "הסרת רצועה: \"%%(title)s\" מהספריה?" msgstr[1] "הסרת רצועות: %(count)d מהספריה?" #: quodlibet/qltk/songsmenu.py:46 msgid "Remove from Library" msgstr "הסרה מהספריה" #: quodlibet/qltk/songsmenu.py:51 #, 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:62 #, 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:134 msgid "Configure Plugins…" msgstr "תיצור מתקעים…" #: quodlibet/qltk/songsmenu.py:329 msgid "Add to _Queue" msgstr "הו_ספה לתור השמעה" #: quodlibet/qltk/songsmenu.py:349 msgid "_Remove from Library…" msgstr "_הסרה מהספריה…" #: quodlibet/qltk/songsmenu.py:414 msgid "Unable to show files" msgstr "לא ניתן להציג קבצים" #: quodlibet/qltk/songsmenu.py:415 msgid "Error showing files, or no program available to show them." msgstr "שגיאה בהצגת קבצים, או שאין תכנית זמינה להציגם." #: quodlibet/qltk/songsmenu.py:422 #, python-format msgid "_Show in File Manager" msgid_plural "_Show %(total)d Files in File Manager" msgstr[0] "_הצגת קובץ במנהל הקבצים" msgstr[1] "_הצגת %(total)d קבצים במנהל הקבצים" #: quodlibet/qltk/tagsfrompath.py:46 msgid "Replace _underscores with spaces" msgstr "החלפת _קווים תחתיים ברווחים" #: quodlibet/qltk/tagsfrompath.py:56 msgid "_Title-case tags" msgstr "_החלפה לאות גדולה ראשונה בכל מילה" #: quodlibet/qltk/tagsfrompath.py:66 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<b>%s</b>\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced brackets (< / >)." msgstr "" "הדפוס\n" "\t<b>%s</b>\n" "שגוי. עשוי להכיל את אותו התג פעמיים או שהוא אינו סגור במירכאות(< / >)." #: quodlibet/qltk/tagsfrompath.py:215 msgid "Invalid tags" msgstr "תגים שגויים" #: quodlibet/qltk/tagsfrompath.py:216 #, 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" "הקבצים שנבחרו אינם תומכים בעריכת התגים אלו." #: 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:923 #, python-format msgid "and %d more…" msgstr "ו %d יותר…" #: quodlibet/qltk/wlw.py:199 msgid "Saving the songs you changed." msgstr "שמירת שירים ששונו." #: quodlibet/qltk/wlw.py:200 #, 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:233 #, 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:425 msgid "Playlists must have a name" msgstr "רשימת ההשמעה חייבת שם" #: quodlibet/util/collection.py:608 #, python-format msgid "A playlist named %s already exists." msgstr "רשימת השמעה בשם %s קיימת כבר." #: quodlibet/util/cover/built_in.py:32 msgid "Embedded album covers" msgstr "עטיפות אלבום משובצות" #: quodlibet/util/cover/built_in.py:33 msgid "Uses covers embedded into audio files." msgstr "שימוש בתמונות עטיפה משובצות בקבצים." #: quodlibet/util/cover/built_in.py:55 msgid "Filesystem cover" msgstr "עטיפת רשימת ספריות" #: quodlibet/util/cover/built_in.py:56 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:76 msgid "Display brief usage information" msgstr "הצגת מידע קצר על השימוש" #: quodlibet/util/__init__.py:78 msgid "Display version and copyright" msgstr "מצג גרסה וזכויות יוצרים" #: quodlibet/util/__init__.py:79 msgid "Print debugging information" msgstr "הדפסת נתוני ניפוי תקלים" #: quodlibet/util/__init__.py:118 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "שימוש: %(program)s %(usage)s" #: quodlibet/util/__init__.py:120 msgid "[options]" msgstr "[אפשרויות]" #: quodlibet/util/__init__.py:165 #, python-format msgid "Option %r not recognized." msgstr "אפשרות %r לא זוהתה." #: quodlibet/util/__init__.py:168 #, python-format msgid "Option %r requires an argument." msgstr "אפשרות %r צריכה ארגומנט." #: quodlibet/util/__init__.py:171 #, python-format msgid "%r is not a unique prefix." msgstr "%r אינה תחילית יִחוּדִית." #: quodlibet/util/__init__.py:347 #, python-format msgid "%d kbps" msgstr "%d קב/ש" #: quodlibet/util/__init__.py:402 #, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%s שניה" msgstr[1] "%s שניות" #: quodlibet/util/__init__.py:415 msgid "No time information" msgstr "נתוני זמן חסרים" #: quodlibet/util/__init__.py:418 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d שניה" msgstr[1] "%d שניות" #: quodlibet/util/__init__.py:419 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d דקה" msgstr[1] "%d דקות" #: quodlibet/util/__init__.py:420 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d שעה" msgstr[1] "%d שעות" #: quodlibet/util/__init__.py:421 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d יום" msgstr[1] "%d ימים" #: quodlibet/util/__init__.py:422 #, 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:514 msgctxt "check" msgid "titlecase?" msgstr "רישיות?" #: quodlibet/util/massagers.py:114 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:129 msgid "Replay Gain gains must be entered in 'x.yy dB' format." msgstr "יש להזין עצמת ריפליי גאיין בתבנית 'x.yy dB'." #: quodlibet/util/massagers.py:150 msgid "Replay Gain peaks must be entered in 'x.yy' format." msgstr "יש להזין עצמה מרבית ריפליי גאיין בתבנית 'x.yy dB'." #: quodlibet/util/massagers.py:172 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:194 msgid "MusicBrainz release status must be 'official', 'promotional', or 'bootleg'." msgstr "" "סטטוס של מוזיקבריינז יכול להיות 'official' (רשמי), 'promotional' (לצרכי קידום) או 'bootleg' (לא " "רשמי)." #: quodlibet/util/massagers.py:207 msgid "Language must be an ISO 639-2 three-letter code" msgstr "שפה חייבת להיות קוד ISO 639-2 בן שלושה תווים" #: quodlibet/util/songwrapper.py:116 msgid "Unable to edit song" msgstr "לא ניתן לערוך שיר" #: quodlibet/util/songwrapper.py:117 #, python-format msgid "" "Saving <b>%s</b> 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:151 msgid "disc" msgstr "תקליטור" #: quodlibet/util/tags.py:115 quodlibet/util/tags.py:153 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 "ארץ מקור" #. 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:130 msgid "MusicBrainz recording ID" msgstr "מזהה הקלטה מוזיקבריינז" #: quodlibet/util/tags.py:131 msgid "MusicBrainz release track ID" msgstr "מזהה מהדורת רצועה מוזיקבריינז" #: quodlibet/util/tags.py:132 msgid "MusicBrainz release ID" msgstr "מזהה רצועה מוזיקבריינז" #: quodlibet/util/tags.py:133 msgid "MusicBrainz artist ID" msgstr "מזהה אמן מוזיקבריינז" #: quodlibet/util/tags.py:134 msgid "MusicBrainz release artist ID" msgstr "מזהה מהדורת אמן מוזיקבריינז" #: quodlibet/util/tags.py:135 msgid "MusicBrainz TRM ID" msgstr "סימון TRM של מוזיקבריינז" #: quodlibet/util/tags.py:136 msgid "MusicIP PUID" msgstr "סימון PUID של MusicIP" #: quodlibet/util/tags.py:137 msgid "MusicBrainz album status" msgstr "סימון מוזיקבריינז של מצב אלבום" #: quodlibet/util/tags.py:138 msgid "MusicBrainz album type" msgstr "סימון סוג אלבום של מוזיקבריינז" #: quodlibet/util/tags.py:139 msgid "MusicBrainz release group ID" msgstr "מזהה קבוצת מהדורה מוזיקבריינז" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:142 msgid "track gain" msgstr "הגברת רצועה" #: quodlibet/util/tags.py:143 msgid "track peak" msgstr "עוצמת רצועה מקסימלית" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:145 msgid "album gain" msgstr "הגברת אלבום" #: quodlibet/util/tags.py:146 msgid "album peak" msgstr "עוצמת אלבום מקסימלית" #: quodlibet/util/tags.py:147 msgid "reference loudness" msgstr "ייחוס עוצמת קול" #: quodlibet/util/tags.py:152 msgid "discs" msgstr "תקליטורים" #: quodlibet/util/tags.py:154 msgid "tracks" msgstr "רצועות" #: quodlibet/util/tags.py:155 msgid "last started" msgstr "הושמעו לאחרונה" #: quodlibet/util/tags.py:156 msgid "full name" msgstr "שם מלא" #: quodlibet/util/tags.py:163 msgid "mount point" msgstr "נקודת עגינה" #: quodlibet/util/tags.py:165 msgid "people" msgstr "יוצרים" #: quodlibet/util/tags.py:167 msgid "year" msgstr "שנה" #: quodlibet/util/tags.py:168 msgid "original release year" msgstr "תאריך מהדורה מקורי" #: quodlibet/util/tags.py:169 msgid "bookmark" msgstr "סימניה" #: quodlibet/util/tags.py:170 msgid "bitdepth" msgstr "עומק סיביות" #: quodlibet/util/tags.py:173 msgid "file format" msgstr "תבנית קובץ" #: quodlibet/util/tags.py:176 msgid "playlists" msgstr "_רשימות השמעה" #: quodlibet/util/tags.py:177 msgid "sample rate" msgstr "קצב דגימה" #: quodlibet/util/tags.py:178 msgid "channel count" msgstr "מונה ערוצים" #. Translators: e.g. "artist (sort)" #: quodlibet/util/tags.py:268 msgid "sort" msgstr "מיון" #. Translators: e.g. "performer (roles)" #: quodlibet/util/tags.py:276 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 "" "קְווֹדְלִיבֵּט היא תכנה לניהול מוזיקה. המספקת דרכים שונות להצגת ספריית השמע, כמו גם תמיכה ברדיו מרשתת " "והזנות שמע. התכנה בעלת גמישות מרבית לעריכת תגי מטה-דטה ויכולות חיפוש." �����������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9631858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/po/hu.po����������������������������������������������������������������������������0000644�0001750�0001750�00000515143�00000000000�014101� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-05-17 18:58+0200\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" #: ../data/exfalso.appdata.xml.in.h:1 ../data/exfalso.desktop.in.h:2 msgid "Edit tags in your audio files" msgstr "Tagok szerkesztése hangfájljaidban" #: ../data/exfalso.appdata.xml.in.h:2 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/exfalso.appdata.xml.in.h:3 ../data/quodlibet.appdata.xml.in.h:3 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/exfalso.desktop.in.h:1 msgid "Audio tag editor" msgstr "Hang tag szerkesztő" #: ../data/quodlibet.appdata.xml.in.h:1 ../data/quodlibet.desktop.in.h:2 msgid "Listen to, browse, or edit your audio collection" msgstr "Hallgasd, böngészd vagy szerkeszd zenéidet" #: ../data/quodlibet.appdata.xml.in.h:2 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 "" #: ../data/quodlibet.desktop.in.h:1 msgid "Music Player" msgstr "Zenelejátszó" #: ../quodlibet/browsers/albums/main.py:168 #: ../quodlibet/browsers/covergrid/main.py:54 #, fuzzy msgid "_Title" msgstr "Cím" #: ../quodlibet/browsers/albums/main.py:169 #: ../quodlibet/browsers/covergrid/main.py:55 ../quodlibet/qltk/prefs.py:49 msgid "_Artist" msgstr "_Művész" #: ../quodlibet/browsers/albums/main.py:170 #: ../quodlibet/browsers/covergrid/main.py:56 ../quodlibet/qltk/prefs.py:54 msgid "_Date" msgstr "_Dátum" #: ../quodlibet/browsers/albums/main.py:171 #: ../quodlibet/browsers/covergrid/main.py:57 ../quodlibet/qltk/prefs.py:53 #, fuzzy msgid "_Genre" msgstr "műfaj" #: ../quodlibet/browsers/albums/main.py:172 #: ../quodlibet/browsers/covergrid/main.py:58 ../quodlibet/qltk/prefs.py:58 #: ../quodlibet/qltk/ratingsmenu.py:39 msgid "_Rating" msgstr "É_rték" #: ../quodlibet/browsers/albums/main.py:178 #: ../quodlibet/browsers/covergrid/main.py:64 #, fuzzy msgid "Sort _by…" msgstr "Rendezés dátum szerint" #: ../quodlibet/browsers/albums/main.py:199 #: ../quodlibet/browsers/covergrid/main.py:85 #: ../quodlibet/browsers/paned/prefs.py:166 #: ../quodlibet/browsers/playlists/main.py:629 #: ../quodlibet/qltk/exfalsowindow.py:109 ../quodlibet/qltk/pluginwin.py:341 #: ../quodlibet/qltk/quodlibetwindow.py:1016 #, fuzzy msgid "_Preferences" msgstr "Jellemzők" #: ../quodlibet/browsers/albums/main.py:361 msgid "Album List" msgstr "Album lista" #: ../quodlibet/browsers/albums/main.py:362 msgid "_Album List" msgstr "_Album lista" #: ../quodlibet/browsers/albums/main.py:472 #: ../quodlibet/browsers/covergrid/main.py:279 #: ../quodlibet/browsers/covergrid/main.py:488 msgid "All Albums" msgstr "Minden album" #: ../quodlibet/browsers/albums/main.py:473 #: ../quodlibet/browsers/covergrid/main.py:280 #: ../quodlibet/browsers/covergrid/main.py:489 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d album" #: ../quodlibet/browsers/albums/main.py:650 #: ../quodlibet/browsers/covergrid/main.py:467 #, 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:381 ../quodlibet/util/collection.py:245 #, 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:379 ../quodlibet/util/collection.py:249 #, 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:120 #, fuzzy msgid "Options" msgstr "[lehetőségek]" #: ../quodlibet/browsers/albums/prefs.py:74 #: ../quodlibet/browsers/covergrid/prefs.py:123 msgid "Album Display" msgstr "Album kiírás" #: ../quodlibet/browsers/albums/prefs.py:78 #: ../quodlibet/browsers/covergrid/prefs.py:127 #: ../quodlibet/browsers/media.py:39 #: ../quodlibet/browsers/playlists/prefs.py:56 #: ../quodlibet/ext/songsmenu/albumart.py:326 #: ../quodlibet/ext/songsmenu/duplicates.py:350 #: ../quodlibet/ext/songsmenu/filterall.py:48 #: ../quodlibet/qltk/bookmarks.py:101 ../quodlibet/qltk/cbes.py:93 #: ../quodlibet/qltk/data_editors.py:99 ../quodlibet/qltk/data_editors.py:324 #: ../quodlibet/qltk/exfalsowindow.py:297 ../quodlibet/qltk/pluginwin.py:79 #: ../quodlibet/qltk/pluginwin.py:427 ../quodlibet/qltk/prefs.py:707 #: ../quodlibet/qltk/textedit.py:164 ../quodlibet/update.py:148 msgid "_Close" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:55 #: ../quodlibet/browsers/audiofeeds.py:67 #: ../quodlibet/browsers/audiofeeds.py:69 #: ../quodlibet/browsers/audiofeeds.py:159 #: ../quodlibet/browsers/paned/models.py:86 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:46 #: ../quodlibet/formats/_audio.py:495 ../quodlibet/order/__init__.py:27 #: ../quodlibet/qltk/information.py:240 ../quodlibet/qltk/information.py:247 #: ../quodlibet/qltk/information.py:273 ../quodlibet/qltk/wlw.py:70 msgid "Unknown" msgstr "Ismeretlen" #: ../quodlibet/browsers/audiofeeds.py:246 msgid "New Feed" msgstr "Új forrás" #: ../quodlibet/browsers/audiofeeds.py:247 msgid "Enter the location of an audio feed:" msgstr "Add meg a hangforrás helyét:" #: ../quodlibet/browsers/audiofeeds.py:248 #: ../quodlibet/browsers/collection/prefs.py:90 #: ../quodlibet/browsers/iradio.py:341 ../quodlibet/browsers/paned/prefs.py:78 #: ../quodlibet/browsers/playlists/menu.py:96 #: ../quodlibet/browsers/playlists/util.py:52 ../quodlibet/qltk/bookmarks.py:62 #: ../quodlibet/qltk/cbes.py:55 ../quodlibet/qltk/data_editors.py:311 #: ../quodlibet/qltk/edittags.py:288 ../quodlibet/qltk/edittags.py:488 #: ../quodlibet/qltk/quodlibetwindow.py:1354 ../quodlibet/qltk/scanbox.py:61 msgid "_Add" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:265 msgid "Audio Feeds" msgstr "Hangforrások" #: ../quodlibet/browsers/audiofeeds.py:266 msgid "_Audio Feeds" msgstr "H_angforrások" #: ../quodlibet/browsers/audiofeeds.py:345 #: ../quodlibet/browsers/audiofeeds.py:350 #, fuzzy msgid "_Download…" msgstr "Letöltés" #: ../quodlibet/browsers/audiofeeds.py:359 msgid "Download Files" msgstr "Fájlok letöltése" #. Save button #: ../quodlibet/browsers/audiofeeds.py:359 #: ../quodlibet/browsers/audiofeeds.py:371 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:81 #: ../quodlibet/ext/songsmenu/albumart.py:322 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:355 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:278 #: ../quodlibet/ext/songsmenu/html.py:76 #: ../quodlibet/ext/songsmenu/lastfmsync.py:216 #: ../quodlibet/ext/songsmenu/playlist.py:51 #: ../quodlibet/ext/songsmenu/replaygain.py:365 #: ../quodlibet/ext/songsmenu/tapbpm.py:182 ../quodlibet/qltk/_editutils.py:39 #: ../quodlibet/qltk/lyrics.py:38 ../quodlibet/qltk/msg.py:52 #: ../quodlibet/qltk/renamefiles.py:168 ../quodlibet/qltk/tracknumbers.py:113 msgid "_Save" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:371 msgid "Download File" msgstr "Fájl letöltése" #: ../quodlibet/browsers/audiofeeds.py:394 #: ../quodlibet/browsers/playlists/main.py:213 #: ../quodlibet/qltk/data_editors.py:96 msgid "_New" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:454 #: ../quodlibet/browsers/audiofeeds.py:513 msgid "Unable to add feed" msgstr "Forrás hozzáadása sikertelen" #: ../quodlibet/browsers/audiofeeds.py:455 #: ../quodlibet/browsers/audiofeeds.py:514 #, fuzzy, python-format msgid "" "%s could not be added. The server may be down, or the location may not be an " "audio feed." msgstr "" "<b>%s</b> nem tölthető be. Talán a kiszolgáló áll, vagy a hely nem " "hangforrás." #. refresh button #: ../quodlibet/browsers/audiofeeds.py:462 ../quodlibet/browsers/media.py:217 #: ../quodlibet/browsers/media.py:386 ../quodlibet/qltk/filesel.py:259 #: ../quodlibet/qltk/pluginwin.py:413 #, fuzzy msgid "_Refresh" msgstr "Daltár _frissítése" #: ../quodlibet/browsers/audiofeeds.py:463 #: ../quodlibet/browsers/playlists/main.py:457 #: ../quodlibet/browsers/playlists/util.py:43 ../quodlibet/qltk/delete.py:143 #: ../quodlibet/qltk/filesel.py:256 ../quodlibet/qltk/lyrics.py:39 #: ../quodlibet/qltk/maskedbox.py:28 ../quodlibet/qltk/songsmenu.py:392 #, fuzzy msgid "_Delete" msgstr "Fájlok törlése" #: ../quodlibet/browsers/audiofeeds.py:530 msgid "" "The current audio backend does not support URLs, Audio Feeds browser " "disabled." msgstr "" #: ../quodlibet/browsers/_base.py:147 ../quodlibet/browsers/_base.py:150 msgid "Library Browser" msgstr "Daltár böngésző" #: ../quodlibet/browsers/_base.py:274 ../quodlibet/ext/songsmenu/refresh.py:30 #: ../quodlibet/qltk/exfalsowindow.py:241 ../quodlibet/qltk/information.py:542 #: ../quodlibet/qltk/maskedbox.py:68 ../quodlibet/util/collection.py:527 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d dal" #: ../quodlibet/browsers/_base.py:402 ../quodlibet/browsers/_base.py:407 #: ../quodlibet/qltk/tagsfrompath.py:194 ../quodlibet/qltk/textedit.py:141 #: ../quodlibet/util/__init__.py:622 msgid "Invalid pattern" msgstr "Hibás minta" #: ../quodlibet/browsers/collection/main.py:78 msgid "Album Collection" msgstr "" #: ../quodlibet/browsers/collection/main.py:79 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:66 #: ../quodlibet/browsers/paned/prefs.py:51 msgid "_Custom" msgstr "Egyedi" #. Remove button #: ../quodlibet/browsers/collection/prefs.py:94 #: ../quodlibet/browsers/paned/prefs.py:82 #: ../quodlibet/browsers/playlists/menu.py:97 #: ../quodlibet/ext/playlist/remove_duplicates.py:60 #: ../quodlibet/qltk/bookmarks.py:97 ../quodlibet/qltk/bookmarks.py:127 #: ../quodlibet/qltk/cbes.py:82 ../quodlibet/qltk/cbes.py:89 #: ../quodlibet/qltk/data_editors.py:81 ../quodlibet/qltk/data_editors.py:94 #: ../quodlibet/qltk/data_editors.py:301 ../quodlibet/qltk/data_editors.py:314 #: ../quodlibet/qltk/data_editors.py:322 ../quodlibet/qltk/edittags.py:494 #: ../quodlibet/qltk/edittags.py:634 ../quodlibet/qltk/maskedbox.py:48 #: ../quodlibet/qltk/maskedbox.py:88 ../quodlibet/qltk/queue.py:350 #: ../quodlibet/qltk/scanbox.py:36 ../quodlibet/qltk/scanbox.py:63 #, fuzzy msgid "_Remove" msgstr "É_rték" #: ../quodlibet/browsers/collection/prefs.py:122 #: ../quodlibet/ext/songsmenu/filterall.py:34 #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:92 #: ../quodlibet/qltk/edittags.py:431 msgid "Tag" msgstr "Tag" #: ../quodlibet/browsers/collection/prefs.py:128 msgid "Merge" msgstr "" #: ../quodlibet/browsers/collection/prefs.py:188 #, fuzzy msgid "Album Collection Preferences" msgstr "Album lista jellemzők" #: ../quodlibet/browsers/collection/prefs.py:195 #: ../quodlibet/browsers/paned/prefs.py:209 #: ../quodlibet/ext/songsmenu/editplaycount.py:45 #: ../quodlibet/ext/songsmenu/exact_rating.py:38 #: ../quodlibet/player/gstbe/prefs.py:40 ../quodlibet/qltk/prefs.py:127 #: ../quodlibet/qltk/textedit.py:65 msgid "_Apply" msgstr "" #: ../quodlibet/browsers/collection/prefs.py:198 #: ../quodlibet/browsers/paned/prefs.py:213 #: ../quodlibet/browsers/playlists/menu.py:95 #: ../quodlibet/browsers/playlists/util.py:42 #: ../quodlibet/errorreport/ui.py:108 #: ../quodlibet/ext/playlist/export_to_folder.py:37 #: ../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:44 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:281 #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:88 #: ../quodlibet/ext/songsmenu/importexport.py:35 #: ../quodlibet/ext/songsmenu/lastfmsync.py:215 #: ../quodlibet/ext/songsmenu/playlist.py:50 #: ../quodlibet/ext/songsmenu/replaygain.py:364 #: ../quodlibet/ext/songsmenu/tapbpm.py:181 ../quodlibet/plugins/playlist.py:39 #: ../quodlibet/qltk/chooser.py:184 ../quodlibet/qltk/chooser.py:205 #: ../quodlibet/qltk/chooser.py:229 ../quodlibet/qltk/chooser.py:253 #: ../quodlibet/qltk/delete.py:90 ../quodlibet/qltk/delete.py:133 #: ../quodlibet/qltk/edittags.py:287 ../quodlibet/qltk/_editutils.py:38 #: ../quodlibet/qltk/getstring.py:28 ../quodlibet/qltk/maskedbox.py:27 #: ../quodlibet/qltk/msg.py:54 ../quodlibet/qltk/msg.py:93 #: ../quodlibet/qltk/ratingsmenu.py:33 ../quodlibet/qltk/songsmenu.py:45 #: ../quodlibet/qltk/songsmenu.py:73 ../quodlibet/update.py:94 msgid "_Cancel" msgstr "" #: ../quodlibet/browsers/covergrid/main.py:125 #, fuzzy msgid "Cover Grid" msgstr "Összméret:" #: ../quodlibet/browsers/covergrid/main.py:126 #, 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:71 #, fuzzy msgid "Show \"All Albums\" Item" msgstr "Minden album" #: ../quodlibet/browsers/covergrid/prefs.py:78 msgid "Vertical Split" msgstr "" #: ../quodlibet/browsers/covergrid/prefs.py:110 #: ../quodlibet/browsers/covergrid/prefs.py:111 #, fuzzy msgid "Cover Magnification" msgstr "szervezet" #: ../quodlibet/browsers/filesystem.py:40 msgid "File System" msgstr "Fájlrendszer" #: ../quodlibet/browsers/filesystem.py:41 msgid "_File System" msgstr "_Fájlrendszer" #: ../quodlibet/browsers/filesystem.py:113 ../quodlibet/browsers/media.py:491 #: ../quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "Dalok másolása sikertelen" #: ../quodlibet/browsers/filesystem.py:114 ../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:189 msgid "_Add to Library" msgstr "Daltárhoz _adás" #: ../quodlibet/browsers/iradio.py:178 msgid "Unsupported file type" msgstr "Nem támogatott fájl típus" #: ../quodlibet/browsers/iradio.py:179 #, 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:219 ../quodlibet/browsers/iradio.py:232 #: ../quodlibet/browsers/iradio.py:810 msgid "Unable to add station" msgstr "Állomás hozzáadása sikertelen" #: ../quodlibet/browsers/iradio.py:243 ../quodlibet/browsers/iradio.py:471 msgid "Internet Radio" msgstr "Internet Rádió" #: ../quodlibet/browsers/iradio.py:243 #, fuzzy msgid "Downloading station list" msgstr "Fájlok letöltése" #: ../quodlibet/browsers/iradio.py:339 msgid "New Station" msgstr "Új állomás" #: ../quodlibet/browsers/iradio.py:340 msgid "Enter the location of an Internet radio station:" msgstr "Add meg egy Internet rádió állomás helyét:" #: ../quodlibet/browsers/iradio.py:358 msgid "Electronic" msgstr "" #: ../quodlibet/browsers/iradio.py:361 msgid "Hip Hop / Rap" msgstr "" #: ../quodlibet/browsers/iradio.py:362 msgid "Oldies" msgstr "" #: ../quodlibet/browsers/iradio.py:363 msgid "R&B" msgstr "" #: ../quodlibet/browsers/iradio.py:364 msgid "Japanese" msgstr "" #: ../quodlibet/browsers/iradio.py:365 msgid "Indian" msgstr "" #: ../quodlibet/browsers/iradio.py:367 msgid "Religious" msgstr "" #: ../quodlibet/browsers/iradio.py:369 msgid "Charts" msgstr "" #: ../quodlibet/browsers/iradio.py:370 msgid "Turkish" msgstr "" #: ../quodlibet/browsers/iradio.py:371 msgid "Reggae / Dancehall" msgstr "" #: ../quodlibet/browsers/iradio.py:372 #, fuzzy msgid "Latin" msgstr "érték" #: ../quodlibet/browsers/iradio.py:373 msgid "College Radio" msgstr "" #: ../quodlibet/browsers/iradio.py:374 msgid "Talk / News" msgstr "" #: ../quodlibet/browsers/iradio.py:375 msgid "Ambient" msgstr "" #: ../quodlibet/browsers/iradio.py:376 msgid "Jazz" msgstr "" #: ../quodlibet/browsers/iradio.py:377 ../quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "" #: ../quodlibet/browsers/iradio.py:378 ../quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "" #: ../quodlibet/browsers/iradio.py:379 msgid "Alternative" msgstr "" #: ../quodlibet/browsers/iradio.py:380 msgid "Metal" msgstr "" #: ../quodlibet/browsers/iradio.py:381 msgid "Country" msgstr "" #: ../quodlibet/browsers/iradio.py:382 msgid "News" msgstr "" #: ../quodlibet/browsers/iradio.py:383 msgid "Schlager" msgstr "" #: ../quodlibet/browsers/iradio.py:384 msgid "Funk" msgstr "" #: ../quodlibet/browsers/iradio.py:385 msgid "Indie" msgstr "" #: ../quodlibet/browsers/iradio.py:386 msgid "Blues" msgstr "" #: ../quodlibet/browsers/iradio.py:387 msgid "Soul" msgstr "" #: ../quodlibet/browsers/iradio.py:388 msgid "Lounge" msgstr "" #: ../quodlibet/browsers/iradio.py:389 msgid "Punk" msgstr "" #: ../quodlibet/browsers/iradio.py:390 msgid "Reggaeton" msgstr "" #: ../quodlibet/browsers/iradio.py:392 msgid "Slavic" msgstr "" #: ../quodlibet/browsers/iradio.py:394 msgid "Greek" msgstr "" #: ../quodlibet/browsers/iradio.py:395 msgid "Gothic" msgstr "" #: ../quodlibet/browsers/iradio.py:396 ../quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "" #: ../quodlibet/browsers/iradio.py:449 msgid "Would you like to load a list of popular radio stations?" msgstr "" #: ../quodlibet/browsers/iradio.py:455 #, fuzzy msgid "_Load Stations" msgstr "Új állomás" #: ../quodlibet/browsers/iradio.py:472 msgid "_Internet Radio" msgstr "_Internet Rádió" #: ../quodlibet/browsers/iradio.py:538 #, fuzzy msgid "_New Station…" msgstr "Új állomás" #: ../quodlibet/browsers/iradio.py:541 #, fuzzy msgid "_Update Stations" msgstr "Új állomás" #: ../quodlibet/browsers/iradio.py:568 #, fuzzy msgid "All Stations" msgstr "Új állomás" #. TODO: support for ~#rating=!None etc (#1940) #: ../quodlibet/browsers/iradio.py:572 #: ../quodlibet/browsers/soundcloud/main.py:64 msgid "Favorites" msgstr "" #: ../quodlibet/browsers/iradio.py:580 msgid "No Category" msgstr "" #: ../quodlibet/browsers/iradio.py:802 msgid "No stations found" msgstr "Nem leltem állomást" #: ../quodlibet/browsers/iradio.py:803 #, 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:811 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:828 #, fuzzy msgid "Add to Favorites" msgstr "Listához _adás" #: ../quodlibet/browsers/iradio.py:832 #, fuzzy msgid "Remove from Favorites" msgstr "Tö_rlés a listáról" #: ../quodlibet/browsers/iradio.py:932 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "%(count)d állomás" #: ../quodlibet/browsers/media.py:36 msgid "Device Properties" msgstr "Eszköz Tulajdonságok" #: ../quodlibet/browsers/media.py:52 msgid "Device:" msgstr "Eszköz:" #: ../quodlibet/browsers/media.py:54 msgid "Not mounted" msgstr "Nincs csatolva" #: ../quodlibet/browsers/media.py:55 #, fuzzy msgid "Mount point:" msgstr "Csatolási pont:" #: ../quodlibet/browsers/media.py:61 ../quodlibet/qltk/cbes.py:40 msgid "_Name:" msgstr "_Név:" #: ../quodlibet/browsers/media.py:135 msgid "Media Devices" msgstr "Média eszközök" #: ../quodlibet/browsers/media.py:136 msgid "_Media Devices" msgstr "_Média eszközök" #. eject button #: ../quodlibet/browsers/media.py:224 ../quodlibet/browsers/media.py:378 msgid "_Eject" msgstr "Kiad" #: ../quodlibet/browsers/media.py:360 #, fuzzy msgid "_Properties" msgstr "Tulajdonságok" #: ../quodlibet/browsers/media.py:365 #: ../quodlibet/browsers/playlists/main.py:464 msgid "_Rename" msgstr "Átnevez" #: ../quodlibet/browsers/media.py:461 #, fuzzy, python-format msgid "%(used-size)s used, %(free-size)s available" msgstr "<b>%s</b> használt, <b>%s</b> elérhető" #: ../quodlibet/browsers/media.py:479 #, fuzzy, python-format msgid "%s is not connected." msgstr "<b>%s</b> nincs csatlakoztatva" #: ../quodlibet/browsers/media.py:499 #, fuzzy, python-format msgid "Copying %(song)s" msgstr "<b>%s</b> másolása" #: ../quodlibet/browsers/media.py:513 ../quodlibet/browsers/media.py:529 msgid "Unable to copy song" msgstr "Dal másolása sikertelen" #: ../quodlibet/browsers/media.py:514 msgid "There is not enough free space for this song." msgstr "Nincs elég hely e dalhoz" #: ../quodlibet/browsers/media.py:526 #, fuzzy, python-format msgid "%s could not be copied." msgstr "<b>%s</b> másolása sikertelen" #: ../quodlibet/browsers/media.py:545 msgid "Unable to delete songs" msgstr "Dalok törlése meghiúsult" #: ../quodlibet/browsers/media.py:557 #, fuzzy, python-format msgid "Deleting %(song)s" msgstr "<b>%s</b> törlése" #: ../quodlibet/browsers/media.py:575 #, fuzzy, python-format msgid "%s could not be deleted." msgstr "<b>%s</b> törlése sikertelen" #: ../quodlibet/browsers/media.py:579 msgid "Unable to delete song" msgstr "A dal törlése sikertelen" #: ../quodlibet/browsers/media.py:594 #, fuzzy, python-format msgid "Ejecting %s failed." msgstr "<b>%s</b> kinyitása sikertelen" #: ../quodlibet/browsers/media.py:597 msgid "Unable to eject device" msgstr "Nem tudom kinyitni az eszközt" #: ../quodlibet/browsers/media.py:603 msgid "No device backend, Media Devices browser disabled." msgstr "" #: ../quodlibet/browsers/paned/main.py:40 ../quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "Paneles böngésző" #: ../quodlibet/browsers/paned/main.py:41 msgid "_Paned Browser" msgstr "_Paneles böngésző" #: ../quodlibet/browsers/paned/main.py:90 msgid "Select _All" msgstr "Mindent kijelöl" #: ../quodlibet/browsers/paned/models.py:104 ../quodlibet/qltk/pluginwin.py:122 #: ../quodlibet/qltk/pluginwin.py:164 msgid "All" msgstr "Minden" #: ../quodlibet/browsers/paned/prefs.py:67 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "<tt>%s</tt>" msgstr "" #: ../quodlibet/browsers/paned/prefs.py:162 msgid "_Wide Mode" msgstr "" #: ../quodlibet/browsers/paned/prefs.py:197 msgid "Paned Browser Preferences" msgstr "Paneles böngésző beállítások" #: ../quodlibet/browsers/paned/prefs.py:204 msgid "Equal pane width" msgstr "" #: ../quodlibet/browsers/playlists/main.py:48 #: ../quodlibet/browsers/playlists/main.py:575 #: ../quodlibet/qltk/pluginwin.py:168 msgid "Playlists" msgstr "Listák" #: ../quodlibet/browsers/playlists/main.py:49 msgid "_Playlists" msgstr "Listák" #: ../quodlibet/browsers/playlists/main.py:152 msgid "_Remove from Playlist" msgstr "Tö_rlés a listáról" #: ../quodlibet/browsers/playlists/main.py:215 #: ../quodlibet/browsers/playlists/main.py:576 msgid "_Import" msgstr "_Import" #: ../quodlibet/browsers/playlists/main.py:391 #: ../quodlibet/browsers/playlists/util.py:50 #: ../quodlibet/util/collection.py:570 msgid "New Playlist" msgstr "Új lista" #: ../quodlibet/browsers/playlists/main.py:413 msgid "Unable to import playlist" msgstr "Lista importálása sikertelen" #: ../quodlibet/browsers/playlists/main.py:414 msgid "Quod Libet can only import playlists in the M3U and PLS formats." msgstr "A Quod Libet csak PLS és M3U listákat tud importálni" #: ../quodlibet/browsers/playlists/main.py:565 msgid "Unable to rename playlist" msgstr "Lista átnevezése sikertelen" #: ../quodlibet/browsers/playlists/main.py:576 msgid "Import Playlist" msgstr "Listák importálása" #: ../quodlibet/browsers/playlists/menu.py:25 #, fuzzy msgid "_New Playlist…" msgstr "Új lista" #: ../quodlibet/browsers/playlists/menu.py:86 #, 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:90 #, 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:33 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "" #: ../quodlibet/browsers/playlists/util.py:35 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" #: ../quodlibet/browsers/playlists/util.py:51 #, fuzzy msgid "Enter a name for the new playlist:" msgstr "Adj nevet az új mappának:" #: ../quodlibet/browsers/playlists/util.py:102 #, 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/search.py:33 msgid "_Limit Results" msgstr "Eredmény kor_lát" #: ../quodlibet/browsers/search.py:48 msgid "Search Library" msgstr "Daltár keresése" #: ../quodlibet/browsers/search.py:49 msgid "_Search Library" msgstr "Daltár kere_sése" #: ../quodlibet/browsers/soundcloud/main.py:38 #, fuzzy msgid "Soundcloud Browser" msgstr "Paneles böngésző" #: ../quodlibet/browsers/soundcloud/main.py:39 msgid "Sound_cloud" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:59 #: ../quodlibet/qltk/searchbar.py:73 msgid "Search" msgstr "Keres" #: ../quodlibet/browsers/soundcloud/main.py:136 #, python-format msgid "Go to %s" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:380 #, fuzzy msgid "Connected" msgstr "hely" #: ../quodlibet/browsers/soundcloud/main.py:381 #, python-format msgid "Quod Libet is now connected, <b>%s</b>!" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:393 #, python-format msgid "Log out of %s" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:395 msgid "Enter code…" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:396 #, python-format msgid "Log in to %s" msgstr "" #: ../quodlibet/browsers/soundcloud/util.py:86 msgid "Soundcloud authorisation" msgstr "" #: ../quodlibet/browsers/soundcloud/util.py:87 msgid "Enter Soundcloud auth code:" msgstr "" #: ../quodlibet/cli.py:50 #, fuzzy msgid "Quod Libet is not running (add '--run' to start it)" msgstr "A Quod Libet nem fut." #: ../quodlibet/cli.py:85 msgid "a music library and player" msgstr "egy zenekönyvtár és lejátszó" #: ../quodlibet/cli.py:86 #, fuzzy msgid "[option]" msgstr "[lehetőségek]" #: ../quodlibet/cli.py:88 msgid "Print the playing song and exit" msgstr "Kiírja a most forgó dalt és kilép" #: ../quodlibet/cli.py:89 msgid "Begin playing immediately" msgstr "Lejátszás kezdése azonnal" #: ../quodlibet/cli.py:90 msgid "Don't show any windows on start" msgstr "" #: ../quodlibet/cli.py:93 msgid "Jump to next song" msgstr "Ugrás a következő dalra" #: ../quodlibet/cli.py:95 msgid "Jump to previous song or restart if near the beginning" msgstr "" #: ../quodlibet/cli.py:96 msgid "Jump to previous song" msgstr "Ugrás az előző dalra" #: ../quodlibet/cli.py:97 msgid "Start playback" msgstr "Lejátszás indítása" #: ../quodlibet/cli.py:98 msgid "Pause playback" msgstr "Lejátszás szünete" #: ../quodlibet/cli.py:99 msgid "Toggle play/pause mode" msgstr "Lejátszás/szünet váltása" #: ../quodlibet/cli.py:100 #, fuzzy msgid "Stop playback" msgstr "Lejátszás indítása" #: ../quodlibet/cli.py:101 msgid "Turn up volume" msgstr "Hang be" #: ../quodlibet/cli.py:102 msgid "Turn down volume" msgstr "Hang ki" #: ../quodlibet/cli.py:103 msgid "Print player status" msgstr "Lejátszó állapot kiírása" #: ../quodlibet/cli.py:104 msgid "Hide main window" msgstr "Főablak rejtése" #: ../quodlibet/cli.py:105 msgid "Show main window" msgstr "Főablak mutatása" #: ../quodlibet/cli.py:106 msgid "Toggle main window visibility" msgstr "Főablak mutatásának váltása" #: ../quodlibet/cli.py:107 msgid "Focus the running player" msgstr "Fókusz a futó lejátszóra" #: ../quodlibet/cli.py:108 msgid "Remove active browser filters" msgstr "Aktív böngésző szűrők törlése" #: ../quodlibet/cli.py:109 #, fuzzy msgid "Refresh and rescan library" msgstr "Daltár _frissítése" #: ../quodlibet/cli.py:110 #, fuzzy msgid "List available browsers" msgstr "Böngésző kikapcsolása" #: ../quodlibet/cli.py:111 msgid "Print the current playlist" msgstr "Mostani lista kiírása" #: ../quodlibet/cli.py:112 msgid "Print the contents of the queue" msgstr "Sor tartalmának kiírása" #: ../quodlibet/cli.py:113 #, fuzzy msgid "Print the active text query" msgstr "Sor tartalmának kiírása" #: ../quodlibet/cli.py:114 msgid "Start without plugins" msgstr "" #: ../quodlibet/cli.py:115 #, fuzzy msgid "Start Quod Libet if it isn't running" msgstr "A Quod Libet nem fut." #: ../quodlibet/cli.py:116 msgid "Exit Quod Libet" msgstr "Quod Libet bezárása" #: ../quodlibet/cli.py:121 msgid "Seek within the playing song" msgstr "Ugrás a forgó dalban" #: ../quodlibet/cli.py:121 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][ÓÓ:]PP:MM" #: ../quodlibet/cli.py:122 #, fuzzy msgid "Set or toggle shuffle mode" msgstr "Lejátszás/szünet váltása" #: ../quodlibet/cli.py:123 msgid "Turn repeat off, on, or toggle it" msgstr "Ismétlés be/ki/váltás" #: ../quodlibet/cli.py:124 msgid "Set the volume" msgstr "Hangerő beállítása" #: ../quodlibet/cli.py:125 msgid "Search your audio library" msgstr "Daltár keresése" #: ../quodlibet/cli.py:125 ../quodlibet/cli.py:137 ../quodlibet/cli.py:141 #: ../quodlibet/cli.py:143 msgid "query" msgstr "lekérés" #: ../quodlibet/cli.py:126 msgid "Play a file" msgstr "Fájl lejátszása" #: ../quodlibet/cli.py:126 ../quodlibet/cli.py:137 ../quodlibet/cli.py:143 #, fuzzy msgctxt "command" msgid "filename" msgstr "fájlnév" #: ../quodlibet/cli.py:127 msgid "Rate the playing song" msgstr "E dal értéke" #: ../quodlibet/cli.py:128 msgid "Set the current browser" msgstr "E böngésző beállítása" #: ../quodlibet/cli.py:129 #, fuzzy msgid "Stop after the playing song" msgstr "E dal értéke" #: ../quodlibet/cli.py:130 msgid "Open a new browser" msgstr "Új böngésző megnyitása" #: ../quodlibet/cli.py:131 msgid "Show or hide the queue" msgstr "Sor mutatása/rejtése" #: ../quodlibet/cli.py:133 #, fuzzy msgid "Show or hide the main song list (deprecated)" msgstr "Fő dal lista mutatása/rejtése" #: ../quodlibet/cli.py:134 msgid "Filter on a random value" msgstr "Szűrő egy véletlen értéken" #: ../quodlibet/cli.py:134 #, fuzzy msgctxt "command" msgid "tag" msgstr "Tag" #: ../quodlibet/cli.py:135 msgid "Filter on a tag value" msgstr "Szűrő egy tag értéken" #: ../quodlibet/cli.py:135 msgid "tag=value" msgstr "tag=érték" #: ../quodlibet/cli.py:136 msgid "Enqueue a file or query" msgstr "Fájl vagy lekérés a lejátszósorba" #: ../quodlibet/cli.py:138 msgid "Enqueue comma-separated files" msgstr "" #: ../quodlibet/cli.py:139 ../quodlibet/util/tags.py:147 msgid "filename" msgstr "fájlnév" #: ../quodlibet/cli.py:140 msgid "Print filenames of results of query to stdout" msgstr "" #: ../quodlibet/cli.py:142 msgid "Unqueue a file or query" msgstr "Fájl vagy lekérés törlése a sorból" #: ../quodlibet/cli.py:203 #, fuzzy, python-format msgid "Invalid argument for '%s'." msgstr "E: Rossz argumentum ehhez: '%s'." #: ../quodlibet/cli.py:204 ../quodlibet/util/__init__.py:190 #, fuzzy, python-format msgid "Try %s --help." msgstr "E: Próbáld ezt: %s --help." #: ../quodlibet/devices/_base.py:65 msgid "Unknown Device" msgstr "Ismeretlen eszköz" #: ../quodlibet/devices/__init__.py:32 #, python-format msgid "Could not import %s, which is needed for device support." msgstr "" #: ../quodlibet/devices/__init__.py:153 #, fuzzy, python-format msgid "%r is not a supported device." msgstr "E: '%s' nem egyedi előtag." #: ../quodlibet/devices/__init__.py:245 ../quodlibet/devices/__init__.py:251 #, python-format msgid "Could not find '%s'." msgstr "" #: ../quodlibet/devices/__init__.py:450 #, fuzzy msgid "Initializing device backend." msgstr "Rossz érték" #: ../quodlibet/devices/__init__.py:451 #, python-format msgid "Trying '%s'" msgstr "" #: ../quodlibet/devices/__init__.py:461 msgid "Couldn't connect to a device backend." msgstr "" #: ../quodlibet/devices/__init__.py:463 msgid "Device backend initialized." msgstr "" #: ../quodlibet/devices/storage.py:57 #, fuzzy msgid "_Filename pattern:" msgstr "_Fájlnév minta:" #: ../quodlibet/devices/storage.py:61 msgid "Copy _album covers" msgstr "_Album borítók másolása" #: ../quodlibet/devices/storage.py:65 msgid "_Remove unused covers and directories" msgstr "Nem használt borítók és mappák törlése" #: ../quodlibet/errorreport/ui.py:60 msgid "An Error Occurred" msgstr "" #: ../quodlibet/errorreport/ui.py:62 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:72 msgid "File Bug Report" msgstr "" #: ../quodlibet/errorreport/ui.py:74 ../quodlibet/errorreport/ui.py:90 msgid "Submit Error Report" msgstr "" #: ../quodlibet/errorreport/ui.py:75 msgid "Quit Program" msgstr "" #: ../quodlibet/errorreport/ui.py:76 #, fuzzy msgid "Ignore Error" msgstr "Hibák mutatása" #: ../quodlibet/errorreport/ui.py:80 msgid "Error details:" msgstr "" #: ../quodlibet/errorreport/ui.py:92 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:100 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "" #: ../quodlibet/errorreport/ui.py:109 msgid "_Send" msgstr "" #: ../quodlibet/errorreport/ui.py:115 #, fuzzy msgid "Short description…" msgstr "leírás" #: ../quodlibet/errorreport/ui.py:118 msgid "Data to be sent:" msgstr "" #: ../quodlibet/exfalso.py:34 msgid "an audio tag editor" msgstr "egy hang tag szerkesztő" #: ../quodlibet/exfalso.py:34 ../quodlibet/util/tags.py:148 msgid "directory" msgstr "könyvtár" #: ../quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "" #: ../quodlibet/ext/covers/artwork_url.py:20 msgid "" "Downloads covers linked to by the artwork_url tag.This works with the " "Soundcloud browser." msgstr "" #: ../quodlibet/ext/covers/discogs.py:25 #, fuzzy msgid "Discogs Cover Source" msgstr "MusicBrainz track ID" #: ../quodlibet/ext/covers/discogs.py:26 msgid "Downloads covers from Discogs." msgstr "" #: ../quodlibet/ext/covers/lastfm.py:22 msgid "Last.fm Cover Source" msgstr "" #: ../quodlibet/ext/covers/lastfm.py:23 msgid "Downloads covers from Last.fm's cover art archive." msgstr "" #: ../quodlibet/ext/covers/musicbrainz.py:19 #, fuzzy msgid "MusicBrainz Cover Source" msgstr "MusicBrainz track ID" #: ../quodlibet/ext/covers/musicbrainz.py:20 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:25 msgid "Kana/Kanji Simple Inverter" msgstr "" #: ../quodlibet/ext/editing/kakasi.py:26 msgid "Converts kana/kanji to romaji before renaming." msgstr "" #: ../quodlibet/ext/editing/kakasi.py:35 msgid "Romanize _Japanese text" msgstr "" #: ../quodlibet/ext/editing/kakasi.py:63 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:19 msgid "" "Allows arbitrary regex substitutions (s///) 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:69 #, fuzzy msgid "Advanced Preferences" msgstr "Paneles böngésző beállítások" #: ../quodlibet/ext/events/advanced_preferences.py:70 msgid "Allow editing of advanced config settings." msgstr "" #: ../quodlibet/ext/events/advanced_preferences.py:162 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:153 msgid "Top of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:154 msgid "Middle of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:155 msgid "Bottom of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:158 msgid "_Position:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:171 #, fuzzy msgid "_Cover size:" msgstr "Összméret:" #: ../quodlibet/ext/events/animosd/prefs.py:177 #: ../quodlibet/ext/events/lyricswindow.py:334 ../quodlibet/qltk/prefs.py:266 #, fuzzy msgid "Display" msgstr "Kijelző szerkesztése" #: ../quodlibet/ext/events/animosd/prefs.py:190 msgid "_Font:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:195 msgid "Left" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:196 msgid "Center" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:197 #, fuzzy msgid "Right" msgstr "Súly" #: ../quodlibet/ext/events/animosd/prefs.py:200 msgid "_Align text:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:206 msgid "Text" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:217 msgid "_Text:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:227 msgid "_Fill:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:232 #: ../quodlibet/ext/events/synchronizedlyrics.py:63 msgid "Colors" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:240 msgid "_Shadows" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:241 msgid "_Outline" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:242 msgid "Rou_nded Corners" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:258 msgid "_Delay:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:264 #: ../quodlibet/qltk/pluginwin.py:172 msgid "Effects" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:270 #, fuzzy msgid "Ed_it Display Pattern…" msgstr "Kijelző szerkesztése" #: ../quodlibet/ext/events/animosd/prefs.py:274 #: ../quodlibet/ext/events/trayicon/prefs.py:78 #, fuzzy msgid "Preview" msgstr "Előnézet" #: ../quodlibet/ext/events/auto_library_update.py:136 msgid "Automatic Library Update" msgstr "" #: ../quodlibet/ext/events/auto_library_update.py:137 #, python-format msgid "Keeps your library up to date with inotify. Requires %s." 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 by Brian Nelson." 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/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:97 msgid "Equalizer" msgstr "" #: ../quodlibet/ext/events/equalizer.py:98 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:132 msgid "The current backend does not support equalization." msgstr "" #: ../quodlibet/ext/events/equalizer.py:138 #, python-format msgid "%.1f kHz" msgstr "" #: ../quodlibet/ext/events/equalizer.py:139 #: ../quodlibet/ext/gstreamer/crossfeed.py:93 #: ../quodlibet/ext/gstreamer/karaoke.py:95 #, python-format msgid "%d Hz" msgstr "" #: ../quodlibet/ext/events/equalizer.py:173 #: ../quodlibet/ext/gstreamer/crossfeed.py:112 #, fuzzy, python-format msgid "%.1f dB" msgstr "%d mp." #: ../quodlibet/ext/events/equalizer.py:192 #: ../quodlibet/ext/gstreamer/crossfeed.py:31 #, fuzzy msgid "Custom" msgstr "Egyedi" #: ../quodlibet/ext/events/equalizer.py:199 #, fuzzy msgid "_Clear" msgstr "Hibák tisztitása" #. Translators: statuses relating to Instant Messenger apps #: ../quodlibet/ext/events/gajim_status.py:27 msgid "online" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:28 msgid "offline" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:29 msgid "chat" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:30 msgid "away" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:31 msgid "xa" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:32 msgid "invisible" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:37 msgid "Gajim Status Message" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:38 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:45 #: ../quodlibet/ext/events/telepathy_status.py:69 msgid "paused" 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:160 msgid "Add '[paused]'" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:163 msgid "If checked, '[paused]' will be added to status message on pause." msgstr "" #: ../quodlibet/ext/events/gajim_status.py:187 msgid "Statuses for which message will be changed" msgstr "" #: ../quodlibet/ext/events/headphonemon.py:156 msgid "Pause on Headphone Unplug" msgstr "" #: ../quodlibet/ext/events/headphonemon.py:157 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" #: ../quodlibet/ext/events/inhibit.py:41 msgid "Inhibit Screensaver" msgstr "" #: ../quodlibet/ext/events/inhibit.py:42 msgid "Prevents the GNOME screensaver from activating while a song is playing." msgstr "" #: ../quodlibet/ext/events/inhibit.py:51 #, fuzzy msgid "Music is playing" msgstr "Zenelejátszó" #: ../quodlibet/ext/events/iradiolog.py:16 #, fuzzy msgid "Internet Radio Log" msgstr "Internet Rádió" #: ../quodlibet/ext/events/iradiolog.py:17 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" #: ../quodlibet/ext/events/jep118.py:29 msgid "JEP-118" msgstr "" #: ../quodlibet/ext/events/jep118.py:30 msgid "Outputs a Jabber User Tunes file to ~/.quodlibet/jabber." 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 msgid "A restart is required for any changes to take effect" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:199 #, fuzzy msgid "No active song" msgstr "Dal mentése sikertelen" #: ../quodlibet/ext/events/lyricswindow.py:215 #, fuzzy msgid "No lyrics found" msgstr "Beillesztések nem találhatók" #: ../quodlibet/ext/events/lyricswindow.py:227 #, fuzzy msgid "Lyrics:" msgstr "Szövegek" #: ../quodlibet/ext/events/lyricswindow.py:284 msgid "_Zoom level:" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:302 msgid "URL:" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:307 msgid "Revert to default" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:322 msgid "Search via above URL if the lyrics couldn't be found in LyricsWikia." msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:339 #, fuzzy msgid "Alternate search" msgstr "Keresés törlése" #: ../quodlibet/ext/events/lyricswindow.py:347 #, fuzzy msgid "Lyrics Window" msgstr "Szövegek" #: ../quodlibet/ext/events/lyricswindow.py:348 msgid "Shows a window containing lyrics of the playing song." msgstr "" #: ../quodlibet/ext/events/mediaserver.py:38 msgid "UPnP AV Media Server" msgstr "" #: ../quodlibet/ext/events/mediaserver.py:39 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." 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:39 msgid "" "Allows control of Quod Libet using the MPRIS 1.0/2.0 D-Bus Interface " "Specification." msgstr "" #: ../quodlibet/ext/events/mpris/__init__.py:45 #: ../quodlibet/ext/events/trayicon/prefs.py:30 #, fuzzy msgid "Hide main window on close" msgstr "Főablak rejtése" #: ../quodlibet/ext/events/mpris/__init__.py:48 #: ../quodlibet/ext/events/themeswitcher.py:84 #: ../quodlibet/ext/gstreamer/compressor.py:99 #: ../quodlibet/ext/gstreamer/crossfeed.py:136 #: ../quodlibet/ext/gstreamer/karaoke.py:99 #: ../quodlibet/ext/gstreamer/pitch.py:83 ../quodlibet/qltk/prefs.py:688 #, fuzzy msgid "Preferences" msgstr "Jellemzők" #: ../quodlibet/ext/events/mqtt.py:50 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/mqtt.py:56 msgid "MQTT Publisher" msgstr "" #: ../quodlibet/ext/events/mqtt.py:57 msgid "Publishes status messages to an MQTT topic." msgstr "" #: ../quodlibet/ext/events/mqtt.py:122 msgid "Broker hostname" msgstr "" #: ../quodlibet/ext/events/mqtt.py:122 msgid "broker hostname / IP" msgstr "" #: ../quodlibet/ext/events/mqtt.py:124 msgid "Broker port" msgstr "" #: ../quodlibet/ext/events/mqtt.py:124 msgid "broker port" msgstr "" #: ../quodlibet/ext/events/mqtt.py:126 msgid "Topic" msgstr "" #: ../quodlibet/ext/events/mqtt.py:128 #, fuzzy msgid "Playing Pattern" msgstr "minta" #: ../quodlibet/ext/events/mqtt.py:130 msgid "Status text when a song is started." msgstr "" #: ../quodlibet/ext/events/mqtt.py:132 #, fuzzy msgid "Paused Pattern" msgstr "minta" #: ../quodlibet/ext/events/mqtt.py:134 msgid "Text when a song is paused." msgstr "" #: ../quodlibet/ext/events/mqtt.py:136 #, fuzzy msgid "No-song Text" msgstr "%d dal" #: ../quodlibet/ext/events/mqtt.py:138 msgid "Plain text for when there is no current song" msgstr "" #: ../quodlibet/ext/events/mqtt.py:149 #, fuzzy msgid "MQTT Configuration" msgstr "Információ" #: ../quodlibet/ext/events/mqtt.py:153 #, fuzzy msgid "Status Text" msgstr "minta" #: ../quodlibet/ext/events/mqtt.py:185 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "" #: ../quodlibet/ext/events/mqtt.py:189 #, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s" msgstr "" #: ../quodlibet/ext/events/mqtt.py:192 #, fuzzy msgid "Connection error" msgstr "hely" #: ../quodlibet/ext/events/notify.py:80 msgid "Notification text" msgstr "" #: ../quodlibet/ext/events/notify.py:88 #, fuzzy msgid "_Title:" msgstr "Cím" #: ../quodlibet/ext/events/notify.py:99 ../quodlibet/ext/events/notify.py:128 msgid "Revert to default pattern" msgstr "" #: ../quodlibet/ext/events/notify.py:118 msgid "_Body:" msgstr "" #: ../quodlibet/ext/events/notify.py:138 msgid "_Show notification" msgstr "" #: ../quodlibet/ext/events/notify.py:156 msgid "Show notifications" msgstr "" #: ../quodlibet/ext/events/notify.py:162 msgid "Only on <i>_manual</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:170 msgid "Only on <i>_automatic</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:178 msgid "On <i>a_ll</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:196 msgid "Only when the main window is not _focused" msgstr "" #: ../quodlibet/ext/events/notify.py:204 msgid "Show \"_Next\" button" msgstr "" #: ../quodlibet/ext/events/notify.py:236 msgid "Connection Error" msgstr "" #: ../quodlibet/ext/events/notify.py:237 ../quodlibet/ext/events/notify.py:391 #: ../quodlibet/ext/events/notify.py:433 msgid "Couldn't connect to notification daemon." msgstr "" #: ../quodlibet/ext/events/notify.py:251 msgid "Song Notifications" msgstr "" #: ../quodlibet/ext/events/notify.py:252 msgid "Displays a notification when the song changes." msgstr "" #: ../quodlibet/ext/events/notify.py:415 ../quodlibet/qltk/unity.py:65 msgid "Next" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:178 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:254 #, python-format msgid "Could not contact service '%s'." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:260 msgid "Authentication failed: invalid URL." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:277 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:282 msgid "Client is banned. Contact the author." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:286 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:351 msgid "AudioScrobbler Submission" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:352 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:450 msgid "Authentication successful." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:462 #, fuzzy msgid "_Service:" msgstr "Eszköz:" #: ../quodlibet/ext/events/qlscrobbler.py:462 msgid "_URL:" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:462 #, fuzzy msgid "User_name:" msgstr "_Név:" #: ../quodlibet/ext/events/qlscrobbler.py:463 msgid "_Password:" msgstr "" #. Translators: Other service #: ../quodlibet/ext/events/qlscrobbler.py:479 #, fuzzy msgid "Other…" msgstr "Más_ok:" #. verify data #: ../quodlibet/ext/events/qlscrobbler.py:517 msgid "_Verify account data" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:522 #: ../quodlibet/ext/songsmenu/lastfmsync.py:304 msgid "Account" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:530 #, fuzzy msgid "_Artist pattern:" msgstr "_Művész" #: ../quodlibet/ext/events/qlscrobbler.py:530 #, fuzzy msgid "_Title pattern:" msgstr "_Fájlnév minta:" #: ../quodlibet/ext/events/qlscrobbler.py:531 msgid "Exclude _filter:" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:549 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:559 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:568 msgid "Songs matching this filter will not be submitted." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:576 msgid "_Offline mode (don't submit anything)" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:580 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:27 #, fuzzy msgid "Random Album Playback" msgstr "Véletlen _album" #: ../quodlibet/ext/events/randomalbum.py:28 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:38 msgid "Rated higher" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:39 msgid "Played more often" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:40 msgid "Skipped more often" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:41 msgid "Played more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:42 msgid "Started more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:43 msgid "Added more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:44 #, fuzzy msgid "Longer albums" msgstr "albumok" #: ../quodlibet/ext/events/randomalbum.py:83 msgid "seconds before starting next album" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:87 #, fuzzy msgid "Weights" msgstr "Súly" #: ../quodlibet/ext/events/randomalbum.py:89 msgid "Play some albums more than others" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:103 msgid "avoid" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:114 msgid "prefer" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:201 #, fuzzy msgid "Random Album" msgstr "Véletlen _album" #: ../quodlibet/ext/events/randomalbum.py:202 #, python-format msgid "Waiting to start %s" msgstr "" #: ../quodlibet/ext/events/rbimport.py:114 #, fuzzy msgid "Import Failed" msgstr "Listák importálása" #: ../quodlibet/ext/events/rbimport.py:119 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "" #: ../quodlibet/ext/events/rbimport.py:127 msgid "Rhythmbox Import" msgstr "" #: ../quodlibet/ext/events/rbimport.py:128 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "" #: ../quodlibet/ext/events/rbimport.py:132 #, fuzzy msgid "Start Import" msgstr "_Import" #: ../quodlibet/ext/events/screensaver.py:25 msgid "Screensaver Pause" msgstr "" #: ../quodlibet/ext/events/screensaver.py:26 msgid "Pauses playback while the GNOME screensaver is active." msgstr "" #: ../quodlibet/ext/events/searchprovider.py:73 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "" #: ../quodlibet/ext/events/searchprovider.py:79 msgid "GNOME Search Provider" msgstr "" #: ../quodlibet/ext/events/searchprovider.py:80 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/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:29 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:57 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:58 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:34 #, fuzzy msgid "Synchronized Lyrics" msgstr "Szövegek" #: ../quodlibet/ext/events/synchronizedlyrics.py:35 msgid "Shows synchronized lyrics from .lrc file with same name as the track." msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:66 msgid "Text:" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:76 msgid "Background:" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:87 msgid "Font" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:90 msgid "Size (px):" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:62 msgid "Telepathy Status Messages" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:63 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:122 #, fuzzy msgid "Playing:" msgstr "Nem játszik" #: ../quodlibet/ext/events/telepathy_status.py:123 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:139 msgid "Paused:" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:140 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:156 msgid "Plain text for status when there is no current song" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:157 #, fuzzy msgid "No song:" msgstr "%d dal" #. Frame #: ../quodlibet/ext/events/telepathy_status.py:164 #, 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/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:77 #: ../quodlibet/ext/events/trayicon/prefs.py:98 #: ../quodlibet/ext/events/trayicon/systemtray.py:177 #: ../quodlibet/qltk/info.py:47 msgid "Not playing" msgstr "Nem játszik" #: ../quodlibet/ext/events/trayicon/__init__.py:53 msgid "Tray Icon" msgstr "" #: ../quodlibet/ext/events/trayicon/__init__.py:54 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:183 #: ../quodlibet/qltk/quodlibetwindow.py:1046 #: ../quodlibet/qltk/quodlibetwindow.py:1238 #, fuzzy msgid "_Play" msgstr "Listák" #: ../quodlibet/ext/events/trayicon/menu.py:63 #: ../quodlibet/qltk/quodlibetwindow.py:185 #: ../quodlibet/qltk/quodlibetwindow.py:1240 ../quodlibet/qltk/wlw.py:51 #, fuzzy msgid "P_ause" msgstr "Lejátszó" #: ../quodlibet/ext/events/trayicon/menu.py:68 #: ../quodlibet/qltk/quodlibetwindow.py:190 #: ../quodlibet/qltk/quodlibetwindow.py:1041 #, fuzzy msgid "Pre_vious" msgstr "Előnézet" #: ../quodlibet/ext/events/trayicon/menu.py:71 #: ../quodlibet/qltk/quodlibetwindow.py:194 #: ../quodlibet/qltk/quodlibetwindow.py:1051 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:1012 #, fuzzy msgid "Open _Browser" msgstr "Új böngésző megnyitása" #: ../quodlibet/ext/events/trayicon/menu.py:103 #: ../quodlibet/qltk/quodlibetwindow.py:1031 ../quodlibet/qltk/songsmenu.py:411 msgid "Edit _Tags" msgstr "_Tag szerkesztés" #: ../quodlibet/ext/events/trayicon/menu.py:112 #: ../quodlibet/qltk/quodlibetwindow.py:975 ../quodlibet/qltk/songsmenu.py:424 msgid "_Information" msgstr "_Információ" #: ../quodlibet/ext/events/trayicon/menu.py:114 #: ../quodlibet/qltk/songsmenu.py:340 #, fuzzy msgid "Play_lists" msgstr "Listák" #: ../quodlibet/ext/events/trayicon/menu.py:132 #: ../quodlibet/qltk/quodlibetwindow.py:1026 msgid "_Quit" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:32 ../quodlibet/qltk/prefs.py:69 msgid "Behavior" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:42 msgid "Scroll wheel adjusts volume" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel changes song" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll _Wheel" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:84 #, fuzzy msgid "Tooltip Display" msgstr "Kijelző szerkesztése" #: ../quodlibet/ext/events/viewlyrics.py:23 #, fuzzy msgid "View Lyrics" msgstr "Szövegek" #: ../quodlibet/ext/events/viewlyrics.py:24 msgid "Automatically displays lyrics beneath the song list in the main window." msgstr "" #: ../quodlibet/ext/events/viewlyrics.py:29 #, fuzzy msgid "_Lyrics" msgstr "Szövegek" #: ../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:406 msgid "Waveform Seek Bar" msgstr "" #: ../quodlibet/ext/events/waveformseekbar.py:410 msgid "A seekbar in the shape of the waveform of the current song." msgstr "" #: ../quodlibet/ext/events/waveformseekbar.py:443 msgid "Override foreground color:" msgstr "" #: ../quodlibet/ext/events/write_cover.py:32 msgid "Picture Saver" msgstr "" #: ../quodlibet/ext/events/write_cover.py:33 msgid "Saves the cover image of the current song to a file." msgstr "" #: ../quodlibet/ext/events/write_cover.py:66 #, fuzzy msgid "File:" msgstr "Fájlok" #: ../quodlibet/ext/gstreamer/compressor.py:20 msgid "_Threshold:" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:21 msgid "Threshold until the filter is activated" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:22 msgid "R_atio:" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:22 msgid "Compression ratio" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:74 #: ../quodlibet/ext/gstreamer/karaoke.py:91 #, python-format msgid "%d %%" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:105 msgid "Audio Compressor" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:106 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:19 #, fuzzy msgid "_Preset:" msgstr "Előnézet" #: ../quodlibet/ext/gstreamer/crossfeed.py:19 #, fuzzy msgid "Filter preset" msgstr "Szűrő a _szerzőn/előadón" #: ../quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Frequency cut:" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Low-pass filter cut frequency" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed _level:" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed level" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:25 msgid "Default" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Chu Moy" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Jan Meier" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:31 #, fuzzy msgid "Custom settings" msgstr "Egyedi" #: ../quodlibet/ext/gstreamer/crossfeed.py:152 msgid "Crossfeed" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:153 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:20 #, fuzzy msgid "Filter _band:" msgstr "Szűrő a _műfajon" #: ../quodlibet/ext/gstreamer/karaoke.py:21 msgid "The Frequency band of the filter" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:22 #, fuzzy msgid "Filter _width:" msgstr "Szűrő a _szerzőn/előadón" #: ../quodlibet/ext/gstreamer/karaoke.py:23 msgid "The Frequency width of the filter" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:24 msgid "_Level:" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:24 msgid "Level of the effect" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:105 msgid "Karaoke" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:106 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:20 msgid "R_ate:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:21 msgid "_Tempo:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:22 msgid "_Pitch:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:89 #, fuzzy msgid "Audio Pitch / Speed" msgstr "Hangforrások" #: ../quodlibet/ext/gstreamer/pitch.py:90 #, fuzzy msgid "Controls the pitch of an audio stream." msgstr "Add meg a hangforrás helyét:" #: ../quodlibet/ext/playlist/export_to_folder.py:29 #: ../quodlibet/ext/playlist/export_to_folder.py:97 #: ../quodlibet/ext/playlist/export_to_folder.py:138 #, fuzzy msgid "Export Playlist to Folder" msgstr "Listák importálása" #: ../quodlibet/ext/playlist/export_to_folder.py:38 #, fuzzy msgid "_Export" msgstr "_Import" #: ../quodlibet/ext/playlist/export_to_folder.py:43 #, fuzzy msgid "Destination folder:" msgstr "Nem leltem állomást" #: ../quodlibet/ext/playlist/export_to_folder.py:58 #, 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:156 #, fuzzy msgid "Default filename pattern:" msgstr "_Fájlnév minta:" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:23 msgid "Export to Squeezebox" msgstr "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:25 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 "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Export playlist to Squeezebox" msgstr "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:80 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 "" "Playback follows your selection, or the next song in the list once exhausted." msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:22 msgid "Playcount Equalizer" msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:23 msgid "Shuffle, preferring 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/queue.py:19 #, fuzzy msgid "Queue Only" msgstr "Lejátszósor" #: ../quodlibet/ext/playorder/queue.py:21 msgid "" "Limits playing of songs to the queue. Select this play order in the main " "window, then double-clicking any song will enqueue it instead of playing." msgstr "" #: ../quodlibet/ext/playorder/reverse.py:14 #, fuzzy msgid "Reverse" msgstr "Soha" #: ../quodlibet/ext/playorder/reverse.py:16 msgid "Reverses the play order of songs." msgstr "" #: ../quodlibet/ext/playorder/skip_songs.py:25 #, fuzzy msgid "Skip Songs" msgstr "Nincs dal" #: ../quodlibet/ext/playorder/skip_songs.py:27 msgid "" "Playback skips over songs with a rating equal or below a given threshold." msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:30 msgid "Repeat Each Track" msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:32 msgid "Shuffle songs, but repeat every track a set number of times." msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:51 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. Syntax is '@(if: " "condition, then, else)'." msgstr "" #: ../quodlibet/ext/query/pythonexpression.py:14 msgid "Python Query" msgstr "" #: ../quodlibet/ext/query/pythonexpression.py:15 msgid "" "Use Python expressions in queries. Syntax is '@(python: expression)'. The " "variable 's' is the song being matched." msgstr "" #: ../quodlibet/ext/query/savedsearch.py:19 #, fuzzy msgid "Include Saved Search" msgstr "Mentett értékek" #: ../quodlibet/ext/query/savedsearch.py:20 msgid "" "Include the results of a saved search as part of another query. Syntax is " "'@(saved: search name)'." 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:116 msgid "Port:" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:121 #, fuzzy msgid "Username:" msgstr "Átnevez" #: ../quodlibet/ext/_shared/squeezebox/base.py:126 msgid "Password:" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:130 msgid "Library directory the server connects to." msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:132 #, fuzzy msgid "Library path:" msgstr "Daltár" #. Add verify button #: ../quodlibet/ext/_shared/squeezebox/base.py:141 msgid "_Verify settings" msgstr "" #. Server settings Frame #: ../quodlibet/ext/_shared/squeezebox/base.py:147 msgid "Squeezebox Server" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:150 msgid "Debug" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:26 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:28 msgid "unidentified Squeezebox server" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:37 #, 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:20 #: ../quodlibet/ext/songsmenu/importexport.py:34 #: ../quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:329 #, fuzzy msgid "Fit image to _window" msgstr "Főablak rejtése" #. Both labels #: ../quodlibet/ext/songsmenu/albumart.py:338 msgid "_Program:" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:343 msgid "_Edit image after saving" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:345 #, fuzzy msgid "File_name:" msgstr "Fájlnév" #: ../quodlibet/ext/songsmenu/albumart.py:457 msgid "Saving failed" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:458 #, fuzzy, python-format msgid "Unable to save \"%s\"." msgstr "Dal mentése sikertelen" #: ../quodlibet/ext/songsmenu/albumart.py:556 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:613 #, fuzzy msgid "Album Art Downloader" msgstr "Album lista" #: ../quodlibet/ext/songsmenu/albumart.py:666 #, python-format msgid "from %(source)s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:669 #, python-format msgid "Resolution: %s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:672 #, fuzzy, python-format msgid "Size: %s" msgstr "Méret" #: ../quodlibet/ext/songsmenu/albumart.py:690 #, fuzzy msgid "_Search" msgstr "Kere_s:" #: ../quodlibet/ext/songsmenu/albumart.py:741 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:451 #, fuzzy msgid "Searching…" msgstr "Keres" #: ../quodlibet/ext/songsmenu/albumart.py:804 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:922 #, fuzzy msgid "Download Album Art" msgstr "Album lista" #: ../quodlibet/ext/songsmenu/albumart.py:923 msgid "Downloads album covers from various websites." msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:936 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 #: ../quodlibet/qltk/downloader.py:52 msgid "Filename" msgstr "Fájlnév" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:130 #, fuzzy msgid "Disc" msgstr "_Lemez" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:131 #: ../quodlibet/ext/songsmenu/replaygain.py:404 #: ../quodlibet/qltk/tracknumbers.py:92 msgid "Track" msgstr "Szám" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:132 #, 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:447 msgid "Please enter a query." msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:465 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:496 msgid "Error encountered. Please retry." msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:472 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:488 msgid "Loading result…" msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:475 #, fuzzy msgid "No results found." msgstr "Beillesztések nem találhatók" #: ../quodlibet/ext/songsmenu/browsefolders.py:159 #, fuzzy msgid "Browse Folders" msgstr "Böngészők" #: ../quodlibet/ext/songsmenu/browsefolders.py:160 msgid "Opens the songs' folders in a file manager." msgstr "" #: ../quodlibet/ext/songsmenu/browsefolders.py:172 #, fuzzy msgid "Unable to open folders" msgstr "Mappa létrehozása sikertelen" #: ../quodlibet/ext/songsmenu/browsefolders.py:173 msgid "No program available to open folders." msgstr "" #: ../quodlibet/ext/songsmenu/console.py:40 msgid "Python Console" msgstr "" #: ../quodlibet/ext/songsmenu/console.py:41 msgid "Interactive Python console." msgstr "" #: ../quodlibet/ext/songsmenu/console.py:72 msgid "You can access the following objects by default:" msgstr "" #: ../quodlibet/ext/songsmenu/console.py:82 msgid "Your current working directory is:" 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:55 #, fuzzy msgid "pattern" msgstr "Hibás minta" #: ../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:91 #, fuzzy msgid "Input value" msgstr "Rossz érték" #: ../quodlibet/ext/songsmenu/custom_commands.py:92 #, python-format msgid "Value for %s?" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:136 #, fuzzy msgid "Custom Commands" msgstr "Egyedi" #: ../quodlibet/ext/songsmenu/custom_commands.py:137 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:188 #: ../quodlibet/ext/songsmenu/custom_commands.py:198 #: ../quodlibet/ext/songsmenu/custom_commands.py:252 msgid "Edit Custom Commands" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:199 msgid "" "Supports QL patterns\n" "eg <tt><~artist~title></tt>" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:283 #, fuzzy, python-format msgid "Unable to run custom command %s" msgstr "Dalok másolása sikertelen" #: ../quodlibet/ext/songsmenu/duplicates.py:290 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "" #: ../quodlibet/ext/songsmenu/duplicates.py:343 msgid "Collapse / Expand all" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:347 #, python-format msgid "Duplicate key expression is '%s'" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:363 #, fuzzy msgid "Duplicates Browser" msgstr "Böngésző kikapcsolása" #: ../quodlibet/ext/songsmenu/duplicates.py:364 msgid "Finds and displays similarly tagged versions of songs." msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:407 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:409 msgid "_Group duplicates by:" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:414 msgid "Duplicate Key" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:419 msgid "Remove _Whitespace" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:420 #, fuzzy msgid "Remove _Diacritics" msgstr "É_rték" #: ../quodlibet/ext/songsmenu/duplicates.py:421 #, fuzzy msgid "Remove _Punctuation" msgstr "É_rték" #: ../quodlibet/ext/songsmenu/duplicates.py:422 msgid "Case _Insensitive" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:430 msgid "Matching options" msgstr "" #. Create a dialog. #: ../quodlibet/ext/songsmenu/editplaycount.py:19 #: ../quodlibet/ext/songsmenu/editplaycount.py:41 #, fuzzy msgid "Edit Playcount" msgstr "Kijelző szerkesztése" #: ../quodlibet/ext/songsmenu/editplaycount.py:20 msgid "" "Edit a song's ~#playcount and ~#skipcount.\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's ~#playcount to 0, the ~#lastplayed and ~#laststarted " "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:68 msgid "Play Count" msgstr "" #: ../quodlibet/ext/songsmenu/editplaycount.py:69 msgid "Skip Count" msgstr "" #: ../quodlibet/ext/songsmenu/embedded.py:24 msgid "Edit Embedded Images" msgstr "" #: ../quodlibet/ext/songsmenu/embedded.py:25 msgid "Removes or replaces embedded images." msgstr "" #: ../quodlibet/ext/songsmenu/embedded.py:78 #, fuzzy msgid "_Remove all Images" msgstr "É_rték" #: ../quodlibet/ext/songsmenu/embedded.py:82 msgid "_Embed Current 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:41 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 #: ../quodlibet/qltk/downloader.py:67 #, 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" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" 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 "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:49 msgid "Generating fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:63 msgid "_Details" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:85 msgid "_Submit" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:115 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:118 msgid "Fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Songs with MBIDs:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with sufficient tags:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs to submit:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:162 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:178 msgid "Submitting fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:186 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/id3tlen.py:21 msgid "Fix MP3 Duration" msgstr "" #: ../quodlibet/ext/songsmenu/id3tlen.py:22 msgid "" "Removes TLEN frames from ID3 tags which can be the cause for invalid song " "durations." msgstr "" #: ../quodlibet/ext/songsmenu/ifp.py:20 msgid "Send to iFP" msgstr "" #: ../quodlibet/ext/songsmenu/ifp.py:21 msgid "Uploads songs to an iRiver iFP device." msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:51 msgid "Export Metadata" msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:52 msgid "Exports metadata of selected songs as a .tags file." msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:92 #, fuzzy msgid "Import Metadata" msgstr "Listák importálása" #: ../quodlibet/ext/songsmenu/importexport.py:93 msgid "Imports metadata for selected songs from a .tags file." msgstr "" #: ../quodlibet/ext/songsmenu/k3b.py:23 msgid "Burn CD" msgstr "" #: ../quodlibet/ext/songsmenu/k3b.py:24 msgid "Burns CDs with K3b, Brasero or xfburn." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:96 msgid "Updating chart list." msgstr "" #. No charts to fetch, no update scheduled. #: ../quodlibet/ext/songsmenu/lastfmsync.py:114 msgid "Already up-to-date." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:121 #, python-format msgid "Fetching chart for week of %s." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:143 msgid "Sync complete." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:149 msgid "Error during sync" msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:214 #: ../quodlibet/ext/songsmenu/lastfmsync.py:244 msgid "Last.fm Sync" msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:245 msgid "Updates your library's statistics from your Last.fm profile." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:293 #, 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 "" #. Create a dialog. #: ../quodlibet/ext/songsmenu/migratemetadata.py:29 #: ../quodlibet/ext/songsmenu/migratemetadata.py:38 #, fuzzy msgid "Migrate Metadata" msgstr "Listák importálása" #: ../quodlibet/ext/songsmenu/migratemetadata.py:32 msgid "Copies the quodlibet-specific metadata between songs." msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:45 msgid "_Copy" msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:47 msgid "_Paste" msgstr "" #. Create the tag table. #: ../quodlibet/ext/songsmenu/migratemetadata.py:57 #, fuzzy msgid "Information to copy/paste" msgstr "Információ" #. Create the indexing box. #: ../quodlibet/ext/songsmenu/migratemetadata.py:79 msgid "Map tracks by disc and track number" msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:80 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 "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:96 #, python-format msgid "There is %d stored track." msgid_plural "There are %d stored tracks." msgstr[0] "" #: ../quodlibet/ext/songsmenu/playlist.py:31 #, fuzzy msgid "Export as Playlist" msgstr "Listák importálása" #: ../quodlibet/ext/songsmenu/playlist.py:32 msgid "Exports songs to an M3U or PLS playlist." msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:77 msgid "Use relative paths" msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:77 msgid "Use absolute paths" msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:132 #, fuzzy msgid "Unable to export playlist" msgstr "Lista importálása sikertelen" #: ../quodlibet/ext/songsmenu/playlist.py:133 #, fuzzy, python-format msgid "Writing to <b>%s</b> 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:362 msgid "ReplayGain Analyzer" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:418 msgid "Progress" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:433 msgid "Gain" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:448 msgid "Peak" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:463 #, python-format msgid "There is <b>%(to-process)s</b> album to update (of %(all)s)" msgid_plural "There are <b>%(to-process)s</b> albums to update (of %(all)s)" msgstr[0] "" #: ../quodlibet/ext/songsmenu/replaygain.py:578 msgid "Replay Gain" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:579 msgid "" "Analyzes and updates ReplayGain information, using GStreamer. Results are " "grouped by album." msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:617 msgid "always" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:618 msgid "if <b>any</b> RG tags are missing" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:620 msgid "if <b>album</b> RG tags are missing" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:637 msgid "_Process albums:" msgstr "" #. Server settings Frame #: ../quodlibet/ext/songsmenu/replaygain.py:649 #, 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 "" #. TRANSLATORS: BPM mean "beats per minute" #: ../quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "" #: ../quodlibet/ext/songsmenu/tapbpm.py:32 #: ../quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" 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:172 #: ../quodlibet/ext/songsmenu/tapbpm.py:179 msgid "Tap BPM" msgstr "" #: ../quodlibet/ext/songsmenu/tapbpm.py:173 #, fuzzy msgid "Tap BPM for the selected song." msgstr "Dalok törlése meghiúsult" #: ../quodlibet/ext/songsmenu/website_search.py:35 #, fuzzy msgid "Website Search" msgstr "Keres" #: ../quodlibet/ext/songsmenu/website_search.py:36 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern-example)s." msgstr "" #: ../quodlibet/ext/songsmenu/website_search.py:78 #, fuzzy msgid "Search URL patterns" msgstr "minta" #: ../quodlibet/ext/songsmenu/website_search.py:88 #, fuzzy msgid "Edit search URLs" msgstr "Mentett értékek szerkesztése..." #. Add link to editor #: ../quodlibet/ext/songsmenu/website_search.py:114 #, fuzzy msgid "Configure Searches…" msgstr "Színes kere_ső kifejezések" #: ../quodlibet/ext/songsmenu/wikipedia.py:46 #, python-format msgid "Search at %(website)s" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:63 msgid "Search Artist in Wikipedia" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:64 msgid "" "Opens a browser window with Wikipedia article on the playing song artist." msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:71 msgid "Search Album in Wikipedia" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:72 msgid "" "Opens a browser window with Wikipedia article on the playing song album." msgstr "" #. then (try to) load all new files #: ../quodlibet/library/libraries.py:650 ../quodlibet/library/libraries.py:660 #: ../quodlibet/library/libraries.py:726 ../quodlibet/library/libraries.py:745 #: ../quodlibet/qltk/information.py:268 ../quodlibet/qltk/prefs.py:639 #: ../quodlibet/util/library.py:124 msgid "Library" msgstr "Daltár" #: ../quodlibet/library/libraries.py:650 msgid "Checking mount points" msgstr "Csatolási pontok ellenőrzése" #: ../quodlibet/library/libraries.py:660 msgid "Scanning library" msgstr "Daltár átnézése" #: ../quodlibet/library/libraries.py:725 #, python-format msgid "Scanning %s" msgstr "%s átnézése" #: ../quodlibet/library/libraries.py:745 msgid "Loading files" msgstr "" #: ../quodlibet/operon/base.py:70 #, python-format msgid "Failed to load file: %r" msgstr "" #: ../quodlibet/operon/commands.py:37 msgid "List tags" msgstr "" #: ../quodlibet/operon/commands.py:42 ../quodlibet/operon/commands.py:81 #: ../quodlibet/operon/commands.py:461 msgid "Print terse output" msgstr "" #: ../quodlibet/operon/commands.py:44 ../quodlibet/operon/commands.py:83 #: ../quodlibet/operon/commands.py:463 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "" #: ../quodlibet/operon/commands.py:47 ../quodlibet/operon/commands.py:86 #, fuzzy msgid "Also list programmatic tags" msgstr "_Programozható tagok mutatása" #: ../quodlibet/operon/commands.py:51 ../quodlibet/operon/commands.py:129 #: ../quodlibet/operon/commands.py:220 ../quodlibet/operon/commands.py:293 #: ../quodlibet/operon/commands.py:336 ../quodlibet/operon/commands.py:340 #: ../quodlibet/operon/commands.py:391 ../quodlibet/operon/commands.py:394 #: ../quodlibet/operon/commands.py:433 ../quodlibet/operon/commands.py:468 #: ../quodlibet/operon/commands.py:508 ../quodlibet/operon/commands.py:543 #: ../quodlibet/operon/commands.py:585 msgid "Not enough arguments" msgstr "" #: ../quodlibet/operon/commands.py:53 ../quodlibet/operon/commands.py:90 #: ../quodlibet/operon/commands.py:131 ../quodlibet/operon/commands.py:222 #: ../quodlibet/operon/commands.py:470 msgid "Too many arguments" msgstr "" #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:92 #: ../quodlibet/operon/commands.py:475 ../quodlibet/qltk/data_editors.py:363 #, fuzzy msgid "Description" msgstr "leírás" #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:475 #: ../quodlibet/qltk/edittags.py:454 msgid "Value" msgstr "Érték" #: ../quodlibet/operon/commands.py:76 msgid "List all common tags" msgstr "" #: ../quodlibet/operon/commands.py:118 msgid "Copy tags from one file to another" msgstr "" #: ../quodlibet/operon/commands.py:123 ../quodlibet/operon/commands.py:164 #: ../quodlibet/operon/commands.py:289 ../quodlibet/operon/commands.py:324 #: ../quodlibet/operon/commands.py:384 msgid "Show changes, don't apply them" msgstr "" #: ../quodlibet/operon/commands.py:125 msgid "Skip tags that can't be written" msgstr "" #: ../quodlibet/operon/commands.py:145 #, python-format msgid "Can't copy tag %r to file: %r" 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:304 ../quodlibet/operon/commands.py:444 #: ../quodlibet/operon/commands.py:676 #, python-format msgid "Can not set %r" msgstr "" #: ../quodlibet/operon/commands.py:319 msgid "Remove tags" msgstr "" #: ../quodlibet/operon/commands.py:326 ../quodlibet/operon/commands.py:386 msgid "Value is a regular expression" msgstr "" #: ../quodlibet/operon/commands.py:328 msgid "Remove all tags" msgstr "" #: ../quodlibet/operon/commands.py:332 msgid "Can't combine '--all' with '--regexp'" msgstr "" #: ../quodlibet/operon/commands.py:366 #, python-format msgid "Can't remove %r from %r" msgstr "" #: ../quodlibet/operon/commands.py:379 #, fuzzy msgid "Remove a tag value" msgstr "Szűrő egy tag értéken" #: ../quodlibet/operon/commands.py:428 #, fuzzy msgid "Add a tag value" msgstr "Szűrő egy tag értéken" #: ../quodlibet/operon/commands.py:456 #, fuzzy msgid "List file information" msgstr "Nincs idő adat" #: ../quodlibet/operon/commands.py:502 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" #: ../quodlibet/operon/commands.py:515 #, fuzzy, python-format msgid "Failed to load image file: %r" msgstr "Fájl átnevezése sikertelen" #: ../quodlibet/operon/commands.py:522 ../quodlibet/operon/commands.py:551 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" #: ../quodlibet/operon/commands.py:538 msgid "Remove all embedded images" msgstr "" #: ../quodlibet/operon/commands.py:568 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "" #: ../quodlibet/operon/commands.py:580 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" #: ../quodlibet/operon/commands.py:639 msgid "Rename files based on tags" msgstr "" #: ../quodlibet/operon/commands.py:654 msgid "Fill tags based on the file path" msgstr "" #: ../quodlibet/operon/commands.py:704 ../quodlibet/qltk/information.py:305 #: ../quodlibet/qltk/properties.py:84 ../quodlibet/qltk/renamefiles.py:176 #: ../quodlibet/qltk/tagsfrompath.py:229 ../quodlibet/qltk/tracknumbers.py:79 msgid "File" msgstr "Fájl" #: ../quodlibet/operon/commands.py:712 msgid "Fill tracknumbers for all files" msgstr "" #: ../quodlibet/operon/commands.py:731 msgid "Print tags based on the given pattern" msgstr "" #: ../quodlibet/operon/commands.py:768 #, fuzzy msgid "Display help information" msgstr "Kiírja a tömör útmutatót" #: ../quodlibet/operon/util.py:40 #, 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:30 #, fuzzy msgid "_Unknown" msgstr "Ismeretlen" #: ../quodlibet/order/__init__.py:142 msgid "In Order" msgstr "Sorban" #: ../quodlibet/order/__init__.py:143 msgid "_In Order" msgstr "_Sorban" #: ../quodlibet/order/reorder.py:23 #, fuzzy msgid "Random" msgstr "Véletlen" #: ../quodlibet/order/reorder.py:24 ../quodlibet/qltk/queue.py:119 msgid "_Random" msgstr "Véletlen" #: ../quodlibet/order/reorder.py:39 ../quodlibet/order/reorder.py:40 msgid "Prefer higher rated" msgstr "" #: ../quodlibet/order/repeat.py:43 ../quodlibet/order/repeat.py:44 msgid "Repeat this track" msgstr "" #: ../quodlibet/order/repeat.py:57 ../quodlibet/order/repeat.py:58 #, fuzzy msgid "Repeat all" msgstr "Ismétlés" #: ../quodlibet/order/repeat.py:73 ../quodlibet/order/repeat.py:74 msgid "One Song" msgstr "Egy dal" #: ../quodlibet/player/gstbe/player.py:98 msgid "Stream" msgstr "" #: ../quodlibet/player/gstbe/player.py:98 msgid "Buffering" msgstr "" #: ../quodlibet/player/gstbe/player.py:319 msgid "Could not create GStreamer pipeline" msgstr "" #: ../quodlibet/player/gstbe/player.py:560 msgid "No GStreamer element found to handle media format" msgstr "" #: ../quodlibet/player/gstbe/player.py:561 #, 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:25 msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. In case the pipeline contains a sink, it will be used instead of " "the default one." msgstr "" #: ../quodlibet/player/gstbe/prefs.py:36 msgid "_Output pipeline:" msgstr "" #: ../quodlibet/player/gstbe/prefs.py:43 #, fuzzy, python-format msgid "%.1f seconds" msgstr "%d mp." #: ../quodlibet/player/gstbe/prefs.py:57 msgid "_Buffer duration:" msgstr "" #: ../quodlibet/player/gstbe/prefs.py:66 msgid "Disable _gapless playback" msgstr "" #: ../quodlibet/player/gstbe/prefs.py:70 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions." msgstr "" #: ../quodlibet/player/gstbe/util.py:93 #, fuzzy msgid "No GStreamer audio sink found" msgstr "Nem leltem állomást" #: ../quodlibet/player/gstbe/util.py:112 msgid "Invalid GStreamer output pipeline" msgstr "" #: ../quodlibet/player/xinebe/player.py:90 #, fuzzy msgid "Unable to create audio output" msgstr "Mappa létrehozása sikertelen" #: ../quodlibet/player/xinebe/player.py:91 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "" #: ../quodlibet/plugins/__init__.py:62 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" #: ../quodlibet/plugins/__init__.py:71 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "" #: ../quodlibet/plugins/playlist.py:30 #, 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:41 ../quodlibet/qltk/songsmenu.py:46 #: ../quodlibet/qltk/songsmenu.py:74 #, fuzzy msgid "_Run Plugin" msgstr "_Pluginok" #: ../quodlibet/qltk/about.py:40 #, python-format msgid "Supported formats: %s" msgstr "Támogatott formátumok: %s" #: ../quodlibet/qltk/about.py:43 #, python-format msgid "Audio device: %s" msgstr "Hang eszköz: %s" #. 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:207 ../quodlibet/qltk/information.py:131 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:48 ../quodlibet/qltk/edittags.py:311 msgid "_Value:" msgstr "Érték:" #: ../quodlibet/qltk/cbes.py:262 msgid "Saved Values" msgstr "Mentett értékek" #: ../quodlibet/qltk/cbes.py:263 #, fuzzy msgid "Edit saved values…" msgstr "Mentett értékek szerkesztése..." #: ../quodlibet/qltk/controls.py:111 msgid "Auto_matic" msgstr "" #: ../quodlibet/qltk/controls.py:112 #, fuzzy msgid "_Track Mode" msgstr "_Sáv fejlécek" #: ../quodlibet/qltk/controls.py:113 #, fuzzy msgid "_Album Mode" msgstr "_Album fejlécek" #. Translators: player state, no action #: ../quodlibet/qltk/controls.py:122 msgid "_Mute" msgstr "" #: ../quodlibet/qltk/controls.py:128 #, fuzzy msgid "_Replay Gain Mode" msgstr "Fájlok átnevezése" #. Translators: New Command/Entry/Item/... #: ../quodlibet/qltk/data_editors.py:119 #, python-format msgid "New %s" msgstr "" #: ../quodlibet/qltk/data_editors.py:218 #, fuzzy msgid "(unknown)" msgstr "Ismeretlen" #: ../quodlibet/qltk/data_editors.py:355 msgid "Tag expression" msgstr "" #: ../quodlibet/qltk/data_editors.py:382 msgid "Tag expression e.g. people:real or ~album~year." msgstr "" #: ../quodlibet/qltk/data_editors.py:383 #, fuzzy msgid "Enter new tag" msgstr "Szűrő egy tag értéken" #: ../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/downloader.py:38 msgid "Downloads" msgstr "Letöltések" #: ../quodlibet/qltk/downloader.py:62 msgid "Size" msgstr "Méret" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: ../quodlibet/qltk/downloader.py:94 ../quodlibet/qltk/renamefiles.py:265 #: ../quodlibet/qltk/wlw.py:50 msgid "_Stop" msgstr "" #: ../quodlibet/qltk/edittags.py:63 ../quodlibet/qltk/edittags.py:74 #, python-format msgid "missing from %d song" msgid_plural "missing from %d songs" msgstr[0] "hiányzik %d dalból" #: ../quodlibet/qltk/edittags.py:67 ../quodlibet/qltk/edittags.py:71 #, 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:193 msgid "Split into _Multiple Values" msgstr "Több értékre szedés" #: ../quodlibet/qltk/edittags.py:211 msgid "Split Disc out of _Album" msgstr "_Album és lemez elválasztása" #: ../quodlibet/qltk/edittags.py:228 msgid "Split _Version out of Title" msgstr "_Verzió és cím elválasztása" #: ../quodlibet/qltk/edittags.py:259 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:264 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:270 #, 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:276 #, fuzzy msgid "Split _Originalartist out of Title" msgstr "_Verzió és cím elválasztása" #: ../quodlibet/qltk/edittags.py:283 msgid "Add a Tag" msgstr "Tag hozzáadása" #: ../quodlibet/qltk/edittags.py:302 msgid "_Tag:" msgstr "_Tag:" #: ../quodlibet/qltk/edittags.py:404 msgid "Edit Tags" msgstr "Tag szerkesztés" #: ../quodlibet/qltk/edittags.py:477 msgid "Show _programmatic tags" msgstr "_Programozható tagok mutatása" #: ../quodlibet/qltk/edittags.py:478 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" #. Translators: Revert button in the tag editor #: ../quodlibet/qltk/edittags.py:508 #, fuzzy msgctxt "edittags" msgid "_Revert" msgstr "Soha" #. Translators: Save button in the tag editor #: ../quodlibet/qltk/edittags.py:513 msgctxt "edittags" msgid "_Save" msgstr "" #: ../quodlibet/qltk/edittags.py:659 msgid "Unable to add tag" msgstr "Tag hozzáadása sikertelen" #: ../quodlibet/qltk/edittags.py:660 #, fuzzy, python-format msgid "Unable to add <b>%s</b>" msgstr "Dal hozzáadása sikertelen" #: ../quodlibet/qltk/edittags.py:662 #, fuzzy, python-format msgid "" "The files currently selected do not support multiple values for <b>%s</b>." 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:689 ../quodlibet/qltk/edittags.py:856 #: ../quodlibet/qltk/tagsfrompath.py:212 ../quodlibet/util/__init__.py:554 #: ../quodlibet/util/tags.py:231 msgid "Invalid tag" msgstr "Rossz tag" #: ../quodlibet/qltk/edittags.py:690 ../quodlibet/qltk/edittags.py:857 #: ../quodlibet/qltk/tagsfrompath.py:213 #, python-format msgid "" "Invalid tag <b>%s</b>\n" "\n" "The files currently selected do not support editing this tag." msgstr "" "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:828 ../quodlibet/qltk/edittags.py:868 msgid "Invalid value" msgstr "Rossz érték" #: ../quodlibet/qltk/edittags.py:829 ../quodlibet/qltk/edittags.py:869 #, python-format msgid "" "Invalid value: <b>%(value)s</b>\n" "\n" "%(error)s" msgstr "" "Hibás érték: <b>%(value)s</b>\n" "\n" "%(error)s" #: ../quodlibet/qltk/_editutils.py:28 msgid "Tag may not be accurate" msgstr "A tag pontatlannak hat" #: ../quodlibet/qltk/_editutils.py:31 #, 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:47 msgid "Unable to save song" msgstr "Dal mentése sikertelen" #: ../quodlibet/qltk/_editutils.py:50 #, 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:142 #, 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:95 #: ../quodlibet/qltk/quodlibetwindow.py:1066 msgid "_About" msgstr "" #: ../quodlibet/qltk/exfalsowindow.py:99 #: ../quodlibet/qltk/quodlibetwindow.py:1088 msgid "_Check for Updates…" msgstr "" #: ../quodlibet/qltk/exfalsowindow.py:105 #: ../quodlibet/qltk/quodlibetwindow.py:1021 ../quodlibet/qltk/songsmenu.py:304 msgid "_Plugins" msgstr "_Pluginok" #: ../quodlibet/qltk/exfalsowindow.py:267 #, 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:279 msgid "Ex Falso Preferences" msgstr "Ex Falso jellemzők" #: ../quodlibet/qltk/exfalsowindow.py:289 ../quodlibet/qltk/prefs.py:598 msgid "Split _on:" msgstr "Vágás így:" #: ../quodlibet/qltk/exfalsowindow.py:295 ../quodlibet/qltk/prefs.py:613 msgid "Tag Editing" msgstr "Tag szerkesztés" #: ../quodlibet/qltk/filesel.py:210 msgid "Folders" msgstr "Mappák" #: ../quodlibet/qltk/filesel.py:253 #, fuzzy msgid "_New Folder…" msgstr "Új mappa" #: ../quodlibet/qltk/filesel.py:262 #, fuzzy msgid "_Select all Sub-Folders" msgstr "Alkönyvtárak kijelölé_se" #: ../quodlibet/qltk/filesel.py:374 msgid "New Folder" msgstr "Új mappa" #: ../quodlibet/qltk/filesel.py:374 msgid "Enter a name for the new folder:" msgstr "Adj nevet az új mappának:" #: ../quodlibet/qltk/filesel.py:387 msgid "Unable to create folder" msgstr "Mappa létrehozása sikertelen" #: ../quodlibet/qltk/filesel.py:404 msgid "Unable to delete folder" msgstr "Mappa törlése sikertelen" #: ../quodlibet/qltk/filesel.py:519 ../quodlibet/qltk/pluginwin.py:167 msgid "Songs" msgstr "Dalok" #. Translators: As in "by Artist Name" #: ../quodlibet/qltk/info.py:42 #, python-format msgid "by %s" msgstr "by %s" #: ../quodlibet/qltk/info.py:43 ../quodlibet/qltk/information.py:167 #: ../quodlibet/qltk/information.py:448 #, python-format msgid "Disc %s" msgstr "%s lemez" #: ../quodlibet/qltk/info.py:44 ../quodlibet/qltk/information.py:172 #, python-format msgid "Track %s" msgstr "%s szám" #: ../quodlibet/qltk/info.py:108 #, fuzzy msgid "_Edit Display…" msgstr "Kijelző szerkesztése" #: ../quodlibet/qltk/information.py:105 msgid "No songs are selected." msgstr "Nincs kijelölt dal" #: ../quodlibet/qltk/information.py:106 msgid "No Songs" msgstr "Nincs dal" #: ../quodlibet/qltk/information.py:121 ../quodlibet/qltk/information.py:338 #: ../quodlibet/qltk/information.py:471 ../quodlibet/qltk/information.py:531 msgid "Information" msgstr "Információ" #: ../quodlibet/qltk/information.py:126 msgid "Lyrics" msgstr "Szövegek" #: ../quodlibet/qltk/information.py:184 ../quodlibet/qltk/information.py:396 #, python-format msgid "Produced by %s" msgstr "Készítette: %s" #: ../quodlibet/qltk/information.py:199 ../quodlibet/util/tags.py:76 msgid "artist" msgstr "művész" #: ../quodlibet/qltk/information.py:200 ../quodlibet/qltk/information.py:561 #: ../quodlibet/util/tags.py:76 msgid "artists" msgstr "művészek" #. for backwards compat #: ../quodlibet/qltk/information.py:221 ../quodlibet/util/tags.py:86 #: ../quodlibet/util/tags.py:114 msgid "performers" msgstr "előadók" #: ../quodlibet/qltk/information.py:235 ../quodlibet/qltk/information.py:248 #: ../quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "Soha" #: ../quodlibet/qltk/information.py:236 #, fuzzy, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "%dx" #: ../quodlibet/qltk/information.py:254 ../quodlibet/util/tags.py:139 msgid "added" msgstr "hozzáadva" #: ../quodlibet/qltk/information.py:255 ../quodlibet/util/tags.py:140 msgid "last played" msgstr "utolsó lejátszás" #: ../quodlibet/qltk/information.py:256 ../quodlibet/util/tags.py:150 msgid "plays" msgstr "lejátszás" #: ../quodlibet/qltk/information.py:257 ../quodlibet/util/tags.py:151 msgid "skips" msgstr "kihagyás" #: ../quodlibet/qltk/information.py:258 ../quodlibet/util/tags.py:156 msgid "rating" msgstr "érték" #: ../quodlibet/qltk/information.py:287 msgid "path" msgstr "" #: ../quodlibet/qltk/information.py:288 ../quodlibet/util/tags.py:154 msgid "length" msgstr "hossz" #: ../quodlibet/qltk/information.py:289 #, fuzzy msgid "format" msgstr "Információ" #: ../quodlibet/qltk/information.py:290 ../quodlibet/util/tags.py:163 msgid "codec" msgstr "" #: ../quodlibet/qltk/information.py:291 ../quodlibet/util/tags.py:164 #, fuzzy msgid "encoding" msgstr "[Hibás kódolás]" #: ../quodlibet/qltk/information.py:292 ../quodlibet/util/tags.py:160 msgid "bitrate" msgstr "bitarány" #: ../quodlibet/qltk/information.py:293 ../quodlibet/util/tags.py:161 msgid "file size" msgstr "fájlméret" #: ../quodlibet/qltk/information.py:294 ../quodlibet/util/tags.py:149 msgid "modified" msgstr "módosítva" #: ../quodlibet/qltk/information.py:331 msgid "Additional" msgstr "" #: ../quodlibet/qltk/information.py:383 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d kijelölt" #: ../quodlibet/qltk/information.py:458 msgid "Track unavailable" msgstr "Elérhetetlen szám" #: ../quodlibet/qltk/information.py:464 msgid "Track List" msgstr "Szám lista" #: ../quodlibet/qltk/information.py:505 ../quodlibet/qltk/information.py:578 #, 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:508 msgid "Selected Discography" msgstr "Kijelölt diszkográfia" #: ../quodlibet/qltk/information.py:558 #, 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:586 ../quodlibet/util/tags.py:74 msgid "albums" msgstr "albumok" #: ../quodlibet/qltk/information.py:599 msgid "Total length:" msgstr "Összhossz:" #: ../quodlibet/qltk/information.py:603 msgid "Total size:" msgstr "Összméret:" #: ../quodlibet/qltk/information.py:606 msgid "Files" msgstr "Fájlok" #: ../quodlibet/qltk/lyrics.py:37 msgid "_Download" msgstr "Letöltés" #: ../quodlibet/qltk/lyrics.py:40 #, fuzzy msgid "_Edit" msgstr "Kijelző sz_erkesztése..." #. buffer.set_text(_("No lyrics found.\n\nYou can click the " #. "Download button to have Quod Libet search " #. "for lyrics online. You can also enter them " #. "yourself and click save.")) #: ../quodlibet/qltk/lyrics.py:73 ../quodlibet/qltk/lyrics.py:109 msgid "No lyrics found for this song." msgstr "Nincs szöveg ehhez a dalhoz." #: ../quodlibet/qltk/lyrics.py:82 #, fuzzy msgid "Searching for lyrics…" msgstr "Szöveg keresése..." #: ../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/msg.py:41 msgid "Discard tag changes?" msgstr "Tag cserék elvetése?" #: ../quodlibet/qltk/msg.py:42 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:55 ../quodlibet/qltk/prefs.py:595 #: ../quodlibet/qltk/textedit.py:64 ../quodlibet/qltk/tracknumbers.py:117 #, fuzzy msgid "_Revert" msgstr "Soha" #: ../quodlibet/qltk/msg.py:86 msgid "File exists" msgstr "A fájl létezik" #: ../quodlibet/qltk/msg.py:88 #, python-format msgid "Replace %(file-name)s?" msgstr "" #: ../quodlibet/qltk/msg.py:94 #, fuzzy msgid "_Replace File" msgstr "Fájlok átnevezése" #: ../quodlibet/qltk/notif.py:182 msgid "Active tasks" msgstr "" #: ../quodlibet/qltk/notif.py:188 #, python-format msgid "%d tasks running" msgstr "" #: ../quodlibet/qltk/playorder.py:254 #, fuzzy msgid "Toggle shuffle mode" msgstr "Lejátszás/szünet váltása" #: ../quodlibet/qltk/playorder.py:270 #, fuzzy msgid "Toggle repeat mode" msgstr "Lejátszás/szünet váltása" #: ../quodlibet/qltk/pluginwin.py:44 msgid "Plugin Errors" msgstr "Plugin hibák" #: ../quodlibet/qltk/pluginwin.py:124 msgid "Enabled" msgstr "" #: ../quodlibet/qltk/pluginwin.py:125 #, fuzzy msgid "Disabled" msgstr "Böngésző kikapcsolása" #: ../quodlibet/qltk/pluginwin.py:131 msgid "No category" msgstr "" #: ../quodlibet/qltk/pluginwin.py:169 msgid "Events" msgstr "" #: ../quodlibet/qltk/pluginwin.py:170 #, fuzzy msgid "Play Order" msgstr "S_orrend:" #: ../quodlibet/qltk/pluginwin.py:171 #, fuzzy msgid "Editing" msgstr "Tag szerkesztés" #: ../quodlibet/qltk/pluginwin.py:173 #, fuzzy msgid "Covers" msgstr "Összméret:" #: ../quodlibet/qltk/pluginwin.py:309 msgid "No plugins found." msgstr "Beillesztések nem találhatók" #: ../quodlibet/qltk/pluginwin.py:358 #, fuzzy msgid "Plugins" msgstr "_Pluginok" #: ../quodlibet/qltk/pluginwin.py:402 msgid "Show _Errors" msgstr "Hibák mutatása" #: ../quodlibet/qltk/prefs.py:45 msgid "_Disc" msgstr "_Lemez" #: ../quodlibet/qltk/prefs.py:46 msgid "_Track" msgstr "_Szám" #: ../quodlibet/qltk/prefs.py:47 #, fuzzy msgid "Grou_ping" msgstr "csoport" #: ../quodlibet/qltk/prefs.py:50 msgid "Al_bum" msgstr "_Album" #: ../quodlibet/qltk/prefs.py:55 msgid "_Filename" msgstr "_Fájlnév" #: ../quodlibet/qltk/prefs.py:57 msgid "_Length" msgstr "_Hossz" #: ../quodlibet/qltk/prefs.py:64 msgid "_Jump to playing song automatically" msgstr "Automatikus ugrás a forgó dalra" #: ../quodlibet/qltk/prefs.py:66 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:82 msgid "_Others:" msgstr "Más_ok:" #: ../quodlibet/qltk/prefs.py:88 #, fuzzy msgid "_Edit…" msgstr "Kijelző sz_erkesztése..." #: ../quodlibet/qltk/prefs.py:91 msgid "Add or remove additional column headers" msgstr "" #: ../quodlibet/qltk/prefs.py:101 msgid "Visible Columns" msgstr "Látható oszlopok" #: ../quodlibet/qltk/prefs.py:104 msgid "Title includes _version" msgstr "_Verzió a címben" #: ../quodlibet/qltk/prefs.py:106 #, fuzzy msgid "Artist includes all _people" msgstr "_Verzió a címben" #: ../quodlibet/qltk/prefs.py:108 msgid "Album includes _disc subtitle" msgstr "" #: ../quodlibet/qltk/prefs.py:110 msgid "Filename includes _folder" msgstr "Mappa a _fájlnévben" #: ../quodlibet/qltk/prefs.py:123 #, fuzzy msgid "Column Preferences" msgstr "Jellemzők" #: ../quodlibet/qltk/prefs.py:129 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "" #: ../quodlibet/qltk/prefs.py:142 ../quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Dal lista" #: ../quodlibet/qltk/prefs.py:222 #, fuzzy msgid "Edit Columns" msgstr "Látható oszlopok" #: ../quodlibet/qltk/prefs.py:259 msgid "Duration totals" msgstr "" #: ../quodlibet/qltk/prefs.py:271 msgid "_Global filter:" msgstr "_Globális szűrő:" #: ../quodlibet/qltk/prefs.py:277 msgid "Apply this query in addition to all others" msgstr "" #. Translators: The heading of the preference group, no action #: ../quodlibet/qltk/prefs.py:283 #, fuzzy msgctxt "heading" msgid "Search" msgstr "Keres" #: ../quodlibet/qltk/prefs.py:287 ../quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Böngészők" #: ../quodlibet/qltk/prefs.py:293 msgid "Confirm _multiple ratings" msgstr "" #: ../quodlibet/qltk/prefs.py:295 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "" #: ../quodlibet/qltk/prefs.py:298 msgid "Enable _one-click ratings" msgstr "" #: ../quodlibet/qltk/prefs.py:300 #, 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:306 ../quodlibet/qltk/prefs.py:616 #, fuzzy msgid "Ratings" msgstr "É_rték" #. Filename choice algorithm config #: ../quodlibet/qltk/prefs.py:312 msgid "Prefer _embedded art" msgstr "" #: ../quodlibet/qltk/prefs.py:314 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" #: ../quodlibet/qltk/prefs.py:319 msgid "_Fixed image filename:" msgstr "" #: ../quodlibet/qltk/prefs.py:321 msgid "The single image filename to use if selected" msgstr "" #: ../quodlibet/qltk/prefs.py:327 msgid "The album art image file to use when forced" msgstr "" #: ../quodlibet/qltk/prefs.py:336 #, fuzzy msgid "Album Art" msgstr "Album lista" #: ../quodlibet/qltk/prefs.py:357 #, fuzzy msgid "Playback" msgstr "Lejátszás szünete" #: ../quodlibet/qltk/prefs.py:362 msgid "Output Configuration" msgstr "" #: ../quodlibet/qltk/prefs.py:373 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" #: ../quodlibet/qltk/prefs.py:376 msgid "_Fall-back gain (dB):" msgstr "" #: ../quodlibet/qltk/prefs.py:387 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "" #: ../quodlibet/qltk/prefs.py:390 msgid "_Pre-amp gain (dB):" msgstr "" #: ../quodlibet/qltk/prefs.py:395 msgid "_Enable Replay Gain volume adjustment" msgstr "" #: ../quodlibet/qltk/prefs.py:420 msgid "Replay Gain Volume Adjustment" msgstr "" #: ../quodlibet/qltk/prefs.py:450 msgid "_Default rating:" msgstr "" #: ../quodlibet/qltk/prefs.py:493 #, fuzzy msgid "Rating _scale:" msgstr "É_rték" #: ../quodlibet/qltk/prefs.py:542 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:547 msgid "_Bayesian averaging amount:" msgstr "" #: ../quodlibet/qltk/prefs.py:556 #, fuzzy msgid "Save ratings and play _counts" msgstr "Értékek és lejátszások mentése" #: ../quodlibet/qltk/prefs.py:560 msgid "_Email:" msgstr "_Email:" #: ../quodlibet/qltk/prefs.py:562 msgid "Ratings and play counts will be set for this email address" msgstr "Értékekhez és lejátszásokhoz beállítandó email cím" #: ../quodlibet/qltk/prefs.py:577 #, fuzzy msgid "Auto-save tag changes" msgstr "Tag cserék elvetése?" #: ../quodlibet/qltk/prefs.py:579 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "" #: ../quodlibet/qltk/prefs.py:587 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:610 #, fuzzy msgid "Tags" msgstr "Tag szerkesztés" #: ../quodlibet/qltk/prefs.py:631 #, fuzzy msgid "Updating for new ratings" msgstr "Új állomás" #: ../quodlibet/qltk/prefs.py:641 #, fuzzy msgid "Scan library _on start" msgstr "Daltár _frissítése" #: ../quodlibet/qltk/prefs.py:651 ../quodlibet/qltk/quodlibetwindow.py:1100 #, fuzzy msgid "_Scan Library" msgstr "Daltár kere_sése" #: ../quodlibet/qltk/prefs.py:653 ../quodlibet/qltk/quodlibetwindow.py:1162 msgid "Check for changes in your library" msgstr "Változások átnézése a daltárban" #: ../quodlibet/qltk/prefs.py:658 #, fuzzy msgid "Re_build Library" msgstr "Daltár újratö_ltése" #: ../quodlibet/qltk/prefs.py:661 #, 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:671 #, fuzzy msgid "Scan Directories" msgstr "Könyvtárak átnézése" #: ../quodlibet/qltk/prefs.py:677 #, fuzzy msgid "Hidden Songs" msgstr "Nincs dal" #: ../quodlibet/qltk/properties.py:158 ../quodlibet/util/collection.py:398 #, 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:162 ../quodlibet/qltk/properties.py:164 msgid "Properties" msgstr "Tulajdonságok" #: ../quodlibet/qltk/queue.py:101 msgid "_Queue" msgstr "Lejátszósor" #: ../quodlibet/qltk/queue.py:126 msgid "Stop Once Empty" msgstr "" #: ../quodlibet/qltk/queue.py:130 #, fuzzy msgid "_Clear Queue" msgstr "Hibák tisztitása" #: ../quodlibet/qltk/queue.py:242 #, 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:198 msgid "_Browse Library" msgstr "Daltár _böngészése" #: ../quodlibet/qltk/quodlibetwindow.py:395 #, fuzzy msgid "Toggle queue visibility" msgstr "Főablak mutatásának váltása" #: ../quodlibet/qltk/quodlibetwindow.py:516 #, fuzzy msgid "Playback Error" msgstr "Lejátszás szünete" #: ../quodlibet/qltk/quodlibetwindow.py:524 #, fuzzy msgid "Set up library directories?" msgstr "Könyvtárak kijelölése" #: ../quodlibet/qltk/quodlibetwindow.py:525 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:531 msgid "_Not Now" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:532 msgid "_Set Up" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:956 msgid "Unable to add songs" msgstr "Dalok hozzáadása sikertelen" #: ../quodlibet/qltk/quodlibetwindow.py:957 #: ../quodlibet/qltk/quodlibetwindow.py:1364 #, fuzzy, python-format msgid "%s uses an unsupported protocol." msgstr "<b>%s</b> nem támogatott protokollt használ" #: ../quodlibet/qltk/quodlibetwindow.py:980 msgid "_Jump to Playing Song" msgstr "_Ugrás a lejátszásra" #: ../quodlibet/qltk/quodlibetwindow.py:986 #, fuzzy msgid "_File" msgstr "Fájl" #: ../quodlibet/qltk/quodlibetwindow.py:987 #, fuzzy msgid "_Song" msgstr "Dalok" #: ../quodlibet/qltk/quodlibetwindow.py:988 msgid "_View" msgstr "_Nézet" #: ../quodlibet/qltk/quodlibetwindow.py:989 #, fuzzy msgid "_Browse" msgstr "Böngészők" #: ../quodlibet/qltk/quodlibetwindow.py:990 msgid "_Control" msgstr "_Vezérlés" #: ../quodlibet/qltk/quodlibetwindow.py:991 msgid "_Help" msgstr "_Súgó" #: ../quodlibet/qltk/quodlibetwindow.py:997 #, fuzzy msgid "_Add a Folder…" msgstr "Mappa hozzá_adása..." #: ../quodlibet/qltk/quodlibetwindow.py:1002 #, fuzzy msgid "_Add a File…" msgstr "Fájl hozzá_adása..." #: ../quodlibet/qltk/quodlibetwindow.py:1007 #, fuzzy msgid "_Add a Location…" msgstr "Hely hozzáadása" #: ../quodlibet/qltk/quodlibetwindow.py:1036 #, fuzzy msgid "Edit Bookmarks…" msgstr "Könyvjelzők sz_erkesztése..." #: ../quodlibet/qltk/quodlibetwindow.py:1056 #, fuzzy msgid "Stop After This Song" msgstr "Stop e szám után" #: ../quodlibet/qltk/quodlibetwindow.py:1062 msgid "_Keyboard Shortcuts" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:1071 msgid "Online Help" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:1080 #, fuzzy msgid "Search Help" msgstr "Keres" #: ../quodlibet/qltk/quodlibetwindow.py:1352 msgid "Add a Location" msgstr "Hely hozzáadása" #: ../quodlibet/qltk/quodlibetwindow.py:1353 msgid "Enter the location of an audio file:" msgstr "Add meg egy hang fájl helyét:" #: ../quodlibet/qltk/quodlibetwindow.py:1358 #: ../quodlibet/qltk/quodlibetwindow.py:1363 msgid "Unable to add location" msgstr "Hely hozzáadása sikertelen" #: ../quodlibet/qltk/quodlibetwindow.py:1359 #, fuzzy, python-format msgid "%s is not a valid location." msgstr "<b>%s</b> nem egy érvényes hely" #: ../quodlibet/qltk/quodlibetwindow.py:1372 #: ../quodlibet/qltk/quodlibetwindow.py:1381 msgid "Add Music" msgstr "Zene hozzáadása" #: ../quodlibet/qltk/quodlibetwindow.py:1372 ../quodlibet/qltk/scanbox.py:99 #, fuzzy msgid "_Add Folders" msgstr "Mappa hozzá_adása..." #: ../quodlibet/qltk/quodlibetwindow.py:1379 #, fuzzy msgid "Music Files" msgstr "Zenelejátszó" #: ../quodlibet/qltk/quodlibetwindow.py:1381 #, fuzzy msgid "_Add Files" msgstr "Fájl hozzá_adása..." #: ../quodlibet/qltk/ratingsmenu.py:24 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "" #: ../quodlibet/qltk/ratingsmenu.py:26 msgid "The saved ratings will be removed" msgstr "" #: ../quodlibet/qltk/ratingsmenu.py:27 #, python-format msgid "The rating of all selected songs will be changed to '%s'" msgstr "" #: ../quodlibet/qltk/ratingsmenu.py:57 ../quodlibet/qltk/ratingsmenu.py:111 #, fuzzy msgid "_Remove Rating" msgstr "É_rték" #: ../quodlibet/qltk/ratingsmenu.py:98 #, fuzzy msgid "Change _Rating" msgstr "É_rték" #: ../quodlibet/qltk/renamefiles.py:46 msgid "Replace spaces with _underscores" msgstr "Szóközök helyett aláhúzások !" #: ../quodlibet/qltk/renamefiles.py:56 msgid "Strip _Windows-incompatible characters" msgstr "w$-inkompatibilis jeleket mellőz" #: ../quodlibet/qltk/renamefiles.py:74 msgid "Strip _diacritical marks" msgstr "Mellékjelek ki" #: ../quodlibet/qltk/renamefiles.py:85 msgid "Strip non-_ASCII characters" msgstr "Nem-_ASCII karakterek ki" #: ../quodlibet/qltk/renamefiles.py:95 msgid "Use only _lowercase characters" msgstr "" #: ../quodlibet/qltk/renamefiles.py:123 msgid "Rename Files" msgstr "Fájlok átnevezése" #: ../quodlibet/qltk/renamefiles.py:139 ../quodlibet/qltk/tagsfrompath.py:116 #, fuzzy msgid "Path Patterns" msgstr "minta" #: ../quodlibet/qltk/renamefiles.py:140 ../quodlibet/qltk/tagsfrompath.py:117 #, fuzzy msgid "Edit saved patterns…" msgstr "Mentett értékek szerkesztése..." #: ../quodlibet/qltk/renamefiles.py:143 ../quodlibet/qltk/tagsfrompath.py:120 #: ../quodlibet/qltk/tracknumbers.py:58 msgid "_Preview" msgstr "Előnézet" #: ../quodlibet/qltk/renamefiles.py:190 msgid "New Name" msgstr "Új név" #: ../quodlibet/qltk/renamefiles.py:255 msgid "Unable to rename file" msgstr "Fájl átnevezése sikertelen" #: ../quodlibet/qltk/renamefiles.py:256 #, fuzzy, python-format msgid "" "Renaming <b>%(old-name)s</b> to <b>%(new-name)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." 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:264 #, fuzzy msgid "Ignore _All Errors" msgstr "Hibák mutatása" #: ../quodlibet/qltk/renamefiles.py:267 msgid "_Continue" msgstr "Tovább" #: ../quodlibet/qltk/renamefiles.py:296 msgid "Path is not absolute" msgstr "Az ösvény nem abszolút" #: ../quodlibet/qltk/renamefiles.py:297 #, python-format msgid "" "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 ~/." 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:47 #, 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:99 msgid "Select Directories" msgstr "Könyvtárak kijelölése" #: ../quodlibet/qltk/searchbar.py:52 #, fuzzy msgid "Saved Searches" msgstr "Mentett értékek" #: ../quodlibet/qltk/searchbar.py:53 #, fuzzy msgid "Edit saved searches…" msgstr "Mentett értékek szerkesztése..." #: ../quodlibet/qltk/searchbar.py:74 msgid "Search your library, using free text or QL queries" msgstr "" #: ../quodlibet/qltk/searchbar.py:129 #, fuzzy msgid "Search after _typing" msgstr "Stop e szám után" #: ../quodlibet/qltk/searchbar.py:132 msgid "Show search results after the user stops typing." msgstr "" #: ../quodlibet/qltk/searchbar.py:187 msgid "_Limit:" msgstr "Kor_lát:" #: ../quodlibet/qltk/searchbar.py:200 msgid "_Weight" msgstr "Súly" #: ../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 ../quodlibet/qltk/shortcuts.py:41 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: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:377 #, python-format msgid "_Filter on %s" msgstr "Szűrő itt: %s" #: ../quodlibet/qltk/songlist.py:1094 #, fuzzy msgid "All _Headers" msgstr "_Album fejlécek" #: ../quodlibet/qltk/songlist.py:1095 msgid "_Track Headers" msgstr "_Sáv fejlécek" #: ../quodlibet/qltk/songlist.py:1096 msgid "_Album Headers" msgstr "_Album fejlécek" #: ../quodlibet/qltk/songlist.py:1097 msgid "_People Headers" msgstr "Személ_y fejlécek" #: ../quodlibet/qltk/songlist.py:1098 msgid "_Date Headers" msgstr "_Dátum fejlécek" #: ../quodlibet/qltk/songlist.py:1099 msgid "_File Headers" msgstr "_Fájl fejlécek" #: ../quodlibet/qltk/songlist.py:1100 msgid "_Production Headers" msgstr "_Termék fejlécek" #: ../quodlibet/qltk/songlist.py:1115 #, fuzzy msgid "_Customize Headers…" msgstr "_Egyéni fejlécek..." #: ../quodlibet/qltk/songlist.py:1120 msgid "_Expand Column" msgstr "" #: ../quodlibet/qltk/songsmenu.py:36 #, 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:64 #, 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:149 #, fuzzy msgid "Configure Plugins…" msgstr "Színes kere_ső kifejezések" #: ../quodlibet/qltk/songsmenu.py:345 msgid "Add to _Queue" msgstr "Sorhoz adás" #: ../quodlibet/qltk/songsmenu.py:368 msgid "_Copy to Device" msgstr "Eszközre másolás" #: ../quodlibet/qltk/songsmenu.py:379 #, fuzzy msgid "_Remove from Library" msgstr "Tö_rlés a listáról" #: ../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:101 msgid "Tags From Path" msgstr "Tagok az ösvényből" #: ../quodlibet/qltk/tagsfrompath.py:138 msgid "Tags replace existing ones" msgstr "Létezőket cserélő tagok" #: ../quodlibet/qltk/tagsfrompath.py:139 msgid "Tags are added to existing ones" msgstr "Létezőkhöz adandó tagok" #. Save button #: ../quodlibet/qltk/tagsfrompath.py:153 msgid "Save" msgstr "" #: ../quodlibet/qltk/tagsfrompath.py:195 #, python-format msgid "" "The pattern\n" "\t<b>%s</b>\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/tagsfrompath.py:216 msgid "Invalid tags" msgstr "Érvénytelen tagok" #: ../quodlibet/qltk/tagsfrompath.py:217 #, 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." #: ../quodlibet/qltk/textedit.py:142 #, 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:158 msgid "Edit Display" msgstr "Kijelző szerkesztése" #: ../quodlibet/qltk/tracknumbers.py:39 msgid "Track Numbers" msgstr "Számok száma" #: ../quodlibet/qltk/tracknumbers.py:42 msgid "Start fro_m:" msgstr "Indítás innen:" #: ../quodlibet/qltk/tracknumbers.py:51 msgid "_Total tracks:" msgstr "Összes szám:" #: ../quodlibet/qltk/unity.py:52 #, fuzzy msgid "Play/Pause" msgstr "Lejátszó" #: ../quodlibet/qltk/unity.py:75 #, fuzzy msgid "Previous" msgstr "Előnézet" #: ../quodlibet/qltk/views.py:923 #, 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:89 #, fuzzy msgid "Checking for Updates" msgstr "Csatolási pontok ellenőrzése" #: ../quodlibet/update.py:124 #, fuzzy msgid "Connection failed" msgstr "hely" #: ../quodlibet/update.py:133 #, python-format msgid "You are already using the newest version %(version)s" msgstr "" #: ../quodlibet/update.py:136 #, 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:420 msgid "Playlists must have a name" msgstr "" #: ../quodlibet/util/collection.py:603 #, python-format msgid "A playlist named %s already exists." msgstr "Már van egy %s nevű lista" #: ../quodlibet/util/cover/built_in.py:26 #, fuzzy msgid "Embedded album covers" msgstr "Album borítók mutatása" #: ../quodlibet/util/cover/built_in.py:27 msgid "Uses covers embedded into audio files." msgstr "" #: ../quodlibet/util/cover/built_in.py:49 #, fuzzy msgid "Filesystem cover" msgstr "Fájlrendszer" #: ../quodlibet/util/cover/built_in.py:50 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "" #: ../quodlibet/util/__init__.py:93 msgid "Display brief usage information" msgstr "Kiírja a tömör útmutatót" #: ../quodlibet/util/__init__.py:95 msgid "Display version and copyright" msgstr "Kiírja a verziót és a szerzői jogokat" #: ../quodlibet/util/__init__.py:135 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "" #: ../quodlibet/util/__init__.py:137 msgid "[options]" msgstr "[lehetőségek]" #: ../quodlibet/util/__init__.py:182 #, fuzzy, python-format msgid "Option %r not recognized." msgstr "E: '%s' nem ismert lehetőség." #: ../quodlibet/util/__init__.py:185 #, fuzzy, python-format msgid "Option %r requires an argument." msgstr "E: '%s' egy argumentumot vár." #: ../quodlibet/util/__init__.py:188 #, fuzzy, python-format msgid "%r is not a unique prefix." msgstr "E: '%s' nem egyedi előtag." #: ../quodlibet/util/__init__.py:364 #, python-format msgid "%d kbps" msgstr "%d kbps" #: ../quodlibet/util/__init__.py:419 #, fuzzy, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%d mp." #: ../quodlibet/util/__init__.py:432 msgid "No time information" msgstr "Nincs idő adat" #: ../quodlibet/util/__init__.py:435 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d mp." #: ../quodlibet/util/__init__.py:436 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d perc" #: ../quodlibet/util/__init__.py:437 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d óra" #: ../quodlibet/util/__init__.py:438 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d nap" #: ../quodlibet/util/__init__.py:439 #, 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:563 #, 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 msgid "Unable to edit song" msgstr "A dal szerkesztése sikertelen" #: ../quodlibet/util/songwrapper.py:113 #, python-format msgid "" "Saving <b>%s</b> 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:34 #: ../quodlibet/util/string/__init__.py:44 msgid "[Invalid Encoding]" msgstr "[Hibás kódolás]" #: ../quodlibet/util/tags.py:74 msgid "album" msgstr "album" #: ../quodlibet/util/tags.py:75 msgid "arranger" msgstr "hangszerelő" #: ../quodlibet/util/tags.py:75 msgid "arrangers" msgstr "hangszerelők" #: ../quodlibet/util/tags.py:75 #, fuzzy msgid "arrangement" msgstr "hangszerelő" #: ../quodlibet/util/tags.py:77 msgid "author" msgstr "szerző" #: ../quodlibet/util/tags.py:77 msgid "authors" msgstr "szerzők" #: ../quodlibet/util/tags.py:78 msgid "composer" msgstr "zeneszerző" #: ../quodlibet/util/tags.py:78 msgid "composers" msgstr "zeneszerzők" #: ../quodlibet/util/tags.py:78 #, fuzzy msgid "composition" msgstr "zeneszerző" #. Translators: conducting as in conducting a musical performance #: ../quodlibet/util/tags.py:80 msgid "conductor" msgstr "karmester" #: ../quodlibet/util/tags.py:80 msgid "conductors" msgstr "karmesterek" #: ../quodlibet/util/tags.py:80 #, fuzzy msgid "conducting" msgstr "karmester" #: ../quodlibet/util/tags.py:81 msgid "contact" msgstr "kapcsolat" #: ../quodlibet/util/tags.py:82 msgid "copyright" msgstr "copyright" #: ../quodlibet/util/tags.py:83 msgid "date" msgstr "dátum" #: ../quodlibet/util/tags.py:84 msgid "description" msgstr "leírás" #: ../quodlibet/util/tags.py:85 msgid "genre" msgstr "műfaj" #: ../quodlibet/util/tags.py:85 #, fuzzy msgid "genres" msgstr "műfaj" #: ../quodlibet/util/tags.py:86 msgid "performer" msgstr "előadó" #: ../quodlibet/util/tags.py:87 msgid "grouping" msgstr "csoport" #: ../quodlibet/util/tags.py:88 msgid "language" msgstr "nyelv" #: ../quodlibet/util/tags.py:89 msgid "license" msgstr "licenc" #: ../quodlibet/util/tags.py:90 msgid "location" msgstr "hely" #: ../quodlibet/util/tags.py:91 msgid "lyricist" msgstr "szövegíró" #: ../quodlibet/util/tags.py:91 msgid "lyricists" msgstr "szövegírók" #: ../quodlibet/util/tags.py:91 #, fuzzy msgid "lyrics" msgstr "szövegíró" #. Translators: Also e.g. "record label", "publisher" #: ../quodlibet/util/tags.py:93 msgid "organization" msgstr "szervezet" #: ../quodlibet/util/tags.py:94 msgid "title" msgstr "cím" #: ../quodlibet/util/tags.py:95 msgid "version" msgstr "verzió" #: ../quodlibet/util/tags.py:96 msgid "website" msgstr "weblap" #: ../quodlibet/util/tags.py:98 msgid "album artist" msgstr "album művész" #: ../quodlibet/util/tags.py:99 msgid "BPM" msgstr "BPM" #. Translators: This used to be called "part". #: ../quodlibet/util/tags.py:102 ../quodlibet/util/tags.py:103 msgid "disc subtitle" msgstr "" #: ../quodlibet/util/tags.py:104 ../quodlibet/util/tags.py:141 msgid "disc" msgstr "lemez" #: ../quodlibet/util/tags.py:105 ../quodlibet/util/tags.py:143 msgid "track" msgstr "szám" # label ID #: ../quodlibet/util/tags.py:106 msgid "label ID" msgstr "címke ID" #: ../quodlibet/util/tags.py:107 msgid "original release date" msgstr "eredeti kiadási dátum" #: ../quodlibet/util/tags.py:108 msgid "original album" msgstr "eredeti album" #: ../quodlibet/util/tags.py:109 msgid "original artist" msgstr "eredeti művész" #: ../quodlibet/util/tags.py:110 msgid "recording date" msgstr "rögzítési dátum" #: ../quodlibet/util/tags.py:111 msgid "release country" msgstr "megjelenés országa" #. 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:120 #, fuzzy msgid "MusicBrainz recording ID" msgstr "MusicBrainz track ID" #: ../quodlibet/util/tags.py:121 #, fuzzy msgid "MusicBrainz release track ID" msgstr "MusicBrainz track ID" #: ../quodlibet/util/tags.py:122 #, fuzzy msgid "MusicBrainz release ID" msgstr "MusicBrainz track ID" #: ../quodlibet/util/tags.py:123 #, fuzzy msgid "MusicBrainz artist ID" msgstr "MusicBrainz artist ID" #: ../quodlibet/util/tags.py:124 #, fuzzy msgid "MusicBrainz release artist ID" msgstr "MusicBrainz track ID" #: ../quodlibet/util/tags.py:125 msgid "MusicBrainz TRM ID" msgstr "MusicBrainz TRM ID" #: ../quodlibet/util/tags.py:126 msgid "MusicIP PUID" msgstr "MusicIP PUID" #: ../quodlibet/util/tags.py:127 msgid "MusicBrainz album status" msgstr "MusicBrainz album állapot" #: ../quodlibet/util/tags.py:128 msgid "MusicBrainz album type" msgstr "MusicBrainz album típus" #: ../quodlibet/util/tags.py:129 #, fuzzy msgid "MusicBrainz release group ID" msgstr "MusicBrainz track ID" #. Translators: "gain" means a volume adjustment, not "to acquire". #: ../quodlibet/util/tags.py:132 msgid "track gain" msgstr "" #: ../quodlibet/util/tags.py:133 msgid "track peak" msgstr "szám csúcs" #. Translators: "gain" means a volume adjustment, not "to acquire". #: ../quodlibet/util/tags.py:135 msgid "album gain" msgstr "" #: ../quodlibet/util/tags.py:136 msgid "album peak" msgstr "album csúcs" #: ../quodlibet/util/tags.py:137 #, fuzzy msgid "reference loudness" msgstr "Jellemzők" #: ../quodlibet/util/tags.py:142 msgid "discs" msgstr "lemezek" #: ../quodlibet/util/tags.py:144 msgid "tracks" msgstr "számok" #: ../quodlibet/util/tags.py:145 msgid "last started" msgstr "utolsó indítás" #: ../quodlibet/util/tags.py:146 msgid "full name" msgstr "pontos elérés" #: ../quodlibet/util/tags.py:153 msgid "mount point" msgstr "csatolási pont" #: ../quodlibet/util/tags.py:155 msgid "people" msgstr "személyek" #: ../quodlibet/util/tags.py:157 msgid "year" msgstr "év" #: ../quodlibet/util/tags.py:158 #, fuzzy msgid "original release year" msgstr "eredeti kiadási dátum" #: ../quodlibet/util/tags.py:159 #, fuzzy msgid "bookmark" msgstr "Könyvjelzők" #: ../quodlibet/util/tags.py:162 #, fuzzy msgid "file format" msgstr "formátum" #: ../quodlibet/util/tags.py:165 #, fuzzy msgid "playlists" msgstr "Listák" #: ../quodlibet/util/tags.py:166 msgid "channel count" msgstr "" #. Translators: e.g. "artist (sort)" #: ../quodlibet/util/tags.py:256 msgid "sort" msgstr "" #. Translators: e.g. "performer (roles)" #: ../quodlibet/util/tags.py:264 msgid "roles" msgstr "" #, fuzzy #~ msgid "browsers" #~ msgstr "Böngészők" #~ msgid "Unable to download lyrics." #~ msgstr "Szöveg letöltése sikertelen" #~ msgid "Remove all songs from the queue" #~ msgstr "Minden dal törlése a sorból" #~ msgid "Watch this folder for new songs" #~ msgstr "Új dalok keresése e mappában" #~ 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 "Model:" #~ msgstr "Modell:" #~ msgid "Capacity:" #~ msgstr "Kapacitás:" #~ msgid "Firmware:" #~ msgstr "Firmware:" #, fuzzy #~ msgid "Removing orphaned iPod track" #~ msgstr "F: elavult iPod sáv eltávolítása" #, 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 "Unable to open input files" #~ msgstr "Fájlok megnyitása sikertelen" #, 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 "_Select" #~ msgstr "Vála_szt" #~ 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 "Choose New Stations" #~ msgstr "Válassz új állomásokat" #~ msgid "Add" #~ msgstr "Hozzáad" #, fuzzy #~ msgid "Bitrate" #~ msgstr "bitarány" #~ msgid "_Stations..." #~ msgstr "Állomá_sok..." #, fuzzy #~ msgid "Quod Libet" #~ msgstr "Quod Libet bezárása" #~ 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9631858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/po/it.po����������������������������������������������������������������������������0000644�0001750�0001750�00000644311�00000000000�014101� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# SOME DESCRIPTIVE TITLE. # 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. msgid "" msgstr "" "Project-Id-Version: Quod Libet 0.22\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2020-02-01 21:16+0100\n" "PO-Revision-Date: 2020-02-28 21:48+0100\n" "Last-Translator: Daniele Primon <ledebass@gmail.com>\n" "Language-Team: Italian\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: Poedit 1.8.11\n" "X-Poedit-Bookmarks: 251,253,873,851,-1,-1,-1,-1,-1,1260\n" #: quodlibet/browsers/albums/main.py:185 #: quodlibet/browsers/covergrid/main.py:55 msgid "_Title" msgstr "Tit_olo" #: quodlibet/browsers/albums/main.py:186 #: quodlibet/browsers/covergrid/main.py:56 quodlibet/qltk/prefs.py:50 msgid "_Artist" msgstr "Arti_sta" #: quodlibet/browsers/albums/main.py:187 #: quodlibet/browsers/covergrid/main.py:57 quodlibet/qltk/prefs.py:55 msgid "_Date" msgstr "_Data" #: quodlibet/browsers/albums/main.py:188 #: quodlibet/browsers/covergrid/main.py:58 quodlibet/qltk/prefs.py:54 msgid "_Genre" msgstr "_Genere" #: quodlibet/browsers/albums/main.py:189 #: quodlibet/browsers/covergrid/main.py:59 quodlibet/qltk/prefs.py:59 #: quodlibet/qltk/ratingsmenu.py:40 msgid "_Rating" msgstr "Giudi_zio" #: quodlibet/browsers/albums/main.py:190 msgid "_Playcount" msgstr "Conteggio ri_produzioni" #: quodlibet/browsers/albums/main.py:196 #: quodlibet/browsers/covergrid/main.py:65 msgid "Sort _by…" msgstr "Ordina _per…" #: quodlibet/browsers/albums/main.py:217 #: quodlibet/browsers/covergrid/main.py:86 #: quodlibet/browsers/paned/prefs.py:193 #: quodlibet/browsers/playlists/main.py:668 quodlibet/qltk/exfalsowindow.py:109 #: quodlibet/qltk/pluginwin.py:342 quodlibet/qltk/quodlibetwindow.py:907 msgid "_Preferences" msgstr "P_referenze" #: quodlibet/browsers/albums/main.py:383 msgid "Album List" msgstr "Lista degli album" #: quodlibet/browsers/albums/main.py:384 msgid "_Album List" msgstr "Lista degli _album" #: quodlibet/browsers/albums/main.py:494 #: quodlibet/browsers/covergrid/main.py:281 #: quodlibet/browsers/covergrid/main.py:494 msgid "All Albums" msgstr "Tutti gli album" #: quodlibet/browsers/albums/main.py:495 #: quodlibet/browsers/covergrid/main.py:282 #: quodlibet/browsers/covergrid/main.py:495 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d album" msgstr[1] "%d album" #: quodlibet/browsers/albums/main.py:676 #: quodlibet/browsers/covergrid/main.py:473 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:29 #: quodlibet/browsers/collection/models.py:17 #: quodlibet/browsers/covergrid/prefs.py:31 msgid "Songs not in an album" msgstr "Brani non in un album" #: quodlibet/browsers/albums/prefs.py:42 #: quodlibet/browsers/covergrid/prefs.py:44 #: quodlibet/browsers/playlists/prefs.py:36 #: quodlibet/ext/songsmenu/brainz/widgets.py:99 #: quodlibet/qltk/information.py:386 quodlibet/util/collection.py:248 #, python-format msgid "%d track" msgid_plural "%d tracks" msgstr[0] "%d traccia" msgstr[1] "%d tracce" #: quodlibet/browsers/albums/prefs.py:43 #: quodlibet/browsers/covergrid/prefs.py:45 #: quodlibet/ext/songsmenu/brainz/widgets.py:98 #: quodlibet/qltk/information.py:384 quodlibet/util/collection.py:252 #, python-format msgid "%d disc" msgid_plural "%d discs" msgstr[0] "%d disco" msgstr[1] "%d dischi" #: quodlibet/browsers/albums/prefs.py:45 #: quodlibet/browsers/covergrid/prefs.py:47 msgid "An Example Album" msgstr "Un album di esempio" #: quodlibet/browsers/albums/prefs.py:53 msgid "Album List Preferences" msgstr "Preferenze lista album" #: quodlibet/browsers/albums/prefs.py:62 msgid "Show album _covers" msgstr "Mostra le _copertine degli album" #: quodlibet/browsers/albums/prefs.py:68 msgid "Inline _search includes people" msgstr "La ricerca in linea include le persone" #: quodlibet/browsers/albums/prefs.py:72 #: quodlibet/browsers/covergrid/prefs.py:121 #: quodlibet/ext/songsmenu/cover_download.py:244 msgid "Options" msgstr "Opzioni" #: quodlibet/browsers/albums/prefs.py:75 #: quodlibet/browsers/covergrid/prefs.py:124 msgid "Album Display" msgstr "Visualizzazione album" #: quodlibet/browsers/albums/prefs.py:79 #: quodlibet/browsers/covergrid/prefs.py:128 #: quodlibet/browsers/playlists/prefs.py:57 #: quodlibet/ext/songsmenu/albumart.py:329 #: quodlibet/ext/songsmenu/duplicates.py:348 #: quodlibet/ext/songsmenu/filterall.py:49 quodlibet/qltk/bookmarks.py:102 #: quodlibet/qltk/cbes.py:94 quodlibet/qltk/data_editors.py:97 #: quodlibet/qltk/data_editors.py:322 quodlibet/qltk/exfalsowindow.py:297 #: quodlibet/qltk/pluginwin.py:80 quodlibet/qltk/pluginwin.py:429 #: quodlibet/qltk/prefs.py:718 quodlibet/qltk/textedit.py:164 #: quodlibet/update.py:150 msgid "_Close" msgstr "_Chiudi" #: quodlibet/browsers/audiofeeds.py:53 quodlibet/browsers/audiofeeds.py:65 #: quodlibet/browsers/audiofeeds.py:67 quodlibet/browsers/audiofeeds.py:157 #: quodlibet/browsers/paned/models.py:86 #: quodlibet/ext/songsmenu/fingerprint/search.py:47 #: quodlibet/formats/_audio.py:484 quodlibet/order/__init__.py:28 #: quodlibet/qltk/information.py:245 quodlibet/qltk/information.py:252 #: quodlibet/qltk/information.py:278 quodlibet/qltk/wlw.py:70 msgid "Unknown" msgstr "Sconosciuto" #: quodlibet/browsers/audiofeeds.py:248 msgid "New Feed" msgstr "Nuovo Feed" #: quodlibet/browsers/audiofeeds.py:249 msgid "Enter the location of an audio feed:" msgstr "Inserire la posizione di un feed audio:" #: quodlibet/browsers/audiofeeds.py:250 #: quodlibet/browsers/collection/prefs.py:90 quodlibet/browsers/iradio.py:357 #: quodlibet/browsers/paned/prefs.py:110 #: quodlibet/browsers/playlists/menu.py:97 #: quodlibet/browsers/playlists/util.py:53 quodlibet/qltk/bookmarks.py:63 #: quodlibet/qltk/cbes.py:56 quodlibet/qltk/data_editors.py:309 #: quodlibet/qltk/edittags.py:292 quodlibet/qltk/edittags.py:492 #: quodlibet/qltk/quodlibetwindow.py:1275 quodlibet/qltk/scanbox.py:62 msgid "_Add" msgstr "A_ggiungi" #: quodlibet/browsers/audiofeeds.py:304 msgid "Audio Feeds" msgstr "Feed audio" #: quodlibet/browsers/audiofeeds.py:305 msgid "_Audio Feeds" msgstr "Feed a_udio" #: quodlibet/browsers/audiofeeds.py:408 quodlibet/qltk/data_editors.py:94 msgid "_New" msgstr "_Nuovo" #: quodlibet/browsers/audiofeeds.py:468 quodlibet/browsers/audiofeeds.py:527 msgid "Unable to add feed" msgstr "Impossibile aggiungere il feed" #: quodlibet/browsers/audiofeeds.py:469 quodlibet/browsers/audiofeeds.py:528 #, python-format msgid "" "%s could not be added. The server may be down, or the location may not be an " "audio feed." msgstr "" "%s non è stato aggiunto. Il server potrebbe essere irraggiungibile, o " "potrebbe non contenere un feed audio." #: quodlibet/browsers/audiofeeds.py:476 quodlibet/qltk/filesel.py:271 #: quodlibet/qltk/pluginwin.py:415 msgid "_Refresh" msgstr "Aggio_rna" #: quodlibet/browsers/audiofeeds.py:477 #: quodlibet/browsers/playlists/main.py:488 #: quodlibet/browsers/playlists/util.py:44 quodlibet/qltk/delete.py:144 #: quodlibet/qltk/filesel.py:268 quodlibet/qltk/lyrics.py:36 #: quodlibet/qltk/maskedbox.py:29 quodlibet/qltk/songsmenu.py:365 msgid "_Delete" msgstr "Elimina" #: quodlibet/browsers/audiofeeds.py:544 msgid "" "The current audio backend does not support URLs, Audio Feeds browser " "disabled." msgstr "" "L'attuale backend audio non supporta gli URL, il navigatore dei feed audio è " "disabilitato." #: quodlibet/browsers/_base.py:147 quodlibet/browsers/_base.py:150 msgid "Library Browser" msgstr "Navigatore libreria" #: quodlibet/browsers/_base.py:274 quodlibet/ext/songsmenu/console.py:46 #: quodlibet/ext/songsmenu/refresh.py:31 quodlibet/qltk/exfalsowindow.py:241 #: quodlibet/qltk/information.py:555 quodlibet/qltk/maskedbox.py:69 #: quodlibet/util/collection.py:533 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d brano" msgstr[1] "%d brani" #: quodlibet/browsers/_base.py:402 quodlibet/browsers/_base.py:407 #: quodlibet/qltk/tagsfrompath.py:194 quodlibet/qltk/textedit.py:141 #: quodlibet/util/__init__.py:574 msgid "Invalid pattern" msgstr "Modello non valido" #: quodlibet/browsers/collection/main.py:80 msgid "Album Collection" msgstr "Collezione album" #: quodlibet/browsers/collection/main.py:81 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:66 #: quodlibet/browsers/paned/prefs.py:83 msgid "_Custom" msgstr "_Personalizzato" #. Remove button #: quodlibet/browsers/collection/prefs.py:94 #: quodlibet/browsers/paned/prefs.py:114 #: quodlibet/browsers/playlists/menu.py:98 #: quodlibet/ext/playlist/remove_duplicates.py:61 #: quodlibet/qltk/bookmarks.py:98 quodlibet/qltk/bookmarks.py:128 #: quodlibet/qltk/cbes.py:83 quodlibet/qltk/cbes.py:90 #: quodlibet/qltk/data_editors.py:79 quodlibet/qltk/data_editors.py:92 #: quodlibet/qltk/data_editors.py:299 quodlibet/qltk/data_editors.py:312 #: quodlibet/qltk/data_editors.py:320 quodlibet/qltk/edittags.py:498 #: quodlibet/qltk/edittags.py:647 quodlibet/qltk/maskedbox.py:49 #: quodlibet/qltk/maskedbox.py:89 quodlibet/qltk/queue.py:413 #: quodlibet/qltk/scanbox.py:37 quodlibet/qltk/scanbox.py:64 msgid "_Remove" msgstr "_Rimuovi" #: quodlibet/browsers/collection/prefs.py:122 #: quodlibet/ext/songsmenu/filterall.py:35 quodlibet/operon/commands.py:56 #: quodlibet/operon/commands.py:92 quodlibet/qltk/edittags.py:435 msgid "Tag" msgstr "Tag" #: quodlibet/browsers/collection/prefs.py:128 msgid "Merge" msgstr "Unisci" #: quodlibet/browsers/collection/prefs.py:188 msgid "Album Collection Preferences" msgstr "Preferenze della collezione di album" #: quodlibet/browsers/collection/prefs.py:195 #: quodlibet/browsers/paned/prefs.py:237 #: quodlibet/ext/songsmenu/editplaycount.py:46 #: quodlibet/ext/songsmenu/exact_rating.py:39 #: quodlibet/player/gstbe/prefs.py:41 quodlibet/qltk/prefs.py:128 #: quodlibet/qltk/textedit.py:65 msgid "_Apply" msgstr "App_lica" #: quodlibet/browsers/collection/prefs.py:198 #: quodlibet/browsers/paned/prefs.py:241 #: quodlibet/browsers/playlists/menu.py:96 #: quodlibet/browsers/playlists/util.py:43 quodlibet/errorreport/ui.py:104 #: quodlibet/ext/playlist/export_to_folder.py:38 #: quodlibet/ext/playlist/remove_duplicates.py:60 #: quodlibet/ext/_shared/squeezebox/util.py:20 #: quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/editplaycount.py:45 #: quodlibet/ext/songsmenu/fingerprint/search.py:282 #: quodlibet/ext/songsmenu/fingerprint/submit.py:91 #: quodlibet/ext/songsmenu/importexport.py:39 #: quodlibet/ext/songsmenu/lastfmsync.py:219 #: quodlibet/ext/songsmenu/playlist.py:51 #: quodlibet/ext/songsmenu/replaygain.py:354 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/chooser.py:189 #: quodlibet/qltk/chooser.py:210 quodlibet/qltk/chooser.py:234 #: quodlibet/qltk/chooser.py:258 quodlibet/qltk/delete.py:91 #: quodlibet/qltk/delete.py:134 quodlibet/qltk/edittags.py:291 #: quodlibet/qltk/_editutils.py:40 quodlibet/qltk/getstring.py:29 #: quodlibet/qltk/maskedbox.py:28 quodlibet/qltk/msg.py:55 #: quodlibet/qltk/msg.py:94 quodlibet/qltk/msg.py:112 #: quodlibet/qltk/ratingsmenu.py:34 quodlibet/update.py:96 msgid "_Cancel" msgstr "_Annulla" #: quodlibet/browsers/covergrid/main.py:127 msgid "Cover Grid" msgstr "Griglia copertine" #: quodlibet/browsers/covergrid/main.py:128 msgid "_Cover Grid" msgstr "_Griglia copertine" #: quodlibet/browsers/covergrid/prefs.py:55 msgid "Cover Grid Preferences" msgstr "Preferenze della griglia copertine" #: quodlibet/browsers/covergrid/prefs.py:65 msgid "Show album _text" msgstr "Mostra _testo album" #: quodlibet/browsers/covergrid/prefs.py:72 msgid "Show \"All Albums\" Item" msgstr "Mostra voce \"Tutti gli album\"" #: quodlibet/browsers/covergrid/prefs.py:79 msgid "Wide Mode" msgstr "Modalità ampia" #: quodlibet/browsers/covergrid/prefs.py:111 #: quodlibet/browsers/covergrid/prefs.py:112 msgid "Cover Magnification" msgstr "Ingrandimento copertina" #: quodlibet/browsers/filesystem.py:40 msgid "File System" msgstr "File system" #: quodlibet/browsers/filesystem.py:41 msgid "_File System" msgstr "File s_ystem" #: quodlibet/browsers/filesystem.py:125 quodlibet/qltk/songlist.py:256 msgid "Unable to copy songs" msgstr "Impossibile copiare i brani" #: quodlibet/browsers/filesystem.py:126 quodlibet/qltk/songlist.py:257 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:198 msgid "_Add to Library" msgstr "_Aggiungi alla libreria" #: quodlibet/browsers/iradio.py:182 msgid "Unsupported file type" msgstr "Tipo di file non supportato" #: quodlibet/browsers/iradio.py:183 #, 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:230 quodlibet/browsers/iradio.py:243 #: quodlibet/browsers/iradio.py:826 msgid "Unable to add station" msgstr "Impossibile aggiungere la stazione" #: quodlibet/browsers/iradio.py:254 quodlibet/browsers/iradio.py:487 msgid "Internet Radio" msgstr "Radio Internet" #: quodlibet/browsers/iradio.py:254 msgid "Downloading station list" msgstr "Scarica lista stazioni" #: quodlibet/browsers/iradio.py:355 msgid "New Station" msgstr "Nuova stazione" #: quodlibet/browsers/iradio.py:356 msgid "Enter the location of an Internet radio station:" msgstr "Inserire l'indirizzo di una stazione radio Internet" #: quodlibet/browsers/iradio.py:374 msgid "Electronic" msgstr "Elettronica" #: quodlibet/browsers/iradio.py:377 msgid "Hip Hop / Rap" msgstr "" #: quodlibet/browsers/iradio.py:378 msgid "Oldies" msgstr "Vecchie glorie" #: quodlibet/browsers/iradio.py:379 msgid "R&B" msgstr "" #: quodlibet/browsers/iradio.py:380 msgid "Japanese" msgstr "Giapponese" #: quodlibet/browsers/iradio.py:381 msgid "Indian" msgstr "Indiana" #: quodlibet/browsers/iradio.py:383 msgid "Religious" msgstr "Religioso" #: quodlibet/browsers/iradio.py:385 msgid "Charts" msgstr "Classifiche" #: quodlibet/browsers/iradio.py:386 msgid "Turkish" msgstr "Turca" #: quodlibet/browsers/iradio.py:387 msgid "Reggae / Dancehall" msgstr "" #: quodlibet/browsers/iradio.py:388 msgid "Latin" msgstr "Latino americana" #: quodlibet/browsers/iradio.py:389 msgid "College Radio" msgstr "" #: quodlibet/browsers/iradio.py:390 msgid "Talk / News" msgstr "Conversazione / Notizie" #: quodlibet/browsers/iradio.py:391 msgid "Ambient" msgstr "" #: quodlibet/browsers/iradio.py:392 msgid "Jazz" msgstr "" #: quodlibet/browsers/iradio.py:393 quodlibet/ext/events/equalizer.py:46 msgid "Classical" msgstr "Classica" #: quodlibet/browsers/iradio.py:394 quodlibet/ext/events/equalizer.py:61 msgid "Pop" msgstr "" #: quodlibet/browsers/iradio.py:395 msgid "Alternative" msgstr "Alternativa" #: quodlibet/browsers/iradio.py:396 msgid "Metal" msgstr "" #: quodlibet/browsers/iradio.py:397 msgid "Country" msgstr "" #: quodlibet/browsers/iradio.py:398 msgid "News" msgstr "Notizie" #: quodlibet/browsers/iradio.py:399 msgid "Schlager" msgstr "" #: quodlibet/browsers/iradio.py:400 msgid "Funk" msgstr "" #: quodlibet/browsers/iradio.py:401 msgid "Indie" msgstr "" #: quodlibet/browsers/iradio.py:402 msgid "Blues" msgstr "" #: quodlibet/browsers/iradio.py:403 msgid "Soul" msgstr "" #: quodlibet/browsers/iradio.py:404 msgid "Lounge" msgstr "" #: quodlibet/browsers/iradio.py:405 msgid "Punk" msgstr "" #: quodlibet/browsers/iradio.py:406 msgid "Reggaeton" msgstr "" #: quodlibet/browsers/iradio.py:408 msgid "Slavic" msgstr "Slava" #: quodlibet/browsers/iradio.py:410 msgid "Greek" msgstr "Greca" #: quodlibet/browsers/iradio.py:411 msgid "Gothic" msgstr "Gotica" #: quodlibet/browsers/iradio.py:412 quodlibet/ext/events/equalizer.py:39 msgid "Rock" msgstr "" #: quodlibet/browsers/iradio.py:465 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:471 msgid "_Load Stations" msgstr "_Carica stazioni" #: quodlibet/browsers/iradio.py:488 msgid "_Internet Radio" msgstr "Radio _Internet" #: quodlibet/browsers/iradio.py:554 msgid "_New Station…" msgstr "_Nuova stazione…" #: quodlibet/browsers/iradio.py:557 msgid "_Update Stations" msgstr "_Aggiorna stazioni" #: quodlibet/browsers/iradio.py:584 msgid "All Stations" msgstr "Tutte le stazioni" #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:588 quodlibet/browsers/soundcloud/main.py:66 msgid "Favorites" msgstr "Preferiti" #: quodlibet/browsers/iradio.py:596 msgid "No Category" msgstr "Nessuna categoria" #: quodlibet/browsers/iradio.py:818 msgid "No stations found" msgstr "Nessuna stazione trovata" #: quodlibet/browsers/iradio.py:819 #, python-format msgid "No Internet radio stations were found at %s." msgstr "Nessuna stazione radio Internet trovata su %s." #: quodlibet/browsers/iradio.py:827 msgid "All stations listed are already in your library." msgstr "Tutte le stazioni elencate sono già nella tua libreria." #: quodlibet/browsers/iradio.py:844 msgid "Add to Favorites" msgstr "Aggiungi ai pre_feriti" #: quodlibet/browsers/iradio.py:848 msgid "Remove from Favorites" msgstr "Rimuovi dai pre_feriti" #: quodlibet/browsers/iradio.py:948 #, 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:43 quodlibet/qltk/shortcuts.py:45 msgid "Paned Browser" msgstr "Navigatore a pannelli" #: quodlibet/browsers/paned/main.py:44 msgid "_Paned Browser" msgstr "Navigatore a _pannelli" #: quodlibet/browsers/paned/main.py:94 msgid "Select _All" msgstr "Selezion_a tutto" #: quodlibet/browsers/paned/models.py:104 quodlibet/qltk/pluginwin.py:123 #: quodlibet/qltk/pluginwin.py:165 msgid "All" msgstr "Tutti" #: quodlibet/browsers/paned/prefs.py:99 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "<tt>%s</tt>" msgstr "" "Modello di tag con markup opzionale es. <tt>composer</tt> o \n" "<tt>%s</tt>" #: quodlibet/browsers/paned/prefs.py:221 msgid "Paned Browser Preferences" msgstr "Preferenze del navigatore a pannelli" #: quodlibet/browsers/paned/prefs.py:226 msgid "Column layout" msgstr "Layout colonne" #: quodlibet/browsers/paned/prefs.py:230 msgid "Column content" msgstr "Contenuto colonne" #: quodlibet/browsers/paned/prefs.py:232 msgid "Equal pane width" msgstr "Larghezza uguale del pannello" #: quodlibet/browsers/playlists/main.py:49 #: quodlibet/browsers/playlists/main.py:604 quodlibet/qltk/pluginwin.py:169 msgid "Playlists" msgstr "Scalette" #: quodlibet/browsers/playlists/main.py:50 msgid "_Playlists" msgstr "_Scalette" #: quodlibet/browsers/playlists/main.py:153 msgid "_Remove from Playlist" msgstr "_Rimuovi dalla scaletta" #: quodlibet/browsers/playlists/main.py:218 msgid "New" msgstr "Nuovo" #: quodlibet/browsers/playlists/main.py:222 msgid "Import" msgstr "Importa" #: quodlibet/browsers/playlists/main.py:444 msgid "Unable to import playlist" msgstr "Impossibile importare la scaletta" #: quodlibet/browsers/playlists/main.py:445 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:495 msgid "_Rename" msgstr "_Rinomina" #: quodlibet/browsers/playlists/main.py:593 msgid "Unable to rename playlist" msgstr "Impossibile rinominare la scaletta" #: quodlibet/browsers/playlists/main.py:605 msgid "Import Playlist" msgstr "Importa una scaletta" #: quodlibet/browsers/playlists/main.py:605 msgid "_Import" msgstr "_Importa" #: quodlibet/browsers/playlists/menu.py:26 msgid "_New Playlist…" msgstr "_Nuova scaletta…" #: quodlibet/browsers/playlists/menu.py:87 #, 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:91 #, python-format msgid "Confirm action for playlist \"%s\"" msgstr "Conferma azione per la scaletta \"%s\"" #: quodlibet/browsers/playlists/prefs.py:22 msgid "empty" msgstr "vuota" #: quodlibet/browsers/playlists/prefs.py:40 msgid "Example Playlist" msgstr "Scaletta di esempio" #: quodlibet/browsers/playlists/prefs.py:48 msgid "Playlist Browser Preferences" msgstr "Preferenze del navigatore delle scalette" #: quodlibet/browsers/playlists/prefs.py:53 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:51 #: quodlibet/browsers/playlists/util.py:126 quodlibet/util/collection.py:576 msgid "New Playlist" msgstr "Nuova scaletta" #: quodlibet/browsers/playlists/util.py:52 msgid "Enter a name for the new playlist:" msgstr "Inserisci un nome per la nuova scaletta:" #: quodlibet/browsers/playlists/util.py:90 #, 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/search.py:32 msgid "_Limit Results" msgstr "_Limita i risultati" #: quodlibet/browsers/search.py:47 msgid "Search Library" msgstr "Cerca nella libreria" #: quodlibet/browsers/search.py:48 msgid "_Search Library" msgstr "_Cerca nella libreria" #: 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:79 msgid "Search" msgstr "Cerca" #: quodlibet/browsers/soundcloud/main.py:70 msgid "My tracks" msgstr "Le mie tracce" #: quodlibet/browsers/soundcloud/main.py:142 #, python-format msgid "Go to %s" msgstr "Vai a %s" #: quodlibet/browsers/soundcloud/main.py:394 msgid "Connected" msgstr "Connesso" #: quodlibet/browsers/soundcloud/main.py:395 #, python-format msgid "Quod Libet is now connected, <b>%s</b>!" msgstr "Quod Libet adesso è connesso, <b>%s</b>!" #: quodlibet/browsers/soundcloud/main.py:407 #, python-format msgid "Log out of %s" msgstr "Uscita di %s" #: quodlibet/browsers/soundcloud/main.py:409 msgid "Enter code…" msgstr "Inserisci il codice…" #: quodlibet/browsers/soundcloud/main.py:410 #, python-format msgid "Log in to %s" msgstr "Ingresso in %s" #: quodlibet/browsers/soundcloud/util.py:87 msgid "Soundcloud authorisation" msgstr "Autorizzazione di Soundcloud" #: quodlibet/browsers/soundcloud/util.py:88 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 "Print player status" msgstr "Mostra lo stato attuale" #: quodlibet/cli.py:106 msgid "Hide main window" msgstr "Nascondi la finestra principale" #: quodlibet/cli.py:107 msgid "Show main window" msgstr "Mostra la finestra principale" #: quodlibet/cli.py:108 msgid "Toggle main window visibility" msgstr "Commuta la visibilità della finestra principale" #: quodlibet/cli.py:109 msgid "Focus the running player" msgstr "Dai il fuoco al riproduttore in esecuzione" #: quodlibet/cli.py:110 msgid "Remove active browser filters" msgstr "Rimuovi i filtri attivi del navigatore" #: quodlibet/cli.py:111 msgid "Refresh and rescan library" msgstr "Aggiorna e riscansiona la libreria" #: quodlibet/cli.py:112 msgid "List available browsers" msgstr "Mostra navigatori disponibili" #: quodlibet/cli.py:113 msgid "Print the current playlist" msgstr "Stampa la scaletta attuale" #: quodlibet/cli.py:114 msgid "Print the contents of the queue" msgstr "Stampa il contenuto della coda" #: quodlibet/cli.py:115 msgid "Print the active text query" msgstr "Stampa l'interrogazione di testo attiva" #: quodlibet/cli.py:116 msgid "Start without plugins" msgstr "Avvia senza plugin" #: quodlibet/cli.py:117 msgid "Start Quod Libet if it isn't running" msgstr "Avvia Quod Libet se non è in esecuzione" #: quodlibet/cli.py:118 msgid "Exit Quod Libet" msgstr "Esci da Quod Libet" #: quodlibet/cli.py:123 msgid "Seek within the playing song" msgstr "Posiziona nel brano in riproduzione" #: quodlibet/cli.py:123 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: quodlibet/cli.py:124 msgid "Set or toggle shuffle mode" msgstr "Imposta o commuta la modalità casuale" #: quodlibet/cli.py:125 msgid "Set shuffle mode type" msgstr "Imposta il tipo di modalità casuale" #: quodlibet/cli.py:126 msgid "Turn repeat off, on, or toggle it" msgstr "Attiva, disattiva o commuta la ripetizione" #: quodlibet/cli.py:127 msgid "Set repeat mode type" msgstr "Imposta il tipo di modalità di ripetizione" #: quodlibet/cli.py:128 msgid "Set the volume" msgstr "Imposta il volume" #: quodlibet/cli.py:129 msgid "Search your audio library" msgstr "Cerca nella tua libreria audio" #: quodlibet/cli.py:129 quodlibet/cli.py:139 quodlibet/cli.py:143 #: quodlibet/cli.py:145 msgid "query" msgstr "interrogazione" #: quodlibet/cli.py:130 msgid "Play a file" msgstr "Riproduci un file" #: quodlibet/cli.py:130 quodlibet/cli.py:139 quodlibet/cli.py:145 msgctxt "command" msgid "filename" msgstr "nome del file" #: quodlibet/cli.py:131 msgid "Rate the playing song" msgstr "Dai un giudizio al brano in riproduzione" #: quodlibet/cli.py:132 msgid "Set the current browser" msgstr "Imposta il navigatore attuale" #: quodlibet/cli.py:133 msgid "Stop after the playing song" msgstr "_Ferma dopo il brano in riproduzione" #: quodlibet/cli.py:134 msgid "Open a new browser" msgstr "Apri un nuovo navigatore" #: quodlibet/cli.py:135 msgid "Show or hide the queue" msgstr "Mostra o nascondi la coda" #: quodlibet/cli.py:136 msgid "Filter on a random value" msgstr "Filtro su un valore casuale" #: quodlibet/cli.py:136 msgctxt "command" msgid "tag" msgstr "tag" #: quodlibet/cli.py:137 msgid "Filter on a tag value" msgstr "Filtro su un tag" #: quodlibet/cli.py:137 msgid "tag=value" msgstr "tag=valore" #: quodlibet/cli.py:138 msgid "Enqueue a file or query" msgstr "Accoda un file o interrogazione" #: quodlibet/cli.py:140 msgid "Enqueue comma-separated files" msgstr "Accoda i file separati dalla virgola" #: quodlibet/cli.py:141 quodlibet/util/tags.py:158 msgid "filename" msgstr "nome del file" #: quodlibet/cli.py:142 msgid "Print filenames of results of query to stdout" msgstr "" "Stampa i nomi dei file ottenuti dall'interrogazione sullo standard output" #: quodlibet/cli.py:144 msgid "Unqueue a file or query" msgstr "Rimuovi un file o una ricerca dalla coda" #: quodlibet/cli.py:146 msgid "Add a file or directory to the library" msgstr "Aggiungi un file o una directory alla libreria" #: quodlibet/cli.py:147 quodlibet/util/tags.py:101 msgid "location" msgstr "posizione" #: quodlibet/cli.py:207 #, python-format msgid "Invalid argument for '%s'." msgstr "Argomento non valido per '%s'." #: quodlibet/cli.py:208 quodlibet/util/__init__.py:174 #, python-format msgid "Try %s --help." msgstr "Prova %s --help." #: quodlibet/errorreport/ui.py:59 msgid "An Error Occurred" msgstr "È avvenuto un errore" #: quodlibet/errorreport/ui.py:61 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:70 quodlibet/errorreport/ui.py:86 msgid "Submit Error Report" msgstr "Invia rapporto di errore" #: quodlibet/errorreport/ui.py:71 msgid "Quit Program" msgstr "Esci dal programma" #: quodlibet/errorreport/ui.py:72 msgid "Ignore Error" msgstr "Ignora l'errore" #: quodlibet/errorreport/ui.py:76 msgid "Error details:" msgstr "Dettagli errore:" #: quodlibet/errorreport/ui.py:88 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:96 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:105 msgid "_Send" msgstr "_Invia" #: quodlibet/errorreport/ui.py:111 msgid "Short description…" msgstr "Breve descrizione…" #: quodlibet/errorreport/ui.py:114 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:20 msgid "Artwork URL Cover Source" msgstr "URL Opera d'arte sorgente copertina " #: quodlibet/ext/covers/artwork_url.py:21 msgid "" "Downloads covers linked to by the artwork_url tag. This works with the " "Soundcloud browser." msgstr "" "Scarica copertine collegate dal tag artwork_url dell'opera d'arte. Questo " "funziona con il navigatore Soundcloud." #: quodlibet/ext/covers/discogs.py:29 msgid "Discogs Cover Source" msgstr "Sorgente copertina Discogs" #: quodlibet/ext/covers/discogs.py:30 msgid "Downloads covers from Discogs." msgstr "Scarica le copertine da Discogs." #: quodlibet/ext/covers/lastfm.py:21 msgid "Last.fm Cover Source" msgstr "Sorgente Last.fm della copertina" #: quodlibet/ext/covers/lastfm.py:22 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:27 msgid "Convert Encodings" msgstr "Converti codifiche" #: quodlibet/ext/editing/iconv.py:28 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:34 msgid "_Convert Encoding…" msgstr "_Converti codifica…" #: quodlibet/ext/editing/kakasi.py:27 msgid "Kana/Kanji Simple Inverter" msgstr "Semplice inverter Kana/Kanji" #: quodlibet/ext/editing/kakasi.py:28 msgid "Converts kana/kanji to romaji before renaming." msgstr "Converte kana/kanji a romaji prima di rinominare" #: quodlibet/ext/editing/kakasi.py:37 msgid "Romanize _Japanese text" msgstr "Romanizza il testo giapponese" #: quodlibet/ext/editing/kakasi.py:69 msgid "Couldn't find the 'Kanji Kana Simple Inverter' (kakasi)." msgstr "Impossibile trovare 'Semplice inverter Kanji Kana' (kakasi)." #: quodlibet/ext/editing/resub.py:19 msgid "Regex Substitution" msgstr "Sostituzione con espressione regolare" #: quodlibet/ext/editing/resub.py:20 msgid "" "Allows arbitrary regex substitutions (s///) 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:21 msgid "Title Case" msgstr "Maiuscole nel titolo" #: quodlibet/ext/editing/titlecase.py:22 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:41 msgid "Title-_case Value" msgstr "Prime lettere maiuscole del valore" #: quodlibet/ext/editing/titlecase.py:52 msgid "Allow _ALL-CAPS in tags" msgstr "_Consenti tutte maiuscole nel titolo" #: quodlibet/ext/editing/titlecase.py:53 msgid "_Human title case" msgstr "Maiuscole nel titolo _umano" #: quodlibet/ext/editing/titlecase.py:54 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:68 msgid "Advanced Preferences" msgstr "Preferenze avanzate" #: quodlibet/ext/events/advanced_preferences.py:69 msgid "Allow editing of advanced config settings." msgstr "Consenti la modifica delle impostazioni di configurazione avanzate." #: quodlibet/ext/events/advanced_preferences.py:94 msgid "ID3 encodings:" msgstr "Codifiche _ID3:" #: quodlibet/ext/events/advanced_preferences.py:95 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." #: quodlibet/ext/events/advanced_preferences.py:102 msgid "Search tags:" msgstr "Ricerca di _tag:" #: quodlibet/ext/events/advanced_preferences.py:103 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 \",\"." #: quodlibet/ext/events/advanced_preferences.py:108 msgid "Rating symbol (full):" msgstr "Simbolo di giudizio (_pieno):" #: quodlibet/ext/events/advanced_preferences.py:113 msgid "Rating symbol (blank):" msgstr "Simbolo di giudizio (_vuoto):" #: quodlibet/ext/events/advanced_preferences.py:118 msgid "Backend:" msgstr "_Backend:" #: quodlibet/ext/events/advanced_preferences.py:119 msgid "Identifier of the playback backend to use" msgstr "Identificatore del backend di riproduzione da usare" #: quodlibet/ext/events/advanced_preferences.py:124 msgid "Disable hints:" msgstr "Disattiva _suggerimenti:" #: quodlibet/ext/events/advanced_preferences.py:125 msgid "Disable popup windows (treeview hints)" msgstr "Disattiva finestre popup (suggerimenti della vista ad albero)" #: quodlibet/ext/events/advanced_preferences.py:130 msgid "Album cover size:" msgstr "Dimensioni _copertina album:" #: quodlibet/ext/events/advanced_preferences.py:131 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)" #: quodlibet/ext/events/advanced_preferences.py:137 msgid "Disable multimedia keys:" msgstr "Disattiva tasti _multimediali" #: quodlibet/ext/events/advanced_preferences.py:138 msgid "(restart required)" msgstr "(richiede il riavvio)" #: quodlibet/ext/events/advanced_preferences.py:143 msgid "Main window title:" msgstr "Titolo della _finestra principale:" #: quodlibet/ext/events/advanced_preferences.py:144 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)" #: quodlibet/ext/events/advanced_preferences.py:150 msgid "DateColumn timestamp format" msgstr "Formato data/ora della _DateColumn" #: quodlibet/ext/events/advanced_preferences.py:151 msgid "A timestamp format, e.g. %Y%m%d %X " msgstr "Un formato data/ora, ad es. %Y%m%d %X " #: quodlibet/ext/events/advanced_preferences.py:156 msgid "Scrollbars always visible:" msgstr "Barre di sc_orrimento sempre visibili:" #: quodlibet/ext/events/advanced_preferences.py:157 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)" #: quodlibet/ext/events/advanced_preferences.py:174 msgid "I know what I'm doing" msgstr "_So quello che sto facendo" #: quodlibet/ext/events/animosd/main.py:28 msgid "Animated On-Screen Display" msgstr "On-Screen Display animato" #: quodlibet/ext/events/animosd/main.py:29 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:178 msgid "_Position:" msgstr "_Posizione:" #: quodlibet/ext/events/animosd/prefs.py:190 msgid "_Cover size:" msgstr "Dimensioni _copertina:" #: quodlibet/ext/events/animosd/prefs.py:196 #: quodlibet/ext/events/weblyrics.py:319 quodlibet/qltk/prefs.py:267 msgid "Display" msgstr "Visualizzazione" #: quodlibet/ext/events/animosd/prefs.py:209 msgid "_Font:" msgstr "Caratt_ere:" #: quodlibet/ext/events/animosd/prefs.py:214 msgid "Left" msgstr "Sinistra" #: quodlibet/ext/events/animosd/prefs.py:215 msgid "Center" msgstr "Centro" #: quodlibet/ext/events/animosd/prefs.py:216 msgid "Right" msgstr "Destra" #: quodlibet/ext/events/animosd/prefs.py:219 msgid "_Align text:" msgstr "_Allinea testo:" #: quodlibet/ext/events/animosd/prefs.py:225 msgid "Text" msgstr "Testo" #: quodlibet/ext/events/animosd/prefs.py:236 msgid "_Text:" msgstr "_Testo:" #: quodlibet/ext/events/animosd/prefs.py:246 msgid "_Fill:" msgstr "_Riempimento:" #: quodlibet/ext/events/animosd/prefs.py:251 #: quodlibet/ext/events/synchronizedlyrics.py:67 msgid "Colors" msgstr "Colori" #: quodlibet/ext/events/animosd/prefs.py:259 msgid "_Shadows" msgstr "O_mbre" #: quodlibet/ext/events/animosd/prefs.py:260 msgid "_Outline" msgstr "C_ontorno" #: quodlibet/ext/events/animosd/prefs.py:261 msgid "Rou_nded Corners" msgstr "A_ngoli arrotondati" #: quodlibet/ext/events/animosd/prefs.py:277 msgid "_Delay:" msgstr "Ritar_do:" #: quodlibet/ext/events/animosd/prefs.py:283 quodlibet/qltk/pluginwin.py:173 msgid "Effects" msgstr "Effetti" #: quodlibet/ext/events/animosd/prefs.py:289 msgid "Ed_it Display Pattern…" msgstr "Modifica modello _visualizzazione…" #: quodlibet/ext/events/animosd/prefs.py:293 #: quodlibet/ext/events/trayicon/prefs.py:87 msgid "Preview" msgstr "Antepr_ima" #: 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" #: quodlibet/ext/events/auto_library_update.py:137 msgid "Automatic Library Update" msgstr "Aggiornamento automatico libreria" #: quodlibet/ext/events/auto_library_update.py:138 #, python-format msgid "Keeps your library up to date with inotify. Requires %s." msgstr "Mantiene la tua libreria aggiornata con inotify. Richiede %s." #: quodlibet/ext/events/automask.py:23 msgid "Automatic Masking" msgstr "Mascheramento automatico" #: quodlibet/ext/events/automask.py:24 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:16 msgid "Automatic Rating" msgstr "Giudizio automatico" #: quodlibet/ext/events/autorating.py:17 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." #: quodlibet/ext/events/clock.py:25 msgid "Alarm Clock" msgstr "Sveglia" #: quodlibet/ext/events/clock.py:26 msgid "Wakes you up with loud music." msgstr "Ti sveglia con musica ad alto volume." #: quodlibet/ext/events/clock.py:120 msgid "Lullaby" msgstr "Ninna nanna" #: quodlibet/ext/events/clock.py:121 msgid "Fades out and pauses your music." msgstr "Sfuma e mette in pausa la tua musica." #: quodlibet/ext/events/equalizer.py:27 msgid "Flat" msgstr "" #: quodlibet/ext/events/equalizer.py:28 msgid "Live" msgstr "" #: quodlibet/ext/events/equalizer.py:30 msgid "Full Bass & Treble" msgstr "" #: quodlibet/ext/events/equalizer.py:33 msgid "Club" msgstr "" #: quodlibet/ext/events/equalizer.py:35 msgid "Large Hall" msgstr "" #: quodlibet/ext/events/equalizer.py:37 msgid "Party" msgstr "" #: quodlibet/ext/events/equalizer.py:41 msgid "Soft" msgstr "" #: quodlibet/ext/events/equalizer.py:43 msgid "Full Bass" msgstr "" #: quodlibet/ext/events/equalizer.py:49 msgid "Reggae" msgstr "" #: quodlibet/ext/events/equalizer.py:51 msgid "Headphones" msgstr "Cuffie" #: quodlibet/ext/events/equalizer.py:54 msgid "Soft Rock" msgstr "" #: quodlibet/ext/events/equalizer.py:56 msgid "Full Treble" msgstr "" #: quodlibet/ext/events/equalizer.py:59 msgid "Dance" msgstr "" #: quodlibet/ext/events/equalizer.py:63 msgid "Techno" msgstr "" #: quodlibet/ext/events/equalizer.py:65 msgid "Ska" msgstr "" #: quodlibet/ext/events/equalizer.py:67 msgid "Laptop" msgstr "Portatile" #: quodlibet/ext/events/equalizer.py:113 msgid "Equalizer" msgstr "Equalizzatore" #: quodlibet/ext/events/equalizer.py:114 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:151 msgid "The current backend does not support equalization." msgstr "L'attuale backend non supporta l'equalizzazione." #: quodlibet/ext/events/equalizer.py:157 #, python-format msgid "%.1f kHz" msgstr "" #: quodlibet/ext/events/equalizer.py:158 #: quodlibet/ext/gstreamer/crossfeed.py:94 #: quodlibet/ext/gstreamer/karaoke.py:96 #, python-format msgid "%d Hz" msgstr "" #: quodlibet/ext/events/equalizer.py:199 #: quodlibet/ext/gstreamer/crossfeed.py:113 #, python-format msgid "%.1f dB" msgstr "" #: quodlibet/ext/events/equalizer.py:273 msgid "Default presets" msgstr "Preset predefiniti" #: quodlibet/ext/events/equalizer.py:279 quodlibet/ext/events/equalizer.py:306 msgid "Select…" msgstr "Seleziona…" #: quodlibet/ext/events/equalizer.py:294 msgid "_Reset EQ" msgstr "_Reimposta EQ" #: quodlibet/ext/events/equalizer.py:300 msgid "Custom presets" msgstr "Preset personalizzati" #: quodlibet/ext/events/equalizer.py:316 msgid "_Delete selected" msgstr "_Elimina selezionati" #: quodlibet/ext/events/equalizer.py:327 msgid "Preset name for saving:" msgstr "Nome del preset per il salvataggio:" #. Save button #: quodlibet/ext/events/equalizer.py:337 #: quodlibet/ext/playlist/export_to_squeezebox.py:81 #: quodlibet/ext/songsmenu/albumart.py:325 #: quodlibet/ext/songsmenu/brainz/widgets.py:356 #: quodlibet/ext/songsmenu/cover_download.py:310 #: quodlibet/ext/songsmenu/fingerprint/search.py:279 #: quodlibet/ext/songsmenu/html.py:76 quodlibet/ext/songsmenu/lastfmsync.py:220 #: quodlibet/ext/songsmenu/playlist.py:52 #: quodlibet/ext/songsmenu/replaygain.py:355 #: quodlibet/ext/songsmenu/tapbpm.py:188 quodlibet/qltk/_editutils.py:41 #: quodlibet/qltk/lyrics.py:35 quodlibet/qltk/msg.py:53 #: quodlibet/qltk/renamefiles.py:217 quodlibet/qltk/tagsfrompath.py:153 #: quodlibet/qltk/tracknumbers.py:113 msgid "_Save" msgstr "_Salva" #. Translators: statuses relating to Instant Messenger apps #: quodlibet/ext/events/gajim_status.py:29 msgid "online" msgstr "connesso" #: quodlibet/ext/events/gajim_status.py:30 msgid "offline" msgstr "disconnesso" #: quodlibet/ext/events/gajim_status.py:31 msgid "chat" msgstr "chat" #: quodlibet/ext/events/gajim_status.py:32 msgid "away" msgstr "lontano" #: quodlibet/ext/events/gajim_status.py:33 msgid "xa" msgstr "xa" #: quodlibet/ext/events/gajim_status.py:34 msgid "invisible" msgstr "invisibile" #: quodlibet/ext/events/gajim_status.py:39 msgid "Gajim Status Message" msgstr "Messaggio di stato di Gajim" #: quodlibet/ext/events/gajim_status.py:40 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:115 quodlibet/ext/events/mqtt.py:51 #: quodlibet/ext/events/telepathy_status.py:76 msgid "paused" msgstr "in pausa" #: quodlibet/ext/events/gajim_status.py:146 msgid "Pattern:" msgstr "Modello:" #: quodlibet/ext/events/gajim_status.py:155 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:158 msgid "Accounts:" msgstr "Account:" #: quodlibet/ext/events/gajim_status.py:162 msgid "Add '[paused]'" msgstr "Aggiungi '[in pausa]'" #: quodlibet/ext/events/gajim_status.py:165 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:189 msgid "Statuses for which message will be changed" msgstr "Stati per i quali il messaggio verrà cambiato" #: quodlibet/ext/events/headphonemon.py:158 msgid "Pause on Headphone Unplug" msgstr "Pausa allo scollegamento cuffie" #: quodlibet/ext/events/headphonemon.py:159 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:43 msgid "Inhibit Screensaver" msgstr "Inibisce salvaschermo" #: quodlibet/ext/events/inhibit.py:44 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." #: quodlibet/ext/events/inhibit.py:53 msgid "Music is playing" msgstr "Musica in riproduzione" #: 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:31 msgid "JEP-118" msgstr "" #: quodlibet/ext/events/jep118.py:32 msgid "Outputs a Jabber User Tunes file to ~/.quodlibet/jabber." msgstr "Emette un file di Jabber User Tunes in ~/.quodlibet/jabber." #: quodlibet/ext/events/language.py:22 msgid "Change Language" msgstr "Cambia lingua" #: quodlibet/ext/events/language.py:23 msgid "Change the user interface language." msgstr "Cambia la lingua dell'interfaccia utente." #: quodlibet/ext/events/language.py:44 msgid "System Default" msgstr "Predefinito di sistema" #: quodlibet/ext/events/language.py:71 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:37 msgid "UPnP AV Media Server" msgstr "Server Media UPnP AV" #: quodlibet/ext/events/mediaserver.py:38 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:45 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:62 msgid "MPD Server" msgstr "Server MPD" #: quodlibet/ext/events/mpdserver/__init__.py:63 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:77 msgid "_Port:" msgstr "_Porta:" #: quodlibet/ext/events/mpdserver/__init__.py:120 msgid "Local _IP:" msgstr "_IP locale:" #: quodlibet/ext/events/mpdserver/__init__.py:126 msgid "P_assword:" msgstr "" #: quodlibet/ext/events/mpdserver/__init__.py:162 msgid "Connection" msgstr "Connessione" #: quodlibet/ext/events/mpdserver/__init__.py:164 msgid "Tested Clients" msgstr "Client testati" #: quodlibet/ext/events/mpris/__init__.py:39 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 MPRIS 1.0/2.0 D-Bus Interface " "Specification." msgstr "" "Consente il controllo di Quod Libet usando la specifica d'interfaccia DBUS " "MPRIS 1.0/2.0" #: quodlibet/ext/events/mpris/__init__.py:46 #: quodlibet/ext/events/trayicon/prefs.py:37 msgid "Hide main window on close" msgstr "_Nascondi la finestra principale alla chiusura" #: quodlibet/ext/events/mpris/__init__.py:49 #: quodlibet/ext/events/themeswitcher.py:85 #: 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/qltk/prefs.py:699 msgid "Preferences" msgstr "Preferenze" #: 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:128 msgid "Broker hostname" msgstr "Nome dell'host del mediatore" #: quodlibet/ext/events/mqtt.py:128 msgid "broker hostname / IP" msgstr "nome dell'host mediatore / IP" #: quodlibet/ext/events/mqtt.py:130 msgid "Broker port" msgstr "Porta del mediatore" #: quodlibet/ext/events/mqtt.py:130 msgid "broker port" msgstr "porta del mediatore" #: quodlibet/ext/events/mqtt.py:132 msgid "Topic" msgstr "Argomento" #: quodlibet/ext/events/mqtt.py:134 msgid "Playing Pattern" msgstr "Modello di riproduzione" #: quodlibet/ext/events/mqtt.py:136 msgid "Status text when a song is started." msgstr "Testo di stato quando il brano è avviato." #: quodlibet/ext/events/mqtt.py:138 msgid "Paused Pattern" msgstr "Modello in pausa" #: quodlibet/ext/events/mqtt.py:140 msgid "Text when a song is paused." msgstr "Testo quando un brano è in pausa." #: quodlibet/ext/events/mqtt.py:142 msgid "No-song Text" msgstr "Testo su nessun brano" #: quodlibet/ext/events/mqtt.py:144 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:155 msgid "MQTT Configuration" msgstr "Configurazione MQTT" #: quodlibet/ext/events/mqtt.py:159 msgid "Status Text" msgstr "Testo di stato" #: quodlibet/ext/events/mqtt.py:191 #, 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:195 #, 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:198 msgid "Connection error" msgstr "Errore di connessione" #: quodlibet/ext/events/notify.py:55 msgid "Notification text" msgstr "Testo di notifica" #: quodlibet/ext/events/notify.py:66 msgid "_Title:" msgstr "_Titolo:" #: quodlibet/ext/events/notify.py:77 quodlibet/ext/events/notify.py:113 msgid "Revert to default pattern" msgstr "Ripristina il modello predefinito" #: quodlibet/ext/events/notify.py:103 msgid "_Body:" msgstr "_Corpo:" #: quodlibet/ext/events/notify.py:123 msgid "_Show notification" msgstr "Mo_stra notifica" #: quodlibet/ext/events/notify.py:141 msgid "Show notifications" msgstr "Mo_stra notifiche" #: quodlibet/ext/events/notify.py:147 msgid "Only on <i>_manual</i> song changes" msgstr "Solo su cambi di brano <i>_manuali</i>" #: quodlibet/ext/events/notify.py:155 msgid "Only on <i>_automatic</i> song changes" msgstr "Solo su cambi di brano <i>_automatici</i>" #: quodlibet/ext/events/notify.py:163 msgid "On <i>a_ll</i> song changes" msgstr "Su <i>t_utti</i> i cambi di brano" #: quodlibet/ext/events/notify.py:178 msgid "Only when the main window is not _focused" msgstr "Solo quando la _finestra principale non ha il fuoco" #: quodlibet/ext/events/notify.py:186 msgid "Show \"_Next\" button" msgstr "Mostra il pulsante \"_Prossimo\"" #: quodlibet/ext/events/notify.py:208 msgid "Connection Error" msgstr "Errore di connessione" #: quodlibet/ext/events/notify.py:209 quodlibet/ext/events/notify.py:369 #: quodlibet/ext/events/notify.py:411 msgid "Couldn't connect to notification daemon." msgstr "Impossibile connettersi al demone di notifica." #: quodlibet/ext/events/notify.py:223 msgid "Song Notifications" msgstr "Notifiche brani" #: quodlibet/ext/events/notify.py:224 msgid "Displays a notification when the song changes." msgstr "Mostra una notifica quando cambia il brano." #: quodlibet/ext/events/notify.py:393 quodlibet/qltk/unity.py:63 msgid "Next" msgstr "Prossimo" #: quodlibet/ext/events/qlscrobbler.py:176 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:253 #, python-format msgid "Could not contact service '%s'." msgstr "Impossibile contattare il servizio '%s'." #: quodlibet/ext/events/qlscrobbler.py:259 msgid "Authentication failed: invalid URL." msgstr "Autenticazione fallita: URL non valido." #: quodlibet/ext/events/qlscrobbler.py:276 #, 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:281 msgid "Client is banned. Contact the author." msgstr "Il client è stato bannato. Contatta l'autore." #: quodlibet/ext/events/qlscrobbler.py:285 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:350 msgid "AudioScrobbler Submission" msgstr "Invio AudioScrobbler" #: quodlibet/ext/events/qlscrobbler.py:351 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:456 msgid "Authentication successful." msgstr "Autenticazione riuscita." #: quodlibet/ext/events/qlscrobbler.py:468 msgid "_Service:" msgstr "_Servizio:" #: quodlibet/ext/events/qlscrobbler.py:468 msgid "_URL:" msgstr "_URL:" #: quodlibet/ext/events/qlscrobbler.py:468 msgid "User_name:" msgstr "_Nome utente:" #: quodlibet/ext/events/qlscrobbler.py:469 msgid "_Password:" msgstr "" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:485 msgid "Other…" msgstr "Altro…" #. verify data #: quodlibet/ext/events/qlscrobbler.py:523 msgid "_Verify account data" msgstr "_Verifica dati account" #: quodlibet/ext/events/qlscrobbler.py:528 #: quodlibet/ext/songsmenu/lastfmsync.py:313 msgid "Account" msgstr "" #: quodlibet/ext/events/qlscrobbler.py:536 msgid "_Artist pattern:" msgstr "Modello _artista:" #: quodlibet/ext/events/qlscrobbler.py:536 msgid "_Title pattern:" msgstr "Modello per il _titolo:" #: quodlibet/ext/events/qlscrobbler.py:537 msgid "Exclude _filter:" msgstr "_Filtro di esclusione:" #: quodlibet/ext/events/qlscrobbler.py:555 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "Autenticazione riuscita." #: quodlibet/ext/events/qlscrobbler.py:565 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:574 msgid "Songs matching this filter will not be submitted." msgstr "I brani corrispondenti a questo filtro non saranno inviati." #: quodlibet/ext/events/qlscrobbler.py:582 msgid "_Offline mode (don't submit anything)" msgstr "Modalità disc_onnessa (non invia niente)." #: quodlibet/ext/events/qlscrobbler.py:586 msgid "Submission" msgstr "Invio" #: quodlibet/ext/events/radioadmute.py:21 msgid "Mute Radio Ads" msgstr "Pubblicità radio mute" #: quodlibet/ext/events/radioadmute.py:22 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:29 msgid "Random Album Playback" msgstr "Riproduzione album casuale" #: quodlibet/ext/events/randomalbum.py:30 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:40 msgid "Rated higher" msgstr "Giudicati più alti" #: quodlibet/ext/events/randomalbum.py:41 msgid "Played more often" msgstr "Riprodotti più spesso" #: quodlibet/ext/events/randomalbum.py:42 msgid "Skipped more often" msgstr "Saltati più spesso" #: quodlibet/ext/events/randomalbum.py:43 msgid "Played more recently" msgstr "Riprodotti più recentemente" #: quodlibet/ext/events/randomalbum.py:44 msgid "Started more recently" msgstr "Avviati più recentemente" #: quodlibet/ext/events/randomalbum.py:45 msgid "Added more recently" msgstr "Aggiunti più recentemente" #: quodlibet/ext/events/randomalbum.py:46 msgid "Longer albums" msgstr "Album più lunghi" #: quodlibet/ext/events/randomalbum.py:85 msgid "seconds before starting next album" msgstr "_secondi prima di avviare il prossimo album" #: quodlibet/ext/events/randomalbum.py:89 msgid "Weights" msgstr "Pesi" #: quodlibet/ext/events/randomalbum.py:91 msgid "Play some albums more than others" msgstr "Riproduci certi album più di altri" #: quodlibet/ext/events/randomalbum.py:105 msgid "avoid" msgstr "evita" #: quodlibet/ext/events/randomalbum.py:116 msgid "prefer" msgstr "preferisci" #: quodlibet/ext/events/randomalbum.py:220 msgid "Random Album" msgstr "Album casuale" #: quodlibet/ext/events/randomalbum.py:221 #, python-format msgid "Waiting to start %s" msgstr "In attesa di avviare %s" #: quodlibet/ext/events/rbimport.py:115 msgid "Import Failed" msgstr "Importazione fallita" #: 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/rbimport.py:133 msgid "Start Import" msgstr "Avvia importazione" #: quodlibet/ext/events/screensaver.py:27 msgid "Screensaver Pause" msgstr "Pausa durante salvaschermo" #: quodlibet/ext/events/screensaver.py:28 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:74 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:80 msgid "GNOME Search Provider" msgstr "Fornitore di ricerca GNOME" #: quodlibet/ext/events/searchprovider.py:81 msgid "Allows GNOME Shell to search the library." msgstr "Consente a GNOME Shell di cercare nella libreria" #: quodlibet/ext/events/seekbar.py:123 msgid "Alternative Seek Bar" msgstr "Barra di posizionamento alternativa" #: quodlibet/ext/events/seekbar.py:124 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:21 msgid "Seekpoint Bookmarks" msgstr "Segnalibri punti di posizionamento" #: quodlibet/ext/events/seekpoints.py:25 msgid "" "Store Seekpoints A and/or B for tracks. Skip to time A and stop after time B " "when track is played.\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:109 msgid "Bookmark name for point A" msgstr "Nome del segnalibro per il punto A" #: quodlibet/ext/events/seekpoints.py:110 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:125 msgid "Bookmark name for point B" msgstr "Nome del segnalibro per il punto B" #: quodlibet/ext/events/seekpoints.py:126 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:29 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:58 #: 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:59 #: 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/synchronizedlyrics.py:35 msgid "Synchronized Lyrics" msgstr "Testi sincronizzati" #: quodlibet/ext/events/synchronizedlyrics.py:36 msgid "Shows synchronized lyrics from .lrc file with same name as the track." msgstr "Mostra testi sincronizzati da file .lrc con lo stesso nome del brano." #: quodlibet/ext/events/synchronizedlyrics.py:70 msgid "Text:" msgstr "_Testo:" #: quodlibet/ext/events/synchronizedlyrics.py:80 msgid "Background:" msgstr "_Sfondo:" #: quodlibet/ext/events/synchronizedlyrics.py:91 msgid "Font" msgstr "Carattere" #: quodlibet/ext/events/synchronizedlyrics.py:94 msgid "Size (px):" msgstr "_Dimensione (px):" #: quodlibet/ext/events/telepathy_status.py:69 msgid "Telepathy Status Messages" msgstr "Messaggi di stato di Telepathy" #: quodlibet/ext/events/telepathy_status.py:70 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:129 msgid "Playing:" msgstr "In riproduzione:" #: quodlibet/ext/events/telepathy_status.py:130 #, 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:146 msgid "Paused:" msgstr "In pausa:" #: quodlibet/ext/events/telepathy_status.py:147 #, 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:163 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:164 msgid "No song:" msgstr "Nessun brano:" #. Frame #: quodlibet/ext/events/telepathy_status.py:171 msgid "Status Patterns" msgstr "Modelli di stato" #: quodlibet/ext/events/themeswitcher.py:26 msgid "Theme Switcher" msgstr "Commutatore di temi" #: quodlibet/ext/events/themeswitcher.py:27 msgid "Changes the active GTK+ theme." msgstr "Cambia il tema GTK+ attivo." #: quodlibet/ext/events/themeswitcher.py:50 msgid "_Theme:" msgstr "_Tema:" #: quodlibet/ext/events/themeswitcher.py:55 msgid "Default Theme" msgstr "Tema predefinito" #: quodlibet/ext/events/themeswitcher.py:67 msgid "Prefer dark theme version" msgstr "_Preferisci la versione scura del tema" #: quodlibet/ext/events/toggle_menu.py:19 msgid "Toggle Menu Bar" msgstr "Commuta barra dei menu" #: quodlibet/ext/events/toggle_menu.py:20 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:77 #: quodlibet/ext/events/trayicon/prefs.py:107 #: quodlibet/ext/events/trayicon/systemtray.py:178 quodlibet/qltk/info.py:48 msgid "Not playing" msgstr "Non in riproduzione" #: quodlibet/ext/events/trayicon/__init__.py:54 msgid "Tray Icon" msgstr "Icona del cassetto" #: quodlibet/ext/events/trayicon/__init__.py:55 msgid "Controls Quod Libet from the system tray." msgstr "Controlla Quod Libet dal cassetto di sistema." #: quodlibet/ext/events/trayicon/menu.py:42 #, python-format msgid "_Show %(application-name)s" msgstr "Mo_stra %(application-name)s" #: quodlibet/ext/events/trayicon/menu.py:61 #: quodlibet/qltk/quodlibetwindow.py:184 quodlibet/qltk/quodlibetwindow.py:937 #: quodlibet/qltk/quodlibetwindow.py:1141 msgid "_Play" msgstr "Ri_produci" #: quodlibet/ext/events/trayicon/menu.py:64 #: quodlibet/qltk/quodlibetwindow.py:186 quodlibet/qltk/quodlibetwindow.py:1143 #: quodlibet/qltk/wlw.py:51 msgid "P_ause" msgstr "P_ausa" #: quodlibet/ext/events/trayicon/menu.py:69 #: quodlibet/qltk/quodlibetwindow.py:191 quodlibet/qltk/quodlibetwindow.py:932 msgid "Pre_vious" msgstr "Prece_dente" #: quodlibet/ext/events/trayicon/menu.py:72 #: quodlibet/qltk/quodlibetwindow.py:195 quodlibet/qltk/quodlibetwindow.py:942 msgid "_Next" msgstr "_Prossimo" #: quodlibet/ext/events/trayicon/menu.py:77 msgid "_Shuffle" msgstr "_Casuale" #: quodlibet/ext/events/trayicon/menu.py:82 msgid "_Repeat" msgstr "_Ripeti" #: quodlibet/ext/events/trayicon/menu.py:87 msgid "Stop _After This Song" msgstr "_Ferma dopo questo brano" #: quodlibet/ext/events/trayicon/menu.py:93 #: quodlibet/qltk/quodlibetwindow.py:903 msgid "Open _Browser" msgstr "Apri na_vigatore" #: quodlibet/ext/events/trayicon/menu.py:104 #: quodlibet/qltk/quodlibetwindow.py:922 quodlibet/qltk/songsmenu.py:384 msgid "Edit _Tags" msgstr "Modifica i _tag" #: quodlibet/ext/events/trayicon/menu.py:113 #: quodlibet/qltk/quodlibetwindow.py:865 quodlibet/qltk/songsmenu.py:397 msgid "_Information" msgstr "_Informazioni" #: quodlibet/ext/events/trayicon/menu.py:115 quodlibet/qltk/songsmenu.py:325 msgid "Play_lists" msgstr "Sca_lette" #: quodlibet/ext/events/trayicon/menu.py:133 #: quodlibet/qltk/quodlibetwindow.py:917 msgid "_Quit" msgstr "_Esci" #: quodlibet/ext/events/trayicon/prefs.py:39 quodlibet/qltk/prefs.py:70 msgid "Behavior" msgstr "Comportamento" #: quodlibet/ext/events/trayicon/prefs.py:49 msgid "Scroll wheel adjusts volume" msgstr "La rotella di scorrimento cambia il _volume" #: quodlibet/ext/events/trayicon/prefs.py:55 msgid "Scroll wheel changes song" msgstr "La rotella di scorrimento cambia il _brano" #: quodlibet/ext/events/trayicon/prefs.py:63 msgid "Scroll _Wheel" msgstr "Rotella di scorrimento" #: quodlibet/ext/events/trayicon/prefs.py:93 msgid "Tooltip Display" msgstr "Visualizzazione _suggerimento" #: quodlibet/ext/events/viewlyrics.py:26 msgid "View Lyrics" msgstr "Vedi i testi" #: quodlibet/ext/events/viewlyrics.py:27 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:88 #, python-format msgid "" "No lyrics found for\n" " %s" msgstr "" "Nessun testo trovato per\n" " %s" #: quodlibet/ext/events/viewlyrics.py:118 quodlibet/ext/events/weblyrics.py:194 msgid "No active song" msgstr "Nessun brano attivo" #: quodlibet/ext/events/visualisations.py:37 msgid "Launch Visualisations" msgstr "Lancia visualizzazioni" #: quodlibet/ext/events/visualisations.py:39 msgid "Launch external visualisations." msgstr "Lancia visualizzazioni esterne." #: quodlibet/ext/events/visualisations.py:56 #, python-format msgid "Couldn't run visualisations using '%s'" msgstr "Impossibile eseguire visualizzazioni usando '%s'" #: quodlibet/ext/events/visualisations.py:58 #: quodlibet/ext/songsmenu/fingerprint/search.py:45 msgid "Error" msgstr "Errore" #: quodlibet/ext/events/visualisations.py:77 msgid "Visualiser executable:" msgstr "Eseguibile visualizzatore" #: quodlibet/ext/events/visualisations.py:92 msgid "Reload" msgstr "_Ricarica" #: quodlibet/ext/events/waveformseekbar.py:604 msgid "Waveform Seek Bar" msgstr "Barra di posizionamento a forma d'onda" #: quodlibet/ext/events/waveformseekbar.py:608 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:677 msgid "Override foreground color:" msgstr "Scavalca colore di primo piano:" #: quodlibet/ext/events/waveformseekbar.py:681 msgid "Override hover color:" msgstr "Scavalca colore svolazzante:" #: quodlibet/ext/events/waveformseekbar.py:685 msgid "Override remaining color:" msgstr "Scavalca colore rimanente:" #: quodlibet/ext/events/waveformseekbar.py:689 msgid "Show current position" msgstr "Mostra la posizione corrente" #: quodlibet/ext/events/waveformseekbar.py:694 msgid "Show time labels" msgstr "Mostra le etichette di tempo" #: quodlibet/ext/events/waveformseekbar.py:702 msgid "Seek amount when scrolling (milliseconds):" msgstr "Quantità di posizionamento allo scorrimento (millisecondi)" #: quodlibet/ext/events/weblyrics.py:209 msgid "No lyrics found" msgstr "Testi non trovati" #: quodlibet/ext/events/weblyrics.py:269 msgid "_Zoom level:" msgstr "Livello di _zoom:" #: quodlibet/ext/events/weblyrics.py:287 msgid "URL:" msgstr "_URL:" # da controllare #: quodlibet/ext/events/weblyrics.py:292 msgid "Revert to default" msgstr "Ripristina il predefinito" #: quodlibet/ext/events/weblyrics.py:307 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." #: quodlibet/ext/events/weblyrics.py:324 msgid "Alternate search" msgstr "Ricerca alternativa" # controllare contesto #: quodlibet/ext/events/weblyrics.py:333 msgid "Web Lyrics" msgstr "Testi Web" #: quodlibet/ext/events/weblyrics.py:334 msgid "Shows a sidebar containing online lyrics of the playing song." msgstr "" "Mostra una barra laterale contenente i testi online del brano corrente." #: quodlibet/ext/events/write_cover.py:34 msgid "Picture Saver" msgstr "Salva immagine" #: quodlibet/ext/events/write_cover.py:35 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:68 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 #, 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:17 msgid "Mono Downmix" msgstr "" #: quodlibet/ext/gstreamer/mono.py:18 msgid "Downmixes audio channels to mono." msgstr "Rimissa i canali audio in mono." #: quodlibet/ext/gstreamer/pitch.py:22 #, fuzzy msgid "R_ate:" msgstr "G_iudizio:" #: quodlibet/ext/gstreamer/pitch.py:23 msgid "_Tempo:" msgstr "" #: quodlibet/ext/gstreamer/pitch.py:24 msgid "_Pitch:" msgstr "Intona_zione:" #: 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:139 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:100 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:157 msgid "Default filename pattern:" msgstr "Modello del nome di file predefinito:" #: quodlibet/ext/playlist/export_to_squeezebox.py:23 msgid "Export to Squeezebox" msgstr "Esporta a Squeezebox" #: quodlibet/ext/playlist/export_to_squeezebox.py:25 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 "" "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:79 msgid "Export playlist to Squeezebox" msgstr "Esporta scaletta a Squeezebox" #: quodlibet/ext/playlist/export_to_squeezebox.py:80 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:21 msgid "Remove Playlist Duplicates" msgstr "Rimuovi duplicati scaletta" #: quodlibet/ext/playlist/remove_duplicates.py:22 msgid "Removes duplicate entries in a playlist." msgstr "Rimuove gli elementi duplicati in una scaletta." #: quodlibet/ext/playlist/remove_duplicates.py:50 #, 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:53 #, 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:16 msgid "Shuffle Playlist" msgstr "Playlist casuale" #: quodlibet/ext/playlist/shuffle.py:17 msgid "Randomly shuffles a playlist." msgstr "Mischia casualmente una scaletta." #: quodlibet/ext/playorder/follow.py:19 msgid "Follow Cursor" msgstr "Segui selezione" #: quodlibet/ext/playorder/follow.py:21 msgid "" "Playback 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/playcounteq.py:22 msgid "Playcount Equalizer" msgstr "Equalizzatore conteggio riproduzione" #: quodlibet/ext/playorder/playcounteq.py:23 msgid "Shuffle, preferring 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/queue.py:20 msgid "Queue Only" msgstr "Accoda solamente" #: quodlibet/ext/playorder/queue.py:22 msgid "" "Limits playing of songs to the queue. 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/reverse.py:15 msgid "Reverse" msgstr "Inverti" #: quodlibet/ext/playorder/reverse.py:17 msgid "Reverses the play order of songs." msgstr "Inverte l'ordine di riproduzione dei brani." #: quodlibet/ext/playorder/shufflebygrouping.py:32 #: quodlibet/ext/playorder/shufflebygrouping.py:94 msgid "Shuffle by Grouping" msgstr "Mischia raggruppando" #: quodlibet/ext/playorder/shufflebygrouping.py:33 msgid "" "Shuffles by a grouping of songs defined by a common tag instead of by track, " "similar to album shuffle. This is useful for shuffling multi-movement " "classical works while 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:95 msgid "Waiting to start new group…" msgstr "In attesa di avviare un nuovo gruppo…" #: quodlibet/ext/playorder/shufflebygrouping.py:145 msgid "Grouping tag:" msgstr "Tag di raggruppamento:" #: quodlibet/ext/playorder/shufflebygrouping.py:149 msgid "Tag to group songs by" msgstr "Tagga per ragruppare i brani per" #: quodlibet/ext/playorder/shufflebygrouping.py:151 msgid "Filter tag:" msgstr "Tag filtro:" # da controllare #: quodlibet/ext/playorder/shufflebygrouping.py:156 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:161 msgid "Delay:" msgstr "Ritardo:" #: quodlibet/ext/playorder/shufflebygrouping.py:167 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:183 msgid "Reset to defaults" msgstr "Ripristina i predefiniti" #: quodlibet/ext/playorder/skip_songs.py:26 msgid "Skip Songs" msgstr "Salta brani" #: quodlibet/ext/playorder/skip_songs.py:28 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." #: quodlibet/ext/playorder/track_repeat.py:31 msgid "Repeat Each Track" msgstr "Ripeti ogni traccia" #: quodlibet/ext/playorder/track_repeat.py:33 msgid "Shuffle songs, but repeat 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:52 msgid "Number of times to play each song:" msgstr "Numero di volte da riprodurre ogni brano:" #: quodlibet/ext/query/conditional.py:16 msgid "Conditional Query" msgstr "Interrogazione condizionale" #: quodlibet/ext/query/conditional.py:17 msgid "" "Chooses the query to match based on a condition query. Syntax is '@(if: " "condition, then, else)'." msgstr "" "Sceglie l'interrogazione da effettuare basandosi su un'interrogazione " "condizionale. La sintassi è '@(if: condition, then, else)'." #: quodlibet/ext/query/missing.py:16 msgid "Missing Query" msgstr "Interrogazione mancanti" #: quodlibet/ext/query/missing.py:17 msgid "Matches songs without the given tag." msgstr "Corrisponde ai brani senza il tag dato." #: quodlibet/ext/query/missing.py:28 msgid "Include empty tags" msgstr "_Include tag vuoti" #: quodlibet/ext/query/pythonexpression.py:19 msgid "Python Query" msgstr "Interrogazione Python" #: quodlibet/ext/query/pythonexpression.py:20 msgid "" "Use Python expressions in queries. Syntax is '@(python: expression)'. The " "variable 's' (or 'a') is the song / album being matched. '_ts' is a (real " "number) timestamp at start of query. Modules 'time' and 'random' are also " "available, and the class 'Random' (==random.Random) 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 msgid "" "Include the results of a saved search as part of another query. Syntax is " "'@(saved: search name)'." msgstr "" "Include i risultati di una ricerca salvata come parte di un'altra " "interrogazione. La sintassi è '@(saved: search name)'." #: quodlibet/ext/_shared/squeezebox/base.py:78 #, python-format msgid "Squeezebox OK. Using the only player (%s)." msgstr "Squeezebox OK. Uso solo il riproduttore (%s)." #: quodlibet/ext/_shared/squeezebox/base.py:87 #, python-format msgid "Couldn't connect to %s" msgstr "Impossibile connettersi a %s" #: quodlibet/ext/_shared/squeezebox/base.py:111 msgid "Hostname:" msgstr "Nome dell'_host:" #: quodlibet/ext/_shared/squeezebox/base.py:117 msgid "Port:" msgstr "_Porta:" #: quodlibet/ext/_shared/squeezebox/base.py:122 msgid "Username:" msgstr "Nome _utente:" #: quodlibet/ext/_shared/squeezebox/base.py:127 msgid "Password:" msgstr "Pass_word:" #: quodlibet/ext/_shared/squeezebox/base.py:131 msgid "Library directory the server connects to." msgstr "Directory della libreria alla quale il server si connette." #: quodlibet/ext/_shared/squeezebox/base.py:133 msgid "Library path:" msgstr "Percorso _libreria:" #. Add verify button #: quodlibet/ext/_shared/squeezebox/base.py:142 msgid "_Verify settings" msgstr "_Verifica impostazioni" #. Server settings Frame #: quodlibet/ext/_shared/squeezebox/base.py:148 msgid "Squeezebox Server" msgstr "Server Squeezebox" #: quodlibet/ext/_shared/squeezebox/base.py:151 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:16 msgid "Choose Squeezebox player" msgstr "Scegli riproduttore Squeezebox" #: quodlibet/ext/_shared/squeezebox/util.py:21 #: quodlibet/ext/songsmenu/importexport.py:38 quodlibet/qltk/getstring.py:22 msgid "_OK" msgstr "" #: quodlibet/ext/_shared/squeezebox/util.py:27 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:332 msgid "Fit image to _window" msgstr "Adatta i_mmagine alla finestra" #: quodlibet/ext/songsmenu/albumart.py:338 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:344 msgid "_Program:" msgstr "_Programma:" #: quodlibet/ext/songsmenu/albumart.py:349 msgid "_Edit image after saving" msgstr "Modifica immagin_e dopo il salvataggio" #: quodlibet/ext/songsmenu/albumart.py:351 msgid "File_name:" msgstr "_Nome del file:" #: quodlibet/ext/songsmenu/albumart.py:467 msgid "Saving failed" msgstr "Salvatagggio fallito" #: quodlibet/ext/songsmenu/albumart.py:468 #, python-format msgid "Unable to save \"%s\"." msgstr "Impossibile salvare \"%s\"." #: quodlibet/ext/songsmenu/albumart.py:566 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "[albumart] Errore HTTP : %s" #: quodlibet/ext/songsmenu/albumart.py:623 msgid "Album Art Downloader" msgstr "Scaricatore grafica album" #: quodlibet/ext/songsmenu/albumart.py:676 #, python-format msgid "from %(source)s" msgstr "da %(source)s" #: quodlibet/ext/songsmenu/albumart.py:679 #, python-format msgid "Resolution: %s" msgstr "Risoluzione: %s" #: quodlibet/ext/songsmenu/albumart.py:682 #, python-format msgid "Size: %s" msgstr "Dimensione: %s" #: quodlibet/ext/songsmenu/albumart.py:728 msgid "Per engine 'at best' results limit" msgstr "Limite di risultati per motore 'al meglio'" #: quodlibet/ext/songsmenu/albumart.py:738 msgid "_Search" msgstr "_Cerca" #: quodlibet/ext/songsmenu/albumart.py:820 #: quodlibet/ext/songsmenu/brainz/widgets.py:452 msgid "Searching…" msgstr "Ricerca…" #: quodlibet/ext/songsmenu/albumart.py:885 #: quodlibet/ext/songsmenu/fingerprint/search.py:43 msgid "Done" msgstr "Fatto" #: quodlibet/ext/songsmenu/albumart.py:1007 msgid "Download Album Art" msgstr "Scarica grafica album" #: quodlibet/ext/songsmenu/albumart.py:1008 msgid "Downloads album covers from various websites." msgstr "Scarica copertine degli album da vari siti web." #: quodlibet/ext/songsmenu/albumart.py:1021 msgid "Sources" msgstr "Sorgenti" #: quodlibet/ext/songsmenu/ape2id3.py:27 msgid "APEv2 to ID3v2" msgstr "Da APEv2 a ID3v2" #: quodlibet/ext/songsmenu/ape2id3.py:28 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:24 msgid "Go to Bookmark" msgstr "Vai al segnalibro" #: quodlibet/ext/songsmenu/bookmarks.py:25 msgid "Manages bookmarks in the selected files." msgstr "Gestisce i segnalibri nei file selezionati." #: quodlibet/ext/songsmenu/bookmarks.py:64 quodlibet/qltk/seekbutton.py:245 msgid "_Edit Bookmarks…" msgstr "Aggiorna S_egnalibri…" #: quodlibet/ext/songsmenu/bookmarks.py:74 msgid "No Bookmarks" msgstr "Nessun segnalibro" #: quodlibet/ext/songsmenu/brainz/__init__.py:25 msgid "MusicBrainz Lookup" msgstr "Ricerca MusicBrainz" #: quodlibet/ext/songsmenu/brainz/__init__.py:27 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:51 msgid "Only use year for \"date\" tag" msgstr "Usa solo l'anno per il tag \"date\"" #: quodlibet/ext/songsmenu/brainz/__init__.py:52 msgid "Write \"_albumartist\" when needed" msgstr "Scrivi \"_albumartist\" quando neccessario" #: quodlibet/ext/songsmenu/brainz/__init__.py:53 msgid "Write sort tags for artist names" msgstr "Scrivi tag di ordinamento per i nomi di artista" #: quodlibet/ext/songsmenu/brainz/__init__.py:54 msgid "Write _standard MusicBrainz tags" msgstr "Scrivi tag MusicBrainz _standard." #: quodlibet/ext/songsmenu/brainz/__init__.py:55 msgid "Write \"labelid\" tag" msgstr "Scrivi tag \"labelid\"" #: quodlibet/ext/songsmenu/brainz/widgets.py:130 msgid "Filename" msgstr "Nome del file" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 msgid "Disc" msgstr "Disco" #: quodlibet/ext/songsmenu/brainz/widgets.py:132 #: quodlibet/ext/songsmenu/replaygain.py:394 quodlibet/qltk/tracknumbers.py:92 msgid "Track" msgstr "Traccia" #: quodlibet/ext/songsmenu/brainz/widgets.py:133 msgid "Title" msgstr "Titolo" #: quodlibet/ext/songsmenu/brainz/widgets.py:134 msgid "Artist" msgstr "Artista" #: quodlibet/ext/songsmenu/brainz/widgets.py:353 msgid "MusicBrainz lookup" msgstr "Ricerca MusicBrainz" # controllare #: quodlibet/ext/songsmenu/brainz/widgets.py:376 msgid "_Query:" msgstr "_Interrogazione:" #: quodlibet/ext/songsmenu/brainz/widgets.py:379 msgid "S_earch" msgstr "C_erca" #: quodlibet/ext/songsmenu/brainz/widgets.py:392 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:49 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "{plugin_name} per {songs} ({app})" #: quodlibet/ext/songsmenu/console.py:56 msgid "Python Console Sidebar" msgstr "Barra laterale console Python" #: quodlibet/ext/songsmenu/console.py:57 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:76 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/cover_download.py:119 msgid "Small" msgstr "Piccolo" #: quodlibet/ext/songsmenu/cover_download.py:120 msgid "Classic" msgstr "Classico" #: quodlibet/ext/songsmenu/cover_download.py:121 msgid "Large" msgstr "Ampio" #: quodlibet/ext/songsmenu/cover_download.py:122 msgid "HD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:123 msgid "Full HD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:124 msgid "WQXGA" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:125 msgid "4K UHD" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:130 msgid "Cover Art Download" msgstr "Scaricamento grafica copertina" #: quodlibet/ext/songsmenu/cover_download.py:181 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "Caricamento di %(source)s - %(dimensions)s…" #: quodlibet/ext/songsmenu/cover_download.py:232 #, python-format msgid "" "Nothing found for albums:\n" "<i>%(albums)s</i>.\n" "\n" "Providers used:\n" "<tt>%(providers)s</tt>" 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:235 msgid "No covers found" msgstr "Nessuna copertina trovata" #: quodlibet/ext/songsmenu/cover_download.py:255 #, python-format msgid "%(size)d ✕ %(size)d px" msgstr "" #: quodlibet/ext/songsmenu/cover_download.py:268 msgid "Preview size" msgstr "Dimensioni _anteprima" #: quodlibet/ext/songsmenu/cover_download.py:277 msgid "Save destination" msgstr "Salva destinazione" #: quodlibet/ext/songsmenu/cover_download.py:337 msgid "Download Cover Art" msgstr "Scarica grafica copertina" #: quodlibet/ext/songsmenu/cover_download.py:338 msgid "Downloads high-quality album covers using cover plugins." msgstr "Scarica copertina di alta qualità usando i plugin copertina." #: quodlibet/ext/songsmenu/custom_commands.py:42 msgid "Command" msgstr "Comando" #: quodlibet/ext/songsmenu/custom_commands.py:45 msgid "name" msgstr "nome" #: quodlibet/ext/songsmenu/custom_commands.py:45 msgid "The name of this command" msgstr "Il nome di questo comando" #: quodlibet/ext/songsmenu/custom_commands.py:47 msgid "command" msgstr "comando" #: quodlibet/ext/songsmenu/custom_commands.py:47 msgid "The shell command syntax to run" msgstr "La sintassi del comando shell da eseguire" #: quodlibet/ext/songsmenu/custom_commands.py:49 msgid "parameter" msgstr "parametro" #: quodlibet/ext/songsmenu/custom_commands.py:50 #, 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 "pattern" msgstr "modello" #: quodlibet/ext/songsmenu/custom_commands.py:57 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:62 msgid "unique" msgstr "unico" #: quodlibet/ext/songsmenu/custom_commands.py:63 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:66 msgid "max args" msgstr "massimo argomenti" #: quodlibet/ext/songsmenu/custom_commands.py:67 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:92 msgid "Input value" msgstr "Valore di ingresso" #: quodlibet/ext/songsmenu/custom_commands.py:93 #, python-format msgid "Value for %s?" msgstr "Valore per %s?" #: quodlibet/ext/songsmenu/custom_commands.py:137 msgid "Custom Commands" msgstr "Comandi personalizzati" #: quodlibet/ext/songsmenu/custom_commands.py:138 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:191 #: quodlibet/ext/songsmenu/custom_commands.py:201 #: quodlibet/ext/songsmenu/custom_commands.py:255 msgid "Edit Custom Commands" msgstr "_Modifica comandi personalizzati" #: quodlibet/ext/songsmenu/custom_commands.py:202 msgid "" "Supports QL patterns\n" "eg <tt><~artist~title></tt>" msgstr "" "Supporta i modelli QL\n" "ad es. <tt><~artist~title></tt>" #: quodlibet/ext/songsmenu/custom_commands.py:286 #, python-format msgid "Unable to run custom command %s" msgstr "Non riesco ad eseguire il comando personalizzato %s" #: quodlibet/ext/songsmenu/duplicates.py:288 #, 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:341 msgid "Collapse / Expand all" msgstr "Collassa / espandi tutto" #: quodlibet/ext/songsmenu/duplicates.py:345 #, python-format msgid "Duplicate key expression is '%s'" msgstr "L'espressione chiave duplicata è '%s'" #: quodlibet/ext/songsmenu/duplicates.py:370 msgid "Duplicates Browser" msgstr "Duplica il navigatore" #: quodlibet/ext/songsmenu/duplicates.py:371 msgid "Finds and displays similarly tagged versions of songs." msgstr "Trova e mostra versioni dei brani taggate similmente." #: quodlibet/ext/songsmenu/duplicates.py:409 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:411 msgid "_Group duplicates by:" msgstr "Ra_ggruppa duplicati per:" #: quodlibet/ext/songsmenu/duplicates.py:416 msgid "Duplicate Key" msgstr "Chiave duplicata" #: quodlibet/ext/songsmenu/duplicates.py:421 msgid "Remove _Whitespace" msgstr "Rimuovi _spazi bianchi" #: quodlibet/ext/songsmenu/duplicates.py:422 msgid "Remove _Diacritics" msgstr "Rimuovi segni _diacritici" #: quodlibet/ext/songsmenu/duplicates.py:423 msgid "Remove _Punctuation" msgstr "Rimuovi _punteggiatura" #: quodlibet/ext/songsmenu/duplicates.py:424 msgid "Case _Insensitive" msgstr "_Insensibile alle maiuscole" #: quodlibet/ext/songsmenu/duplicates.py:432 msgid "Matching options" msgstr "Opzioni di corrispondenza" #. Create a dialog. #: quodlibet/ext/songsmenu/editplaycount.py:20 #: quodlibet/ext/songsmenu/editplaycount.py:42 msgid "Edit Playcount" msgstr "Modifica conteggio riproduzioni" #: quodlibet/ext/songsmenu/editplaycount.py:21 msgid "" "Edit a song's ~#playcount and ~#skipcount.\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's ~#playcount to 0, the ~#lastplayed and ~#laststarted " "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:69 msgid "Play Count" msgstr "Conteggio riproduzione" #: quodlibet/ext/songsmenu/editplaycount.py:70 msgid "Skip Count" msgstr "Conteggio saltati" #: quodlibet/ext/songsmenu/embedded.py:26 msgid "Edit Embedded Images" msgstr "Modifica immagini incorporate" #: quodlibet/ext/songsmenu/embedded.py:27 msgid "Removes or replaces embedded images." msgstr "Rimuove o rimpiazza le immagini incorporate." #: quodlibet/ext/songsmenu/embedded.py:82 msgid "_Remove all Images" msgstr "_Rimuovi tutte le immagini" #: quodlibet/ext/songsmenu/embedded.py:86 msgid "_Embed Current Image" msgstr "Incorpora immagin_e corrente" #: quodlibet/ext/songsmenu/exact_rating.py:24 msgid "Set Exact Rating" msgstr "Imposta giudizio esatto" #: quodlibet/ext/songsmenu/exact_rating.py:25 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:37 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:81 msgid "Filter on Any Tag" msgstr "Filtro per qualsiasi tag" #: quodlibet/ext/songsmenu/filterall.py:82 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:20 msgid "Filter on Directory" msgstr "Filtro per directory" #: quodlibet/ext/songsmenu/filterbrowser.py:21 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:31 msgid "Acoustic Fingerprint Lookup" msgstr "Ricerca impronta acustica" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:32 msgid "Looks up song metadata through acoustic fingerprinting." msgstr "Ricerca metadati del brano tramite l'impronta acustica." #: quodlibet/ext/songsmenu/fingerprint/__init__.py:52 #: quodlibet/ext/songsmenu/fingerprint/submit.py:41 msgid "Submit Acoustic Fingerprints" msgstr "Invia impronte acustiche" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:53 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:61 msgid "API Key Missing" msgstr "Chiave API mancante" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:62 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:76 msgid "Request API key" msgstr "_Richiedi chiave API" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:83 msgid "API _key:" msgstr "_Chiave API:" #: quodlibet/ext/songsmenu/fingerprint/__init__.py:90 msgid "AcoustID Web Service" msgstr "Web Service AcoustID" #: quodlibet/ext/songsmenu/fingerprint/search.py:37 msgid "Queued" msgstr "Accodato" #: quodlibet/ext/songsmenu/fingerprint/search.py:39 msgid "Analyzing" msgstr "Analisi" #: quodlibet/ext/songsmenu/fingerprint/search.py:41 msgid "Lookup" msgstr "Ricerca" #: quodlibet/ext/songsmenu/fingerprint/search.py:117 msgid "Write" msgstr "Scrivi" #: quodlibet/ext/songsmenu/fingerprint/search.py:145 msgid "Status" msgstr "Stato" #. Translators: album release ID #: quodlibet/ext/songsmenu/fingerprint/search.py:159 msgid "Release" msgstr "ID rilascio" #: quodlibet/ext/songsmenu/fingerprint/search.py:291 msgid "Write MusicBrainz tags" msgstr "Scrivi tag MusicBrainz" #: quodlibet/ext/songsmenu/fingerprint/search.py:297 msgid "Group by directory" msgstr "Raggruppa per directory" #: quodlibet/ext/songsmenu/fingerprint/search.py:306 msgid "Album Mode" msgstr "Modalità _album" #: quodlibet/ext/songsmenu/fingerprint/search.py:308 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:49 msgid "Generating fingerprints:" msgstr "Generazione impronte:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:65 msgid "_Details" msgstr "_Dettagli" #: quodlibet/ext/songsmenu/fingerprint/submit.py:88 msgid "_Submit" msgstr "_Invia" #: quodlibet/ext/songsmenu/fingerprint/submit.py:118 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:121 msgid "Fingerprints:" msgstr "Impronte:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:123 msgid "Songs with MBIDs:" msgstr "Brani con MBID:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:125 msgid "Songs with sufficient tags:" msgstr "Brani con tag sufficienti:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:127 msgid "Songs to submit:" msgstr "Brani da inviare:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:165 #, 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:181 msgid "Submitting fingerprints:" msgstr "Invio impronte:" #: quodlibet/ext/songsmenu/fingerprint/submit.py:189 msgid "Submitting…" msgstr "Invio…" #: quodlibet/ext/songsmenu/forcewrite.py:18 msgid "Update Tags in Files" msgstr "Aggiorna tag nei file" #: quodlibet/ext/songsmenu/forcewrite.py:19 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:22 msgid "Send to iFP" msgstr "Invia a iFP" #: quodlibet/ext/songsmenu/ifp.py:23 msgid "Uploads songs to an iRiver iFP device." msgstr "Carica brani su un dispositivo iFP iRiver." #: quodlibet/ext/songsmenu/ifp.py:31 msgid "No iFP device found" msgstr "Nessun dispositivo iFP trovato" #: quodlibet/ext/songsmenu/ifp.py:32 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:40 #, python-format msgid "Uploading %(current)d/%(total)d" msgstr "Sto caricando %(current)d/%(total)d." #: quodlibet/ext/songsmenu/ifp.py:63 msgid "Error uploading" msgstr "Errore mentre carico" #: quodlibet/ext/songsmenu/ifp.py:64 #, python-format msgid "" "Unable to upload <b>%s</b>. 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/importexport.py:59 msgid "Export Metadata" msgstr "Esporta metadati" #: quodlibet/ext/songsmenu/importexport.py:60 msgid "Exports metadata of selected songs as a .tags file." msgstr "Esporta metadati dei brani selezionati come file .tags." #: quodlibet/ext/songsmenu/importexport.py:104 msgid "Import Metadata" msgstr "Importa metadati" #: quodlibet/ext/songsmenu/importexport.py:105 msgid "Imports metadata for selected songs from a .tags file." msgstr "Importa metadati per i brani selezionati da un file .tags." #: quodlibet/ext/songsmenu/k3b.py:24 msgid "Burn CD" msgstr "Scrivi CD" #: quodlibet/ext/songsmenu/k3b.py:25 msgid "Burns CDs with K3b, Brasero or xfburn." msgstr "Masterizza CD con K3b, Brasero o xfburn." #: quodlibet/ext/songsmenu/lastfmsync.py:98 msgid "Updating chart list." msgstr "Aggiornamento elenco classifica." #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:117 msgid "Already up-to-date." msgstr "Già aggiornato." #: quodlibet/ext/songsmenu/lastfmsync.py:125 #, python-format msgid "Fetching chart for week of %s." msgstr "Ottenimento classifica per la settimana di %s." #: quodlibet/ext/songsmenu/lastfmsync.py:147 msgid "Sync complete." msgstr "Sincronizzazione completa." #: quodlibet/ext/songsmenu/lastfmsync.py:153 msgid "Error during sync" msgstr "Errore durante la sincronizzazione" #: quodlibet/ext/songsmenu/lastfmsync.py:218 #: quodlibet/ext/songsmenu/lastfmsync.py:248 msgid "Last.fm Sync" msgstr "Sincronizzazione Last.fm" #: quodlibet/ext/songsmenu/lastfmsync.py:249 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:302 msgid "_Username:" msgstr "Nome _utente:" #: quodlibet/ext/songsmenu/makesorttags.py:37 msgid "Create Sort Tags" msgstr "Crea tag di ordinamento" #: quodlibet/ext/songsmenu/makesorttags.py:38 msgid "Converts album and artist names to sort names, poorly." msgstr "Converte nomi di album e artista in nomi di ordinamento, poveramente." #. Create a dialog. #: quodlibet/ext/songsmenu/migratemetadata.py:37 #: quodlibet/ext/songsmenu/migratemetadata.py:46 msgid "Migrate Metadata" msgstr "Migra metadati" #: quodlibet/ext/songsmenu/migratemetadata.py:40 msgid "Copies the quodlibet-specific metadata between songs." msgstr "Copia metadati specifici di Quod Libet tra i brani." #: quodlibet/ext/songsmenu/migratemetadata.py:53 msgid "_Copy" msgstr "_Copia" #: quodlibet/ext/songsmenu/migratemetadata.py:55 msgid "_Paste" msgstr "_Incolla" #. Create the tag table. #: quodlibet/ext/songsmenu/migratemetadata.py:65 msgid "Information to copy/paste" msgstr "Informazioni da copiare/incollare" #. Create the indexing box. #: quodlibet/ext/songsmenu/migratemetadata.py:87 msgid "Map tracks by disc and track number" msgstr "Mappa tracce per disco e numero traccia" #: quodlibet/ext/songsmenu/migratemetadata.py:88 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." #: quodlibet/ext/songsmenu/migratemetadata.py:104 #, python-format 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." #: quodlibet/ext/songsmenu/playlist.py:32 msgid "Export as Playlist" msgstr "Esporta come scaletta" #: quodlibet/ext/songsmenu/playlist.py:33 msgid "Exports songs to an M3U or PLS playlist." msgstr "Esporta brani su una scaletta M3U o PLS." #: quodlibet/ext/songsmenu/playlist.py:78 msgid "Use relative paths" msgstr "Usa percorsi relativi" #: quodlibet/ext/songsmenu/playlist.py:78 msgid "Use absolute paths" msgstr "Usa percorsi assoluti" #: quodlibet/ext/songsmenu/playlist.py:133 msgid "Unable to export playlist" msgstr "Impossibile esportare la scaletta" #: quodlibet/ext/songsmenu/playlist.py:134 #, python-format msgid "Writing to <b>%s</b> failed." msgstr "Scrittura su <b>%s</b> fallita." #. Translators: Plugin name #: quodlibet/ext/songsmenu/refresh.py:23 msgid "Rescan Songs" msgstr "Riscansiona brani" #: quodlibet/ext/songsmenu/refresh.py:24 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:32 msgid "Rescan songs" msgstr "Riscansiona brani" #: quodlibet/ext/songsmenu/replaygain.py:352 msgid "ReplayGain Analyzer" msgstr "Analizzatore Replay Gain" #: 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 #, python-format msgid "There is <b>%(to-process)s</b> album to update (of %(all)s)" msgid_plural "There are <b>%(to-process)s</b> 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:570 msgid "" "Analyzes and updates ReplayGain information, using GStreamer. Results are " "grouped by album." msgstr "" "Analizza ed aggiorna informazioni Replay Gain, usando GStreamer. I risultati " "sono raggruppati per album." #: quodlibet/ext/songsmenu/replaygain.py:608 msgid "always" msgstr "sempre" #: quodlibet/ext/songsmenu/replaygain.py:609 msgid "if <b>any</b> RG tags are missing" msgstr "se <b>qualunque</b> tag RG è mancante" #: quodlibet/ext/songsmenu/replaygain.py:611 msgid "if <b>album</b> RG tags are missing" msgstr "se tag RG <b>album</b> sono mancanti" #: quodlibet/ext/songsmenu/replaygain.py:628 msgid "_Process albums:" msgstr "_Elabora album:" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:640 msgid "Existing Tags" msgstr "Tag esistenti" #: quodlibet/ext/songsmenu/splitting.py:32 msgid "Split Tags" msgstr "Separa tag" #: quodlibet/ext/songsmenu/splitting.py:33 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:57 msgid "Split Album" msgstr "Separa album" #: quodlibet/ext/songsmenu/splitting.py:58 msgid "Split out disc number." msgstr "Separa il numero del disco." #: quodlibet/ext/songsmenu/tapbpm.py:24 quodlibet/ext/songsmenu/tapbpm.py:33 #: quodlibet/ext/songsmenu/tapbpm.py:62 msgid "n/a" msgstr "n/d" #. TRANSLATORS: BPM mean "beats per minute" #: quodlibet/ext/songsmenu/tapbpm.py:32 msgid "BPM:" msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:37 msgid "Reset" msgstr "Reimposta" #: quodlibet/ext/songsmenu/tapbpm.py:43 msgid "Tap" msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:178 quodlibet/ext/songsmenu/tapbpm.py:185 msgid "Tap BPM" msgstr "" #: quodlibet/ext/songsmenu/tapbpm.py:179 msgid "Tap BPM for the selected song." msgstr "Tap dei BPM per i brani selezionati." #: quodlibet/ext/songsmenu/website_search.py:38 msgid "Website Search" msgstr "Cerca nel sito" #: quodlibet/ext/songsmenu/website_search.py:39 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern-example)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:81 msgid "Search URL patterns" msgstr "Cerca modelli URL" #: quodlibet/ext/songsmenu/website_search.py:91 msgid "Edit search URLs" msgstr "Modifica _URL di ricerca" #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:117 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:71 #: quodlibet/ext/songsmenu/wikipedia.py:77 quodlibet/qltk/edittags.py:408 msgid "Edit Tags" msgstr "Modifica i tag" #: quodlibet/ext/songsmenu/wikipedia.py:112 msgid "Search failed" msgstr "Ricerca fallita" #: quodlibet/ext/songsmenu/wikipedia.py:113 #, python-format msgid "Tag \"%s\" not found." msgstr "Tag \"%s\" non trovato." #. then (try to) load all new files #: quodlibet/library/libraries.py:652 quodlibet/library/libraries.py:662 #: quodlibet/library/libraries.py:728 quodlibet/library/libraries.py:747 #: quodlibet/qltk/information.py:273 quodlibet/qltk/prefs.py:650 #: quodlibet/util/library.py:124 msgid "Library" msgstr "Libreria" #: quodlibet/library/libraries.py:652 msgid "Checking mount points" msgstr "Controllo dei punti di mount" #: quodlibet/library/libraries.py:662 msgid "Scanning library" msgstr "Scansione della libreria" #: quodlibet/library/libraries.py:727 #, python-format msgid "Scanning %s" msgstr "Scansione di %s" #: quodlibet/library/libraries.py:747 msgid "Loading files" msgstr "Caricamento files" #: quodlibet/main.py:51 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:37 msgid "List tags" msgstr "Elenca tag" #: quodlibet/operon/commands.py:42 quodlibet/operon/commands.py:81 #: quodlibet/operon/commands.py:463 msgid "Print terse output" msgstr "Stampa uscita breve" #: quodlibet/operon/commands.py:44 quodlibet/operon/commands.py:83 #: quodlibet/operon/commands.py:465 #, 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:47 quodlibet/operon/commands.py:86 msgid "Also list programmatic tags" msgstr "Elenca anche i tag programmatici" #: quodlibet/operon/commands.py:51 quodlibet/operon/commands.py:129 #: quodlibet/operon/commands.py:221 quodlibet/operon/commands.py:294 #: quodlibet/operon/commands.py:337 quodlibet/operon/commands.py:341 #: quodlibet/operon/commands.py:393 quodlibet/operon/commands.py:396 #: quodlibet/operon/commands.py:435 quodlibet/operon/commands.py:470 #: quodlibet/operon/commands.py:510 quodlibet/operon/commands.py:545 #: quodlibet/operon/commands.py:587 msgid "Not enough arguments" msgstr "Argomenti insufficienti" #: quodlibet/operon/commands.py:53 quodlibet/operon/commands.py:90 #: quodlibet/operon/commands.py:131 quodlibet/operon/commands.py:223 #: quodlibet/operon/commands.py:472 msgid "Too many arguments" msgstr "Troppi argomenti" #: quodlibet/operon/commands.py:56 quodlibet/operon/commands.py:92 #: quodlibet/operon/commands.py:477 quodlibet/qltk/data_editors.py:353 msgid "Description" msgstr "Descrizione" #: quodlibet/operon/commands.py:56 quodlibet/operon/commands.py:477 #: quodlibet/qltk/edittags.py:458 msgid "Value" msgstr "Valore" #: quodlibet/operon/commands.py:76 msgid "List all common tags" msgstr "Elenca tutti i tag comuni" #: quodlibet/operon/commands.py:118 msgid "Copy tags from one file to another" msgstr "Copia tag da un file all'altro" #: quodlibet/operon/commands.py:123 quodlibet/operon/commands.py:165 #: quodlibet/operon/commands.py:290 quodlibet/operon/commands.py:325 #: quodlibet/operon/commands.py:386 msgid "Show changes, don't apply them" msgstr "Mostra cambiamenti, non applicarli" #: quodlibet/operon/commands.py:125 msgid "Skip tags that can't be written" msgstr "Salta i tag che non possono essere scritti" #: quodlibet/operon/commands.py:146 #, 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:158 msgid "Edit tags in a text editor" msgstr "Modifica i tag in un editor di testo" #: quodlibet/operon/commands.py:252 msgid "Editing aborted" msgstr "Modifica annullata" #: quodlibet/operon/commands.py:256 #, python-format msgid "Starting text editor '%(editor-name)s' failed." msgstr "Avvio dell'editor di testo '%(editor-name)s' fallito." #: quodlibet/operon/commands.py:261 msgid "No changes detected" msgstr "Nessun cambiamento rilevato" #: quodlibet/operon/commands.py:285 msgid "Set a tag and remove existing values" msgstr "Imposta un tag e rimuovi i valori esistenti" #: quodlibet/operon/commands.py:305 quodlibet/operon/commands.py:446 #: quodlibet/operon/commands.py:678 #, python-format msgid "Can not set %r" msgstr "Impossibile impostare %r" #: quodlibet/operon/commands.py:320 msgid "Remove tags" msgstr "Rimuovi tag" #: quodlibet/operon/commands.py:327 quodlibet/operon/commands.py:388 msgid "Value is a regular expression" msgstr "Il valore è un'espressione regolare" #: quodlibet/operon/commands.py:329 msgid "Remove all tags" msgstr "Rimuovi tutti i tag" #: quodlibet/operon/commands.py:333 msgid "Can't combine '--all' with '--regexp'" msgstr "Impossibile combinare '-all' con '--regexp'" #: quodlibet/operon/commands.py:367 #, python-brace-format msgid "Can't remove {tagname} from {filename}" msgstr "Impossibile rimuovere {tagname} da {filename}" #: quodlibet/operon/commands.py:381 msgid "Remove a tag value" msgstr "Rimuovi il valore di un tag" #: quodlibet/operon/commands.py:430 msgid "Add a tag value" msgstr "Aggiungi il valore di un tag" #: quodlibet/operon/commands.py:458 msgid "List file information" msgstr "Elenca informazioni sul file" #: quodlibet/operon/commands.py:504 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:517 #, python-format msgid "Failed to load image file: %r" msgstr "Fallito caricamento file immagine: %r" #: quodlibet/operon/commands.py:524 quodlibet/operon/commands.py:553 #, 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:540 msgid "Remove all embedded images" msgstr "Rimuovi tutte le immagini incorporate" #: quodlibet/operon/commands.py:570 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "Estrai le immagini incorporate su %(filepath)s" #: quodlibet/operon/commands.py:582 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:641 msgid "Rename files based on tags" msgstr "Rinomina file basandosi sui tag" #: quodlibet/operon/commands.py:656 msgid "Fill tags based on the file path" msgstr "Riempi i tag basandosi sul percorso del file" #: quodlibet/operon/commands.py:706 quodlibet/qltk/information.py:310 #: quodlibet/qltk/properties.py:84 quodlibet/qltk/renamefiles.py:225 #: quodlibet/qltk/tagsfrompath.py:229 quodlibet/qltk/tracknumbers.py:79 msgid "File" msgstr "File" #: quodlibet/operon/commands.py:714 msgid "Fill tracknumbers for all files" msgstr "Riempi i numeri di traccia per tutti i file" #: quodlibet/operon/commands.py:733 msgid "Print tags based on the given pattern" msgstr "Stampa tag basandosi su un dato modello" #: quodlibet/operon/commands.py:770 msgid "Display help information" msgstr "Mostra informazioni di aiuto" #: quodlibet/operon/util.py:43 #, 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:31 msgid "_Unknown" msgstr "Sconosci_uto" #: quodlibet/order/__init__.py:143 msgid "In Order" msgstr "In ordine" #: quodlibet/order/__init__.py:144 msgid "_In Order" msgstr "_In ordine" #: quodlibet/order/reorder.py:23 msgid "Random" msgstr "Casuale" #: quodlibet/order/reorder.py:24 quodlibet/qltk/queue.py:123 msgid "_Random" msgstr "Ca_suale" #: quodlibet/order/reorder.py:41 quodlibet/order/reorder.py:42 msgid "Prefer higher rated" msgstr "Preferisci i _giudicati più alti" #: quodlibet/order/repeat.py:44 quodlibet/order/repeat.py:45 msgid "Repeat this track" msgstr "_Ripeti questa traccia" #: quodlibet/order/repeat.py:58 quodlibet/order/repeat.py:59 msgid "Repeat all" msgstr "Ripeti _tutti" #: quodlibet/order/repeat.py:74 quodlibet/order/repeat.py:75 msgid "One Song" msgstr "_Un brano" #: quodlibet/player/gstbe/player.py:99 msgid "Stream" msgstr "Flusso" #: quodlibet/player/gstbe/player.py:99 msgid "Buffering" msgstr "" #: quodlibet/player/gstbe/player.py:453 msgid "Could not create GStreamer pipeline" msgstr "Impossibile creare pipeline GStreamer" #: quodlibet/player/gstbe/player.py:652 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:653 #, python-format msgid "Media format: %(format-description)s" msgstr "Formato media: %(format-description)s" #: quodlibet/player/gstbe/plugins.py:36 #, 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 msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. In case 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:37 msgid "_Output pipeline:" msgstr "Pipeline di _output:" #: quodlibet/player/gstbe/prefs.py:44 #, python-format msgid "%.1f seconds" msgstr "%.1f secondi" #: quodlibet/player/gstbe/prefs.py:58 msgid "_Buffer duration:" msgstr "Durata _buffer:" #: quodlibet/player/gstbe/prefs.py:67 msgid "Disable _gapless playback" msgstr "Disabilita riproduzione _senza pause" #: quodlibet/player/gstbe/prefs.py:71 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/util.py:102 msgid "No GStreamer audio sink found" msgstr "Nessun sink audio GStreamer trovato" #: quodlibet/player/gstbe/util.py:121 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:62 #, 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:71 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "Impossibile trovare l'elemento di GStreamer '{element}'." #: quodlibet/plugins/playlist.py:24 #, 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:28 quodlibet/qltk/songsmenu.py:56 #: quodlibet/qltk/songsmenu.py:67 msgid "_Run Plugin" msgstr "_Esegui plugin" #. Translators: Refers to the beginning of the playing song. #: quodlibet/qltk/bookmarks.py:28 msgid "Beginning" msgstr "Inizio" #: quodlibet/qltk/bookmarks.py:39 quodlibet/qltk/bookmarks.py:79 msgid "N/A" msgstr "N/D" #: quodlibet/qltk/bookmarks.py:84 msgid "Time" msgstr "Tempo" #: quodlibet/qltk/bookmarks.py:90 quodlibet/qltk/bookmarks.py:125 msgid "Bookmark Name" msgstr "Nome del segnalibro" #: quodlibet/qltk/bookmarks.py:123 msgid "MM:SS" msgstr "MM:SS" #: quodlibet/qltk/bookmarks.py:211 quodlibet/qltk/information.py:133 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:41 msgid "_Name:" msgstr "_Nome:" #: quodlibet/qltk/cbes.py:49 quodlibet/qltk/edittags.py:315 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:345 msgid "Tag expression" msgstr "Espressione tag" #: quodlibet/qltk/data_editors.py:372 msgid "Tag expression e.g. people:real or ~album~year." msgstr "Espressione tag es people:real o ~album~year." #: quodlibet/qltk/data_editors.py:373 msgid "Enter new tag" msgstr "Inserisci nuovo tag" #: quodlibet/qltk/delete.py:38 msgid "Files:" msgstr "File:" #: quodlibet/qltk/delete.py:64 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:73 msgid "The selected files will be deleted from disk." msgstr "I file selezionati verranno eliminati dal disco." #: quodlibet/qltk/delete.py:77 #, 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:92 msgid "_Delete Files" msgstr "Elimina i file" #: quodlibet/qltk/delete.py:107 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:116 msgid "The selected files will be moved to the trash." msgstr "I file selezionati verranno spostati nel cestino." #: quodlibet/qltk/delete.py:121 #, 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:135 quodlibet/qltk/delete.py:142 msgid "_Move to Trash" msgstr "_Sposta nel cestino" #: quodlibet/qltk/delete.py:153 quodlibet/qltk/delete.py:188 #, python-format msgid "Moving %(current)d/%(total)d." msgstr "Spostamento di %(current)d/%(total)d." #: quodlibet/qltk/delete.py:174 quodlibet/qltk/delete.py:206 msgid "Unable to move to trash" msgstr "Impossibile spostare nel cestino" #: quodlibet/qltk/delete.py:175 quodlibet/qltk/delete.py:207 msgid "Moving one or more files to the trash failed." msgstr "Spostamento di uno o più file nel cestino fallito." #: quodlibet/qltk/delete.py:217 quodlibet/qltk/delete.py:251 #, python-format msgid "Deleting %(current)d/%(total)d." msgstr "Cancellazione di %(current)d/%(total)d." #: quodlibet/qltk/delete.py:237 quodlibet/qltk/delete.py:270 msgid "Unable to delete files" msgstr "Impossibile eliminare i file" #: quodlibet/qltk/delete.py:238 quodlibet/qltk/delete.py:271 msgid "Deleting one or more files failed." msgstr "Non è stato possibile eliminare uno o più 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:197 msgid "Split into _Multiple Values" msgstr "Separa in valori _multipli" #: quodlibet/qltk/edittags.py:215 msgid "Split Disc out of _Album" msgstr "Separa i dischi dall'_album" #: quodlibet/qltk/edittags.py:232 msgid "Split _Version out of Title" msgstr "Separa la _versione dal titolo" #: quodlibet/qltk/edittags.py:263 msgid "Split Arranger out of Ar_tist" msgstr "Separa l'arrangiatore dall'ar_tista" #: quodlibet/qltk/edittags.py:268 msgid "Split _Performer out of Artist" msgstr "Separa l'e_secutore dall'artista" #: quodlibet/qltk/edittags.py:274 msgid "Split _Performer out of Title" msgstr "Separa l'e_secutore dal titolo" #: quodlibet/qltk/edittags.py:280 msgid "Split _Originalartist out of Title" msgstr "Separa l'artista originale dal titolo" #: quodlibet/qltk/edittags.py:287 msgid "Add a Tag" msgstr "Aggiungi un tag" #: quodlibet/qltk/edittags.py:306 msgid "_Tag:" msgstr "_Tag:" #: quodlibet/qltk/edittags.py:481 msgid "Show _programmatic tags" msgstr "Mostra tag programmatici" #: quodlibet/qltk/edittags.py:482 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" #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:512 msgctxt "edittags" msgid "_Revert" msgstr "_Ripristina" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:517 msgctxt "edittags" msgid "_Save" msgstr "_Salva" #: quodlibet/qltk/edittags.py:642 msgid "_Copy Value(s)" msgstr "Copia valore/i" #: quodlibet/qltk/edittags.py:673 msgid "Unable to add tag" msgstr "Impossibile aggiungere tag" #: quodlibet/qltk/edittags.py:674 #, python-format msgid "Unable to add <b>%s</b>" msgstr "Impossibile aggiungere <b>%s</b>" #: quodlibet/qltk/edittags.py:676 #, python-format msgid "" "The files currently selected do not support multiple values for <b>%s</b>." msgstr "" "I file attualmente selezionati non supportano valori multipli per <b>%s</b>." #. Can't add the new tag. #: quodlibet/qltk/edittags.py:703 quodlibet/qltk/edittags.py:884 #: quodlibet/qltk/tagsfrompath.py:212 quodlibet/util/__init__.py:506 #: quodlibet/util/tags.py:244 msgid "Invalid tag" msgstr "Tag non valido" #: quodlibet/qltk/edittags.py:704 quodlibet/qltk/edittags.py:885 #: quodlibet/qltk/tagsfrompath.py:213 #, python-format msgid "" "Invalid tag <b>%s</b>\n" "\n" "The files currently selected do not support editing this tag." msgstr "" "Tag <b>%s</b> non valido\n" "\n" "I file attualmente selezionati non supportano la modifica di questo tag." #: quodlibet/qltk/edittags.py:855 quodlibet/qltk/edittags.py:896 msgid "Invalid value" msgstr "Valore non valido" #: quodlibet/qltk/edittags.py:856 quodlibet/qltk/edittags.py:897 #, python-format msgid "" "Invalid value: <b>%(value)s</b>\n" "\n" "%(error)s" msgstr "" "Valore non valido: <b>%(value)s</b>\n" "\n" "%(error)s" #: quodlibet/qltk/_editutils.py:30 msgid "Tag may not be accurate" msgstr "Il tag potrebbe non essere accurato" #: quodlibet/qltk/_editutils.py:33 #, 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:49 msgid "Unable to save song" msgstr "Impossibile salvare il brano" #: quodlibet/qltk/_editutils.py:52 #, 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:79 msgid "_Undo" msgstr "_Annulla" #: quodlibet/qltk/entry.py:81 msgid "_Redo" msgstr "_Ripeti" #: quodlibet/qltk/exfalsowindow.py:95 quodlibet/qltk/quodlibetwindow.py:957 msgid "_About" msgstr "_A proposito" #: quodlibet/qltk/exfalsowindow.py:99 quodlibet/qltk/quodlibetwindow.py:979 msgid "_Check for Updates…" msgstr "_Controlla per aggiornamenti…" #: quodlibet/qltk/exfalsowindow.py:105 quodlibet/qltk/quodlibetwindow.py:912 #: quodlibet/qltk/songsmenu.py:290 msgid "_Plugins" msgstr "P_lugin" #: quodlibet/qltk/exfalsowindow.py:267 #, 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:279 msgid "Ex Falso Preferences" msgstr "Preferenze di Ex Falso" #: quodlibet/qltk/exfalsowindow.py:289 quodlibet/qltk/prefs.py:609 msgid "Split _on:" msgstr "Dividi s_u:" #: quodlibet/qltk/exfalsowindow.py:295 quodlibet/qltk/prefs.py:624 msgid "Tag Editing" msgstr "Modifica dei tag" #: quodlibet/qltk/filesel.py:210 msgid "Folders" msgstr "Cartelle" #: quodlibet/qltk/filesel.py:265 msgid "_New Folder…" msgstr "_Nuova cartella…" #: quodlibet/qltk/filesel.py:274 msgid "_Select all Sub-Folders" msgstr "_Seleziona tutte le sottocartelle" #: quodlibet/qltk/filesel.py:384 msgid "New Folder" msgstr "Nuova cartella" #: quodlibet/qltk/filesel.py:384 msgid "Enter a name for the new folder:" msgstr "Inserire un nome per la nuova cartella:" #: quodlibet/qltk/filesel.py:397 msgid "Unable to create folder" msgstr "Impossibile creare la cartella" #: quodlibet/qltk/filesel.py:414 msgid "Unable to delete folder" msgstr "Impossibile eliminare la cartella" #: quodlibet/qltk/filesel.py:530 quodlibet/qltk/pluginwin.py:168 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:172 #: quodlibet/qltk/information.py:453 #, python-format msgid "Disc %s" msgstr "Disco %s" #: quodlibet/qltk/info.py:45 quodlibet/qltk/information.py:177 #, python-format msgid "Track %s" msgstr "Traccia %s" #: quodlibet/qltk/info.py:99 msgid "Current _Song" msgstr "Brano cor_rente" #: quodlibet/qltk/info.py:109 msgid "_Edit Display…" msgstr "Mod_ifica visualizzazione…" #: quodlibet/qltk/information.py:107 msgid "No songs are selected." msgstr "Nessun brano selezionato." #: quodlibet/qltk/information.py:108 msgid "No Songs" msgstr "Nessun brano" #: quodlibet/qltk/information.py:123 quodlibet/qltk/information.py:343 #: quodlibet/qltk/information.py:476 quodlibet/qltk/information.py:544 msgid "Information" msgstr "Informazioni" #: quodlibet/qltk/information.py:128 msgid "Lyrics" msgstr "Testi" #: quodlibet/qltk/information.py:189 quodlibet/qltk/information.py:401 #, python-format msgid "Produced by %s" msgstr "Prodotto da %s" #: quodlibet/qltk/information.py:204 quodlibet/util/tags.py:86 msgid "artist" msgstr "artista" #: quodlibet/qltk/information.py:205 quodlibet/qltk/information.py:574 #: quodlibet/util/tags.py:86 msgid "artists" msgstr "artisti" #. for backwards compat #: quodlibet/qltk/information.py:226 quodlibet/util/tags.py:97 #: quodlibet/util/tags.py:125 msgid "performers" msgstr "esecutori" #: quodlibet/qltk/information.py:240 quodlibet/qltk/information.py:253 #: quodlibet/qltk/songlistcolumns.py:277 msgid "Never" msgstr "Mai" #: quodlibet/qltk/information.py:241 #, 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:259 quodlibet/util/tags.py:150 msgid "added" msgstr "aggiunto" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:151 msgid "last played" msgstr "ultimo passaggio" #: quodlibet/qltk/information.py:261 quodlibet/util/tags.py:161 msgid "plays" msgstr "riproduzioni" #: quodlibet/qltk/information.py:262 quodlibet/util/tags.py:162 msgid "skips" msgstr "saltati" #: quodlibet/qltk/information.py:263 quodlibet/util/tags.py:167 msgid "rating" msgstr "giudizio" #: quodlibet/qltk/information.py:292 msgid "path" msgstr "percorso" #: quodlibet/qltk/information.py:293 quodlibet/util/tags.py:165 msgid "length" msgstr "lunghezza" #: quodlibet/qltk/information.py:294 msgid "format" msgstr "formato" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:175 msgid "codec" msgstr "" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:176 msgid "encoding" msgstr "codifica" #: quodlibet/qltk/information.py:297 quodlibet/util/tags.py:172 msgid "bitrate" msgstr "bitrate" #: quodlibet/qltk/information.py:298 quodlibet/util/tags.py:173 msgid "file size" msgstr "dimensioni file" #: quodlibet/qltk/information.py:299 quodlibet/util/tags.py:160 msgid "modified" msgstr "modificato" #: quodlibet/qltk/information.py:336 msgid "Additional" msgstr "Addizionale" #: quodlibet/qltk/information.py:388 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d selezionato" msgstr[1] "%d selezionati" #: quodlibet/qltk/information.py:463 msgid "Track unavailable" msgstr "Traccia non disponibile" #: quodlibet/qltk/information.py:469 msgid "Track List" msgstr "Elenco tracce" #: quodlibet/qltk/information.py:501 quodlibet/qltk/information.py:591 #, 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:504 msgid "Selected Discography" msgstr "Discografia selezionata" #: quodlibet/qltk/information.py:571 #, 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:599 quodlibet/util/tags.py:84 msgid "albums" msgstr "album" #: quodlibet/qltk/information.py:612 msgid "Total length:" msgstr "Lunghezza totale:" #: quodlibet/qltk/information.py:616 msgid "Total size:" msgstr "Dimensioni totali:" #: quodlibet/qltk/information.py:619 msgid "Files" msgstr "File" #: quodlibet/qltk/lyrics.py:37 msgid "_View online" msgstr "_Visualizza online" #: quodlibet/qltk/lyrics.py:65 msgid "No lyrics found for this song." msgstr "Nessun testo trovato per questo brano." #: quodlibet/qltk/lyrics.py:76 msgid "Searching for lyrics…" msgstr "Ricerca di testi…" #: quodlibet/qltk/maskedbox.py:21 msgid "Are you sure you want to remove all songs?" msgstr "Sei sicuro di voler rimuovere tutti i brani?" #: quodlibet/qltk/maskedbox.py:22 msgid "The selected songs will be removed from the library." msgstr "I brani selezionati saranno rimossi dalla libreria." #: quodlibet/qltk/maskedbox.py:45 msgid "Unhide" msgstr "Mostra" #: quodlibet/qltk/maskedbox.py:87 msgid "_Unhide" msgstr "M_ostra" #: quodlibet/qltk/msg.py:42 msgid "Discard tag changes?" msgstr "Tralasciare le modifiche ai tag?" #: quodlibet/qltk/msg.py:43 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:56 quodlibet/qltk/prefs.py:606 #: quodlibet/qltk/textedit.py:64 quodlibet/qltk/tracknumbers.py:117 msgid "_Revert" msgstr "_Ripristina" #: quodlibet/qltk/msg.py:105 msgid "File exists" msgstr "Il file esiste" #: quodlibet/qltk/msg.py:107 #, python-format msgid "Replace %(file-name)s?" msgstr "Sostituire %(file-name)s?" #: quodlibet/qltk/msg.py:113 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:257 msgid "Toggle shuffle mode" msgstr "Commuta modalità casuale" #: quodlibet/qltk/playorder.py:273 msgid "Toggle repeat mode" msgstr "Commuta modalità ripetizione" #: quodlibet/qltk/pluginwin.py:45 msgid "Plugin Errors" msgstr "Errori dei plugin" #: quodlibet/qltk/pluginwin.py:125 msgid "Enabled" msgstr "Attivo" #: quodlibet/qltk/pluginwin.py:126 msgid "Disabled" msgstr "Disattivato" #: quodlibet/qltk/pluginwin.py:132 msgid "No category" msgstr "Nessuna categoria" #: quodlibet/qltk/pluginwin.py:170 msgid "Events" msgstr "Eventi" #: quodlibet/qltk/pluginwin.py:171 msgid "Play Order" msgstr "Ordine di riproduzione" #: quodlibet/qltk/pluginwin.py:172 msgid "Editing" msgstr "Modifica" #: quodlibet/qltk/pluginwin.py:174 msgid "Covers" msgstr "Copertine" #: quodlibet/qltk/pluginwin.py:310 msgid "No plugins found." msgstr "Nessun plugin trovato." #: quodlibet/qltk/pluginwin.py:359 msgid "Plugins" msgstr "Plugin" #: quodlibet/qltk/pluginwin.py:383 msgid "Filter by plugin state / tag" msgstr "Filtra per stato plugin / tag" #: quodlibet/qltk/pluginwin.py:389 msgid "Filter by plugin type" msgstr "Filtra per tipo plugin" #: quodlibet/qltk/pluginwin.py:395 msgid "Filter by plugin name or description" msgstr "Filtra per nome plugin o descrizione" #: quodlibet/qltk/pluginwin.py:404 msgid "Show _Errors" msgstr "Mostra _errori" #: quodlibet/qltk/prefs.py:46 msgid "_Disc" msgstr "_Disco" #: quodlibet/qltk/prefs.py:47 msgid "_Track" msgstr "_Traccia" #: quodlibet/qltk/prefs.py:48 msgid "Grou_ping" msgstr "Raggru_ppamento" #: quodlibet/qltk/prefs.py:51 msgid "Al_bum" msgstr "Al_bum" #: quodlibet/qltk/prefs.py:56 msgid "_Filename" msgstr "Nome del _file" #: quodlibet/qltk/prefs.py:58 msgid "_Length" msgstr "_Lunghezza" #: quodlibet/qltk/prefs.py:65 msgid "_Jump to playing song automatically" msgstr "Salta automaticamente al brano in _riproduzione" #: quodlibet/qltk/prefs.py:67 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:83 msgid "_Others:" msgstr "Altr_i:" #: quodlibet/qltk/prefs.py:89 msgid "_Edit…" msgstr "M_odifica…" #: quodlibet/qltk/prefs.py:92 msgid "Add or remove additional column headers" msgstr "Aggiungi o rimuovi intestazioni di colonna addizionali" #: quodlibet/qltk/prefs.py:102 msgid "Visible Columns" msgstr "Colonne visibili" #: quodlibet/qltk/prefs.py:105 msgid "Title includes _version" msgstr "Il titolo include la _versione" #: quodlibet/qltk/prefs.py:107 msgid "Artist includes all _people" msgstr "L'artista incl_ude tutte le persone" #: quodlibet/qltk/prefs.py:109 msgid "Album includes _disc subtitle" msgstr "L'album includ_e il sottotitolo del disco" #: quodlibet/qltk/prefs.py:111 msgid "Filename includes _folder" msgstr "Il nome del file include la _cartella" #: quodlibet/qltk/prefs.py:124 msgid "Column Preferences" msgstr "Preferenze colonna" #: quodlibet/qltk/prefs.py:130 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:143 quodlibet/qltk/shortcuts.py:25 msgid "Song List" msgstr "Elenco Brani" #: quodlibet/qltk/prefs.py:223 msgid "Edit Columns" msgstr "Modifica colonne" #: quodlibet/qltk/prefs.py:260 msgid "Duration totals" msgstr "_Totali durata" #: quodlibet/qltk/prefs.py:272 msgid "_Global filter:" msgstr "Filtro _globale:" #: quodlibet/qltk/prefs.py:278 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:284 msgctxt "heading" msgid "Search" msgstr "Cerca" #: quodlibet/qltk/prefs.py:288 quodlibet/qltk/shortcuts.py:22 msgid "Browsers" msgstr "Navigatori" #: quodlibet/qltk/prefs.py:294 msgid "Confirm _multiple ratings" msgstr "Conferma giudizi _multipli" #: quodlibet/qltk/prefs.py:296 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:299 msgid "Enable _one-click ratings" msgstr "Abilita giudizi con un _click" #: quodlibet/qltk/prefs.py:301 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:307 quodlibet/qltk/prefs.py:627 msgid "Ratings" msgstr "Giudizi" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:313 msgid "Prefer _embedded art" msgstr "Pr_eferisci grafica incorporata" #: quodlibet/qltk/prefs.py:315 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:320 msgid "_Fixed image filename:" msgstr "Nome _fisso del file dell'immagine:" #: quodlibet/qltk/prefs.py:322 msgid "The single image filename to use if selected" msgstr "Il nome di file di immagine singola da usare se selezionato" #: quodlibet/qltk/prefs.py:328 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)" #: quodlibet/qltk/prefs.py:338 msgid "Album Art" msgstr "Grafica album" #: quodlibet/qltk/prefs.py:359 msgid "Playback" msgstr "Riproduzione" #: quodlibet/qltk/prefs.py:364 msgid "Output Configuration" msgstr "Configurazione uscita" #: quodlibet/qltk/prefs.py:375 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:378 msgid "_Fall-back gain (dB):" msgstr "Guadagno di _fall-back (dB):" #: quodlibet/qltk/prefs.py:389 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:392 msgid "_Pre-amp gain (dB):" msgstr "Guadagno _pre-amp (dB):" #: quodlibet/qltk/prefs.py:397 msgid "_Enable Replay Gain volume adjustment" msgstr "Abilita l'aggiustamento del volume _Replay Gain" #: quodlibet/qltk/prefs.py:422 msgid "Replay Gain Volume Adjustment" msgstr "Aggiustamento Replay Gain del volume " #: quodlibet/qltk/prefs.py:452 msgid "_Default rating:" msgstr "Giudizio pre_definito:" #: quodlibet/qltk/prefs.py:495 msgid "Rating _scale:" msgstr "_Scala giudizio" #: quodlibet/qltk/prefs.py:544 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:549 msgid "_Bayesian averaging amount:" msgstr "Quantità media _Bayesiana" #: quodlibet/qltk/prefs.py:558 msgid "Save ratings and play _counts in tags" msgstr "Salva i giudizi e il _numero di riproduzioni nei tag" #: quodlibet/qltk/prefs.py:566 msgid "_Email:" msgstr "_Email:" #: quodlibet/qltk/prefs.py:568 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:588 msgid "Auto-save tag changes" msgstr "Salvataggio automatico _modifiche dei tag" #: quodlibet/qltk/prefs.py:590 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:598 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:621 msgid "Tags" msgstr "Tag" #: quodlibet/qltk/prefs.py:642 msgid "Updating for new ratings" msgstr "Aggiornamento per nuovi giudizi" #: quodlibet/qltk/prefs.py:652 msgid "Scan library _on start" msgstr "Scansi_ona la libreria all'avvio" #: quodlibet/qltk/prefs.py:662 quodlibet/qltk/quodlibetwindow.py:991 msgid "_Scan Library" msgstr "_Scansiona libreria" #: quodlibet/qltk/prefs.py:664 quodlibet/qltk/quodlibetwindow.py:1053 msgid "Check for changes in your library" msgstr "Controlla cambiamenti nella tua libreria" #: quodlibet/qltk/prefs.py:669 msgid "Re_build Library" msgstr "Ri_costruisci libreria" #: quodlibet/qltk/prefs.py:672 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:682 msgid "Scan Directories" msgstr "Scansiona directory" #: quodlibet/qltk/prefs.py:688 msgid "Hidden Songs" msgstr "Brani nascosti" #: quodlibet/qltk/properties.py:158 quodlibet/util/collection.py:404 #, 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:162 quodlibet/qltk/properties.py:164 msgid "Properties" msgstr "Proprietà" #: quodlibet/qltk/queue.py:105 msgid "_Queue" msgstr "Co_da" #: quodlibet/qltk/queue.py:129 msgid "Stop at End" msgstr "_Ferma alla fine" #: quodlibet/qltk/queue.py:134 msgid "Ignore" msgstr "_Ignora" #: quodlibet/qltk/queue.py:139 msgid "Keep Songs" msgstr "_Tieni i brani" #: quodlibet/qltk/queue.py:142 msgid "Keep songs in the queue after playing them" msgstr "Tieni i brani in coda dopo averli riprodotti." #: quodlibet/qltk/queue.py:146 msgid "_Clear Queue" msgstr "_Pulisci coda" #: quodlibet/qltk/queue.py:269 #, 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:846 msgid "Unable to add songs" msgstr "Impossibile aggiungere i brani" #: quodlibet/qltk/quodlibetwindow.py:847 quodlibet/qltk/quodlibetwindow.py:1285 #, python-format msgid "%s uses an unsupported protocol." msgstr "%s usa un protocollo non supportato." #: quodlibet/qltk/quodlibetwindow.py:870 msgid "_Jump to Playing Song" msgstr "_Salta al brano in riproduzione" #: quodlibet/qltk/quodlibetwindow.py:877 msgid "_File" msgstr "_File" #: quodlibet/qltk/quodlibetwindow.py:878 msgid "_Song" msgstr "_Brano" #: quodlibet/qltk/quodlibetwindow.py:879 msgid "_View" msgstr "_Visualizza" #: quodlibet/qltk/quodlibetwindow.py:880 msgid "_Browse" msgstr "_Esplora" #: quodlibet/qltk/quodlibetwindow.py:881 msgid "_Control" msgstr "_Controllo" #: quodlibet/qltk/quodlibetwindow.py:882 msgid "_Help" msgstr "_Aiuto" #: quodlibet/qltk/quodlibetwindow.py:888 msgid "_Add a Folder…" msgstr "_Aggiungi una cartella…" #: quodlibet/qltk/quodlibetwindow.py:893 msgid "_Add a File…" msgstr "Aggiungi un _file…" #: quodlibet/qltk/quodlibetwindow.py:898 msgid "_Add a Location…" msgstr "Aggiungi una _posizione…" #: quodlibet/qltk/quodlibetwindow.py:927 msgid "Edit Bookmarks…" msgstr "Modifica segnali_bri…" #: quodlibet/qltk/quodlibetwindow.py:947 msgid "Stop After This Song" msgstr "_Ferma dopo questo brano" #: quodlibet/qltk/quodlibetwindow.py:953 msgid "_Keyboard Shortcuts" msgstr "Scorciatoie da _tastiera" #: quodlibet/qltk/quodlibetwindow.py:962 msgid "Online Help" msgstr "Aiuto in _linea" #: quodlibet/qltk/quodlibetwindow.py:971 msgid "Search Help" msgstr "C_erca nell'aiuto" #: quodlibet/qltk/quodlibetwindow.py:1273 msgid "Add a Location" msgstr "Aggiungi una posizione" #: quodlibet/qltk/quodlibetwindow.py:1274 msgid "Enter the location of an audio file:" msgstr "Inserire la posizione di un file audio:" #: quodlibet/qltk/quodlibetwindow.py:1279 #: quodlibet/qltk/quodlibetwindow.py:1284 msgid "Unable to add location" msgstr "Impossibile aggiungere la posizione" #: quodlibet/qltk/quodlibetwindow.py:1280 #, python-format msgid "%s is not a valid location." msgstr "%s non è una posizione valida." #: quodlibet/qltk/quodlibetwindow.py:1293 #: quodlibet/qltk/quodlibetwindow.py:1302 msgid "Add Music" msgstr "Aggiungi musica" #: quodlibet/qltk/quodlibetwindow.py:1293 quodlibet/qltk/scanbox.py:100 msgid "_Add Folders" msgstr "Aggiungi _cartelle" #: quodlibet/qltk/quodlibetwindow.py:1300 msgid "Music Files" msgstr "File musicali" #: quodlibet/qltk/quodlibetwindow.py:1302 msgid "_Add Files" msgstr "Aggiungi _file" #: quodlibet/qltk/ratingsmenu.py:25 #, 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:27 msgid "The saved ratings will be removed" msgstr "I giudizi salvati verranno rimossi" #: quodlibet/qltk/ratingsmenu.py:28 #, 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:58 quodlibet/qltk/ratingsmenu.py:112 msgid "_Remove Rating" msgstr "_Rimuovi giudizio" #: quodlibet/qltk/ratingsmenu.py:99 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 "Strip _Windows-incompatible characters" msgstr "Elimina i caratteri incompatibili con _Windows" #: quodlibet/qltk/renamefiles.py:80 msgid "Strip _diacritical marks" msgstr "Elimina i segni _diacritici" #: quodlibet/qltk/renamefiles.py:91 msgid "Strip non-_ASCII characters" msgstr "Elimina i caratteri non-_ASCII" #: quodlibet/qltk/renamefiles.py:101 msgid "Use only _lowercase characters" msgstr "Usa solo caratteri _minuscoli" #: quodlibet/qltk/renamefiles.py:129 msgid "Rename Files" msgstr "Rinomina i file" #: quodlibet/qltk/renamefiles.py:147 quodlibet/qltk/tagsfrompath.py:116 msgid "Path Patterns" msgstr "Modelli del percorso" #: quodlibet/qltk/renamefiles.py:148 quodlibet/qltk/tagsfrompath.py:117 msgid "Edit saved patterns…" msgstr "Modifica modelli salvati…" #: quodlibet/qltk/renamefiles.py:151 quodlibet/qltk/tagsfrompath.py:120 #: quodlibet/qltk/tracknumbers.py:58 msgid "_Preview" msgstr "Ante_prima" #: quodlibet/qltk/renamefiles.py:178 msgid "File names" msgstr "Nomi dei file" #: quodlibet/qltk/renamefiles.py:188 msgid "_Move album art" msgstr "Sposta grafica dell'albu_m" #: quodlibet/qltk/renamefiles.py:191 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:196 msgid "_Overwrite album art at target" msgstr "S_ovrascrivi grafica album alla destinazione" #: quodlibet/qltk/renamefiles.py:204 msgid "_Remove empty directories" msgstr "_Rimuovi directory vuote" #: quodlibet/qltk/renamefiles.py:210 msgid "Album art" msgstr "Grafica album" #: quodlibet/qltk/renamefiles.py:239 msgid "New Name" msgstr "Nuovo nome" #: quodlibet/qltk/renamefiles.py:316 msgid "Unable to rename file" msgstr "Impossibile rinominare il file" #: quodlibet/qltk/renamefiles.py:317 #, python-format msgid "" "Renaming <b>%(old-name)s</b> to <b>%(new-name)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." 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:325 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:326 quodlibet/qltk/wlw.py:50 msgid "_Stop" msgstr "_Ferma" #: quodlibet/qltk/renamefiles.py:328 msgid "_Continue" msgstr "_Continua" #: quodlibet/qltk/renamefiles.py:441 msgid "Path is not absolute" msgstr "Il percorso non è assoluto" #: quodlibet/qltk/renamefiles.py:442 #, python-format msgid "" "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 ~/." 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:48 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:100 msgid "Select Directories" msgstr "Selezionare le directory" #: quodlibet/qltk/searchbar.py:55 msgid "Saved Searches" msgstr "Ricerche salvate" #: quodlibet/qltk/searchbar.py:56 msgid "Edit saved searches…" msgstr "Modifica ricerche salvate…" #: quodlibet/qltk/searchbar.py:80 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:142 msgid "Search after _typing" msgstr "Cerca _dopo aver digitato" #: quodlibet/qltk/searchbar.py:145 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:212 msgid "_Limit:" msgstr "_Limite:" #: quodlibet/qltk/searchbar.py:225 msgid "_Weight" msgstr "_Peso" #: quodlibet/qltk/seekbutton.py:239 msgid "Display remaining time" msgstr "_Mostra il tempo rimanente" #: quodlibet/qltk/shortcuts.py:17 msgid "Main Window" msgstr "Finestra principale" #: quodlibet/qltk/shortcuts.py:18 msgid "Seek backwards by 10 seconds" msgstr "Posiziona all'indietro di 10 secondi" #: quodlibet/qltk/shortcuts.py:19 msgid "Seek forward by 10 seconds" msgstr "Posiziona in avanti di 10 secondi" #: quodlibet/qltk/shortcuts.py:20 msgid "Focus the search entry" msgstr "Dai il fuoco al campo di ricerca" #: quodlibet/qltk/shortcuts.py:23 msgid "Reset filters and jump to the playing song" msgstr "Reimposta filtri e salta al brano in riproduzione" #: quodlibet/qltk/shortcuts.py:27 msgid "Open the information window for the selected songs" msgstr "Apri la finestra di informazioni per i brani selezionati" #: quodlibet/qltk/shortcuts.py:28 msgid "Open the tag editor for the selected songs" msgstr "Apri l'editor di tag per i brani selezionati" #: quodlibet/qltk/shortcuts.py:29 msgid "Queue the selected songs" msgstr "Accoda i brani selezionati" #: quodlibet/qltk/shortcuts.py:30 msgid "Delete the selected songs" msgstr "Elimina i brani selezionati" #: quodlibet/qltk/shortcuts.py:31 msgid "Show the inline search entry" msgstr "Mostra la ricerca in linea" #: quodlibet/qltk/shortcuts.py:32 msgid "Left click on a column header" msgstr "Clic sinistro su un'intestazione di colonna" #: quodlibet/qltk/shortcuts.py:33 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:35 msgid "Tree View" msgstr "Vista ad albero" #: quodlibet/qltk/shortcuts.py:37 msgid "Collapses the element or select the parent element" msgstr "Collassa l'elemento o seleziona l'elemento padre" #: quodlibet/qltk/shortcuts.py:38 msgid "Expands the element" msgstr "Espande l'elemento" #: quodlibet/qltk/shortcuts.py:40 msgid "Text Entries" msgstr "Voci di testo" #: quodlibet/qltk/shortcuts.py:42 msgid "Undo the last change" msgstr "Annulla l'ultimo cambiamento" #: quodlibet/qltk/shortcuts.py:43 msgid "Redo the last undone change" msgstr "Ripeti l'ultimo cambiamento annullato" #: quodlibet/qltk/shortcuts.py:46 msgid "Select all songs in all panes" msgstr "Seleziona tutti i brani in tutti i pannelli" #: quodlibet/qltk/songlist.py:376 #, python-format msgid "_Filter on %s" msgstr "_Filtro su %s" #: quodlibet/qltk/songlist.py:1094 msgid "All _Headers" msgstr "Tutte le _intestazioni" #: quodlibet/qltk/songlist.py:1095 msgid "_Track Headers" msgstr "Intestazioni delle _tracce" #: quodlibet/qltk/songlist.py:1096 msgid "_Album Headers" msgstr "Intestazioni degli _album" #: quodlibet/qltk/songlist.py:1097 msgid "_People Headers" msgstr "Intestazioni delle pe_rsone" #: quodlibet/qltk/songlist.py:1098 msgid "_Date Headers" msgstr "Intestazione della _data" #: quodlibet/qltk/songlist.py:1099 msgid "_File Headers" msgstr "Intestazioni dei _file" #: quodlibet/qltk/songlist.py:1100 msgid "_Production Headers" msgstr "Intestazioni della _produzione " #: quodlibet/qltk/songlist.py:1115 msgid "_Customize Headers…" msgstr "Personali_zza intestazioni…" #: quodlibet/qltk/songlist.py:1120 msgid "_Expand Column" msgstr "_Espandi colonna" #: quodlibet/qltk/songsmenu.py:41 #, python-format msgid "Remove track: \"%%(title)s\" from library?" msgid_plural "Remove %(count)d tracks from library?" msgstr[0] "Eliminare traccia : \"%%(title)s\" dalla libreria?" msgstr[1] "Eliminare %(count)d tracce dalla libreria?" #: quodlibet/qltk/songsmenu.py:47 msgid "Remove from Library" msgstr "_Rimuovi dalla libreria" #: quodlibet/qltk/songsmenu.py:52 #, 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:63 #, 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:135 msgid "Configure Plugins…" msgstr "_Configura i plugin…" #: quodlibet/qltk/songsmenu.py:330 msgid "Add to _Queue" msgstr "Metti in _coda" #: quodlibet/qltk/songsmenu.py:350 msgid "_Remove from Library…" msgstr "_Rimuovi dalla libreria…" #: quodlibet/qltk/songsmenu.py:415 msgid "Unable to show files" msgstr "Impossibile mostrare i file" #: quodlibet/qltk/songsmenu.py:416 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:423 #, 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/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:101 msgid "Tags From Path" msgstr "Tag dal percorso" #: quodlibet/qltk/tagsfrompath.py:138 msgid "Tags replace existing ones" msgstr "I tag rimpiazzano quelli esistenti" #: quodlibet/qltk/tagsfrompath.py:139 msgid "Tags are added to existing ones" msgstr "I tag sono aggiunti a quelli esistenti" #: quodlibet/qltk/tagsfrompath.py:195 #, python-format msgid "" "The pattern\n" "\t<b>%s</b>\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/tagsfrompath.py:216 msgid "Invalid tags" msgstr "Tag non validi" #: quodlibet/qltk/tagsfrompath.py:217 #, 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." #: quodlibet/qltk/textedit.py:142 #, 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:158 msgid "Edit Display" msgstr "Modifica visualizzazione" #: quodlibet/qltk/tracknumbers.py:39 msgid "Track Numbers" msgstr "Numeri delle tracce" #: quodlibet/qltk/tracknumbers.py:42 msgid "Start fro_m:" msgstr "Parti _da:" #: quodlibet/qltk/tracknumbers.py:51 msgid "_Total tracks:" msgstr "_Tracce totali:" #: quodlibet/qltk/unity.py:53 msgid "Play/Pause" msgstr "Riproduci/Pausa" #: quodlibet/qltk/unity.py:73 msgid "Previous" msgstr "Precedente" #: quodlibet/qltk/views.py:924 #, 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:91 msgid "Checking for Updates" msgstr "Controllo aggiornamenti" #: quodlibet/update.py:126 msgid "Connection failed" msgstr "Connessione fallita" #: quodlibet/update.py:135 #, 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:138 #, 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:426 msgid "Playlists must have a name" msgstr "Le scalette devono avere un nome" #: quodlibet/util/collection.py:609 #, python-format msgid "A playlist named %s already exists." msgstr "Esiste già una scaletta chiamata %s." #: quodlibet/util/cover/built_in.py:33 msgid "Embedded album covers" msgstr "Copertine dell'album incorporate" #: quodlibet/util/cover/built_in.py:34 msgid "Uses covers embedded into audio files." msgstr "Usa le copertine incorporate nei file audio." #: quodlibet/util/cover/built_in.py:56 msgid "Filesystem cover" msgstr "Copertina filesystem" #: quodlibet/util/cover/built_in.py:57 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:231 msgid "Cover Art" msgstr "Grafica copertina" #: quodlibet/util/cover/manager.py:231 msgid "Querying album art providers" msgstr "Interrogazione dei fornitori di grafiche degli album" #: quodlibet/util/__init__.py:77 msgid "Display brief usage information" msgstr "Mostra brevi informazioni sull'utilizzo" #: quodlibet/util/__init__.py:79 msgid "Display version and copyright" msgstr "Mostra versione e copyright" #: quodlibet/util/__init__.py:80 msgid "Print debugging information" msgstr "Stampa informazioni di debug" #: quodlibet/util/__init__.py:119 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "Uso: %(program)s %(usage)s" #: quodlibet/util/__init__.py:121 msgid "[options]" msgstr "[opzioni]" #: quodlibet/util/__init__.py:166 #, python-format msgid "Option %r not recognized." msgstr "Opzione %r non riconosciuta." #: quodlibet/util/__init__.py:169 #, python-format msgid "Option %r requires an argument." msgstr "L'opzione %r richiede un argomento." #: quodlibet/util/__init__.py:172 #, python-format msgid "%r is not a unique prefix." msgstr "%r non è un prefisso unico." #: quodlibet/util/__init__.py:348 #, python-format msgid "%d kbps" msgstr "%d kbps" #: quodlibet/util/__init__.py:403 #, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%s secondo" msgstr[1] "%s secondi" #: quodlibet/util/__init__.py:416 msgid "No time information" msgstr "Nessuna informazione sulla durata" #: quodlibet/util/__init__.py:419 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d secondo" msgstr[1] "%d secondi" #: quodlibet/util/__init__.py:420 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d minuto" msgstr[1] "%d minuti" #: quodlibet/util/__init__.py:421 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d ora" msgstr[1] "%d ore" #: quodlibet/util/__init__.py:422 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d giorno" msgstr[1] "%d giorni" #: quodlibet/util/__init__.py:423 #, 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:515 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:117 msgid "Unable to edit song" msgstr "Impossibile modificare il brano" #: quodlibet/util/songwrapper.py:118 #, python-format msgid "" "Saving <b>%s</b> 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:33 quodlibet/util/string/__init__.py:43 msgid "[Invalid Encoding]" msgstr "[Codifica non valida]" #: quodlibet/util/tags.py:84 msgid "album" msgstr "album" #: quodlibet/util/tags.py:85 msgid "arranger" msgstr "arrangiatore" #: quodlibet/util/tags.py:85 msgid "arrangers" msgstr "arrangiatori" #: quodlibet/util/tags.py:85 msgid "arrangement" msgstr "arrangiamento" #: quodlibet/util/tags.py:87 msgid "author" msgstr "autore" #: quodlibet/util/tags.py:87 msgid "authors" msgstr "autori" #: quodlibet/util/tags.py:88 msgid "comment" msgstr "commento" #: quodlibet/util/tags.py:89 msgid "composer" msgstr "compositore" #: quodlibet/util/tags.py:89 msgid "composers" msgstr "compositori" #: quodlibet/util/tags.py:89 msgid "composition" msgstr "composizione" #. Translators: conducting as in conducting a musical performance #: quodlibet/util/tags.py:91 msgid "conductor" msgstr "direttore" #: quodlibet/util/tags.py:91 msgid "conductors" msgstr "direttori" #: quodlibet/util/tags.py:91 msgid "conducting" msgstr "direzione" #: quodlibet/util/tags.py:92 msgid "contact" msgstr "contatto" #: quodlibet/util/tags.py:93 msgid "copyright" msgstr "copyright" #: quodlibet/util/tags.py:94 msgid "date" msgstr "data" #: quodlibet/util/tags.py:95 msgid "description" msgstr "descrizione" #: quodlibet/util/tags.py:96 msgid "genre" msgstr "genere" #: quodlibet/util/tags.py:96 msgid "genres" msgstr "generi" #: quodlibet/util/tags.py:97 msgid "performer" msgstr "esecutore" #: quodlibet/util/tags.py:97 msgid "performance" msgstr "esecuzione" #: quodlibet/util/tags.py:98 msgid "grouping" msgstr "raggruppamento" #: quodlibet/util/tags.py:99 msgid "language" msgstr "lingua" #: quodlibet/util/tags.py:100 msgid "license" msgstr "licenza" #: quodlibet/util/tags.py:102 msgid "lyricist" msgstr "paroliere" #: quodlibet/util/tags.py:102 msgid "lyricists" msgstr "parolieri" #: quodlibet/util/tags.py:102 msgid "lyrics" msgstr "testi" #. Translators: Also e.g. "record label", "publisher" #: quodlibet/util/tags.py:104 msgid "organization" msgstr "etichetta discografica" #: quodlibet/util/tags.py:105 msgid "title" msgstr "titolo" #: quodlibet/util/tags.py:106 msgid "version" msgstr "versione" #: quodlibet/util/tags.py:107 msgid "website" msgstr "sito web" #: quodlibet/util/tags.py:109 msgid "album artist" msgstr "artista dell'album" #: quodlibet/util/tags.py:110 msgid "BPM" msgstr "BPM" #. Translators: This used to be called "part". #: quodlibet/util/tags.py:113 quodlibet/util/tags.py:114 msgid "disc subtitle" msgstr "Sottotitolo disco" #: quodlibet/util/tags.py:115 quodlibet/util/tags.py:152 msgid "disc" msgstr "disco" #: quodlibet/util/tags.py:116 quodlibet/util/tags.py:154 msgid "track" msgstr "traccia" #: quodlibet/util/tags.py:117 msgid "label ID" msgstr "ID etichetta" #: quodlibet/util/tags.py:118 msgid "original release date" msgstr "data d'uscita originale" #: quodlibet/util/tags.py:119 msgid "original album" msgstr "album originale" #: quodlibet/util/tags.py:120 msgid "original artist" msgstr "artista originale" #: quodlibet/util/tags.py:121 msgid "recording date" msgstr "data di registrazione" #: quodlibet/util/tags.py:122 msgid "release country" msgstr "Stato di rilascio" #. 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 #, fuzzy 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 #, fuzzy msgid "sample rate" msgstr "ampiezza 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/exfalso.desktop.in:3 data/exfalso.appdata.xml.in:5 msgid "Ex Falso" msgstr "" #: data/exfalso.desktop.in:4 msgid "Audio tag editor" msgstr "Editor di tag audio" #: data/exfalso.desktop.in:5 data/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/exfalso.appdata.xml.in:16 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/exfalso.appdata.xml.in:21 #: 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 "_Download…" #~ msgstr "S_carica" #~ msgid "Download Files" #~ msgstr "Scarica i file" #~ msgid "Download File" #~ msgstr "Scarica il file" #~ msgid "Device Properties" #~ msgstr "Proprietà del dispositivo" #~ msgid "Device:" #~ msgstr "Dispositivo:" #~ msgid "Not mounted" #~ msgstr "Non montato" #, fuzzy #~ msgid "Mount point:" #~ msgstr "Punto di mount:" #~ msgid "Media Devices" #~ msgstr "Dispositivo multimediale" #~ msgid "_Media Devices" #~ msgstr "Dispositivo_Multimediale" #~ msgid "_Eject" #~ msgstr "_Espelli" #, fuzzy #~ msgid "_Properties" #~ msgstr "Proprietà" #, fuzzy #~ msgid "%(used-size)s used, %(free-size)s available" #~ msgstr "<b>%s</b> utilizzato, <b>%s</b> disponibile" #, fuzzy #~ msgid "%s is not connected." #~ msgstr "<b>%s</b> non è connesso." #, fuzzy #~ msgid "Copying %(song)s" #~ msgstr "Sto copiando <b>%(song)s</b>." #~ 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." #, fuzzy #~ msgid "%s could not be copied." #~ msgstr "<b>%s</b> non può essere copiato." #~ msgid "Unable to delete songs" #~ msgstr "Impossibile eliminare i brani" #, fuzzy #~ msgid "Deleting %(song)s" #~ msgstr "Elimino <b>%(song)s</b>" #, fuzzy #~ msgid "%s could not be deleted." #~ msgstr "<b>%s</b> non può essere eliminato." #~ msgid "Unable to delete song" #~ msgstr "Impossibile eliminare il brano" #, fuzzy #~ msgid "Ejecting %s failed." #~ msgstr "Esplusione di <b>%s</b>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." #, fuzzy #~ msgid "Show or hide the main song list (deprecated)" #~ msgstr "Mostra o nascondi la lista di brani" #~ msgid "Unknown Device" #~ msgstr "Dispositivo sconosciuto" #, fuzzy #~ msgid "Could not import %s, which is needed for device support." #~ msgstr "" #~ "Non riesco a imporare dbus-python, che è necessario per leggere il " #~ "dispositivo." #~ msgid "%r is not a supported device." #~ msgstr "'%r' non è un dispositivo supportato." #, fuzzy #~ msgid "Could not find '%s'." #~ msgstr "%s: Non trovo libudev." #~ 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" #, fuzzy #~ msgid "_Clear" #~ msgstr "_Pulisci gli Errori" #, fuzzy #~ msgid "Lyrics:" #~ msgstr "Testi" #, fuzzy #~ msgid "Lyrics Window" #~ msgstr "Testi" #, fuzzy #~ msgid "_Lyrics" #~ msgstr "Testi" #, fuzzy #~ msgid "Browse Folders" #~ msgstr "Catalogo" #, fuzzy #~ msgid "Unable to open folders" #~ msgstr "Impossibile creare la cartella" #~ msgid "Audio device: %s" #~ msgstr "Dispositivo audio: %s" #~ msgid "Downloads" #~ msgstr "Scaricati" #~ msgid "Size" #~ msgstr "Dimensioni" #~ msgid "_Download" #~ msgstr "S_carica" #, fuzzy #~ msgid "_Edit" #~ msgstr "_Modifica Display..." #~ msgid "_Copy to Device" #~ msgstr "Copia sul dispositivo" #, fuzzy #~ msgid "browsers" #~ msgstr "Catalogo" #, fuzzy #~ msgid "Could not import %s. Audio Feeds browser disabled." #~ msgstr "" #~ "Non posso importare il python-feedparser, il navigatore degli Audio Feed " #~ "è 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 "Watch this folder for new songs" #~ msgstr "Controlla la presenza di nuovi brani in questa cartella" #~ 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 "Model:" #~ msgstr "Modello:" #~ msgid "Capacity:" #~ msgstr "Capienza:" #~ msgid "Firmware:" #~ msgstr "Firmware:" #~ msgid "Removing orphaned iPod track" #~ msgstr "Sto rimuovendo le tracce iPod orfane" #, 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" #, fuzzy #~ msgid "Could not find libgpod, iPod support disabled." #~ msgstr "Non posso importare python-gpod, il supporto a iPod è disabilitato." #, fuzzy #~ msgid "Track Repeat" #~ msgstr "picco della 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" #, fuzzy #~ msgid "Force Write" #~ msgstr "Scrivi" #~ 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" #, fuzzy #~ msgid "Add Bookmark" #~ msgstr "Segnalibri" #~ msgid "Song _List" #~ msgstr "_Lista dei Brani" #, fuzzy #~ msgid "D:" #~ msgstr "W: " #, fuzzy #~ msgid "W:" #~ msgstr "W: " #, fuzzy #~ msgid "E:" #~ msgstr "E: " #, fuzzy #~ 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 ..." #, fuzzy #~ msgid "Split _disc from album" #~ msgstr "Separa i dischi dell'_album" #, fuzzy #~ msgid "Timeout" #~ msgstr "Tempo" #, fuzzy #~ msgid "Select an album" #~ msgstr "_Seleziona Tutto" #, 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 altri %(count)d" #, fuzzy #~ msgid "Playlist Export" #~ msgstr "Scalette" #~ msgid "_Use rounded corners on thumbnails" #~ msgstr "_Usa angoli arrotondati nelle anteprime" #, fuzzy #~ msgid "Round the corners of album artwork thumbnail images." #~ msgstr "" #~ "Arrotonda gli angoli delle anteprime delle immagini degli album. Richiede " #~ "il riavvio per avere effetto." #~ msgid "Re_fresh Library" #~ msgstr "A_ggiorna la Libreria" #, fuzzy #~ msgid "_Remove rating" #~ msgstr "_Rimuovi Stazione" #~ msgid "Unable to open input files" #~ msgstr "Impossibile aprire i file di input" #~ 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?" #, fuzzy #~ msgid "Track Headers" #~ msgstr "Headers delle _Tracce" #, fuzzy #~ msgid "People Headers" #~ msgstr "Headers della _Gente" #, fuzzy #~ 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 " #, fuzzy #~ 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 "General" #~ msgstr "Generale" #~ 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9671857 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/po/ja.po����������������������������������������������������������������������������0000644�0001750�0001750�00000537573�00000000000�014072� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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: 2017-05-17 18:58+0200\n" "PO-Revision-Date: 2013-07-20 22:35+0100\n" "Last-Translator: Yasushi Iwata <yasusii@lowlife.jp>\n" "Language-Team: Japanese\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: Poedit 1.5.4\n" #: ../data/exfalso.appdata.xml.in.h:1 ../data/exfalso.desktop.in.h:2 msgid "Edit tags in your audio files" msgstr "オーディオファイルのタグ編集" #: ../data/exfalso.appdata.xml.in.h:2 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/exfalso.appdata.xml.in.h:3 ../data/quodlibet.appdata.xml.in.h:3 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/exfalso.desktop.in.h:1 msgid "Audio tag editor" msgstr "オーディオタグ・エディタ" #: ../data/quodlibet.appdata.xml.in.h:1 ../data/quodlibet.desktop.in.h:2 msgid "Listen to, browse, or edit your audio collection" msgstr "オーディオファイルの再生、内容表示、編集ができます" #: ../data/quodlibet.appdata.xml.in.h:2 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 "" #: ../data/quodlibet.desktop.in.h:1 msgid "Music Player" msgstr "ミュージックプレイヤー" #: ../quodlibet/browsers/albums/main.py:168 #: ../quodlibet/browsers/covergrid/main.py:54 #, fuzzy msgid "_Title" msgstr "タイトル" #: ../quodlibet/browsers/albums/main.py:169 #: ../quodlibet/browsers/covergrid/main.py:55 ../quodlibet/qltk/prefs.py:49 msgid "_Artist" msgstr "アーティスト(_A)" #: ../quodlibet/browsers/albums/main.py:170 #: ../quodlibet/browsers/covergrid/main.py:56 ../quodlibet/qltk/prefs.py:54 msgid "_Date" msgstr "日付(_D)" #: ../quodlibet/browsers/albums/main.py:171 #: ../quodlibet/browsers/covergrid/main.py:57 ../quodlibet/qltk/prefs.py:53 #, fuzzy msgid "_Genre" msgstr "ジャンル" #: ../quodlibet/browsers/albums/main.py:172 #: ../quodlibet/browsers/covergrid/main.py:58 ../quodlibet/qltk/prefs.py:58 #: ../quodlibet/qltk/ratingsmenu.py:39 msgid "_Rating" msgstr "レイティング(_R)" #: ../quodlibet/browsers/albums/main.py:178 #: ../quodlibet/browsers/covergrid/main.py:64 #, fuzzy msgid "Sort _by…" msgstr "日付で並び換え" #: ../quodlibet/browsers/albums/main.py:199 #: ../quodlibet/browsers/covergrid/main.py:85 #: ../quodlibet/browsers/paned/prefs.py:166 #: ../quodlibet/browsers/playlists/main.py:629 #: ../quodlibet/qltk/exfalsowindow.py:109 ../quodlibet/qltk/pluginwin.py:341 #: ../quodlibet/qltk/quodlibetwindow.py:1016 #, fuzzy msgid "_Preferences" msgstr "設定" #: ../quodlibet/browsers/albums/main.py:361 msgid "Album List" msgstr "アルバムリスト" #: ../quodlibet/browsers/albums/main.py:362 msgid "_Album List" msgstr "アルバムリスト(_A)" #: ../quodlibet/browsers/albums/main.py:472 #: ../quodlibet/browsers/covergrid/main.py:279 #: ../quodlibet/browsers/covergrid/main.py:488 msgid "All Albums" msgstr "全てのアルバム" #: ../quodlibet/browsers/albums/main.py:473 #: ../quodlibet/browsers/covergrid/main.py:280 #: ../quodlibet/browsers/covergrid/main.py:489 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%dアルバム" #: ../quodlibet/browsers/albums/main.py:650 #: ../quodlibet/browsers/covergrid/main.py:467 #, fuzzy 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:381 ../quodlibet/util/collection.py:245 #, 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:379 ../quodlibet/util/collection.py:249 #, python-format msgid "%d disc" msgid_plural "%d discs" msgstr[0] "%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 "アルバムのカバーを表示する(_c)" #: ../quodlibet/browsers/albums/prefs.py:67 msgid "Inline _search includes people" msgstr "" #: ../quodlibet/browsers/albums/prefs.py:71 #: ../quodlibet/browsers/covergrid/prefs.py:120 #, fuzzy msgid "Options" msgstr "場所" #: ../quodlibet/browsers/albums/prefs.py:74 #: ../quodlibet/browsers/covergrid/prefs.py:123 msgid "Album Display" msgstr "アルバムの表示" #: ../quodlibet/browsers/albums/prefs.py:78 #: ../quodlibet/browsers/covergrid/prefs.py:127 #: ../quodlibet/browsers/media.py:39 #: ../quodlibet/browsers/playlists/prefs.py:56 #: ../quodlibet/ext/songsmenu/albumart.py:326 #: ../quodlibet/ext/songsmenu/duplicates.py:350 #: ../quodlibet/ext/songsmenu/filterall.py:48 #: ../quodlibet/qltk/bookmarks.py:101 ../quodlibet/qltk/cbes.py:93 #: ../quodlibet/qltk/data_editors.py:99 ../quodlibet/qltk/data_editors.py:324 #: ../quodlibet/qltk/exfalsowindow.py:297 ../quodlibet/qltk/pluginwin.py:79 #: ../quodlibet/qltk/pluginwin.py:427 ../quodlibet/qltk/prefs.py:707 #: ../quodlibet/qltk/textedit.py:164 ../quodlibet/update.py:148 msgid "_Close" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:55 #: ../quodlibet/browsers/audiofeeds.py:67 #: ../quodlibet/browsers/audiofeeds.py:69 #: ../quodlibet/browsers/audiofeeds.py:159 #: ../quodlibet/browsers/paned/models.py:86 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:46 #: ../quodlibet/formats/_audio.py:495 ../quodlibet/order/__init__.py:27 #: ../quodlibet/qltk/information.py:240 ../quodlibet/qltk/information.py:247 #: ../quodlibet/qltk/information.py:273 ../quodlibet/qltk/wlw.py:70 msgid "Unknown" msgstr "不明" #: ../quodlibet/browsers/audiofeeds.py:246 msgid "New Feed" msgstr "新規フィード" #: ../quodlibet/browsers/audiofeeds.py:247 msgid "Enter the location of an audio feed:" msgstr "オーディオフィードの場所を入力してください:" #: ../quodlibet/browsers/audiofeeds.py:248 #: ../quodlibet/browsers/collection/prefs.py:90 #: ../quodlibet/browsers/iradio.py:341 ../quodlibet/browsers/paned/prefs.py:78 #: ../quodlibet/browsers/playlists/menu.py:96 #: ../quodlibet/browsers/playlists/util.py:52 ../quodlibet/qltk/bookmarks.py:62 #: ../quodlibet/qltk/cbes.py:55 ../quodlibet/qltk/data_editors.py:311 #: ../quodlibet/qltk/edittags.py:288 ../quodlibet/qltk/edittags.py:488 #: ../quodlibet/qltk/quodlibetwindow.py:1354 ../quodlibet/qltk/scanbox.py:61 msgid "_Add" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:265 msgid "Audio Feeds" msgstr "オーディオフィード" #: ../quodlibet/browsers/audiofeeds.py:266 msgid "_Audio Feeds" msgstr "オーディオフィード(_A)" #: ../quodlibet/browsers/audiofeeds.py:345 #: ../quodlibet/browsers/audiofeeds.py:350 #, fuzzy msgid "_Download…" msgstr "ダウンロード(_D)" #: ../quodlibet/browsers/audiofeeds.py:359 msgid "Download Files" msgstr "ファイルのダウンロード" #. Save button #: ../quodlibet/browsers/audiofeeds.py:359 #: ../quodlibet/browsers/audiofeeds.py:371 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:81 #: ../quodlibet/ext/songsmenu/albumart.py:322 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:355 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:278 #: ../quodlibet/ext/songsmenu/html.py:76 #: ../quodlibet/ext/songsmenu/lastfmsync.py:216 #: ../quodlibet/ext/songsmenu/playlist.py:51 #: ../quodlibet/ext/songsmenu/replaygain.py:365 #: ../quodlibet/ext/songsmenu/tapbpm.py:182 ../quodlibet/qltk/_editutils.py:39 #: ../quodlibet/qltk/lyrics.py:38 ../quodlibet/qltk/msg.py:52 #: ../quodlibet/qltk/renamefiles.py:168 ../quodlibet/qltk/tracknumbers.py:113 msgid "_Save" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:371 msgid "Download File" msgstr "ファイルのダウンロード" #: ../quodlibet/browsers/audiofeeds.py:394 #: ../quodlibet/browsers/playlists/main.py:213 #: ../quodlibet/qltk/data_editors.py:96 msgid "_New" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:454 #: ../quodlibet/browsers/audiofeeds.py:513 msgid "Unable to add feed" msgstr "フィードを追加できません" #: ../quodlibet/browsers/audiofeeds.py:455 #: ../quodlibet/browsers/audiofeeds.py:514 #, fuzzy, python-format msgid "" "%s could not be added. The server may be down, or the location may not be an " "audio feed." msgstr "" "<b>%s</b> を追加できませんでした。サーバがダウンしているか、もしくはオーディ" "オフィードの場所を間違えている可能性があります。" #. refresh button #: ../quodlibet/browsers/audiofeeds.py:462 ../quodlibet/browsers/media.py:217 #: ../quodlibet/browsers/media.py:386 ../quodlibet/qltk/filesel.py:259 #: ../quodlibet/qltk/pluginwin.py:413 #, fuzzy msgid "_Refresh" msgstr "ライブラリの再表示(_f)" #: ../quodlibet/browsers/audiofeeds.py:463 #: ../quodlibet/browsers/playlists/main.py:457 #: ../quodlibet/browsers/playlists/util.py:43 ../quodlibet/qltk/delete.py:143 #: ../quodlibet/qltk/filesel.py:256 ../quodlibet/qltk/lyrics.py:39 #: ../quodlibet/qltk/maskedbox.py:28 ../quodlibet/qltk/songsmenu.py:392 #, fuzzy msgid "_Delete" msgstr "ファイルの削除" #: ../quodlibet/browsers/audiofeeds.py:530 msgid "" "The current audio backend does not support URLs, Audio Feeds browser " "disabled." msgstr "" #: ../quodlibet/browsers/_base.py:147 ../quodlibet/browsers/_base.py:150 msgid "Library Browser" msgstr "ライブラリブラウザ" #: ../quodlibet/browsers/_base.py:274 ../quodlibet/ext/songsmenu/refresh.py:30 #: ../quodlibet/qltk/exfalsowindow.py:241 ../quodlibet/qltk/information.py:542 #: ../quodlibet/qltk/maskedbox.py:68 ../quodlibet/util/collection.py:527 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d曲" #: ../quodlibet/browsers/_base.py:402 ../quodlibet/browsers/_base.py:407 #: ../quodlibet/qltk/tagsfrompath.py:194 ../quodlibet/qltk/textedit.py:141 #: ../quodlibet/util/__init__.py:622 msgid "Invalid pattern" msgstr "不正なパターン" #: ../quodlibet/browsers/collection/main.py:78 msgid "Album Collection" msgstr "" #: ../quodlibet/browsers/collection/main.py:79 msgid "Album _Collection" msgstr "" #: ../quodlibet/browsers/collection/models.py:24 #, fuzzy, python-format msgid "Unknown %s" msgstr "不明" #: ../quodlibet/browsers/collection/models.py:25 #, fuzzy, python-format msgid "Multiple %s Values" msgstr "複数の値に分割(_M)" #: ../quodlibet/browsers/collection/prefs.py:66 #: ../quodlibet/browsers/paned/prefs.py:51 msgid "_Custom" msgstr "カスタム(_C)" #. Remove button #: ../quodlibet/browsers/collection/prefs.py:94 #: ../quodlibet/browsers/paned/prefs.py:82 #: ../quodlibet/browsers/playlists/menu.py:97 #: ../quodlibet/ext/playlist/remove_duplicates.py:60 #: ../quodlibet/qltk/bookmarks.py:97 ../quodlibet/qltk/bookmarks.py:127 #: ../quodlibet/qltk/cbes.py:82 ../quodlibet/qltk/cbes.py:89 #: ../quodlibet/qltk/data_editors.py:81 ../quodlibet/qltk/data_editors.py:94 #: ../quodlibet/qltk/data_editors.py:301 ../quodlibet/qltk/data_editors.py:314 #: ../quodlibet/qltk/data_editors.py:322 ../quodlibet/qltk/edittags.py:494 #: ../quodlibet/qltk/edittags.py:634 ../quodlibet/qltk/maskedbox.py:48 #: ../quodlibet/qltk/maskedbox.py:88 ../quodlibet/qltk/queue.py:350 #: ../quodlibet/qltk/scanbox.py:36 ../quodlibet/qltk/scanbox.py:63 #, fuzzy msgid "_Remove" msgstr "ラジオ局の削除(_R)" #: ../quodlibet/browsers/collection/prefs.py:122 #: ../quodlibet/ext/songsmenu/filterall.py:34 #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:92 #: ../quodlibet/qltk/edittags.py:431 msgid "Tag" msgstr "タグ" #: ../quodlibet/browsers/collection/prefs.py:128 msgid "Merge" msgstr "" #: ../quodlibet/browsers/collection/prefs.py:188 #, fuzzy msgid "Album Collection Preferences" msgstr "アルバムリストの設定" #: ../quodlibet/browsers/collection/prefs.py:195 #: ../quodlibet/browsers/paned/prefs.py:209 #: ../quodlibet/ext/songsmenu/editplaycount.py:45 #: ../quodlibet/ext/songsmenu/exact_rating.py:38 #: ../quodlibet/player/gstbe/prefs.py:40 ../quodlibet/qltk/prefs.py:127 #: ../quodlibet/qltk/textedit.py:65 msgid "_Apply" msgstr "" #: ../quodlibet/browsers/collection/prefs.py:198 #: ../quodlibet/browsers/paned/prefs.py:213 #: ../quodlibet/browsers/playlists/menu.py:95 #: ../quodlibet/browsers/playlists/util.py:42 #: ../quodlibet/errorreport/ui.py:108 #: ../quodlibet/ext/playlist/export_to_folder.py:37 #: ../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:44 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:281 #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:88 #: ../quodlibet/ext/songsmenu/importexport.py:35 #: ../quodlibet/ext/songsmenu/lastfmsync.py:215 #: ../quodlibet/ext/songsmenu/playlist.py:50 #: ../quodlibet/ext/songsmenu/replaygain.py:364 #: ../quodlibet/ext/songsmenu/tapbpm.py:181 ../quodlibet/plugins/playlist.py:39 #: ../quodlibet/qltk/chooser.py:184 ../quodlibet/qltk/chooser.py:205 #: ../quodlibet/qltk/chooser.py:229 ../quodlibet/qltk/chooser.py:253 #: ../quodlibet/qltk/delete.py:90 ../quodlibet/qltk/delete.py:133 #: ../quodlibet/qltk/edittags.py:287 ../quodlibet/qltk/_editutils.py:38 #: ../quodlibet/qltk/getstring.py:28 ../quodlibet/qltk/maskedbox.py:27 #: ../quodlibet/qltk/msg.py:54 ../quodlibet/qltk/msg.py:93 #: ../quodlibet/qltk/ratingsmenu.py:33 ../quodlibet/qltk/songsmenu.py:45 #: ../quodlibet/qltk/songsmenu.py:73 ../quodlibet/update.py:94 msgid "_Cancel" msgstr "" #: ../quodlibet/browsers/covergrid/main.py:125 #, fuzzy msgid "Cover Grid" msgstr "合計サイズ" #: ../quodlibet/browsers/covergrid/main.py:126 #, 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 "アルバムのカバーを表示する(_c)" #: ../quodlibet/browsers/covergrid/prefs.py:71 #, fuzzy msgid "Show \"All Albums\" Item" msgstr "全てのアルバム" #: ../quodlibet/browsers/covergrid/prefs.py:78 msgid "Vertical Split" msgstr "" #: ../quodlibet/browsers/covergrid/prefs.py:110 #: ../quodlibet/browsers/covergrid/prefs.py:111 #, fuzzy msgid "Cover Magnification" msgstr "新しいラジオ局はありません" #: ../quodlibet/browsers/filesystem.py:40 msgid "File System" msgstr "ファイルシステム" #: ../quodlibet/browsers/filesystem.py:41 msgid "_File System" msgstr "ファイルシステム(_F)" #: ../quodlibet/browsers/filesystem.py:113 ../quodlibet/browsers/media.py:491 #: ../quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "曲のコピーができません" #: ../quodlibet/browsers/filesystem.py:114 ../quodlibet/qltk/songlist.py:268 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "選択されたファイルのソングリストまたはキューへのコピーに失敗しました。" #: ../quodlibet/browsers/filesystem.py:189 msgid "_Add to Library" msgstr "ライブラリへ追加(_A)" #: ../quodlibet/browsers/iradio.py:178 msgid "Unsupported file type" msgstr "サポートしていないファイル形式です" #: ../quodlibet/browsers/iradio.py:179 #, 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:219 ../quodlibet/browsers/iradio.py:232 #: ../quodlibet/browsers/iradio.py:810 msgid "Unable to add station" msgstr "ラジオ局を追加できません" #: ../quodlibet/browsers/iradio.py:243 ../quodlibet/browsers/iradio.py:471 msgid "Internet Radio" msgstr "インターネットラジオ" #: ../quodlibet/browsers/iradio.py:243 #, fuzzy msgid "Downloading station list" msgstr "ファイルのダウンロード" #: ../quodlibet/browsers/iradio.py:339 msgid "New Station" msgstr "新規ラジオ局" #: ../quodlibet/browsers/iradio.py:340 msgid "Enter the location of an Internet radio station:" msgstr "インターネットラジオ局の場所を入力してください:" #: ../quodlibet/browsers/iradio.py:358 msgid "Electronic" msgstr "" #: ../quodlibet/browsers/iradio.py:361 msgid "Hip Hop / Rap" msgstr "" #: ../quodlibet/browsers/iradio.py:362 msgid "Oldies" msgstr "" #: ../quodlibet/browsers/iradio.py:363 msgid "R&B" msgstr "" #: ../quodlibet/browsers/iradio.py:364 msgid "Japanese" msgstr "" #: ../quodlibet/browsers/iradio.py:365 msgid "Indian" msgstr "" #: ../quodlibet/browsers/iradio.py:367 msgid "Religious" msgstr "" #: ../quodlibet/browsers/iradio.py:369 msgid "Charts" msgstr "" #: ../quodlibet/browsers/iradio.py:370 msgid "Turkish" msgstr "" #: ../quodlibet/browsers/iradio.py:371 msgid "Reggae / Dancehall" msgstr "" #: ../quodlibet/browsers/iradio.py:372 #, fuzzy msgid "Latin" msgstr "レイティング" #: ../quodlibet/browsers/iradio.py:373 msgid "College Radio" msgstr "" #: ../quodlibet/browsers/iradio.py:374 msgid "Talk / News" msgstr "" #: ../quodlibet/browsers/iradio.py:375 msgid "Ambient" msgstr "" #: ../quodlibet/browsers/iradio.py:376 msgid "Jazz" msgstr "" #: ../quodlibet/browsers/iradio.py:377 ../quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "" #: ../quodlibet/browsers/iradio.py:378 ../quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "" #: ../quodlibet/browsers/iradio.py:379 msgid "Alternative" msgstr "" #: ../quodlibet/browsers/iradio.py:380 msgid "Metal" msgstr "" #: ../quodlibet/browsers/iradio.py:381 msgid "Country" msgstr "" #: ../quodlibet/browsers/iradio.py:382 msgid "News" msgstr "" #: ../quodlibet/browsers/iradio.py:383 msgid "Schlager" msgstr "" #: ../quodlibet/browsers/iradio.py:384 msgid "Funk" msgstr "" #: ../quodlibet/browsers/iradio.py:385 msgid "Indie" msgstr "" #: ../quodlibet/browsers/iradio.py:386 msgid "Blues" msgstr "" #: ../quodlibet/browsers/iradio.py:387 msgid "Soul" msgstr "" #: ../quodlibet/browsers/iradio.py:388 msgid "Lounge" msgstr "" #: ../quodlibet/browsers/iradio.py:389 msgid "Punk" msgstr "" #: ../quodlibet/browsers/iradio.py:390 msgid "Reggaeton" msgstr "" #: ../quodlibet/browsers/iradio.py:392 msgid "Slavic" msgstr "" #: ../quodlibet/browsers/iradio.py:394 msgid "Greek" msgstr "" #: ../quodlibet/browsers/iradio.py:395 msgid "Gothic" msgstr "" #: ../quodlibet/browsers/iradio.py:396 ../quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "" #: ../quodlibet/browsers/iradio.py:449 msgid "Would you like to load a list of popular radio stations?" msgstr "" #: ../quodlibet/browsers/iradio.py:455 #, fuzzy msgid "_Load Stations" msgstr "新規ラジオ局(_N)" #: ../quodlibet/browsers/iradio.py:472 msgid "_Internet Radio" msgstr "インターネットラジオ(_I)" #: ../quodlibet/browsers/iradio.py:538 #, fuzzy msgid "_New Station…" msgstr "新規ラジオ局" #: ../quodlibet/browsers/iradio.py:541 #, fuzzy msgid "_Update Stations" msgstr "新規ラジオ局(_N)" #: ../quodlibet/browsers/iradio.py:568 #, fuzzy msgid "All Stations" msgstr "新規ラジオ局" #. TODO: support for ~#rating=!None etc (#1940) #: ../quodlibet/browsers/iradio.py:572 #: ../quodlibet/browsers/soundcloud/main.py:64 msgid "Favorites" msgstr "" #: ../quodlibet/browsers/iradio.py:580 msgid "No Category" msgstr "" #: ../quodlibet/browsers/iradio.py:802 msgid "No stations found" msgstr "ラジオ局が見つかりません" #: ../quodlibet/browsers/iradio.py:803 #, python-format msgid "No Internet radio stations were found at %s." msgstr "%sにインターネットラジオ局が見つかりません。" #: ../quodlibet/browsers/iradio.py:811 msgid "All stations listed are already in your library." msgstr "一覧にあるラジオ局は全てライブラリに登録されています。" #: ../quodlibet/browsers/iradio.py:828 #, fuzzy msgid "Add to Favorites" msgstr "プレイリストへ追加(_A)" #: ../quodlibet/browsers/iradio.py:832 #, fuzzy msgid "Remove from Favorites" msgstr "プレイリストから削除(_R)" #: ../quodlibet/browsers/iradio.py:932 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "%(count)d局" #: ../quodlibet/browsers/media.py:36 #, fuzzy msgid "Device Properties" msgstr "プロパティ" #: ../quodlibet/browsers/media.py:52 msgid "Device:" msgstr "デバイス:" #: ../quodlibet/browsers/media.py:54 msgid "Not mounted" msgstr "マウントされていません" #: ../quodlibet/browsers/media.py:55 #, fuzzy msgid "Mount point:" msgstr "マウントポイント" #: ../quodlibet/browsers/media.py:61 ../quodlibet/qltk/cbes.py:40 msgid "_Name:" msgstr "名前(_N)" #: ../quodlibet/browsers/media.py:135 #, fuzzy msgid "Media Devices" msgstr "オーディオデバイス: %s" #: ../quodlibet/browsers/media.py:136 #, fuzzy msgid "_Media Devices" msgstr "オーディオデバイス: %s" #. eject button #: ../quodlibet/browsers/media.py:224 ../quodlibet/browsers/media.py:378 #, fuzzy msgid "_Eject" msgstr "イジェクト(_E)" #: ../quodlibet/browsers/media.py:360 #, fuzzy msgid "_Properties" msgstr "プロパティ" #: ../quodlibet/browsers/media.py:365 #: ../quodlibet/browsers/playlists/main.py:464 msgid "_Rename" msgstr "名前の変更(_R)" #: ../quodlibet/browsers/media.py:461 #, fuzzy, python-format msgid "%(used-size)s used, %(free-size)s available" msgstr "使用中<b>%s</b>、利用可能<b>%s</b>" #: ../quodlibet/browsers/media.py:479 #, fuzzy, python-format msgid "%s is not connected." msgstr "指定された場所 <b>%s</b> にアクセスできません。" #: ../quodlibet/browsers/media.py:499 #, fuzzy, python-format msgid "Copying %(song)s" msgstr "<b>%s</b>の削除失敗。" #: ../quodlibet/browsers/media.py:513 ../quodlibet/browsers/media.py:529 #, fuzzy msgid "Unable to copy song" msgstr "曲のコピーができません" #: ../quodlibet/browsers/media.py:514 msgid "There is not enough free space for this song." msgstr "この曲を保存するための空き領域が不足しています" #: ../quodlibet/browsers/media.py:526 #, fuzzy, python-format msgid "%s could not be copied." msgstr "<b>%s</b>のコピーに失敗しました。" #: ../quodlibet/browsers/media.py:545 #, fuzzy msgid "Unable to delete songs" msgstr "曲を追加できません" #: ../quodlibet/browsers/media.py:557 #, fuzzy, python-format msgid "Deleting %(song)s" msgstr "<b>%s</b>の削除失敗。" #: ../quodlibet/browsers/media.py:575 #, fuzzy, python-format msgid "%s could not be deleted." msgstr "指定された場所 <b>%s</b> にアクセスできません。" #: ../quodlibet/browsers/media.py:579 #, fuzzy msgid "Unable to delete song" msgstr "曲の編集に失敗しました" #: ../quodlibet/browsers/media.py:594 #, fuzzy, python-format msgid "Ejecting %s failed." msgstr "<b>%s</b>のイジェクト失敗。" #: ../quodlibet/browsers/media.py:597 #, fuzzy msgid "Unable to eject device" msgstr "ファイルを削除できませんでした。" #: ../quodlibet/browsers/media.py:603 msgid "No device backend, Media Devices browser disabled." msgstr "" #: ../quodlibet/browsers/paned/main.py:40 ../quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "ペインブラウザ" #: ../quodlibet/browsers/paned/main.py:41 msgid "_Paned Browser" msgstr "ペインブラウザ(_P)" #: ../quodlibet/browsers/paned/main.py:90 msgid "Select _All" msgstr "全て選択(_A)" #: ../quodlibet/browsers/paned/models.py:104 ../quodlibet/qltk/pluginwin.py:122 #: ../quodlibet/qltk/pluginwin.py:164 msgid "All" msgstr "全て" #: ../quodlibet/browsers/paned/prefs.py:67 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "<tt>%s</tt>" msgstr "" #: ../quodlibet/browsers/paned/prefs.py:162 msgid "_Wide Mode" msgstr "" #: ../quodlibet/browsers/paned/prefs.py:197 msgid "Paned Browser Preferences" msgstr "ペインブラウザの設定" #: ../quodlibet/browsers/paned/prefs.py:204 msgid "Equal pane width" msgstr "" #: ../quodlibet/browsers/playlists/main.py:48 #: ../quodlibet/browsers/playlists/main.py:575 #: ../quodlibet/qltk/pluginwin.py:168 msgid "Playlists" msgstr "プレイリスト" #: ../quodlibet/browsers/playlists/main.py:49 msgid "_Playlists" msgstr "プレイリスト(_P)" #: ../quodlibet/browsers/playlists/main.py:152 msgid "_Remove from Playlist" msgstr "プレイリストから削除(_R)" #: ../quodlibet/browsers/playlists/main.py:215 #: ../quodlibet/browsers/playlists/main.py:576 msgid "_Import" msgstr "インポート(_I)" #: ../quodlibet/browsers/playlists/main.py:391 #: ../quodlibet/browsers/playlists/util.py:50 #: ../quodlibet/util/collection.py:570 msgid "New Playlist" msgstr "新規プレイリスト" #: ../quodlibet/browsers/playlists/main.py:413 msgid "Unable to import playlist" msgstr "プレイリストをインポートできません" #: ../quodlibet/browsers/playlists/main.py:414 msgid "Quod Libet can only import playlists in the M3U and PLS formats." msgstr "Quod LibetではM3UとPLS形式のプレイリストしかインポートできません。" #: ../quodlibet/browsers/playlists/main.py:565 msgid "Unable to rename playlist" msgstr "プレイリストの名前を変更できません" #: ../quodlibet/browsers/playlists/main.py:576 msgid "Import Playlist" msgstr "プレイリストのインポート" #: ../quodlibet/browsers/playlists/menu.py:25 #, fuzzy msgid "_New Playlist…" msgstr "新規プレイリスト(_N)" #: ../quodlibet/browsers/playlists/menu.py:86 #, 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:90 #, 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:33 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "" #: ../quodlibet/browsers/playlists/util.py:35 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" #: ../quodlibet/browsers/playlists/util.py:51 #, fuzzy msgid "Enter a name for the new playlist:" msgstr "フォルダ名を入力してください:" #: ../quodlibet/browsers/playlists/util.py:102 #, fuzzy, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" "プレイリストをインポートしています。\n" "\n" "%d/%d 曲を追加しました。" #: ../quodlibet/browsers/search.py:33 msgid "_Limit Results" msgstr "検索結果の上限を設定(_L)" #: ../quodlibet/browsers/search.py:48 msgid "Search Library" msgstr "ライブラリの検索" #: ../quodlibet/browsers/search.py:49 msgid "_Search Library" msgstr "ライブラリの検索(_S)" #: ../quodlibet/browsers/soundcloud/main.py:38 #, fuzzy msgid "Soundcloud Browser" msgstr "ペインブラウザ" #: ../quodlibet/browsers/soundcloud/main.py:39 msgid "Sound_cloud" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:59 #: ../quodlibet/qltk/searchbar.py:73 msgid "Search" msgstr "検索" #: ../quodlibet/browsers/soundcloud/main.py:136 #, python-format msgid "Go to %s" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:380 #, fuzzy msgid "Connected" msgstr "場所" #: ../quodlibet/browsers/soundcloud/main.py:381 #, python-format msgid "Quod Libet is now connected, <b>%s</b>!" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:393 #, python-format msgid "Log out of %s" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:395 msgid "Enter code…" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:396 #, python-format msgid "Log in to %s" msgstr "" #: ../quodlibet/browsers/soundcloud/util.py:86 msgid "Soundcloud authorisation" msgstr "" #: ../quodlibet/browsers/soundcloud/util.py:87 msgid "Enter Soundcloud auth code:" msgstr "" #: ../quodlibet/cli.py:50 #, fuzzy msgid "Quod Libet is not running (add '--run' to start it)" msgstr "Quod Libetが起動していません。" #: ../quodlibet/cli.py:85 msgid "a music library and player" msgstr "ミュージックライブラリ/プレイヤー" #: ../quodlibet/cli.py:86 #, fuzzy msgid "[option]" msgstr "場所" #: ../quodlibet/cli.py:88 msgid "Print the playing song and exit" msgstr "再生中の曲名を表示して終了" #: ../quodlibet/cli.py:89 msgid "Begin playing immediately" msgstr "直ちに再生開始" #: ../quodlibet/cli.py:90 msgid "Don't show any windows on start" msgstr "" #: ../quodlibet/cli.py:93 msgid "Jump to next song" msgstr "次の曲へジャンプ" #: ../quodlibet/cli.py:95 msgid "Jump to previous song or restart if near the beginning" msgstr "" #: ../quodlibet/cli.py:96 msgid "Jump to previous song" msgstr "前の曲へジャンプ" #: ../quodlibet/cli.py:97 msgid "Start playback" msgstr "再生開始" #: ../quodlibet/cli.py:98 msgid "Pause playback" msgstr "一時停止" #: ../quodlibet/cli.py:99 msgid "Toggle play/pause mode" msgstr "再生/一時停止の切替" #: ../quodlibet/cli.py:100 #, fuzzy msgid "Stop playback" msgstr "再生開始" #: ../quodlibet/cli.py:101 msgid "Turn up volume" msgstr "音量を上げる" #: ../quodlibet/cli.py:102 msgid "Turn down volume" msgstr "音量を下げる" #: ../quodlibet/cli.py:103 msgid "Print player status" msgstr "プレイヤーの状態を表示" #: ../quodlibet/cli.py:104 msgid "Hide main window" msgstr "メインウィンドウを隠す" #: ../quodlibet/cli.py:105 msgid "Show main window" msgstr "メインウィンドウを表示する" #: ../quodlibet/cli.py:106 msgid "Toggle main window visibility" msgstr "メインウィンドウの表示/非表示切り替え" #: ../quodlibet/cli.py:107 msgid "Focus the running player" msgstr "起動中のプレイヤーにフォーカス" #: ../quodlibet/cli.py:108 msgid "Remove active browser filters" msgstr "アクティブなフィルタを削除" #: ../quodlibet/cli.py:109 #, fuzzy msgid "Refresh and rescan library" msgstr "ライブラリの再表示(_f)" #: ../quodlibet/cli.py:110 #, fuzzy msgid "List available browsers" msgstr "ブラウザの無効化" #: ../quodlibet/cli.py:111 msgid "Print the current playlist" msgstr "現在のプレイリストを表示" #: ../quodlibet/cli.py:112 msgid "Print the contents of the queue" msgstr "キューの内容を表示" #: ../quodlibet/cli.py:113 #, fuzzy msgid "Print the active text query" msgstr "キューの内容を表示" #: ../quodlibet/cli.py:114 msgid "Start without plugins" msgstr "" #: ../quodlibet/cli.py:115 #, fuzzy msgid "Start Quod Libet if it isn't running" msgstr "Quod Libetが起動していません。" #: ../quodlibet/cli.py:116 msgid "Exit Quod Libet" msgstr "Quod Libetの終了" #: ../quodlibet/cli.py:121 msgid "Seek within the playing song" msgstr "再生中の曲をシーク" #: ../quodlibet/cli.py:121 msgid "[+|-][HH:]MM:SS" msgstr "" #: ../quodlibet/cli.py:122 #, fuzzy msgid "Set or toggle shuffle mode" msgstr "再生/一時停止の切替" #: ../quodlibet/cli.py:123 msgid "Turn repeat off, on, or toggle it" msgstr "リピートのオン/オフまたは切替" #: ../quodlibet/cli.py:124 msgid "Set the volume" msgstr "音量のセット" #: ../quodlibet/cli.py:125 msgid "Search your audio library" msgstr "オーディオライブラリの検索" #: ../quodlibet/cli.py:125 ../quodlibet/cli.py:137 ../quodlibet/cli.py:141 #: ../quodlibet/cli.py:143 msgid "query" msgstr "" #: ../quodlibet/cli.py:126 msgid "Play a file" msgstr "ファイルの再生" #: ../quodlibet/cli.py:126 ../quodlibet/cli.py:137 ../quodlibet/cli.py:143 #, fuzzy msgctxt "command" msgid "filename" msgstr "ファイル名" #: ../quodlibet/cli.py:127 msgid "Rate the playing song" msgstr "再生中の曲をレイティング" #: ../quodlibet/cli.py:128 msgid "Set the current browser" msgstr "現在のブラウザをセット" #: ../quodlibet/cli.py:129 #, fuzzy msgid "Stop after the playing song" msgstr "再生中の曲をレイティング" #: ../quodlibet/cli.py:130 msgid "Open a new browser" msgstr "新しいブラウザを開く" #: ../quodlibet/cli.py:131 msgid "Show or hide the queue" msgstr "キューの表示/非表示" #: ../quodlibet/cli.py:133 #, fuzzy msgid "Show or hide the main song list (deprecated)" msgstr "メインソングリストの表示/非表示" #: ../quodlibet/cli.py:134 msgid "Filter on a random value" msgstr "ランダムな値でフィルタリング" #: ../quodlibet/cli.py:134 #, fuzzy msgctxt "command" msgid "tag" msgstr "タグ" #: ../quodlibet/cli.py:135 msgid "Filter on a tag value" msgstr "タグの値でフィルタリング" #: ../quodlibet/cli.py:135 msgid "tag=value" msgstr "" #: ../quodlibet/cli.py:136 msgid "Enqueue a file or query" msgstr "ファイルまたはクエリの内容をキューに入れる" #: ../quodlibet/cli.py:138 msgid "Enqueue comma-separated files" msgstr "" #: ../quodlibet/cli.py:139 ../quodlibet/util/tags.py:147 msgid "filename" msgstr "ファイル名" #: ../quodlibet/cli.py:140 msgid "Print filenames of results of query to stdout" msgstr "" #: ../quodlibet/cli.py:142 #, fuzzy msgid "Unqueue a file or query" msgstr "ファイルまたはクエリの内容をキューから削除" #: ../quodlibet/cli.py:203 #, fuzzy, python-format msgid "Invalid argument for '%s'." msgstr "E: 不正な引数'%s'が指定されました。" #: ../quodlibet/cli.py:204 ../quodlibet/util/__init__.py:190 #, fuzzy, python-format msgid "Try %s --help." msgstr "E: %s --help を試してみてください。" #: ../quodlibet/devices/_base.py:65 #, fuzzy msgid "Unknown Device" msgstr "不明なデバイス" #: ../quodlibet/devices/__init__.py:32 #, python-format msgid "Could not import %s, which is needed for device support." msgstr "" #: ../quodlibet/devices/__init__.py:153 #, fuzzy, python-format msgid "%r is not a supported device." msgstr "E: '%s'はユニークなプリフィックスではありません。" #: ../quodlibet/devices/__init__.py:245 ../quodlibet/devices/__init__.py:251 #, python-format msgid "Could not find '%s'." msgstr "" #: ../quodlibet/devices/__init__.py:450 #, fuzzy msgid "Initializing device backend." msgstr "不正な値" #: ../quodlibet/devices/__init__.py:451 #, python-format msgid "Trying '%s'" msgstr "" #: ../quodlibet/devices/__init__.py:461 msgid "Couldn't connect to a device backend." msgstr "" #: ../quodlibet/devices/__init__.py:463 msgid "Device backend initialized." msgstr "" #: ../quodlibet/devices/storage.py:57 #, fuzzy msgid "_Filename pattern:" msgstr "ファイル名のパターン(_F)" #: ../quodlibet/devices/storage.py:61 #, fuzzy msgid "Copy _album covers" msgstr "アルバムのカバーを表示する(_c)" #: ../quodlibet/devices/storage.py:65 msgid "_Remove unused covers and directories" msgstr "使われていないカバーアートとディレクトリを削除(_R)" #: ../quodlibet/errorreport/ui.py:60 msgid "An Error Occurred" msgstr "" #: ../quodlibet/errorreport/ui.py:62 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:72 msgid "File Bug Report" msgstr "" #: ../quodlibet/errorreport/ui.py:74 ../quodlibet/errorreport/ui.py:90 msgid "Submit Error Report" msgstr "" #: ../quodlibet/errorreport/ui.py:75 msgid "Quit Program" msgstr "" #: ../quodlibet/errorreport/ui.py:76 #, fuzzy msgid "Ignore Error" msgstr "エラーの表示(_E)" #: ../quodlibet/errorreport/ui.py:80 msgid "Error details:" msgstr "" #: ../quodlibet/errorreport/ui.py:92 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:100 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "" #: ../quodlibet/errorreport/ui.py:109 msgid "_Send" msgstr "" #: ../quodlibet/errorreport/ui.py:115 #, fuzzy msgid "Short description…" msgstr "説明" #: ../quodlibet/errorreport/ui.py:118 msgid "Data to be sent:" msgstr "" #: ../quodlibet/exfalso.py:34 msgid "an audio tag editor" msgstr "オーディオタグ・エディタ" #: ../quodlibet/exfalso.py:34 ../quodlibet/util/tags.py:148 msgid "directory" msgstr "ディレクトリ" #: ../quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "" #: ../quodlibet/ext/covers/artwork_url.py:20 msgid "" "Downloads covers linked to by the artwork_url tag.This works with the " "Soundcloud browser." msgstr "" #: ../quodlibet/ext/covers/discogs.py:25 #, fuzzy msgid "Discogs Cover Source" msgstr "MusicBrainzトラックID" #: ../quodlibet/ext/covers/discogs.py:26 msgid "Downloads covers from Discogs." msgstr "" #: ../quodlibet/ext/covers/lastfm.py:22 msgid "Last.fm Cover Source" msgstr "" #: ../quodlibet/ext/covers/lastfm.py:23 msgid "Downloads covers from Last.fm's cover art archive." msgstr "" #: ../quodlibet/ext/covers/musicbrainz.py:19 #, fuzzy msgid "MusicBrainz Cover Source" msgstr "MusicBrainzトラックID" #: ../quodlibet/ext/covers/musicbrainz.py:20 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:25 msgid "Kana/Kanji Simple Inverter" msgstr "" #: ../quodlibet/ext/editing/kakasi.py:26 msgid "Converts kana/kanji to romaji before renaming." msgstr "" #: ../quodlibet/ext/editing/kakasi.py:35 msgid "Romanize _Japanese text" msgstr "" #: ../quodlibet/ext/editing/kakasi.py:63 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:19 msgid "" "Allows arbitrary regex substitutions (s///) 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 "タイトルの単語をキャピタライズする(_T)" #: ../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:69 #, fuzzy msgid "Advanced Preferences" msgstr "ペインブラウザの設定" #: ../quodlibet/ext/events/advanced_preferences.py:70 msgid "Allow editing of advanced config settings." msgstr "" #: ../quodlibet/ext/events/advanced_preferences.py:162 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:153 msgid "Top of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:154 msgid "Middle of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:155 msgid "Bottom of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:158 msgid "_Position:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:171 #, fuzzy msgid "_Cover size:" msgstr "合計サイズ" #: ../quodlibet/ext/events/animosd/prefs.py:177 #: ../quodlibet/ext/events/lyricswindow.py:334 ../quodlibet/qltk/prefs.py:266 #, fuzzy msgid "Display" msgstr "ディスプレイの編集" #: ../quodlibet/ext/events/animosd/prefs.py:190 msgid "_Font:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:195 msgid "Left" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:196 msgid "Center" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:197 #, fuzzy msgid "Right" msgstr "ウェイト(_W)" #: ../quodlibet/ext/events/animosd/prefs.py:200 msgid "_Align text:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:206 msgid "Text" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:217 msgid "_Text:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:227 msgid "_Fill:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:232 #: ../quodlibet/ext/events/synchronizedlyrics.py:63 msgid "Colors" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:240 msgid "_Shadows" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:241 msgid "_Outline" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:242 msgid "Rou_nded Corners" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:258 msgid "_Delay:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:264 #: ../quodlibet/qltk/pluginwin.py:172 msgid "Effects" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:270 #, fuzzy msgid "Ed_it Display Pattern…" msgstr "ディスプレイの編集" #: ../quodlibet/ext/events/animosd/prefs.py:274 #: ../quodlibet/ext/events/trayicon/prefs.py:78 #, fuzzy msgid "Preview" msgstr "プレビュー(_P)" #: ../quodlibet/ext/events/auto_library_update.py:136 msgid "Automatic Library Update" msgstr "" #: ../quodlibet/ext/events/auto_library_update.py:137 #, python-format msgid "Keeps your library up to date with inotify. Requires %s." 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 by Brian Nelson." 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/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:97 msgid "Equalizer" msgstr "" #: ../quodlibet/ext/events/equalizer.py:98 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:132 msgid "The current backend does not support equalization." msgstr "" #: ../quodlibet/ext/events/equalizer.py:138 #, python-format msgid "%.1f kHz" msgstr "" #: ../quodlibet/ext/events/equalizer.py:139 #: ../quodlibet/ext/gstreamer/crossfeed.py:93 #: ../quodlibet/ext/gstreamer/karaoke.py:95 #, python-format msgid "%d Hz" msgstr "" #: ../quodlibet/ext/events/equalizer.py:173 #: ../quodlibet/ext/gstreamer/crossfeed.py:112 #, fuzzy, python-format msgid "%.1f dB" msgstr "%d秒" #: ../quodlibet/ext/events/equalizer.py:192 #: ../quodlibet/ext/gstreamer/crossfeed.py:31 #, fuzzy msgid "Custom" msgstr "カスタム(_C)" #: ../quodlibet/ext/events/equalizer.py:199 #, fuzzy msgid "_Clear" msgstr "プラグインのエラー" #. Translators: statuses relating to Instant Messenger apps #: ../quodlibet/ext/events/gajim_status.py:27 msgid "online" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:28 msgid "offline" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:29 msgid "chat" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:30 msgid "away" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:31 msgid "xa" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:32 msgid "invisible" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:37 msgid "Gajim Status Message" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:38 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:45 #: ../quodlibet/ext/events/telepathy_status.py:69 msgid "paused" 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:160 msgid "Add '[paused]'" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:163 msgid "If checked, '[paused]' will be added to status message on pause." msgstr "" #: ../quodlibet/ext/events/gajim_status.py:187 msgid "Statuses for which message will be changed" msgstr "" #: ../quodlibet/ext/events/headphonemon.py:156 msgid "Pause on Headphone Unplug" msgstr "" #: ../quodlibet/ext/events/headphonemon.py:157 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" #: ../quodlibet/ext/events/inhibit.py:41 msgid "Inhibit Screensaver" msgstr "" #: ../quodlibet/ext/events/inhibit.py:42 msgid "Prevents the GNOME screensaver from activating while a song is playing." msgstr "" #: ../quodlibet/ext/events/inhibit.py:51 #, fuzzy msgid "Music is playing" msgstr "ミュージックプレイヤー" #: ../quodlibet/ext/events/iradiolog.py:16 #, fuzzy msgid "Internet Radio Log" msgstr "インターネットラジオ" #: ../quodlibet/ext/events/iradiolog.py:17 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" #: ../quodlibet/ext/events/jep118.py:29 msgid "JEP-118" msgstr "" #: ../quodlibet/ext/events/jep118.py:30 msgid "Outputs a Jabber User Tunes file to ~/.quodlibet/jabber." msgstr "" #: ../quodlibet/ext/events/language.py:21 #, fuzzy msgid "Change Language" msgstr "レイティング(_R)" #: ../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 msgid "A restart is required for any changes to take effect" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:199 #, fuzzy msgid "No active song" msgstr "曲を保存できません" #: ../quodlibet/ext/events/lyricswindow.py:215 #, fuzzy msgid "No lyrics found" msgstr "プラグインが見つかりません" #: ../quodlibet/ext/events/lyricswindow.py:227 #, fuzzy msgid "Lyrics:" msgstr "歌詞" #: ../quodlibet/ext/events/lyricswindow.py:284 msgid "_Zoom level:" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:302 msgid "URL:" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:307 msgid "Revert to default" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:322 msgid "Search via above URL if the lyrics couldn't be found in LyricsWikia." msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:339 #, fuzzy msgid "Alternate search" msgstr "検索条件をクリア" #: ../quodlibet/ext/events/lyricswindow.py:347 #, fuzzy msgid "Lyrics Window" msgstr "歌詞" #: ../quodlibet/ext/events/lyricswindow.py:348 msgid "Shows a window containing lyrics of the playing song." msgstr "" #: ../quodlibet/ext/events/mediaserver.py:38 msgid "UPnP AV Media Server" msgstr "" #: ../quodlibet/ext/events/mediaserver.py:39 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." 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:39 msgid "" "Allows control of Quod Libet using the MPRIS 1.0/2.0 D-Bus Interface " "Specification." msgstr "" #: ../quodlibet/ext/events/mpris/__init__.py:45 #: ../quodlibet/ext/events/trayicon/prefs.py:30 #, fuzzy msgid "Hide main window on close" msgstr "メインウィンドウを隠す" #: ../quodlibet/ext/events/mpris/__init__.py:48 #: ../quodlibet/ext/events/themeswitcher.py:84 #: ../quodlibet/ext/gstreamer/compressor.py:99 #: ../quodlibet/ext/gstreamer/crossfeed.py:136 #: ../quodlibet/ext/gstreamer/karaoke.py:99 #: ../quodlibet/ext/gstreamer/pitch.py:83 ../quodlibet/qltk/prefs.py:688 #, fuzzy msgid "Preferences" msgstr "設定" #: ../quodlibet/ext/events/mqtt.py:50 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/mqtt.py:56 msgid "MQTT Publisher" msgstr "" #: ../quodlibet/ext/events/mqtt.py:57 msgid "Publishes status messages to an MQTT topic." msgstr "" #: ../quodlibet/ext/events/mqtt.py:122 msgid "Broker hostname" msgstr "" #: ../quodlibet/ext/events/mqtt.py:122 msgid "broker hostname / IP" msgstr "" #: ../quodlibet/ext/events/mqtt.py:124 msgid "Broker port" msgstr "" #: ../quodlibet/ext/events/mqtt.py:124 msgid "broker port" msgstr "" #: ../quodlibet/ext/events/mqtt.py:126 msgid "Topic" msgstr "" #: ../quodlibet/ext/events/mqtt.py:128 #, fuzzy msgid "Playing Pattern" msgstr "パターン" #: ../quodlibet/ext/events/mqtt.py:130 msgid "Status text when a song is started." msgstr "" #: ../quodlibet/ext/events/mqtt.py:132 #, fuzzy msgid "Paused Pattern" msgstr "パターン" #: ../quodlibet/ext/events/mqtt.py:134 msgid "Text when a song is paused." msgstr "" #: ../quodlibet/ext/events/mqtt.py:136 #, fuzzy msgid "No-song Text" msgstr "%d曲" #: ../quodlibet/ext/events/mqtt.py:138 msgid "Plain text for when there is no current song" msgstr "" #: ../quodlibet/ext/events/mqtt.py:149 #, fuzzy msgid "MQTT Configuration" msgstr "情報" #: ../quodlibet/ext/events/mqtt.py:153 #, fuzzy msgid "Status Text" msgstr "パターン" #: ../quodlibet/ext/events/mqtt.py:185 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "" #: ../quodlibet/ext/events/mqtt.py:189 #, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s" msgstr "" #: ../quodlibet/ext/events/mqtt.py:192 #, fuzzy msgid "Connection error" msgstr "場所" #: ../quodlibet/ext/events/notify.py:80 msgid "Notification text" msgstr "" #: ../quodlibet/ext/events/notify.py:88 #, fuzzy msgid "_Title:" msgstr "タイトル" #: ../quodlibet/ext/events/notify.py:99 ../quodlibet/ext/events/notify.py:128 msgid "Revert to default pattern" msgstr "" #: ../quodlibet/ext/events/notify.py:118 msgid "_Body:" msgstr "" #: ../quodlibet/ext/events/notify.py:138 msgid "_Show notification" msgstr "" #: ../quodlibet/ext/events/notify.py:156 #, fuzzy msgid "Show notifications" msgstr "新しいラジオ局はありません" #: ../quodlibet/ext/events/notify.py:162 msgid "Only on <i>_manual</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:170 msgid "Only on <i>_automatic</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:178 msgid "On <i>a_ll</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:196 msgid "Only when the main window is not _focused" msgstr "" #: ../quodlibet/ext/events/notify.py:204 msgid "Show \"_Next\" button" msgstr "" #: ../quodlibet/ext/events/notify.py:236 msgid "Connection Error" msgstr "" #: ../quodlibet/ext/events/notify.py:237 ../quodlibet/ext/events/notify.py:391 #: ../quodlibet/ext/events/notify.py:433 msgid "Couldn't connect to notification daemon." msgstr "" #: ../quodlibet/ext/events/notify.py:251 #, fuzzy msgid "Song Notifications" msgstr "新しいラジオ局はありません" #: ../quodlibet/ext/events/notify.py:252 msgid "Displays a notification when the song changes." msgstr "" #: ../quodlibet/ext/events/notify.py:415 ../quodlibet/qltk/unity.py:65 msgid "Next" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:178 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:254 #, python-format msgid "Could not contact service '%s'." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:260 msgid "Authentication failed: invalid URL." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:277 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:282 msgid "Client is banned. Contact the author." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:286 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:351 msgid "AudioScrobbler Submission" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:352 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:450 msgid "Authentication successful." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:462 #, fuzzy msgid "_Service:" msgstr "デバイス:" #: ../quodlibet/ext/events/qlscrobbler.py:462 msgid "_URL:" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:462 #, fuzzy msgid "User_name:" msgstr "名前(_N)" #: ../quodlibet/ext/events/qlscrobbler.py:463 msgid "_Password:" msgstr "" #. Translators: Other service #: ../quodlibet/ext/events/qlscrobbler.py:479 #, fuzzy msgid "Other…" msgstr "その他(_O)" #. verify data #: ../quodlibet/ext/events/qlscrobbler.py:517 msgid "_Verify account data" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:522 #: ../quodlibet/ext/songsmenu/lastfmsync.py:304 msgid "Account" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:530 #, fuzzy msgid "_Artist pattern:" msgstr "アーティスト(_A)" #: ../quodlibet/ext/events/qlscrobbler.py:530 #, fuzzy msgid "_Title pattern:" msgstr "ファイル名のパターン(_F)" #: ../quodlibet/ext/events/qlscrobbler.py:531 msgid "Exclude _filter:" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:549 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:559 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:568 msgid "Songs matching this filter will not be submitted." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:576 msgid "_Offline mode (don't submit anything)" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:580 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:27 #, fuzzy msgid "Random Album Playback" msgstr "アルバムでランダム選択(_b)" #: ../quodlibet/ext/events/randomalbum.py:28 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:38 msgid "Rated higher" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:39 msgid "Played more often" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:40 msgid "Skipped more often" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:41 msgid "Played more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:42 msgid "Started more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:43 msgid "Added more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:44 #, fuzzy msgid "Longer albums" msgstr "アルバム" #: ../quodlibet/ext/events/randomalbum.py:83 msgid "seconds before starting next album" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:87 #, fuzzy msgid "Weights" msgstr "ウェイト(_W)" #: ../quodlibet/ext/events/randomalbum.py:89 msgid "Play some albums more than others" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:103 msgid "avoid" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:114 msgid "prefer" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:201 #, fuzzy msgid "Random Album" msgstr "アルバムでランダム選択(_b)" #: ../quodlibet/ext/events/randomalbum.py:202 #, python-format msgid "Waiting to start %s" msgstr "" #: ../quodlibet/ext/events/rbimport.py:114 #, fuzzy msgid "Import Failed" msgstr "プレイリストのインポート" #: ../quodlibet/ext/events/rbimport.py:119 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "" #: ../quodlibet/ext/events/rbimport.py:127 msgid "Rhythmbox Import" msgstr "" #: ../quodlibet/ext/events/rbimport.py:128 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "" #: ../quodlibet/ext/events/rbimport.py:132 #, fuzzy msgid "Start Import" msgstr "インポート(_I)" #: ../quodlibet/ext/events/screensaver.py:25 msgid "Screensaver Pause" msgstr "" #: ../quodlibet/ext/events/screensaver.py:26 msgid "Pauses playback while the GNOME screensaver is active." msgstr "" #: ../quodlibet/ext/events/searchprovider.py:73 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "" #: ../quodlibet/ext/events/searchprovider.py:79 msgid "GNOME Search Provider" msgstr "" #: ../quodlibet/ext/events/searchprovider.py:80 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/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:29 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:57 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:58 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:34 #, fuzzy msgid "Synchronized Lyrics" msgstr "歌詞" #: ../quodlibet/ext/events/synchronizedlyrics.py:35 msgid "Shows synchronized lyrics from .lrc file with same name as the track." msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:66 msgid "Text:" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:76 msgid "Background:" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:87 msgid "Font" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:90 msgid "Size (px):" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:62 msgid "Telepathy Status Messages" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:63 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:122 #, fuzzy msgid "Playing:" msgstr "再生中の曲はありません" #: ../quodlibet/ext/events/telepathy_status.py:123 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:139 msgid "Paused:" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:140 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:156 msgid "Plain text for status when there is no current song" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:157 #, fuzzy msgid "No song:" msgstr "%d曲" #. Frame #: ../quodlibet/ext/events/telepathy_status.py:164 #, 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/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:77 #: ../quodlibet/ext/events/trayicon/prefs.py:98 #: ../quodlibet/ext/events/trayicon/systemtray.py:177 #: ../quodlibet/qltk/info.py:47 msgid "Not playing" msgstr "再生中の曲はありません" #: ../quodlibet/ext/events/trayicon/__init__.py:53 msgid "Tray Icon" msgstr "" #: ../quodlibet/ext/events/trayicon/__init__.py:54 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:183 #: ../quodlibet/qltk/quodlibetwindow.py:1046 #: ../quodlibet/qltk/quodlibetwindow.py:1238 #, fuzzy msgid "_Play" msgstr "プレイリスト(_P)" #: ../quodlibet/ext/events/trayicon/menu.py:63 #: ../quodlibet/qltk/quodlibetwindow.py:185 #: ../quodlibet/qltk/quodlibetwindow.py:1240 ../quodlibet/qltk/wlw.py:51 #, fuzzy msgid "P_ause" msgstr "プレイヤー" #: ../quodlibet/ext/events/trayicon/menu.py:68 #: ../quodlibet/qltk/quodlibetwindow.py:190 #: ../quodlibet/qltk/quodlibetwindow.py:1041 #, fuzzy msgid "Pre_vious" msgstr "プレビュー(_P)" #: ../quodlibet/ext/events/trayicon/menu.py:71 #: ../quodlibet/qltk/quodlibetwindow.py:194 #: ../quodlibet/qltk/quodlibetwindow.py:1051 msgid "_Next" msgstr "" #: ../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 #, fuzzy msgid "Stop _After This Song" msgstr "この曲の後で停止" #: ../quodlibet/ext/events/trayicon/menu.py:92 #: ../quodlibet/qltk/quodlibetwindow.py:1012 #, fuzzy msgid "Open _Browser" msgstr "新しいブラウザを開く" #: ../quodlibet/ext/events/trayicon/menu.py:103 #: ../quodlibet/qltk/quodlibetwindow.py:1031 ../quodlibet/qltk/songsmenu.py:411 msgid "Edit _Tags" msgstr "タグの編集(_T)" #: ../quodlibet/ext/events/trayicon/menu.py:112 #: ../quodlibet/qltk/quodlibetwindow.py:975 ../quodlibet/qltk/songsmenu.py:424 msgid "_Information" msgstr "情報(_I)" #: ../quodlibet/ext/events/trayicon/menu.py:114 #: ../quodlibet/qltk/songsmenu.py:340 #, fuzzy msgid "Play_lists" msgstr "プレイリスト" #: ../quodlibet/ext/events/trayicon/menu.py:132 #: ../quodlibet/qltk/quodlibetwindow.py:1026 msgid "_Quit" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:32 ../quodlibet/qltk/prefs.py:69 msgid "Behavior" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:42 msgid "Scroll wheel adjusts volume" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel changes song" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll _Wheel" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:84 #, fuzzy msgid "Tooltip Display" msgstr "ディスプレイの編集" #: ../quodlibet/ext/events/viewlyrics.py:23 #, fuzzy msgid "View Lyrics" msgstr "歌詞" #: ../quodlibet/ext/events/viewlyrics.py:24 msgid "Automatically displays lyrics beneath the song list in the main window." msgstr "" #: ../quodlibet/ext/events/viewlyrics.py:29 #, fuzzy msgid "_Lyrics" 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:406 msgid "Waveform Seek Bar" msgstr "" #: ../quodlibet/ext/events/waveformseekbar.py:410 msgid "A seekbar in the shape of the waveform of the current song." msgstr "" #: ../quodlibet/ext/events/waveformseekbar.py:443 msgid "Override foreground color:" msgstr "" #: ../quodlibet/ext/events/write_cover.py:32 msgid "Picture Saver" msgstr "" #: ../quodlibet/ext/events/write_cover.py:33 msgid "Saves the cover image of the current song to a file." msgstr "" #: ../quodlibet/ext/events/write_cover.py:66 #, fuzzy msgid "File:" msgstr "ファイル" #: ../quodlibet/ext/gstreamer/compressor.py:20 msgid "_Threshold:" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:21 msgid "Threshold until the filter is activated" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:22 msgid "R_atio:" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:22 msgid "Compression ratio" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:74 #: ../quodlibet/ext/gstreamer/karaoke.py:91 #, python-format msgid "%d %%" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:105 msgid "Audio Compressor" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:106 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:19 #, fuzzy msgid "_Preset:" msgstr "プレビュー(_P)" #: ../quodlibet/ext/gstreamer/crossfeed.py:19 #, fuzzy msgid "Filter preset" msgstr "アーティストでフィルタリング(_A)" #: ../quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Frequency cut:" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Low-pass filter cut frequency" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed _level:" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed level" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:25 msgid "Default" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Chu Moy" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Jan Meier" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:31 #, fuzzy msgid "Custom settings" msgstr "カスタム(_C)" #: ../quodlibet/ext/gstreamer/crossfeed.py:152 msgid "Crossfeed" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:153 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:20 #, fuzzy msgid "Filter _band:" msgstr "ジャンルでフィルタリング(_G)" #: ../quodlibet/ext/gstreamer/karaoke.py:21 msgid "The Frequency band of the filter" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:22 #, fuzzy msgid "Filter _width:" msgstr "アーティストでフィルタリング(_A)" #: ../quodlibet/ext/gstreamer/karaoke.py:23 msgid "The Frequency width of the filter" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:24 msgid "_Level:" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:24 msgid "Level of the effect" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:105 msgid "Karaoke" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:106 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:20 msgid "R_ate:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:21 msgid "_Tempo:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:22 msgid "_Pitch:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:89 #, fuzzy msgid "Audio Pitch / Speed" msgstr "オーディオフィード" #: ../quodlibet/ext/gstreamer/pitch.py:90 #, fuzzy msgid "Controls the pitch of an audio stream." msgstr "オーディオフィードの場所を入力してください:" #: ../quodlibet/ext/playlist/export_to_folder.py:29 #: ../quodlibet/ext/playlist/export_to_folder.py:97 #: ../quodlibet/ext/playlist/export_to_folder.py:138 #, fuzzy msgid "Export Playlist to Folder" msgstr "プレイリストのインポート" #: ../quodlibet/ext/playlist/export_to_folder.py:38 #, fuzzy msgid "_Export" msgstr "インポート(_I)" #: ../quodlibet/ext/playlist/export_to_folder.py:43 #, fuzzy msgid "Destination folder:" msgstr "ラジオ局が見つかりません" #: ../quodlibet/ext/playlist/export_to_folder.py:58 #, fuzzy msgid "Filename pattern:" msgstr "ファイル名のパターン(_F)" #: ../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:156 #, fuzzy msgid "Default filename pattern:" msgstr "ファイル名のパターン(_F)" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:23 msgid "Export to Squeezebox" msgstr "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:25 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 "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Export playlist to Squeezebox" msgstr "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:80 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 "プレイリストから削除(_R)" #: ../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 "" "Playback follows your selection, or the next song in the list once exhausted." msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:22 msgid "Playcount Equalizer" msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:23 msgid "Shuffle, preferring songs with fewer total plays." msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:25 #, fuzzy msgid "Prefer less played" msgstr "最終再生日時" #: ../quodlibet/ext/playorder/queue.py:19 #, fuzzy msgid "Queue Only" msgstr "キュー(_Q)" #: ../quodlibet/ext/playorder/queue.py:21 msgid "" "Limits playing of songs to the queue. Select this play order in the main " "window, then double-clicking any song will enqueue it instead of playing." msgstr "" #: ../quodlibet/ext/playorder/reverse.py:14 #, fuzzy msgid "Reverse" msgstr "なし" #: ../quodlibet/ext/playorder/reverse.py:16 msgid "Reverses the play order of songs." msgstr "" #: ../quodlibet/ext/playorder/skip_songs.py:25 #, fuzzy msgid "Skip Songs" msgstr "曲がありません" #: ../quodlibet/ext/playorder/skip_songs.py:27 msgid "" "Playback skips over songs with a rating equal or below a given threshold." msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:30 msgid "Repeat Each Track" msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:32 msgid "Shuffle songs, but repeat every track a set number of times." msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:51 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. Syntax is '@(if: " "condition, then, else)'." msgstr "" #: ../quodlibet/ext/query/pythonexpression.py:14 msgid "Python Query" msgstr "" #: ../quodlibet/ext/query/pythonexpression.py:15 msgid "" "Use Python expressions in queries. Syntax is '@(python: expression)'. The " "variable 's' is the song being matched." msgstr "" #: ../quodlibet/ext/query/savedsearch.py:19 #, fuzzy msgid "Include Saved Search" msgstr "保存された値" #: ../quodlibet/ext/query/savedsearch.py:20 msgid "" "Include the results of a saved search as part of another query. Syntax is " "'@(saved: search name)'." 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:116 msgid "Port:" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:121 #, fuzzy msgid "Username:" msgstr "名前の変更(_R)" #: ../quodlibet/ext/_shared/squeezebox/base.py:126 msgid "Password:" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:130 msgid "Library directory the server connects to." msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:132 #, fuzzy msgid "Library path:" msgstr "ライブラリ" #. Add verify button #: ../quodlibet/ext/_shared/squeezebox/base.py:141 msgid "_Verify settings" msgstr "" #. Server settings Frame #: ../quodlibet/ext/_shared/squeezebox/base.py:147 msgid "Squeezebox Server" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:150 msgid "Debug" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:26 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:28 msgid "unidentified Squeezebox server" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:37 #, 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:20 #: ../quodlibet/ext/songsmenu/importexport.py:34 #: ../quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:329 #, fuzzy msgid "Fit image to _window" msgstr "メインウィンドウを隠す" #. Both labels #: ../quodlibet/ext/songsmenu/albumart.py:338 msgid "_Program:" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:343 msgid "_Edit image after saving" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:345 #, fuzzy msgid "File_name:" msgstr "ファイル名" #: ../quodlibet/ext/songsmenu/albumart.py:457 msgid "Saving failed" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:458 #, fuzzy, python-format msgid "Unable to save \"%s\"." msgstr "曲を保存できません" #: ../quodlibet/ext/songsmenu/albumart.py:556 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:613 #, fuzzy msgid "Album Art Downloader" msgstr "アルバムリスト" #: ../quodlibet/ext/songsmenu/albumart.py:666 #, python-format msgid "from %(source)s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:669 #, python-format msgid "Resolution: %s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:672 #, fuzzy, python-format msgid "Size: %s" msgstr "サイズ" #: ../quodlibet/ext/songsmenu/albumart.py:690 #, fuzzy msgid "_Search" msgstr "検索" #: ../quodlibet/ext/songsmenu/albumart.py:741 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:451 #, fuzzy msgid "Searching…" msgstr "検索" #: ../quodlibet/ext/songsmenu/albumart.py:804 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:922 #, fuzzy msgid "Download Album Art" msgstr "アルバムリスト" #: ../quodlibet/ext/songsmenu/albumart.py:923 msgid "Downloads album covers from various websites." msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:936 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 "ブックマークの編集(_E)" #: ../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 "ブックマークの編集(_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 アルバム ID" #: ../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 #: ../quodlibet/qltk/downloader.py:52 msgid "Filename" msgstr "ファイル名" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:130 #, fuzzy msgid "Disc" msgstr "ディスク(_D)" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:131 #: ../quodlibet/ext/songsmenu/replaygain.py:404 #: ../quodlibet/qltk/tracknumbers.py:92 msgid "Track" msgstr "トラック" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:132 #, fuzzy msgid "Title" msgstr "タイトル" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:133 #, fuzzy msgid "Artist" msgstr "アーティスト(_A)" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:352 #, fuzzy msgid "MusicBrainz lookup" msgstr "MusicBrainz アルバム ID" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:375 #, fuzzy 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:447 msgid "Please enter a query." msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:465 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:496 msgid "Error encountered. Please retry." msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:472 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:488 msgid "Loading result…" msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:475 #, fuzzy msgid "No results found." msgstr "プラグインが見つかりません" #: ../quodlibet/ext/songsmenu/browsefolders.py:159 #, fuzzy msgid "Browse Folders" msgstr "ブラウザ" #: ../quodlibet/ext/songsmenu/browsefolders.py:160 msgid "Opens the songs' folders in a file manager." msgstr "" #: ../quodlibet/ext/songsmenu/browsefolders.py:172 #, fuzzy msgid "Unable to open folders" msgstr "フォルダを作成できません" #: ../quodlibet/ext/songsmenu/browsefolders.py:173 msgid "No program available to open folders." msgstr "" #: ../quodlibet/ext/songsmenu/console.py:40 msgid "Python Console" msgstr "" #: ../quodlibet/ext/songsmenu/console.py:41 msgid "Interactive Python console." msgstr "" #: ../quodlibet/ext/songsmenu/console.py:72 msgid "You can access the following objects by default:" msgstr "" #: ../quodlibet/ext/songsmenu/console.py:82 msgid "Your current working directory is:" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:41 msgid "Command" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:44 #, fuzzy msgid "name" msgstr "名前の変更(_R)" #: ../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:55 #, fuzzy msgid "pattern" 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:91 #, fuzzy msgid "Input value" msgstr "不正な値" #: ../quodlibet/ext/songsmenu/custom_commands.py:92 #, python-format msgid "Value for %s?" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:136 #, fuzzy msgid "Custom Commands" msgstr "カスタム(_C)" #: ../quodlibet/ext/songsmenu/custom_commands.py:137 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:188 #: ../quodlibet/ext/songsmenu/custom_commands.py:198 #: ../quodlibet/ext/songsmenu/custom_commands.py:252 msgid "Edit Custom Commands" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:199 msgid "" "Supports QL patterns\n" "eg <tt><~artist~title></tt>" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:283 #, fuzzy, python-format msgid "Unable to run custom command %s" msgstr "曲のコピーができません" #: ../quodlibet/ext/songsmenu/duplicates.py:290 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "" #: ../quodlibet/ext/songsmenu/duplicates.py:343 msgid "Collapse / Expand all" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:347 #, python-format msgid "Duplicate key expression is '%s'" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:363 #, fuzzy msgid "Duplicates Browser" msgstr "ブラウザの無効化" #: ../quodlibet/ext/songsmenu/duplicates.py:364 msgid "Finds and displays similarly tagged versions of songs." msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:407 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:409 msgid "_Group duplicates by:" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:414 msgid "Duplicate Key" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:419 #, fuzzy msgid "Remove _Whitespace" msgstr "ラジオ局の削除(_R)" #: ../quodlibet/ext/songsmenu/duplicates.py:420 #, fuzzy msgid "Remove _Diacritics" msgstr "ラジオ局の削除(_R)" #: ../quodlibet/ext/songsmenu/duplicates.py:421 #, fuzzy msgid "Remove _Punctuation" msgstr "ラジオ局の削除(_R)" #: ../quodlibet/ext/songsmenu/duplicates.py:422 msgid "Case _Insensitive" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:430 msgid "Matching options" msgstr "" #. Create a dialog. #: ../quodlibet/ext/songsmenu/editplaycount.py:19 #: ../quodlibet/ext/songsmenu/editplaycount.py:41 #, fuzzy msgid "Edit Playcount" msgstr "ディスプレイの編集" #: ../quodlibet/ext/songsmenu/editplaycount.py:20 msgid "" "Edit a song's ~#playcount and ~#skipcount.\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's ~#playcount to 0, the ~#lastplayed and ~#laststarted " "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:68 msgid "Play Count" msgstr "" #: ../quodlibet/ext/songsmenu/editplaycount.py:69 msgid "Skip Count" msgstr "" #: ../quodlibet/ext/songsmenu/embedded.py:24 #, fuzzy msgid "Edit Embedded Images" msgstr "ラジオ局の削除(_R)" #: ../quodlibet/ext/songsmenu/embedded.py:25 #, fuzzy msgid "Removes or replaces embedded images." msgstr "ラジオ局の削除(_R)" #: ../quodlibet/ext/songsmenu/embedded.py:78 #, fuzzy msgid "_Remove all Images" msgstr "ラジオ局の削除(_R)" #: ../quodlibet/ext/songsmenu/embedded.py:82 #, fuzzy msgid "_Embed Current Image" msgstr "ラジオ局の削除(_R)" #: ../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 "ジャンルでフィルタリング(_G)" #: ../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:41 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 #: ../quodlibet/qltk/downloader.py:67 #, fuzzy msgid "Queued" msgstr "キュー(_Q)" #: ../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 "書き込み" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" 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トラックID" #: ../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 "アルバムヘッダ(_A)" #: ../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:49 msgid "Generating fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:63 msgid "_Details" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:85 msgid "_Submit" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:115 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:118 msgid "Fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Songs with MBIDs:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with sufficient tags:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs to submit:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:162 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:178 msgid "Submitting fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:186 msgid "Submitting…" msgstr "" #: ../quodlibet/ext/songsmenu/forcewrite.py:17 #, fuzzy msgid "Update Tags in Files" msgstr "新規ラジオ局(_N)" #: ../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/id3tlen.py:21 msgid "Fix MP3 Duration" msgstr "" #: ../quodlibet/ext/songsmenu/id3tlen.py:22 msgid "" "Removes TLEN frames from ID3 tags which can be the cause for invalid song " "durations." msgstr "" #: ../quodlibet/ext/songsmenu/ifp.py:20 msgid "Send to iFP" msgstr "" #: ../quodlibet/ext/songsmenu/ifp.py:21 msgid "Uploads songs to an iRiver iFP device." msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:51 msgid "Export Metadata" msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:52 msgid "Exports metadata of selected songs as a .tags file." msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:92 #, fuzzy msgid "Import Metadata" msgstr "プレイリストのインポート" #: ../quodlibet/ext/songsmenu/importexport.py:93 msgid "Imports metadata for selected songs from a .tags file." msgstr "" #: ../quodlibet/ext/songsmenu/k3b.py:23 msgid "Burn CD" msgstr "" #: ../quodlibet/ext/songsmenu/k3b.py:24 msgid "Burns CDs with K3b, Brasero or xfburn." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:96 msgid "Updating chart list." msgstr "" #. No charts to fetch, no update scheduled. #: ../quodlibet/ext/songsmenu/lastfmsync.py:114 msgid "Already up-to-date." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:121 #, python-format msgid "Fetching chart for week of %s." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:143 msgid "Sync complete." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:149 msgid "Error during sync" msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:214 #: ../quodlibet/ext/songsmenu/lastfmsync.py:244 msgid "Last.fm Sync" msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:245 msgid "Updates your library's statistics from your Last.fm profile." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:293 #, fuzzy msgid "_Username:" msgstr "名前の変更(_R)" #: ../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 "" #. Create a dialog. #: ../quodlibet/ext/songsmenu/migratemetadata.py:29 #: ../quodlibet/ext/songsmenu/migratemetadata.py:38 #, fuzzy msgid "Migrate Metadata" msgstr "プレイリストのインポート" #: ../quodlibet/ext/songsmenu/migratemetadata.py:32 msgid "Copies the quodlibet-specific metadata between songs." msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:45 msgid "_Copy" msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:47 msgid "_Paste" msgstr "" #. Create the tag table. #: ../quodlibet/ext/songsmenu/migratemetadata.py:57 #, fuzzy msgid "Information to copy/paste" msgstr "情報" #. Create the indexing box. #: ../quodlibet/ext/songsmenu/migratemetadata.py:79 msgid "Map tracks by disc and track number" msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:80 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 "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:96 #, python-format msgid "There is %d stored track." msgid_plural "There are %d stored tracks." msgstr[0] "" #: ../quodlibet/ext/songsmenu/playlist.py:31 #, fuzzy msgid "Export as Playlist" msgstr "プレイリストのインポート" #: ../quodlibet/ext/songsmenu/playlist.py:32 msgid "Exports songs to an M3U or PLS playlist." msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:77 msgid "Use relative paths" msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:77 msgid "Use absolute paths" msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:132 #, fuzzy msgid "Unable to export playlist" msgstr "プレイリストをインポートできません" #: ../quodlibet/ext/songsmenu/playlist.py:133 #, fuzzy, python-format msgid "Writing to <b>%s</b> failed." msgstr "<b>%s</b>のイジェクト失敗。" #. Translators: Plugin name #: ../quodlibet/ext/songsmenu/refresh.py:22 #, fuzzy msgid "Rescan Songs" msgstr "ライブラリの再表示(_f)" #: ../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 "ライブラリの再表示(_f)" #: ../quodlibet/ext/songsmenu/replaygain.py:362 msgid "ReplayGain Analyzer" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:418 msgid "Progress" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:433 msgid "Gain" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:448 msgid "Peak" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:463 #, python-format msgid "There is <b>%(to-process)s</b> album to update (of %(all)s)" msgid_plural "There are <b>%(to-process)s</b> albums to update (of %(all)s)" msgstr[0] "" #: ../quodlibet/ext/songsmenu/replaygain.py:578 msgid "Replay Gain" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:579 msgid "" "Analyzes and updates ReplayGain information, using GStreamer. Results are " "grouped by album." msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:617 msgid "always" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:618 msgid "if <b>any</b> RG tags are missing" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:620 msgid "if <b>album</b> RG tags are missing" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:637 msgid "_Process albums:" msgstr "" #. Server settings Frame #: ../quodlibet/ext/songsmenu/replaygain.py:649 #, 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 "" #. TRANSLATORS: BPM mean "beats per minute" #: ../quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "" #: ../quodlibet/ext/songsmenu/tapbpm.py:32 #: ../quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" msgstr "" #: ../quodlibet/ext/songsmenu/tapbpm.py:36 #, fuzzy msgid "Reset" msgstr "プレビュー(_P)" #: ../quodlibet/ext/songsmenu/tapbpm.py:42 #, fuzzy msgid "Tap" msgstr "タグ" #: ../quodlibet/ext/songsmenu/tapbpm.py:172 #: ../quodlibet/ext/songsmenu/tapbpm.py:179 msgid "Tap BPM" msgstr "" #: ../quodlibet/ext/songsmenu/tapbpm.py:173 #, fuzzy msgid "Tap BPM for the selected song." msgstr "曲を追加できません" #: ../quodlibet/ext/songsmenu/website_search.py:35 #, fuzzy msgid "Website Search" msgstr "検索" #: ../quodlibet/ext/songsmenu/website_search.py:36 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern-example)s." msgstr "" #: ../quodlibet/ext/songsmenu/website_search.py:78 #, fuzzy msgid "Search URL patterns" msgstr "パターン" #: ../quodlibet/ext/songsmenu/website_search.py:88 #, fuzzy msgid "Edit search URLs" msgstr "保存されている値を編集..." #. Add link to editor #: ../quodlibet/ext/songsmenu/website_search.py:114 #, fuzzy msgid "Configure Searches…" msgstr "検索文字列のカラー表示" #: ../quodlibet/ext/songsmenu/wikipedia.py:46 #, python-format msgid "Search at %(website)s" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:63 msgid "Search Artist in Wikipedia" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:64 msgid "" "Opens a browser window with Wikipedia article on the playing song artist." msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:71 msgid "Search Album in Wikipedia" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:72 msgid "" "Opens a browser window with Wikipedia article on the playing song album." msgstr "" #. then (try to) load all new files #: ../quodlibet/library/libraries.py:650 ../quodlibet/library/libraries.py:660 #: ../quodlibet/library/libraries.py:726 ../quodlibet/library/libraries.py:745 #: ../quodlibet/qltk/information.py:268 ../quodlibet/qltk/prefs.py:639 #: ../quodlibet/util/library.py:124 msgid "Library" msgstr "ライブラリ" #: ../quodlibet/library/libraries.py:650 #, fuzzy msgid "Checking mount points" msgstr "マウントポイントを確認中" #: ../quodlibet/library/libraries.py:660 #, fuzzy msgid "Scanning library" msgstr "ソングライブラリ読み込み中" #: ../quodlibet/library/libraries.py:725 #, fuzzy, python-format msgid "Scanning %s" msgstr "%sをチェックしています" #: ../quodlibet/library/libraries.py:745 msgid "Loading files" msgstr "" #: ../quodlibet/operon/base.py:70 #, python-format msgid "Failed to load file: %r" msgstr "" #: ../quodlibet/operon/commands.py:37 msgid "List tags" msgstr "" #: ../quodlibet/operon/commands.py:42 ../quodlibet/operon/commands.py:81 #: ../quodlibet/operon/commands.py:461 msgid "Print terse output" msgstr "" #: ../quodlibet/operon/commands.py:44 ../quodlibet/operon/commands.py:83 #: ../quodlibet/operon/commands.py:463 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "" #: ../quodlibet/operon/commands.py:47 ../quodlibet/operon/commands.py:86 #, fuzzy msgid "Also list programmatic tags" msgstr "プログラマチックタグの表示(_p)" #: ../quodlibet/operon/commands.py:51 ../quodlibet/operon/commands.py:129 #: ../quodlibet/operon/commands.py:220 ../quodlibet/operon/commands.py:293 #: ../quodlibet/operon/commands.py:336 ../quodlibet/operon/commands.py:340 #: ../quodlibet/operon/commands.py:391 ../quodlibet/operon/commands.py:394 #: ../quodlibet/operon/commands.py:433 ../quodlibet/operon/commands.py:468 #: ../quodlibet/operon/commands.py:508 ../quodlibet/operon/commands.py:543 #: ../quodlibet/operon/commands.py:585 msgid "Not enough arguments" msgstr "" #: ../quodlibet/operon/commands.py:53 ../quodlibet/operon/commands.py:90 #: ../quodlibet/operon/commands.py:131 ../quodlibet/operon/commands.py:222 #: ../quodlibet/operon/commands.py:470 msgid "Too many arguments" msgstr "" #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:92 #: ../quodlibet/operon/commands.py:475 ../quodlibet/qltk/data_editors.py:363 #, fuzzy msgid "Description" msgstr "説明" #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:475 #: ../quodlibet/qltk/edittags.py:454 msgid "Value" msgstr "値" #: ../quodlibet/operon/commands.py:76 msgid "List all common tags" msgstr "" #: ../quodlibet/operon/commands.py:118 msgid "Copy tags from one file to another" msgstr "" #: ../quodlibet/operon/commands.py:123 ../quodlibet/operon/commands.py:164 #: ../quodlibet/operon/commands.py:289 ../quodlibet/operon/commands.py:324 #: ../quodlibet/operon/commands.py:384 msgid "Show changes, don't apply them" msgstr "" #: ../quodlibet/operon/commands.py:125 msgid "Skip tags that can't be written" msgstr "" #: ../quodlibet/operon/commands.py:145 #, python-format msgid "Can't copy tag %r to file: %r" 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:304 ../quodlibet/operon/commands.py:444 #: ../quodlibet/operon/commands.py:676 #, python-format msgid "Can not set %r" msgstr "" #: ../quodlibet/operon/commands.py:319 #, fuzzy msgid "Remove tags" msgstr "ラジオ局の削除(_R)" #: ../quodlibet/operon/commands.py:326 ../quodlibet/operon/commands.py:386 msgid "Value is a regular expression" msgstr "" #: ../quodlibet/operon/commands.py:328 #, fuzzy msgid "Remove all tags" msgstr "ラジオ局の削除(_R)" #: ../quodlibet/operon/commands.py:332 msgid "Can't combine '--all' with '--regexp'" msgstr "" #: ../quodlibet/operon/commands.py:366 #, python-format msgid "Can't remove %r from %r" msgstr "" #: ../quodlibet/operon/commands.py:379 #, fuzzy msgid "Remove a tag value" msgstr "タグの値でフィルタリング" #: ../quodlibet/operon/commands.py:428 #, fuzzy msgid "Add a tag value" msgstr "タグの値でフィルタリング" #: ../quodlibet/operon/commands.py:456 #, fuzzy msgid "List file information" msgstr "時間情報なし" #: ../quodlibet/operon/commands.py:502 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" #: ../quodlibet/operon/commands.py:515 #, fuzzy, python-format msgid "Failed to load image file: %r" msgstr "ファイル名を変更できません" #: ../quodlibet/operon/commands.py:522 ../quodlibet/operon/commands.py:551 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" #: ../quodlibet/operon/commands.py:538 #, fuzzy msgid "Remove all embedded images" msgstr "ラジオ局の削除(_R)" #: ../quodlibet/operon/commands.py:568 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "" #: ../quodlibet/operon/commands.py:580 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" #: ../quodlibet/operon/commands.py:639 msgid "Rename files based on tags" msgstr "" #: ../quodlibet/operon/commands.py:654 msgid "Fill tags based on the file path" msgstr "" #: ../quodlibet/operon/commands.py:704 ../quodlibet/qltk/information.py:305 #: ../quodlibet/qltk/properties.py:84 ../quodlibet/qltk/renamefiles.py:176 #: ../quodlibet/qltk/tagsfrompath.py:229 ../quodlibet/qltk/tracknumbers.py:79 msgid "File" msgstr "ファイル" #: ../quodlibet/operon/commands.py:712 msgid "Fill tracknumbers for all files" msgstr "" #: ../quodlibet/operon/commands.py:731 msgid "Print tags based on the given pattern" msgstr "" #: ../quodlibet/operon/commands.py:768 #, fuzzy msgid "Display help information" msgstr "基本的な使い方を表示" #: ../quodlibet/operon/util.py:40 #, 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:30 #, fuzzy msgid "_Unknown" msgstr "不明" #: ../quodlibet/order/__init__.py:142 msgid "In Order" msgstr "並び順" #: ../quodlibet/order/__init__.py:143 msgid "_In Order" msgstr "並び順(_I)" #: ../quodlibet/order/reorder.py:23 #, fuzzy msgid "Random" msgstr "ランダム(_R)" #: ../quodlibet/order/reorder.py:24 ../quodlibet/qltk/queue.py:119 msgid "_Random" msgstr "ランダム(_R)" #: ../quodlibet/order/reorder.py:39 ../quodlibet/order/reorder.py:40 msgid "Prefer higher rated" msgstr "" #: ../quodlibet/order/repeat.py:43 ../quodlibet/order/repeat.py:44 msgid "Repeat this track" msgstr "" #: ../quodlibet/order/repeat.py:57 ../quodlibet/order/repeat.py:58 #, fuzzy msgid "Repeat all" msgstr "繰り返し(_R)" #: ../quodlibet/order/repeat.py:73 ../quodlibet/order/repeat.py:74 msgid "One Song" msgstr "1曲だけ" #: ../quodlibet/player/gstbe/player.py:98 msgid "Stream" msgstr "" #: ../quodlibet/player/gstbe/player.py:98 msgid "Buffering" msgstr "" #: ../quodlibet/player/gstbe/player.py:319 msgid "Could not create GStreamer pipeline" msgstr "" #: ../quodlibet/player/gstbe/player.py:560 msgid "No GStreamer element found to handle media format" msgstr "" #: ../quodlibet/player/gstbe/player.py:561 #, 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:25 msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. In case the pipeline contains a sink, it will be used instead of " "the default one." msgstr "" #: ../quodlibet/player/gstbe/prefs.py:36 msgid "_Output pipeline:" msgstr "" #: ../quodlibet/player/gstbe/prefs.py:43 #, fuzzy, python-format msgid "%.1f seconds" msgstr "%d秒" #: ../quodlibet/player/gstbe/prefs.py:57 msgid "_Buffer duration:" msgstr "" #: ../quodlibet/player/gstbe/prefs.py:66 msgid "Disable _gapless playback" msgstr "" #: ../quodlibet/player/gstbe/prefs.py:70 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions." msgstr "" #: ../quodlibet/player/gstbe/util.py:93 #, fuzzy msgid "No GStreamer audio sink found" msgstr "ラジオ局が見つかりません" #: ../quodlibet/player/gstbe/util.py:112 msgid "Invalid GStreamer output pipeline" msgstr "" #: ../quodlibet/player/xinebe/player.py:90 #, fuzzy msgid "Unable to create audio output" msgstr "フォルダを作成できません" #: ../quodlibet/player/xinebe/player.py:91 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "" #: ../quodlibet/plugins/__init__.py:62 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" #: ../quodlibet/plugins/__init__.py:71 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "" #: ../quodlibet/plugins/playlist.py:30 #, 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:41 ../quodlibet/qltk/songsmenu.py:46 #: ../quodlibet/qltk/songsmenu.py:74 #, fuzzy msgid "_Run Plugin" msgstr "プラグイン(_P)" #: ../quodlibet/qltk/about.py:40 #, python-format msgid "Supported formats: %s" msgstr "サポートしているフォーマット: %s" #: ../quodlibet/qltk/about.py:43 #, python-format msgid "Audio device: %s" msgstr "オーディオデバイス: %s" #. 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:207 ../quodlibet/qltk/information.py:131 msgid "Bookmarks" msgstr "ブックマーク" #: ../quodlibet/qltk/browser.py:56 msgid "_Filters" msgstr "フィルタ(_F)" #: ../quodlibet/qltk/browser.py:57 #, fuzzy msgid "Recently _Played" msgstr "まだ1度も再生していない曲(_N)" #: ../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 #, 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 "ジャンルでランダム選択(_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:48 ../quodlibet/qltk/edittags.py:311 msgid "_Value:" msgstr "値(_V)" #: ../quodlibet/qltk/cbes.py:262 msgid "Saved Values" msgstr "保存された値" #: ../quodlibet/qltk/cbes.py:263 #, fuzzy msgid "Edit saved values…" msgstr "保存されている値を編集..." #: ../quodlibet/qltk/controls.py:111 msgid "Auto_matic" msgstr "" #: ../quodlibet/qltk/controls.py:112 #, fuzzy msgid "_Track Mode" msgstr "トラック番号ヘッダ(_T)" #: ../quodlibet/qltk/controls.py:113 #, fuzzy msgid "_Album Mode" msgstr "アルバムヘッダ(_A)" #. Translators: player state, no action #: ../quodlibet/qltk/controls.py:122 msgid "_Mute" msgstr "" #: ../quodlibet/qltk/controls.py:128 #, fuzzy msgid "_Replay Gain Mode" msgstr "リプレイの度に音量調整をする(_R)" #. Translators: New Command/Entry/Item/... #: ../quodlibet/qltk/data_editors.py:119 #, python-format msgid "New %s" msgstr "" #: ../quodlibet/qltk/data_editors.py:218 #, fuzzy msgid "(unknown)" msgstr "不明" #: ../quodlibet/qltk/data_editors.py:355 msgid "Tag expression" msgstr "" #: ../quodlibet/qltk/data_editors.py:382 msgid "Tag expression e.g. people:real or ~album~year." msgstr "" #: ../quodlibet/qltk/data_editors.py:383 #, fuzzy msgid "Enter new tag" 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] "" #: ../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] "" #: ../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 #, 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/downloader.py:38 msgid "Downloads" msgstr "ダウンロード" #: ../quodlibet/qltk/downloader.py:62 msgid "Size" msgstr "サイズ" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: ../quodlibet/qltk/downloader.py:94 ../quodlibet/qltk/renamefiles.py:265 #: ../quodlibet/qltk/wlw.py:50 msgid "_Stop" msgstr "" #: ../quodlibet/qltk/edittags.py:63 ../quodlibet/qltk/edittags.py:74 #, python-format msgid "missing from %d song" msgid_plural "missing from %d songs" msgstr[0] "%d曲が欠落しています" #: ../quodlibet/qltk/edittags.py:67 ../quodlibet/qltk/edittags.py:71 #, python-format msgid "different across %d song" msgid_plural "different across %d songs" msgstr[0] "%d曲の内容がそれぞれ異なっています" #: ../quodlibet/qltk/edittags.py:193 msgid "Split into _Multiple Values" msgstr "複数の値に分割(_M)" #: ../quodlibet/qltk/edittags.py:211 msgid "Split Disc out of _Album" msgstr "albumからdiscを分離(_A)" #: ../quodlibet/qltk/edittags.py:228 msgid "Split _Version out of Title" msgstr "titleからversionを分離(_V)" #: ../quodlibet/qltk/edittags.py:259 msgid "Split Arranger out of Ar_tist" msgstr "artisitからarrangerを分離(_t)" #: ../quodlibet/qltk/edittags.py:264 msgid "Split _Performer out of Artist" msgstr "artistからperformer を分離(_P)" #: ../quodlibet/qltk/edittags.py:270 #, fuzzy msgid "Split _Performer out of Title" msgstr "artistからperformer を分離(_P)" #: ../quodlibet/qltk/edittags.py:276 #, fuzzy msgid "Split _Originalartist out of Title" msgstr "titleからversionを分離(_V)" #: ../quodlibet/qltk/edittags.py:283 msgid "Add a Tag" msgstr "タグの追加" #: ../quodlibet/qltk/edittags.py:302 msgid "_Tag:" msgstr "タグ(_T)" #: ../quodlibet/qltk/edittags.py:404 msgid "Edit Tags" msgstr "タグの編集" #: ../quodlibet/qltk/edittags.py:477 msgid "Show _programmatic tags" msgstr "プログラマチックタグの表示(_p)" #: ../quodlibet/qltk/edittags.py:478 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" #. Translators: Revert button in the tag editor #: ../quodlibet/qltk/edittags.py:508 #, fuzzy msgctxt "edittags" msgid "_Revert" msgstr "なし" #. Translators: Save button in the tag editor #: ../quodlibet/qltk/edittags.py:513 msgctxt "edittags" msgid "_Save" msgstr "" #: ../quodlibet/qltk/edittags.py:659 msgid "Unable to add tag" msgstr "タグを追加できません" #: ../quodlibet/qltk/edittags.py:660 #, fuzzy, python-format msgid "Unable to add <b>%s</b>" msgstr "曲を追加できません" #: ../quodlibet/qltk/edittags.py:662 #, fuzzy, python-format msgid "" "The files currently selected do not support multiple values for <b>%s</b>." msgstr "" " <b>%s</b> を追加できません。\n" "\n" "選択されているファイルは複数のタグをサポートしていません。" #. Can't add the new tag. #: ../quodlibet/qltk/edittags.py:689 ../quodlibet/qltk/edittags.py:856 #: ../quodlibet/qltk/tagsfrompath.py:212 ../quodlibet/util/__init__.py:554 #: ../quodlibet/util/tags.py:231 msgid "Invalid tag" msgstr "不正なタグ" #: ../quodlibet/qltk/edittags.py:690 ../quodlibet/qltk/edittags.py:857 #: ../quodlibet/qltk/tagsfrompath.py:213 #, python-format msgid "" "Invalid tag <b>%s</b>\n" "\n" "The files currently selected do not support editing this tag." msgstr "" "不正なタグ <b>%s</b>\n" "\n" "選択されているファイルはこのタグをサポートしていません。" #: ../quodlibet/qltk/edittags.py:828 ../quodlibet/qltk/edittags.py:868 msgid "Invalid value" msgstr "不正な値" #: ../quodlibet/qltk/edittags.py:829 ../quodlibet/qltk/edittags.py:869 #, python-format msgid "" "Invalid value: <b>%(value)s</b>\n" "\n" "%(error)s" msgstr "" "不正な値: <b>%(value)s</b>\n" "\n" "%(error)s" #: ../quodlibet/qltk/_editutils.py:28 msgid "Tag may not be accurate" msgstr "タグが正しくない可能性があります" #: ../quodlibet/qltk/_editutils.py:31 #, 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" "それでも保存を実行しますか? " #: ../quodlibet/qltk/_editutils.py:47 msgid "Unable to save song" msgstr "曲を保存できません" #: ../quodlibet/qltk/_editutils.py:50 #, 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:142 #, fuzzy 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:95 #: ../quodlibet/qltk/quodlibetwindow.py:1066 msgid "_About" msgstr "" #: ../quodlibet/qltk/exfalsowindow.py:99 #: ../quodlibet/qltk/quodlibetwindow.py:1088 msgid "_Check for Updates…" msgstr "" #: ../quodlibet/qltk/exfalsowindow.py:105 #: ../quodlibet/qltk/quodlibetwindow.py:1021 ../quodlibet/qltk/songsmenu.py:304 msgid "_Plugins" msgstr "プラグイン(_P)" #: ../quodlibet/qltk/exfalsowindow.py:267 #, python-format msgid "%(title)s and %(count)s more" msgid_plural "%(title)s and %(count)s more" msgstr[0] "" #: ../quodlibet/qltk/exfalsowindow.py:279 msgid "Ex Falso Preferences" msgstr "Ex Falsoの設定" #: ../quodlibet/qltk/exfalsowindow.py:289 ../quodlibet/qltk/prefs.py:598 msgid "Split _on:" msgstr "タグの分割に用いる文字(_o)" #: ../quodlibet/qltk/exfalsowindow.py:295 ../quodlibet/qltk/prefs.py:613 msgid "Tag Editing" msgstr "タグの編集" #: ../quodlibet/qltk/filesel.py:210 msgid "Folders" msgstr "フォルダ" #: ../quodlibet/qltk/filesel.py:253 #, fuzzy msgid "_New Folder…" msgstr "新規フォルダ" #: ../quodlibet/qltk/filesel.py:262 #, fuzzy msgid "_Select all Sub-Folders" msgstr "全て選択(_S)" #: ../quodlibet/qltk/filesel.py:374 msgid "New Folder" msgstr "新規フォルダ" #: ../quodlibet/qltk/filesel.py:374 msgid "Enter a name for the new folder:" msgstr "フォルダ名を入力してください:" #: ../quodlibet/qltk/filesel.py:387 msgid "Unable to create folder" msgstr "フォルダを作成できません" #: ../quodlibet/qltk/filesel.py:404 msgid "Unable to delete folder" msgstr "フォルダを削除できません" #: ../quodlibet/qltk/filesel.py:519 ../quodlibet/qltk/pluginwin.py:167 msgid "Songs" msgstr "曲" #. Translators: As in "by Artist Name" #: ../quodlibet/qltk/info.py:42 #, python-format msgid "by %s" msgstr "" #: ../quodlibet/qltk/info.py:43 ../quodlibet/qltk/information.py:167 #: ../quodlibet/qltk/information.py:448 #, python-format msgid "Disc %s" msgstr "ディスク %s" #: ../quodlibet/qltk/info.py:44 ../quodlibet/qltk/information.py:172 #, python-format msgid "Track %s" msgstr "トラック %s" #: ../quodlibet/qltk/info.py:108 #, fuzzy msgid "_Edit Display…" msgstr "ディスプレイの編集" #: ../quodlibet/qltk/information.py:105 msgid "No songs are selected." msgstr "曲が選択されていません" #: ../quodlibet/qltk/information.py:106 msgid "No Songs" msgstr "曲がありません" #: ../quodlibet/qltk/information.py:121 ../quodlibet/qltk/information.py:338 #: ../quodlibet/qltk/information.py:471 ../quodlibet/qltk/information.py:531 msgid "Information" msgstr "情報" #: ../quodlibet/qltk/information.py:126 msgid "Lyrics" msgstr "歌詞" #: ../quodlibet/qltk/information.py:184 ../quodlibet/qltk/information.py:396 #, python-format msgid "Produced by %s" msgstr "プロデュース %s" #: ../quodlibet/qltk/information.py:199 ../quodlibet/util/tags.py:76 msgid "artist" msgstr "アーティスト" #: ../quodlibet/qltk/information.py:200 ../quodlibet/qltk/information.py:561 #: ../quodlibet/util/tags.py:76 msgid "artists" msgstr "アーティスト" #. for backwards compat #: ../quodlibet/qltk/information.py:221 ../quodlibet/util/tags.py:86 #: ../quodlibet/util/tags.py:114 msgid "performers" msgstr "演奏者" #: ../quodlibet/qltk/information.py:235 ../quodlibet/qltk/information.py:248 #: ../quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "なし" #: ../quodlibet/qltk/information.py:236 #, fuzzy, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "%d 回" #: ../quodlibet/qltk/information.py:254 ../quodlibet/util/tags.py:139 msgid "added" msgstr "登録日時" #: ../quodlibet/qltk/information.py:255 ../quodlibet/util/tags.py:140 msgid "last played" msgstr "最終再生日時" #: ../quodlibet/qltk/information.py:256 ../quodlibet/util/tags.py:150 msgid "plays" msgstr "再生回数" #: ../quodlibet/qltk/information.py:257 ../quodlibet/util/tags.py:151 msgid "skips" msgstr "スキップ回数" #: ../quodlibet/qltk/information.py:258 ../quodlibet/util/tags.py:156 msgid "rating" msgstr "レイティング" #: ../quodlibet/qltk/information.py:287 msgid "path" msgstr "" #: ../quodlibet/qltk/information.py:288 ../quodlibet/util/tags.py:154 msgid "length" msgstr "時間" #: ../quodlibet/qltk/information.py:289 #, fuzzy msgid "format" msgstr "情報" #: ../quodlibet/qltk/information.py:290 ../quodlibet/util/tags.py:163 msgid "codec" msgstr "" #: ../quodlibet/qltk/information.py:291 ../quodlibet/util/tags.py:164 #, fuzzy msgid "encoding" msgstr "[不正なエンコーディング]" #: ../quodlibet/qltk/information.py:292 ../quodlibet/util/tags.py:160 msgid "bitrate" msgstr "ビットレート" #: ../quodlibet/qltk/information.py:293 ../quodlibet/util/tags.py:161 msgid "file size" msgstr "サイズ" #: ../quodlibet/qltk/information.py:294 ../quodlibet/util/tags.py:149 msgid "modified" msgstr "修正日時" #: ../quodlibet/qltk/information.py:331 msgid "Additional" msgstr "" #: ../quodlibet/qltk/information.py:383 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d曲選択済み" #: ../quodlibet/qltk/information.py:458 msgid "Track unavailable" msgstr "トラック情報が取得できません" #: ../quodlibet/qltk/information.py:464 msgid "Track List" msgstr "トラックリスト" #: ../quodlibet/qltk/information.py:505 ../quodlibet/qltk/information.py:578 #, python-format msgid "%d song with no album" msgid_plural "%d songs with no album" msgstr[0] "%d曲にアルバム情報がありません" #: ../quodlibet/qltk/information.py:508 msgid "Selected Discography" msgstr "選択済みディスコグラフィ" #: ../quodlibet/qltk/information.py:558 #, python-format msgid "%d song with no artist" msgid_plural "%d songs with no artist" msgstr[0] "%d曲にアーティスト情報がありません" #: ../quodlibet/qltk/information.py:586 ../quodlibet/util/tags.py:74 msgid "albums" msgstr "アルバム" #: ../quodlibet/qltk/information.py:599 msgid "Total length:" msgstr "合計時間" #: ../quodlibet/qltk/information.py:603 msgid "Total size:" msgstr "合計サイズ" #: ../quodlibet/qltk/information.py:606 msgid "Files" msgstr "ファイル" #: ../quodlibet/qltk/lyrics.py:37 msgid "_Download" msgstr "ダウンロード(_D)" #: ../quodlibet/qltk/lyrics.py:40 #, fuzzy msgid "_Edit" msgstr "ディスプレイの編集(_E)" #. buffer.set_text(_("No lyrics found.\n\nYou can click the " #. "Download button to have Quod Libet search " #. "for lyrics online. You can also enter them " #. "yourself and click save.")) #: ../quodlibet/qltk/lyrics.py:73 ../quodlibet/qltk/lyrics.py:109 msgid "No lyrics found for this song." msgstr "この曲の歌詞は見つかりませんでした。" #: ../quodlibet/qltk/lyrics.py:82 #, fuzzy msgid "Searching for lyrics…" 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/msg.py:41 msgid "Discard tag changes?" msgstr "タグの変更を破棄しますか?" #: ../quodlibet/qltk/msg.py:42 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "" "タグが変更されましたが、まだ保存されていません。保存しますか?それとも元に戻" "して変更を破棄しますか?" #: ../quodlibet/qltk/msg.py:55 ../quodlibet/qltk/prefs.py:595 #: ../quodlibet/qltk/textedit.py:64 ../quodlibet/qltk/tracknumbers.py:117 #, fuzzy msgid "_Revert" msgstr "なし" #: ../quodlibet/qltk/msg.py:86 #, fuzzy msgid "File exists" msgstr "同名のファイルが存在します" #: ../quodlibet/qltk/msg.py:88 #, python-format msgid "Replace %(file-name)s?" msgstr "" #: ../quodlibet/qltk/msg.py:94 #, fuzzy msgid "_Replace File" msgstr "ファイル名の変更" #: ../quodlibet/qltk/notif.py:182 msgid "Active tasks" msgstr "" #: ../quodlibet/qltk/notif.py:188 #, python-format msgid "%d tasks running" msgstr "" #: ../quodlibet/qltk/playorder.py:254 #, fuzzy msgid "Toggle shuffle mode" msgstr "再生/一時停止の切替" #: ../quodlibet/qltk/playorder.py:270 #, fuzzy msgid "Toggle repeat mode" msgstr "再生/一時停止の切替" #: ../quodlibet/qltk/pluginwin.py:44 msgid "Plugin Errors" msgstr "プラグインのエラー" #: ../quodlibet/qltk/pluginwin.py:124 msgid "Enabled" msgstr "" #: ../quodlibet/qltk/pluginwin.py:125 #, fuzzy msgid "Disabled" msgstr "ブラウザの無効化" #: ../quodlibet/qltk/pluginwin.py:131 msgid "No category" msgstr "" #: ../quodlibet/qltk/pluginwin.py:169 msgid "Events" msgstr "" #: ../quodlibet/qltk/pluginwin.py:170 #, fuzzy msgid "Play Order" msgstr "再生順(_O)" #: ../quodlibet/qltk/pluginwin.py:171 #, fuzzy msgid "Editing" msgstr "タグの編集" #: ../quodlibet/qltk/pluginwin.py:173 #, fuzzy msgid "Covers" msgstr "合計サイズ" #: ../quodlibet/qltk/pluginwin.py:309 msgid "No plugins found." msgstr "プラグインが見つかりません" #: ../quodlibet/qltk/pluginwin.py:358 #, fuzzy msgid "Plugins" msgstr "プラグイン(_P)" #: ../quodlibet/qltk/pluginwin.py:402 msgid "Show _Errors" msgstr "エラーの表示(_E)" #: ../quodlibet/qltk/prefs.py:45 msgid "_Disc" msgstr "ディスク(_D)" #: ../quodlibet/qltk/prefs.py:46 msgid "_Track" msgstr "トラック(_T)" #: ../quodlibet/qltk/prefs.py:47 #, fuzzy msgid "Grou_ping" msgstr "グループ" #: ../quodlibet/qltk/prefs.py:50 msgid "Al_bum" msgstr "アルバム(_b)" #: ../quodlibet/qltk/prefs.py:55 msgid "_Filename" msgstr "ファイル名(_F)" #: ../quodlibet/qltk/prefs.py:57 msgid "_Length" msgstr "時間(_L)" #: ../quodlibet/qltk/prefs.py:64 msgid "_Jump to playing song automatically" msgstr "再生中の曲へ自動的にジャンプする(_J)" #: ../quodlibet/qltk/prefs.py:66 msgid "When the playing song changes, scroll to it in the song list" msgstr "再生する曲が変わったときにソングリストをスクロールさせます" #: ../quodlibet/qltk/prefs.py:82 msgid "_Others:" msgstr "その他(_O)" #: ../quodlibet/qltk/prefs.py:88 #, fuzzy msgid "_Edit…" msgstr "ディスプレイの編集(_E)" #: ../quodlibet/qltk/prefs.py:91 msgid "Add or remove additional column headers" msgstr "" #: ../quodlibet/qltk/prefs.py:101 msgid "Visible Columns" msgstr "表示するカラム" #: ../quodlibet/qltk/prefs.py:104 msgid "Title includes _version" msgstr "タイトルにバージョンを含める(_v)" #: ../quodlibet/qltk/prefs.py:106 #, fuzzy msgid "Artist includes all _people" msgstr "タイトルにバージョンを含める(_v)" #: ../quodlibet/qltk/prefs.py:108 #, fuzzy msgid "Album includes _disc subtitle" msgstr "アルバムにパートを含める(_p)" #: ../quodlibet/qltk/prefs.py:110 msgid "Filename includes _folder" msgstr "ファイル名にフォルダ名を含める(_f)" #: ../quodlibet/qltk/prefs.py:123 #, fuzzy msgid "Column Preferences" msgstr "設定" #: ../quodlibet/qltk/prefs.py:129 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "" #: ../quodlibet/qltk/prefs.py:142 ../quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "ソングリスト" #: ../quodlibet/qltk/prefs.py:222 #, fuzzy msgid "Edit Columns" msgstr "表示するカラム" #: ../quodlibet/qltk/prefs.py:259 msgid "Duration totals" msgstr "" #: ../quodlibet/qltk/prefs.py:271 msgid "_Global filter:" msgstr "グローバルに適用するフィルタ(_G)" #: ../quodlibet/qltk/prefs.py:277 msgid "Apply this query in addition to all others" msgstr "" #. Translators: The heading of the preference group, no action #: ../quodlibet/qltk/prefs.py:283 #, fuzzy msgctxt "heading" msgid "Search" msgstr "検索" #: ../quodlibet/qltk/prefs.py:287 ../quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "ブラウザ" #: ../quodlibet/qltk/prefs.py:293 msgid "Confirm _multiple ratings" msgstr "" #: ../quodlibet/qltk/prefs.py:295 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "" #: ../quodlibet/qltk/prefs.py:298 msgid "Enable _one-click ratings" msgstr "" #: ../quodlibet/qltk/prefs.py:300 #, fuzzy msgid "Enable rating by clicking on the rating column in the song list" msgstr "再生する曲が変わったときにソングリストをスクロールさせます" #: ../quodlibet/qltk/prefs.py:306 ../quodlibet/qltk/prefs.py:616 #, fuzzy msgid "Ratings" msgstr "レイティング(_R)" #. Filename choice algorithm config #: ../quodlibet/qltk/prefs.py:312 msgid "Prefer _embedded art" msgstr "" #: ../quodlibet/qltk/prefs.py:314 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" #: ../quodlibet/qltk/prefs.py:319 msgid "_Fixed image filename:" msgstr "" #: ../quodlibet/qltk/prefs.py:321 msgid "The single image filename to use if selected" msgstr "" #: ../quodlibet/qltk/prefs.py:327 msgid "The album art image file to use when forced" msgstr "" #: ../quodlibet/qltk/prefs.py:336 #, fuzzy msgid "Album Art" msgstr "アルバムリスト" #: ../quodlibet/qltk/prefs.py:357 #, fuzzy msgid "Playback" msgstr "一時停止" #: ../quodlibet/qltk/prefs.py:362 msgid "Output Configuration" msgstr "" #: ../quodlibet/qltk/prefs.py:373 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" #: ../quodlibet/qltk/prefs.py:376 #, fuzzy msgid "_Fall-back gain (dB):" msgstr "ボリュームゲイン(dB)" #: ../quodlibet/qltk/prefs.py:387 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "" #: ../quodlibet/qltk/prefs.py:390 #, fuzzy msgid "_Pre-amp gain (dB):" msgstr "ボリュームゲイン(dB)" #: ../quodlibet/qltk/prefs.py:395 #, fuzzy msgid "_Enable Replay Gain volume adjustment" msgstr "リプレイの度に音量調整をする(_R)" #: ../quodlibet/qltk/prefs.py:420 #, fuzzy msgid "Replay Gain Volume Adjustment" msgstr "リプレイの度に音量調整をする(_R)" #: ../quodlibet/qltk/prefs.py:450 msgid "_Default rating:" msgstr "" #: ../quodlibet/qltk/prefs.py:493 #, fuzzy msgid "Rating _scale:" msgstr "レイティング(_R)" #: ../quodlibet/qltk/prefs.py:542 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:547 msgid "_Bayesian averaging amount:" msgstr "" #: ../quodlibet/qltk/prefs.py:556 #, fuzzy msgid "Save ratings and play _counts" msgstr "レイティングと再生回数を保存する" #: ../quodlibet/qltk/prefs.py:560 msgid "_Email:" msgstr "メールアドレス(_E)" #: ../quodlibet/qltk/prefs.py:562 msgid "Ratings and play counts will be set for this email address" msgstr "レイティングと再生回数はこのメールアドレスにセットされます" #: ../quodlibet/qltk/prefs.py:577 #, fuzzy msgid "Auto-save tag changes" msgstr "タグの変更を破棄しますか?" #: ../quodlibet/qltk/prefs.py:579 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "" #: ../quodlibet/qltk/prefs.py:587 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:610 #, fuzzy msgid "Tags" msgstr "タグの編集" #: ../quodlibet/qltk/prefs.py:631 #, fuzzy msgid "Updating for new ratings" msgstr "新規ラジオ局(_N)" #: ../quodlibet/qltk/prefs.py:641 #, fuzzy msgid "Scan library _on start" msgstr "ライブラリの再表示(_f)" #: ../quodlibet/qltk/prefs.py:651 ../quodlibet/qltk/quodlibetwindow.py:1100 #, fuzzy msgid "_Scan Library" msgstr "ライブラリの検索(_S)" #: ../quodlibet/qltk/prefs.py:653 ../quodlibet/qltk/quodlibetwindow.py:1162 msgid "Check for changes in your library" msgstr "ライブラリの変更内容をチェックします" #: ../quodlibet/qltk/prefs.py:658 #, fuzzy msgid "Re_build Library" msgstr "ライブラリの再読込(_l)" #: ../quodlibet/qltk/prefs.py:661 #, fuzzy msgid "Reload all songs in your library. This can take a long time." msgstr "ライブラリの再読込(この処理はやや時間がかかるかもしれません)" #: ../quodlibet/qltk/prefs.py:671 #, fuzzy msgid "Scan Directories" msgstr "スキャンするディレクトリ(_D)" #: ../quodlibet/qltk/prefs.py:677 #, fuzzy msgid "Hidden Songs" msgstr "曲がありません" #: ../quodlibet/qltk/properties.py:158 ../quodlibet/util/collection.py:398 #, python-format msgid "%(title)s and %(count)d more" msgid_plural "%(title)s and %(count)d more" msgstr[0] "" #: ../quodlibet/qltk/properties.py:162 ../quodlibet/qltk/properties.py:164 msgid "Properties" msgstr "プロパティ" #: ../quodlibet/qltk/queue.py:101 msgid "_Queue" msgstr "キュー(_Q)" #: ../quodlibet/qltk/queue.py:126 msgid "Stop Once Empty" msgstr "" #: ../quodlibet/qltk/queue.py:130 #, fuzzy msgid "_Clear Queue" msgstr "プラグインのエラー" #: ../quodlibet/qltk/queue.py:242 #, 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:198 msgid "_Browse Library" msgstr "ライブラリの参照(_B)" #: ../quodlibet/qltk/quodlibetwindow.py:395 #, fuzzy msgid "Toggle queue visibility" msgstr "メインウィンドウの表示/非表示切り替え" #: ../quodlibet/qltk/quodlibetwindow.py:516 #, fuzzy msgid "Playback Error" msgstr "一時停止" #: ../quodlibet/qltk/quodlibetwindow.py:524 #, fuzzy msgid "Set up library directories?" msgstr "ディレクトリの選択" #: ../quodlibet/qltk/quodlibetwindow.py:525 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:531 msgid "_Not Now" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:532 msgid "_Set Up" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:956 msgid "Unable to add songs" msgstr "曲を追加できません" #: ../quodlibet/qltk/quodlibetwindow.py:957 #: ../quodlibet/qltk/quodlibetwindow.py:1364 #, fuzzy, python-format msgid "%s uses an unsupported protocol." msgstr "<b>%s</b>で使われているプロトコルをサポートしていません。" #: ../quodlibet/qltk/quodlibetwindow.py:980 msgid "_Jump to Playing Song" msgstr "再生中の曲にジャンプ(_J)" #: ../quodlibet/qltk/quodlibetwindow.py:986 #, fuzzy msgid "_File" msgstr "ファイル" #: ../quodlibet/qltk/quodlibetwindow.py:987 #, fuzzy msgid "_Song" msgstr "曲" #: ../quodlibet/qltk/quodlibetwindow.py:988 msgid "_View" msgstr "表示(_V)" #: ../quodlibet/qltk/quodlibetwindow.py:989 #, fuzzy msgid "_Browse" msgstr "ブラウザ" #: ../quodlibet/qltk/quodlibetwindow.py:990 msgid "_Control" msgstr "操作(_C)" #: ../quodlibet/qltk/quodlibetwindow.py:991 msgid "_Help" msgstr "ヘルプ(_H)" #: ../quodlibet/qltk/quodlibetwindow.py:997 #, fuzzy msgid "_Add a Folder…" msgstr "フォルダの追加(_A)" #: ../quodlibet/qltk/quodlibetwindow.py:1002 #, fuzzy msgid "_Add a File…" msgstr "ファイルの追加(_A)" #: ../quodlibet/qltk/quodlibetwindow.py:1007 #, fuzzy msgid "_Add a Location…" msgstr "場所の追加" #: ../quodlibet/qltk/quodlibetwindow.py:1036 #, fuzzy msgid "Edit Bookmarks…" msgstr "ブックマークの編集(_E)" #: ../quodlibet/qltk/quodlibetwindow.py:1056 #, fuzzy msgid "Stop After This Song" msgstr "この曲の後で停止" #: ../quodlibet/qltk/quodlibetwindow.py:1062 msgid "_Keyboard Shortcuts" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:1071 msgid "Online Help" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:1080 #, fuzzy msgid "Search Help" msgstr "検索" #: ../quodlibet/qltk/quodlibetwindow.py:1352 msgid "Add a Location" msgstr "場所の追加" #: ../quodlibet/qltk/quodlibetwindow.py:1353 msgid "Enter the location of an audio file:" msgstr "オーディオファイルのある場所を入力してください:" #: ../quodlibet/qltk/quodlibetwindow.py:1358 #: ../quodlibet/qltk/quodlibetwindow.py:1363 msgid "Unable to add location" msgstr "場所の追加ができません" #: ../quodlibet/qltk/quodlibetwindow.py:1359 #, fuzzy, python-format msgid "%s is not a valid location." msgstr "指定された場所 <b>%s</b> にアクセスできません。" #: ../quodlibet/qltk/quodlibetwindow.py:1372 #: ../quodlibet/qltk/quodlibetwindow.py:1381 msgid "Add Music" msgstr "ミュージックの追加" #: ../quodlibet/qltk/quodlibetwindow.py:1372 ../quodlibet/qltk/scanbox.py:99 #, fuzzy msgid "_Add Folders" msgstr "フォルダの追加(_A)" #: ../quodlibet/qltk/quodlibetwindow.py:1379 #, fuzzy msgid "Music Files" msgstr "ミュージックプレイヤー" #: ../quodlibet/qltk/quodlibetwindow.py:1381 #, fuzzy msgid "_Add Files" msgstr "ファイルの追加(_A)" #: ../quodlibet/qltk/ratingsmenu.py:24 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "" #: ../quodlibet/qltk/ratingsmenu.py:26 msgid "The saved ratings will be removed" msgstr "" #: ../quodlibet/qltk/ratingsmenu.py:27 #, python-format msgid "The rating of all selected songs will be changed to '%s'" msgstr "" #: ../quodlibet/qltk/ratingsmenu.py:57 ../quodlibet/qltk/ratingsmenu.py:111 #, fuzzy msgid "_Remove Rating" msgstr "ラジオ局の削除(_R)" #: ../quodlibet/qltk/ratingsmenu.py:98 #, fuzzy msgid "Change _Rating" msgstr "レイティング(_R)" #: ../quodlibet/qltk/renamefiles.py:46 msgid "Replace spaces with _underscores" msgstr "スペースをアンダースコアに置き換える(_u)" #: ../quodlibet/qltk/renamefiles.py:56 msgid "Strip _Windows-incompatible characters" msgstr "Windowsと互換性のない文字を削除する(_W)" #: ../quodlibet/qltk/renamefiles.py:74 msgid "Strip _diacritical marks" msgstr "発音記号を削除する" #: ../quodlibet/qltk/renamefiles.py:85 msgid "Strip non-_ASCII characters" msgstr "非 ASCII 文字を削除する" #: ../quodlibet/qltk/renamefiles.py:95 msgid "Use only _lowercase characters" msgstr "" #: ../quodlibet/qltk/renamefiles.py:123 msgid "Rename Files" msgstr "ファイル名の変更" #: ../quodlibet/qltk/renamefiles.py:139 ../quodlibet/qltk/tagsfrompath.py:116 #, fuzzy msgid "Path Patterns" msgstr "パターン" #: ../quodlibet/qltk/renamefiles.py:140 ../quodlibet/qltk/tagsfrompath.py:117 #, fuzzy msgid "Edit saved patterns…" msgstr "保存されている値を編集..." #: ../quodlibet/qltk/renamefiles.py:143 ../quodlibet/qltk/tagsfrompath.py:120 #: ../quodlibet/qltk/tracknumbers.py:58 msgid "_Preview" msgstr "プレビュー(_P)" #: ../quodlibet/qltk/renamefiles.py:190 msgid "New Name" msgstr "新しい名前" #: ../quodlibet/qltk/renamefiles.py:255 msgid "Unable to rename file" msgstr "ファイル名を変更できません" #: ../quodlibet/qltk/renamefiles.py:256 #, fuzzy, python-format msgid "" "Renaming <b>%(old-name)s</b> to <b>%(new-name)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." msgstr "" "<b>%s</b>から<b>%s</b>への名前変更に失敗しました。変更先のファイルが既に存在" "する、新規ファイルを作成する権限がない、旧ファイルを削除する権限がないなどの" "可能性があります。" #: ../quodlibet/qltk/renamefiles.py:264 #, fuzzy msgid "Ignore _All Errors" msgstr "エラーの表示(_E)" #: ../quodlibet/qltk/renamefiles.py:267 msgid "_Continue" msgstr "続行する(_C)" #: ../quodlibet/qltk/renamefiles.py:296 msgid "Path is not absolute" msgstr "パス名が絶対パスになっていません" #: ../quodlibet/qltk/renamefiles.py:297 #, python-format msgid "" "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 ~/." msgstr "" "パターン\n" " <b>%s</b>\n" "に /が含まれていますが、ルートとなる位置を示していません。パターンを/か~/から" "始め、ルート位置を特定してください。" #: ../quodlibet/qltk/scanbox.py:47 #, fuzzy msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "" "入力されたフォルダをライブラリに追加します(複数入力するときは ':' で区切る)" #: ../quodlibet/qltk/scanbox.py:99 msgid "Select Directories" msgstr "ディレクトリの選択" #: ../quodlibet/qltk/searchbar.py:52 #, fuzzy msgid "Saved Searches" msgstr "保存された値" #: ../quodlibet/qltk/searchbar.py:53 #, fuzzy msgid "Edit saved searches…" msgstr "保存されている値を編集..." #: ../quodlibet/qltk/searchbar.py:74 msgid "Search your library, using free text or QL queries" msgstr "" #: ../quodlibet/qltk/searchbar.py:129 #, fuzzy msgid "Search after _typing" msgstr "この曲の後で停止" #: ../quodlibet/qltk/searchbar.py:132 msgid "Show search results after the user stops typing." msgstr "" #: ../quodlibet/qltk/searchbar.py:187 msgid "_Limit:" msgstr "検索結果の上限(_L)" #: ../quodlibet/qltk/searchbar.py:200 msgid "_Weight" msgstr "ウェイト(_W)" #: ../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 ../quodlibet/qltk/shortcuts.py:41 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: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:377 #, python-format msgid "_Filter on %s" msgstr "%sでフィルタリング(_F)" #: ../quodlibet/qltk/songlist.py:1094 #, fuzzy msgid "All _Headers" msgstr "アルバムヘッダ(_A)" #: ../quodlibet/qltk/songlist.py:1095 #, fuzzy msgid "_Track Headers" msgstr "トラック番号ヘッダ(_T)" #: ../quodlibet/qltk/songlist.py:1096 #, fuzzy msgid "_Album Headers" msgstr "アルバムヘッダ(_A)" #: ../quodlibet/qltk/songlist.py:1097 msgid "_People Headers" msgstr "_Peopleヘッダ" #: ../quodlibet/qltk/songlist.py:1098 msgid "_Date Headers" msgstr "_Dateヘッダ" #: ../quodlibet/qltk/songlist.py:1099 #, fuzzy msgid "_File Headers" msgstr "_Fileヘッダ" #: ../quodlibet/qltk/songlist.py:1100 #, fuzzy msgid "_Production Headers" msgstr "_Productionヘッダ" #: ../quodlibet/qltk/songlist.py:1115 #, fuzzy msgid "_Customize Headers…" msgstr "_Customizeヘッダ" #: ../quodlibet/qltk/songlist.py:1120 msgid "_Expand Column" msgstr "" #: ../quodlibet/qltk/songsmenu.py:36 #, 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:64 #, 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:149 #, fuzzy msgid "Configure Plugins…" msgstr "検索文字列のカラー表示" #: ../quodlibet/qltk/songsmenu.py:345 msgid "Add to _Queue" msgstr "キューへ追加(_Q)" #: ../quodlibet/qltk/songsmenu.py:368 msgid "_Copy to Device" msgstr "デバイスへコピー(_C)" #: ../quodlibet/qltk/songsmenu.py:379 #, fuzzy msgid "_Remove from Library" msgstr "プレイリストから削除(_R)" #: ../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:101 msgid "Tags From Path" msgstr "パス名からタグへの変換" #: ../quodlibet/qltk/tagsfrompath.py:138 msgid "Tags replace existing ones" msgstr "既存のタグを置き換える" #: ../quodlibet/qltk/tagsfrompath.py:139 msgid "Tags are added to existing ones" msgstr "既存のタグに追加する" #. Save button #: ../quodlibet/qltk/tagsfrompath.py:153 msgid "Save" msgstr "" #: ../quodlibet/qltk/tagsfrompath.py:195 #, python-format msgid "" "The pattern\n" "\t<b>%s</b>\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" "不正なパターンが入力されました。\n" " <b>%s</b>\n" "同じタグが2度使われているか、ブラケットの開始、終了の対応(< / >)が取れ" "ていない可能性があります。" #: ../quodlibet/qltk/tagsfrompath.py:216 msgid "Invalid tags" msgstr "不正なタグ" #: ../quodlibet/qltk/tagsfrompath.py:217 #, 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" "選択されたファイルは上記のタグをサポートしていません。" #: ../quodlibet/qltk/textedit.py:142 #, 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:158 msgid "Edit Display" msgstr "ディスプレイの編集" #: ../quodlibet/qltk/tracknumbers.py:39 msgid "Track Numbers" msgstr "トラック番号" #: ../quodlibet/qltk/tracknumbers.py:42 msgid "Start fro_m:" msgstr "開始番号(_m)" #: ../quodlibet/qltk/tracknumbers.py:51 msgid "_Total tracks:" msgstr "合計トラック数(_T)" #: ../quodlibet/qltk/unity.py:52 #, fuzzy msgid "Play/Pause" msgstr "プレイヤー" #: ../quodlibet/qltk/unity.py:75 #, fuzzy msgid "Previous" msgstr "プレビュー(_P)" #: ../quodlibet/qltk/views.py:923 #, 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 #, fuzzy, python-format msgid "%(current)s of %(all)s" msgstr "%d/%d移動中。" #: ../quodlibet/update.py:89 #, fuzzy msgid "Checking for Updates" msgstr "マウントポイントを確認中" #: ../quodlibet/update.py:124 #, fuzzy msgid "Connection failed" msgstr "場所" #: ../quodlibet/update.py:133 #, python-format msgid "You are already using the newest version %(version)s" msgstr "" #: ../quodlibet/update.py:136 #, 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:420 msgid "Playlists must have a name" msgstr "" #: ../quodlibet/util/collection.py:603 #, python-format msgid "A playlist named %s already exists." msgstr "プレイリスト%sは既に存在します。" #: ../quodlibet/util/cover/built_in.py:26 #, fuzzy msgid "Embedded album covers" msgstr "アルバムのカバーを表示する(_c)" #: ../quodlibet/util/cover/built_in.py:27 msgid "Uses covers embedded into audio files." msgstr "" #: ../quodlibet/util/cover/built_in.py:49 #, fuzzy msgid "Filesystem cover" msgstr "ファイルシステム" #: ../quodlibet/util/cover/built_in.py:50 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "" #: ../quodlibet/util/__init__.py:93 msgid "Display brief usage information" msgstr "基本的な使い方を表示" #: ../quodlibet/util/__init__.py:95 msgid "Display version and copyright" msgstr "バージョンと著作権情報を表示" #: ../quodlibet/util/__init__.py:135 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "" #: ../quodlibet/util/__init__.py:137 msgid "[options]" msgstr "" #: ../quodlibet/util/__init__.py:182 #, fuzzy, python-format msgid "Option %r not recognized." msgstr "E: オプション'%s'は認識できません。" #: ../quodlibet/util/__init__.py:185 #, fuzzy, python-format msgid "Option %r requires an argument." msgstr "E: オプション'%s'には引数が必要です。" #: ../quodlibet/util/__init__.py:188 #, fuzzy, python-format msgid "%r is not a unique prefix." msgstr "E: '%s'はユニークなプリフィックスではありません。" #: ../quodlibet/util/__init__.py:364 #, python-format msgid "%d kbps" msgstr "" #: ../quodlibet/util/__init__.py:419 #, fuzzy, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%d秒" #: ../quodlibet/util/__init__.py:432 msgid "No time information" msgstr "時間情報なし" #: ../quodlibet/util/__init__.py:435 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d秒" #: ../quodlibet/util/__init__.py:436 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d分" #: ../quodlibet/util/__init__.py:437 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d時間" #: ../quodlibet/util/__init__.py:438 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d日" #: ../quodlibet/util/__init__.py:439 #, 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:563 #, 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 "" "日付は'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 "" #: ../quodlibet/util/songwrapper.py:112 msgid "Unable to edit song" msgstr "曲の編集に失敗しました" #: ../quodlibet/util/songwrapper.py:113 #, python-format msgid "" "Saving <b>%s</b> 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:34 #: ../quodlibet/util/string/__init__.py:44 msgid "[Invalid Encoding]" msgstr "[不正なエンコーディング]" #: ../quodlibet/util/tags.py:74 msgid "album" msgstr "アルバム" #: ../quodlibet/util/tags.py:75 msgid "arranger" msgstr "アレンジャー" #: ../quodlibet/util/tags.py:75 msgid "arrangers" msgstr "アレンジャー" #: ../quodlibet/util/tags.py:75 #, fuzzy msgid "arrangement" msgstr "アレンジャー" #: ../quodlibet/util/tags.py:77 msgid "author" msgstr "著作者" #: ../quodlibet/util/tags.py:77 msgid "authors" msgstr "著作者" #: ../quodlibet/util/tags.py:78 msgid "composer" msgstr "作曲者" #: ../quodlibet/util/tags.py:78 msgid "composers" msgstr "作曲者" #: ../quodlibet/util/tags.py:78 #, fuzzy msgid "composition" msgstr "作曲者" #. Translators: conducting as in conducting a musical performance #: ../quodlibet/util/tags.py:80 msgid "conductor" msgstr "指揮者" #: ../quodlibet/util/tags.py:80 msgid "conductors" msgstr "指揮者" #: ../quodlibet/util/tags.py:80 #, fuzzy msgid "conducting" msgstr "指揮者" #: ../quodlibet/util/tags.py:81 msgid "contact" msgstr "連絡先" #: ../quodlibet/util/tags.py:82 msgid "copyright" msgstr "著作権" #: ../quodlibet/util/tags.py:83 msgid "date" msgstr "日時" #: ../quodlibet/util/tags.py:84 msgid "description" msgstr "説明" #: ../quodlibet/util/tags.py:85 msgid "genre" msgstr "ジャンル" #: ../quodlibet/util/tags.py:85 #, fuzzy msgid "genres" msgstr "ジャンル" #: ../quodlibet/util/tags.py:86 msgid "performer" msgstr "演奏者" #: ../quodlibet/util/tags.py:87 msgid "grouping" msgstr "グループ" #: ../quodlibet/util/tags.py:88 msgid "language" msgstr "言語" #: ../quodlibet/util/tags.py:89 msgid "license" msgstr "ライセンス" #: ../quodlibet/util/tags.py:90 msgid "location" msgstr "場所" #: ../quodlibet/util/tags.py:91 msgid "lyricist" msgstr "作詞者" #: ../quodlibet/util/tags.py:91 msgid "lyricists" msgstr "作詞者" #: ../quodlibet/util/tags.py:91 #, fuzzy msgid "lyrics" msgstr "作詞者" #. Translators: Also e.g. "record label", "publisher" #: ../quodlibet/util/tags.py:93 msgid "organization" msgstr "組織" #: ../quodlibet/util/tags.py:94 msgid "title" msgstr "タイトル" #: ../quodlibet/util/tags.py:95 msgid "version" msgstr "バージョン" #: ../quodlibet/util/tags.py:96 msgid "website" msgstr "ウェブサイト" #: ../quodlibet/util/tags.py:98 msgid "album artist" msgstr "アルバムアーティスト" #: ../quodlibet/util/tags.py:99 msgid "BPM" msgstr "" #. Translators: This used to be called "part". #: ../quodlibet/util/tags.py:102 ../quodlibet/util/tags.py:103 msgid "disc subtitle" msgstr "" #: ../quodlibet/util/tags.py:104 ../quodlibet/util/tags.py:141 msgid "disc" msgstr "ディスク" #: ../quodlibet/util/tags.py:105 ../quodlibet/util/tags.py:143 msgid "track" msgstr "トラック" #: ../quodlibet/util/tags.py:106 msgid "label ID" msgstr "レーベルID" #: ../quodlibet/util/tags.py:107 msgid "original release date" msgstr "オリジナルリリース日時" #: ../quodlibet/util/tags.py:108 msgid "original album" msgstr "オリジナルアルバム" #: ../quodlibet/util/tags.py:109 msgid "original artist" msgstr "オリジナルアーティスト" #: ../quodlibet/util/tags.py:110 msgid "recording date" msgstr "録音日時" #: ../quodlibet/util/tags.py:111 msgid "release country" 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:120 #, fuzzy msgid "MusicBrainz recording ID" msgstr "MusicBrainzトラックID" #: ../quodlibet/util/tags.py:121 #, fuzzy msgid "MusicBrainz release track ID" msgstr "MusicBrainzトラックID" #: ../quodlibet/util/tags.py:122 #, fuzzy msgid "MusicBrainz release ID" msgstr "MusicBrainzトラックID" #: ../quodlibet/util/tags.py:123 #, fuzzy msgid "MusicBrainz artist ID" msgstr "MusicBarainzアーティストID" #: ../quodlibet/util/tags.py:124 #, fuzzy msgid "MusicBrainz release artist ID" msgstr "MusicBrainzトラックID" #: ../quodlibet/util/tags.py:125 msgid "MusicBrainz TRM ID" msgstr "" #: ../quodlibet/util/tags.py:126 msgid "MusicIP PUID" msgstr "" #: ../quodlibet/util/tags.py:127 #, fuzzy msgid "MusicBrainz album status" msgstr "MusicBrainzアルバムアーティストID" #: ../quodlibet/util/tags.py:128 #, fuzzy msgid "MusicBrainz album type" msgstr "MusicBrainz アルバム ID" #: ../quodlibet/util/tags.py:129 #, fuzzy msgid "MusicBrainz release group ID" msgstr "MusicBrainzトラックID" #. Translators: "gain" means a volume adjustment, not "to acquire". #: ../quodlibet/util/tags.py:132 msgid "track gain" msgstr "トラックのゲイン" #: ../quodlibet/util/tags.py:133 msgid "track peak" msgstr "トラックのピーク" #. Translators: "gain" means a volume adjustment, not "to acquire". #: ../quodlibet/util/tags.py:135 msgid "album gain" msgstr "アルバムのゲイン" #: ../quodlibet/util/tags.py:136 msgid "album peak" msgstr "アルバムのピーク" #: ../quodlibet/util/tags.py:137 #, fuzzy msgid "reference loudness" msgstr "設定" #: ../quodlibet/util/tags.py:142 msgid "discs" msgstr "ディスク" #: ../quodlibet/util/tags.py:144 msgid "tracks" msgstr "トラック" #: ../quodlibet/util/tags.py:145 #, fuzzy msgid "last started" msgstr "最終再生開始日時" #: ../quodlibet/util/tags.py:146 msgid "full name" msgstr "フルネーム" #: ../quodlibet/util/tags.py:153 msgid "mount point" msgstr "マウントポイント" #: ../quodlibet/util/tags.py:155 msgid "people" msgstr "ピープル" #: ../quodlibet/util/tags.py:157 msgid "year" msgstr "年" #: ../quodlibet/util/tags.py:158 #, fuzzy msgid "original release year" msgstr "オリジナルリリース日時" #: ../quodlibet/util/tags.py:159 #, fuzzy msgid "bookmark" msgstr "ブックマーク" #: ../quodlibet/util/tags.py:162 #, fuzzy msgid "file format" msgstr "フォーマット" #: ../quodlibet/util/tags.py:165 #, fuzzy msgid "playlists" msgstr "プレイリスト" #: ../quodlibet/util/tags.py:166 msgid "channel count" msgstr "" #. Translators: e.g. "artist (sort)" #: ../quodlibet/util/tags.py:256 msgid "sort" msgstr "" #. Translators: e.g. "performer (roles)" #: ../quodlibet/util/tags.py:264 msgid "roles" msgstr "" #, fuzzy #~ msgid "browsers" #~ msgstr "ブラウザ" #~ msgid "Unable to download lyrics." #~ msgstr "歌詞のダウンロードに失敗しました。" #~ msgid "Remove all songs from the queue" #~ msgstr "キューの曲をすべて削除" #~ msgid "Watch this folder for new songs" #~ 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 "Model:" #~ msgstr "モデル" #~ msgid "Capacity:" #~ msgstr "容量" #~ msgid "Firmware:" #~ msgstr "ファームウェア" #, fuzzy #~ msgid "Removing orphaned iPod track" #~ msgstr "警告: 関連付けされていない iPod トラックを削除します" #, 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 "Unable to open input files" #~ msgstr "ファイルのオープンに失敗しました" #, 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 "_Select" #~ msgstr "フォルダの選択(_S)" #~ 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 "Choose New Stations" #~ msgstr "新しいラジオ局を選択してください" #~ msgid "Add" #~ msgstr "追加" #, fuzzy #~ msgid "Bitrate" #~ msgstr "ビットレート" #~ msgid "_Stations..." #~ msgstr "ラジオ局(_S)" #, fuzzy #~ msgid "Quod Libet" #~ msgstr "Quod Libetの終了" #~ 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9671857 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/po/ko.po����������������������������������������������������������������������������0000644�0001750�0001750�00000521241�00000000000�014072� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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: 2017-05-17 18:58+0200\n" "PO-Revision-Date: 2013-07-20 22:35+0100\n" "Last-Translator: ChangBom Yoon <changbom.yoon@gmail.com>\n" "Language-Team: The FreeBSD Korean Documentation Project <doc@kr.FreeBSD." "org>\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: Poedit 1.5.4\n" #: ../data/exfalso.appdata.xml.in.h:1 ../data/exfalso.desktop.in.h:2 msgid "Edit tags in your audio files" msgstr "오디오 파일 태그 편집" #: ../data/exfalso.appdata.xml.in.h:2 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/exfalso.appdata.xml.in.h:3 ../data/quodlibet.appdata.xml.in.h:3 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/exfalso.desktop.in.h:1 msgid "Audio tag editor" msgstr "오디오 태그 편집기" #: ../data/quodlibet.appdata.xml.in.h:1 ../data/quodlibet.desktop.in.h:2 msgid "Listen to, browse, or edit your audio collection" msgstr "듣기, 검색 및 오디오 모음 편집" #: ../data/quodlibet.appdata.xml.in.h:2 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 "" #: ../data/quodlibet.desktop.in.h:1 msgid "Music Player" msgstr "음악 재생기" #: ../quodlibet/browsers/albums/main.py:168 #: ../quodlibet/browsers/covergrid/main.py:54 #, fuzzy msgid "_Title" msgstr "제목" #: ../quodlibet/browsers/albums/main.py:169 #: ../quodlibet/browsers/covergrid/main.py:55 ../quodlibet/qltk/prefs.py:49 msgid "_Artist" msgstr "아티스트" #: ../quodlibet/browsers/albums/main.py:170 #: ../quodlibet/browsers/covergrid/main.py:56 ../quodlibet/qltk/prefs.py:54 msgid "_Date" msgstr "날짜" #: ../quodlibet/browsers/albums/main.py:171 #: ../quodlibet/browsers/covergrid/main.py:57 ../quodlibet/qltk/prefs.py:53 #, fuzzy msgid "_Genre" msgstr "장르" #: ../quodlibet/browsers/albums/main.py:172 #: ../quodlibet/browsers/covergrid/main.py:58 ../quodlibet/qltk/prefs.py:58 #: ../quodlibet/qltk/ratingsmenu.py:39 msgid "_Rating" msgstr "재생율" #: ../quodlibet/browsers/albums/main.py:178 #: ../quodlibet/browsers/covergrid/main.py:64 #, fuzzy msgid "Sort _by…" msgstr "날짜 순 정렬" #: ../quodlibet/browsers/albums/main.py:199 #: ../quodlibet/browsers/covergrid/main.py:85 #: ../quodlibet/browsers/paned/prefs.py:166 #: ../quodlibet/browsers/playlists/main.py:629 #: ../quodlibet/qltk/exfalsowindow.py:109 ../quodlibet/qltk/pluginwin.py:341 #: ../quodlibet/qltk/quodlibetwindow.py:1016 #, fuzzy msgid "_Preferences" msgstr "설정" #: ../quodlibet/browsers/albums/main.py:361 msgid "Album List" msgstr "앨범 목록" #: ../quodlibet/browsers/albums/main.py:362 msgid "_Album List" msgstr "앨범 목록" #: ../quodlibet/browsers/albums/main.py:472 #: ../quodlibet/browsers/covergrid/main.py:279 #: ../quodlibet/browsers/covergrid/main.py:488 msgid "All Albums" msgstr "모든 앨범" #: ../quodlibet/browsers/albums/main.py:473 #: ../quodlibet/browsers/covergrid/main.py:280 #: ../quodlibet/browsers/covergrid/main.py:489 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d 앨범" #: ../quodlibet/browsers/albums/main.py:650 #: ../quodlibet/browsers/covergrid/main.py:467 #, fuzzy msgid "Reload album _cover" msgid_plural "Reload album _covers" msgstr[0] "앨범 표지 보이기" #: ../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:381 ../quodlibet/util/collection.py:245 #, 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:379 ../quodlibet/util/collection.py:249 #, python-format msgid "%d disc" msgid_plural "%d discs" msgstr[0] "%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:120 #, fuzzy msgid "Options" msgstr "[옵션]" #: ../quodlibet/browsers/albums/prefs.py:74 #: ../quodlibet/browsers/covergrid/prefs.py:123 msgid "Album Display" msgstr "앨범 표시" #: ../quodlibet/browsers/albums/prefs.py:78 #: ../quodlibet/browsers/covergrid/prefs.py:127 #: ../quodlibet/browsers/media.py:39 #: ../quodlibet/browsers/playlists/prefs.py:56 #: ../quodlibet/ext/songsmenu/albumart.py:326 #: ../quodlibet/ext/songsmenu/duplicates.py:350 #: ../quodlibet/ext/songsmenu/filterall.py:48 #: ../quodlibet/qltk/bookmarks.py:101 ../quodlibet/qltk/cbes.py:93 #: ../quodlibet/qltk/data_editors.py:99 ../quodlibet/qltk/data_editors.py:324 #: ../quodlibet/qltk/exfalsowindow.py:297 ../quodlibet/qltk/pluginwin.py:79 #: ../quodlibet/qltk/pluginwin.py:427 ../quodlibet/qltk/prefs.py:707 #: ../quodlibet/qltk/textedit.py:164 ../quodlibet/update.py:148 msgid "_Close" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:55 #: ../quodlibet/browsers/audiofeeds.py:67 #: ../quodlibet/browsers/audiofeeds.py:69 #: ../quodlibet/browsers/audiofeeds.py:159 #: ../quodlibet/browsers/paned/models.py:86 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:46 #: ../quodlibet/formats/_audio.py:495 ../quodlibet/order/__init__.py:27 #: ../quodlibet/qltk/information.py:240 ../quodlibet/qltk/information.py:247 #: ../quodlibet/qltk/information.py:273 ../quodlibet/qltk/wlw.py:70 msgid "Unknown" msgstr "Unknown" #: ../quodlibet/browsers/audiofeeds.py:246 msgid "New Feed" msgstr "새 피드" #: ../quodlibet/browsers/audiofeeds.py:247 msgid "Enter the location of an audio feed:" msgstr "오디오 피드의 주소를 입력하십시오:" #: ../quodlibet/browsers/audiofeeds.py:248 #: ../quodlibet/browsers/collection/prefs.py:90 #: ../quodlibet/browsers/iradio.py:341 ../quodlibet/browsers/paned/prefs.py:78 #: ../quodlibet/browsers/playlists/menu.py:96 #: ../quodlibet/browsers/playlists/util.py:52 ../quodlibet/qltk/bookmarks.py:62 #: ../quodlibet/qltk/cbes.py:55 ../quodlibet/qltk/data_editors.py:311 #: ../quodlibet/qltk/edittags.py:288 ../quodlibet/qltk/edittags.py:488 #: ../quodlibet/qltk/quodlibetwindow.py:1354 ../quodlibet/qltk/scanbox.py:61 msgid "_Add" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:265 msgid "Audio Feeds" msgstr "오디오 피드" #: ../quodlibet/browsers/audiofeeds.py:266 msgid "_Audio Feeds" msgstr "오디오 피드" #: ../quodlibet/browsers/audiofeeds.py:345 #: ../quodlibet/browsers/audiofeeds.py:350 #, fuzzy msgid "_Download…" msgstr "내려받기" #: ../quodlibet/browsers/audiofeeds.py:359 msgid "Download Files" msgstr "파일 내려받기" #. Save button #: ../quodlibet/browsers/audiofeeds.py:359 #: ../quodlibet/browsers/audiofeeds.py:371 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:81 #: ../quodlibet/ext/songsmenu/albumart.py:322 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:355 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:278 #: ../quodlibet/ext/songsmenu/html.py:76 #: ../quodlibet/ext/songsmenu/lastfmsync.py:216 #: ../quodlibet/ext/songsmenu/playlist.py:51 #: ../quodlibet/ext/songsmenu/replaygain.py:365 #: ../quodlibet/ext/songsmenu/tapbpm.py:182 ../quodlibet/qltk/_editutils.py:39 #: ../quodlibet/qltk/lyrics.py:38 ../quodlibet/qltk/msg.py:52 #: ../quodlibet/qltk/renamefiles.py:168 ../quodlibet/qltk/tracknumbers.py:113 msgid "_Save" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:371 msgid "Download File" msgstr "파일 내려받기" #: ../quodlibet/browsers/audiofeeds.py:394 #: ../quodlibet/browsers/playlists/main.py:213 #: ../quodlibet/qltk/data_editors.py:96 msgid "_New" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:454 #: ../quodlibet/browsers/audiofeeds.py:513 msgid "Unable to add feed" msgstr "피드를 추가할 수 없습니다" #: ../quodlibet/browsers/audiofeeds.py:455 #: ../quodlibet/browsers/audiofeeds.py:514 #, fuzzy, python-format msgid "" "%s could not be added. The server may be down, or the location may not be an " "audio feed." msgstr "" "<b>%s</b> 는 추가할 수 없습니다. 서버가 죽었거나 입력한 주소는오디오 피드가 " "아닙니다." #. refresh button #: ../quodlibet/browsers/audiofeeds.py:462 ../quodlibet/browsers/media.py:217 #: ../quodlibet/browsers/media.py:386 ../quodlibet/qltk/filesel.py:259 #: ../quodlibet/qltk/pluginwin.py:413 #, fuzzy msgid "_Refresh" msgstr "라이브러리 새로고침" #: ../quodlibet/browsers/audiofeeds.py:463 #: ../quodlibet/browsers/playlists/main.py:457 #: ../quodlibet/browsers/playlists/util.py:43 ../quodlibet/qltk/delete.py:143 #: ../quodlibet/qltk/filesel.py:256 ../quodlibet/qltk/lyrics.py:39 #: ../quodlibet/qltk/maskedbox.py:28 ../quodlibet/qltk/songsmenu.py:392 #, fuzzy msgid "_Delete" msgstr "파일 지우기" #: ../quodlibet/browsers/audiofeeds.py:530 msgid "" "The current audio backend does not support URLs, Audio Feeds browser " "disabled." msgstr "" #: ../quodlibet/browsers/_base.py:147 ../quodlibet/browsers/_base.py:150 msgid "Library Browser" msgstr "라이브러리 브라우저" #: ../quodlibet/browsers/_base.py:274 ../quodlibet/ext/songsmenu/refresh.py:30 #: ../quodlibet/qltk/exfalsowindow.py:241 ../quodlibet/qltk/information.py:542 #: ../quodlibet/qltk/maskedbox.py:68 ../quodlibet/util/collection.py:527 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d 곡" #: ../quodlibet/browsers/_base.py:402 ../quodlibet/browsers/_base.py:407 #: ../quodlibet/qltk/tagsfrompath.py:194 ../quodlibet/qltk/textedit.py:141 #: ../quodlibet/util/__init__.py:622 msgid "Invalid pattern" msgstr "유효하지 않은 양식" #: ../quodlibet/browsers/collection/main.py:78 msgid "Album Collection" msgstr "" #: ../quodlibet/browsers/collection/main.py:79 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:66 #: ../quodlibet/browsers/paned/prefs.py:51 msgid "_Custom" msgstr "_Custom" #. Remove button #: ../quodlibet/browsers/collection/prefs.py:94 #: ../quodlibet/browsers/paned/prefs.py:82 #: ../quodlibet/browsers/playlists/menu.py:97 #: ../quodlibet/ext/playlist/remove_duplicates.py:60 #: ../quodlibet/qltk/bookmarks.py:97 ../quodlibet/qltk/bookmarks.py:127 #: ../quodlibet/qltk/cbes.py:82 ../quodlibet/qltk/cbes.py:89 #: ../quodlibet/qltk/data_editors.py:81 ../quodlibet/qltk/data_editors.py:94 #: ../quodlibet/qltk/data_editors.py:301 ../quodlibet/qltk/data_editors.py:314 #: ../quodlibet/qltk/data_editors.py:322 ../quodlibet/qltk/edittags.py:494 #: ../quodlibet/qltk/edittags.py:634 ../quodlibet/qltk/maskedbox.py:48 #: ../quodlibet/qltk/maskedbox.py:88 ../quodlibet/qltk/queue.py:350 #: ../quodlibet/qltk/scanbox.py:36 ../quodlibet/qltk/scanbox.py:63 #, fuzzy msgid "_Remove" msgstr "재생율" #: ../quodlibet/browsers/collection/prefs.py:122 #: ../quodlibet/ext/songsmenu/filterall.py:34 #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:92 #: ../quodlibet/qltk/edittags.py:431 msgid "Tag" msgstr "태그" #: ../quodlibet/browsers/collection/prefs.py:128 msgid "Merge" msgstr "" #: ../quodlibet/browsers/collection/prefs.py:188 #, fuzzy msgid "Album Collection Preferences" msgstr "앨범 목록 설정" #: ../quodlibet/browsers/collection/prefs.py:195 #: ../quodlibet/browsers/paned/prefs.py:209 #: ../quodlibet/ext/songsmenu/editplaycount.py:45 #: ../quodlibet/ext/songsmenu/exact_rating.py:38 #: ../quodlibet/player/gstbe/prefs.py:40 ../quodlibet/qltk/prefs.py:127 #: ../quodlibet/qltk/textedit.py:65 msgid "_Apply" msgstr "" #: ../quodlibet/browsers/collection/prefs.py:198 #: ../quodlibet/browsers/paned/prefs.py:213 #: ../quodlibet/browsers/playlists/menu.py:95 #: ../quodlibet/browsers/playlists/util.py:42 #: ../quodlibet/errorreport/ui.py:108 #: ../quodlibet/ext/playlist/export_to_folder.py:37 #: ../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:44 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:281 #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:88 #: ../quodlibet/ext/songsmenu/importexport.py:35 #: ../quodlibet/ext/songsmenu/lastfmsync.py:215 #: ../quodlibet/ext/songsmenu/playlist.py:50 #: ../quodlibet/ext/songsmenu/replaygain.py:364 #: ../quodlibet/ext/songsmenu/tapbpm.py:181 ../quodlibet/plugins/playlist.py:39 #: ../quodlibet/qltk/chooser.py:184 ../quodlibet/qltk/chooser.py:205 #: ../quodlibet/qltk/chooser.py:229 ../quodlibet/qltk/chooser.py:253 #: ../quodlibet/qltk/delete.py:90 ../quodlibet/qltk/delete.py:133 #: ../quodlibet/qltk/edittags.py:287 ../quodlibet/qltk/_editutils.py:38 #: ../quodlibet/qltk/getstring.py:28 ../quodlibet/qltk/maskedbox.py:27 #: ../quodlibet/qltk/msg.py:54 ../quodlibet/qltk/msg.py:93 #: ../quodlibet/qltk/ratingsmenu.py:33 ../quodlibet/qltk/songsmenu.py:45 #: ../quodlibet/qltk/songsmenu.py:73 ../quodlibet/update.py:94 msgid "_Cancel" msgstr "" #: ../quodlibet/browsers/covergrid/main.py:125 #, fuzzy msgid "Cover Grid" msgstr "총 크기:" #: ../quodlibet/browsers/covergrid/main.py:126 #, fuzzy msgid "_Cover Grid" msgstr "총 크기:" #: ../quodlibet/browsers/covergrid/prefs.py:54 #, fuzzy msgid "Cover Grid Preferences" msgstr "Paned Browser 설정" #: ../quodlibet/browsers/covergrid/prefs.py:64 #, fuzzy msgid "Show album _text" msgstr "앨범 표지 보이기" #: ../quodlibet/browsers/covergrid/prefs.py:71 #, fuzzy msgid "Show \"All Albums\" Item" msgstr "모든 앨범" #: ../quodlibet/browsers/covergrid/prefs.py:78 msgid "Vertical Split" msgstr "" #: ../quodlibet/browsers/covergrid/prefs.py:110 #: ../quodlibet/browsers/covergrid/prefs.py:111 #, fuzzy msgid "Cover Magnification" msgstr "조직" #: ../quodlibet/browsers/filesystem.py:40 msgid "File System" msgstr "파일 시스템" #: ../quodlibet/browsers/filesystem.py:41 msgid "_File System" msgstr "파일 시스템" #: ../quodlibet/browsers/filesystem.py:113 ../quodlibet/browsers/media.py:491 #: ../quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "노래를 복사할 수 없습니다" #: ../quodlibet/browsers/filesystem.py:114 ../quodlibet/qltk/songlist.py:268 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "선택한 파일은 다른 노래 목록이나 대기열로 복사 할 수 없습니다." #: ../quodlibet/browsers/filesystem.py:189 msgid "_Add to Library" msgstr "라이브러리 추가" #: ../quodlibet/browsers/iradio.py:178 msgid "Unsupported file type" msgstr "지원하지 않는 파일 형식" #: ../quodlibet/browsers/iradio.py:179 #, 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:219 ../quodlibet/browsers/iradio.py:232 #: ../quodlibet/browsers/iradio.py:810 msgid "Unable to add station" msgstr "방송국을 추가할 수 없습니다" #: ../quodlibet/browsers/iradio.py:243 ../quodlibet/browsers/iradio.py:471 msgid "Internet Radio" msgstr "인터넷 라디오" #: ../quodlibet/browsers/iradio.py:243 #, fuzzy msgid "Downloading station list" msgstr "파일 내려받기" #: ../quodlibet/browsers/iradio.py:339 msgid "New Station" msgstr "새방송국" #: ../quodlibet/browsers/iradio.py:340 msgid "Enter the location of an Internet radio station:" msgstr "인터넷 라디오 방송국의 주소를 입력하십시오:" #: ../quodlibet/browsers/iradio.py:358 msgid "Electronic" msgstr "" #: ../quodlibet/browsers/iradio.py:361 msgid "Hip Hop / Rap" msgstr "" #: ../quodlibet/browsers/iradio.py:362 msgid "Oldies" msgstr "" #: ../quodlibet/browsers/iradio.py:363 msgid "R&B" msgstr "" #: ../quodlibet/browsers/iradio.py:364 msgid "Japanese" msgstr "" #: ../quodlibet/browsers/iradio.py:365 msgid "Indian" msgstr "" #: ../quodlibet/browsers/iradio.py:367 msgid "Religious" msgstr "" #: ../quodlibet/browsers/iradio.py:369 msgid "Charts" msgstr "" #: ../quodlibet/browsers/iradio.py:370 msgid "Turkish" msgstr "" #: ../quodlibet/browsers/iradio.py:371 msgid "Reggae / Dancehall" msgstr "" #: ../quodlibet/browsers/iradio.py:372 #, fuzzy msgid "Latin" msgstr "재생율" #: ../quodlibet/browsers/iradio.py:373 msgid "College Radio" msgstr "" #: ../quodlibet/browsers/iradio.py:374 msgid "Talk / News" msgstr "" #: ../quodlibet/browsers/iradio.py:375 msgid "Ambient" msgstr "" #: ../quodlibet/browsers/iradio.py:376 msgid "Jazz" msgstr "" #: ../quodlibet/browsers/iradio.py:377 ../quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "" #: ../quodlibet/browsers/iradio.py:378 ../quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "" #: ../quodlibet/browsers/iradio.py:379 msgid "Alternative" msgstr "" #: ../quodlibet/browsers/iradio.py:380 msgid "Metal" msgstr "" #: ../quodlibet/browsers/iradio.py:381 msgid "Country" msgstr "" #: ../quodlibet/browsers/iradio.py:382 msgid "News" msgstr "" #: ../quodlibet/browsers/iradio.py:383 msgid "Schlager" msgstr "" #: ../quodlibet/browsers/iradio.py:384 msgid "Funk" msgstr "" #: ../quodlibet/browsers/iradio.py:385 msgid "Indie" msgstr "" #: ../quodlibet/browsers/iradio.py:386 msgid "Blues" msgstr "" #: ../quodlibet/browsers/iradio.py:387 msgid "Soul" msgstr "" #: ../quodlibet/browsers/iradio.py:388 msgid "Lounge" msgstr "" #: ../quodlibet/browsers/iradio.py:389 msgid "Punk" msgstr "" #: ../quodlibet/browsers/iradio.py:390 msgid "Reggaeton" msgstr "" #: ../quodlibet/browsers/iradio.py:392 msgid "Slavic" msgstr "" #: ../quodlibet/browsers/iradio.py:394 msgid "Greek" msgstr "" #: ../quodlibet/browsers/iradio.py:395 msgid "Gothic" msgstr "" #: ../quodlibet/browsers/iradio.py:396 ../quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "" #: ../quodlibet/browsers/iradio.py:449 msgid "Would you like to load a list of popular radio stations?" msgstr "" #: ../quodlibet/browsers/iradio.py:455 #, fuzzy msgid "_Load Stations" msgstr "새 방송국" #: ../quodlibet/browsers/iradio.py:472 msgid "_Internet Radio" msgstr "인터넷 라디오" #: ../quodlibet/browsers/iradio.py:538 #, fuzzy msgid "_New Station…" msgstr "새방송국" #: ../quodlibet/browsers/iradio.py:541 #, fuzzy msgid "_Update Stations" msgstr "새 방송국" #: ../quodlibet/browsers/iradio.py:568 #, fuzzy msgid "All Stations" msgstr "새방송국" #. TODO: support for ~#rating=!None etc (#1940) #: ../quodlibet/browsers/iradio.py:572 #: ../quodlibet/browsers/soundcloud/main.py:64 msgid "Favorites" msgstr "" #: ../quodlibet/browsers/iradio.py:580 msgid "No Category" msgstr "" #: ../quodlibet/browsers/iradio.py:802 msgid "No stations found" msgstr "발견된 방송국이 없습니다" #: ../quodlibet/browsers/iradio.py:803 #, python-format msgid "No Internet radio stations were found at %s." msgstr "%s 에서 발견된 인터넷 라디오 방송국이 없습니다." #: ../quodlibet/browsers/iradio.py:811 msgid "All stations listed are already in your library." msgstr "목록에 있는 모든 방송국은 이미 라이브러리에 존재합니다." #: ../quodlibet/browsers/iradio.py:828 #, fuzzy msgid "Add to Favorites" msgstr "재생목록 추가" #: ../quodlibet/browsers/iradio.py:832 #, fuzzy msgid "Remove from Favorites" msgstr "재생목록으로부터 제거" #: ../quodlibet/browsers/iradio.py:932 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "%(count)d station" #: ../quodlibet/browsers/media.py:36 #, fuzzy msgid "Device Properties" msgstr "등록정보" #: ../quodlibet/browsers/media.py:52 msgid "Device:" msgstr "" #: ../quodlibet/browsers/media.py:54 msgid "Not mounted" msgstr "" #: ../quodlibet/browsers/media.py:55 #, fuzzy msgid "Mount point:" msgstr "마운트 지점" #: ../quodlibet/browsers/media.py:61 ../quodlibet/qltk/cbes.py:40 msgid "_Name:" msgstr "이름:" #: ../quodlibet/browsers/media.py:135 #, fuzzy msgid "Media Devices" msgstr "오디오 장치: %s" #: ../quodlibet/browsers/media.py:136 #, fuzzy msgid "_Media Devices" msgstr "오디오 장치: %s" #. eject button #: ../quodlibet/browsers/media.py:224 ../quodlibet/browsers/media.py:378 #, fuzzy msgid "_Eject" msgstr "선택" #: ../quodlibet/browsers/media.py:360 #, fuzzy msgid "_Properties" msgstr "등록정보" #: ../quodlibet/browsers/media.py:365 #: ../quodlibet/browsers/playlists/main.py:464 msgid "_Rename" msgstr "이름 바꾸기" #: ../quodlibet/browsers/media.py:461 #, python-format msgid "%(used-size)s used, %(free-size)s available" msgstr "" #: ../quodlibet/browsers/media.py:479 #, fuzzy, python-format msgid "%s is not connected." msgstr "<b>%s</b> 는 유효하지 않은 주소입니다." #: ../quodlibet/browsers/media.py:499 #, fuzzy, python-format msgid "Copying %(song)s" msgstr "<b>%s</b> 삭제 실패." #: ../quodlibet/browsers/media.py:513 ../quodlibet/browsers/media.py:529 #, fuzzy msgid "Unable to copy song" msgstr "노래를 복사할 수 없습니다" #: ../quodlibet/browsers/media.py:514 msgid "There is not enough free space for this song." msgstr "" #: ../quodlibet/browsers/media.py:526 #, fuzzy, python-format msgid "%s could not be copied." msgstr "<b>%s</b> 는 유효하지 않은 주소입니다." #: ../quodlibet/browsers/media.py:545 #, fuzzy msgid "Unable to delete songs" msgstr "노래를 추가할 수 없습니다" #: ../quodlibet/browsers/media.py:557 #, fuzzy, python-format msgid "Deleting %(song)s" msgstr "<b>%s</b> 삭제 실패." #: ../quodlibet/browsers/media.py:575 #, fuzzy, python-format msgid "%s could not be deleted." msgstr "<b>%s</b> 는 유효하지 않은 주소입니다." #: ../quodlibet/browsers/media.py:579 #, fuzzy msgid "Unable to delete song" msgstr "노래를 편집할 수 없습니다" #: ../quodlibet/browsers/media.py:594 #, fuzzy, python-format msgid "Ejecting %s failed." msgstr "<b>%s</b> 삭제 실패." #: ../quodlibet/browsers/media.py:597 #, fuzzy msgid "Unable to eject device" msgstr "파일 삭제에 실패했습니다" #: ../quodlibet/browsers/media.py:603 msgid "No device backend, Media Devices browser disabled." msgstr "" #: ../quodlibet/browsers/paned/main.py:40 ../quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "Paned Browser" #: ../quodlibet/browsers/paned/main.py:41 msgid "_Paned Browser" msgstr "_Paned Browser" #: ../quodlibet/browsers/paned/main.py:90 msgid "Select _All" msgstr "모두 선택" #: ../quodlibet/browsers/paned/models.py:104 ../quodlibet/qltk/pluginwin.py:122 #: ../quodlibet/qltk/pluginwin.py:164 msgid "All" msgstr "All" #: ../quodlibet/browsers/paned/prefs.py:67 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "<tt>%s</tt>" msgstr "" #: ../quodlibet/browsers/paned/prefs.py:162 msgid "_Wide Mode" msgstr "" #: ../quodlibet/browsers/paned/prefs.py:197 msgid "Paned Browser Preferences" msgstr "Paned Browser 설정" #: ../quodlibet/browsers/paned/prefs.py:204 msgid "Equal pane width" msgstr "" #: ../quodlibet/browsers/playlists/main.py:48 #: ../quodlibet/browsers/playlists/main.py:575 #: ../quodlibet/qltk/pluginwin.py:168 msgid "Playlists" msgstr "재생목록" #: ../quodlibet/browsers/playlists/main.py:49 msgid "_Playlists" msgstr "재생목록" #: ../quodlibet/browsers/playlists/main.py:152 msgid "_Remove from Playlist" msgstr "재생목록으로부터 제거" #: ../quodlibet/browsers/playlists/main.py:215 #: ../quodlibet/browsers/playlists/main.py:576 msgid "_Import" msgstr "가져오기" #: ../quodlibet/browsers/playlists/main.py:391 #: ../quodlibet/browsers/playlists/util.py:50 #: ../quodlibet/util/collection.py:570 msgid "New Playlist" msgstr "새 재생목록" #: ../quodlibet/browsers/playlists/main.py:413 msgid "Unable to import playlist" msgstr "재생목록을 가져올 수 없습니다" #: ../quodlibet/browsers/playlists/main.py:414 msgid "Quod Libet can only import playlists in the M3U and PLS formats." msgstr "Quod Libet 은 M3U 와 PLS 포맷에서만 재생목록을 가져올 수 있습니다." #: ../quodlibet/browsers/playlists/main.py:565 msgid "Unable to rename playlist" msgstr "재생목록 이름을 바꿀 수 없습니다" #: ../quodlibet/browsers/playlists/main.py:576 msgid "Import Playlist" msgstr "재생목록 가져오기" #: ../quodlibet/browsers/playlists/menu.py:25 #, fuzzy msgid "_New Playlist…" msgstr "새 재생목록" #: ../quodlibet/browsers/playlists/menu.py:86 #, 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:90 #, 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 "Paned Browser 설정" #: ../quodlibet/browsers/playlists/prefs.py:52 #, fuzzy msgid "Playlist display" msgstr "재생목록" #: ../quodlibet/browsers/playlists/util.py:33 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "" #: ../quodlibet/browsers/playlists/util.py:35 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" #: ../quodlibet/browsers/playlists/util.py:51 #, fuzzy msgid "Enter a name for the new playlist:" msgstr "새 폴더 이름을 입력하십시오:" #: ../quodlibet/browsers/playlists/util.py:102 #, fuzzy, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" "재생목록을 가져옵니다.\n" "\n" "%d/%d 곡을 추가했습니다." #: ../quodlibet/browsers/search.py:33 msgid "_Limit Results" msgstr "결과 제한" #: ../quodlibet/browsers/search.py:48 msgid "Search Library" msgstr "라이브러리 검색" #: ../quodlibet/browsers/search.py:49 msgid "_Search Library" msgstr "라이브러리 검색" #: ../quodlibet/browsers/soundcloud/main.py:38 #, fuzzy msgid "Soundcloud Browser" msgstr "Paned Browser" #: ../quodlibet/browsers/soundcloud/main.py:39 msgid "Sound_cloud" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:59 #: ../quodlibet/qltk/searchbar.py:73 msgid "Search" msgstr "검색" #: ../quodlibet/browsers/soundcloud/main.py:136 #, python-format msgid "Go to %s" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:380 #, fuzzy msgid "Connected" msgstr "주소" #: ../quodlibet/browsers/soundcloud/main.py:381 #, python-format msgid "Quod Libet is now connected, <b>%s</b>!" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:393 #, python-format msgid "Log out of %s" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:395 msgid "Enter code…" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:396 #, python-format msgid "Log in to %s" msgstr "" #: ../quodlibet/browsers/soundcloud/util.py:86 msgid "Soundcloud authorisation" msgstr "" #: ../quodlibet/browsers/soundcloud/util.py:87 msgid "Enter Soundcloud auth code:" msgstr "" #: ../quodlibet/cli.py:50 #, fuzzy msgid "Quod Libet is not running (add '--run' to start it)" msgstr "Quod Libet 이 실행중이 아닙니다." #: ../quodlibet/cli.py:85 msgid "a music library and player" msgstr "음악 라이브러리 및 재생기" #: ../quodlibet/cli.py:86 #, fuzzy msgid "[option]" msgstr "[옵션]" #: ../quodlibet/cli.py:88 msgid "Print the playing song and exit" msgstr "재생중인 노래 표시 후 마침" #: ../quodlibet/cli.py:89 msgid "Begin playing immediately" msgstr "곧 노래 시작" #: ../quodlibet/cli.py:90 msgid "Don't show any windows on start" msgstr "" #: ../quodlibet/cli.py:93 msgid "Jump to next song" msgstr "다음 노래로 가기" #: ../quodlibet/cli.py:95 msgid "Jump to previous song or restart if near the beginning" msgstr "" #: ../quodlibet/cli.py:96 msgid "Jump to previous song" msgstr "이전 노래로 가기" #: ../quodlibet/cli.py:97 msgid "Start playback" msgstr "연주 시작" #: ../quodlibet/cli.py:98 msgid "Pause playback" msgstr "연주 일시정지" #: ../quodlibet/cli.py:99 msgid "Toggle play/pause mode" msgstr "재생/일시정지 토글(Toggle) 모드" #: ../quodlibet/cli.py:100 #, fuzzy msgid "Stop playback" msgstr "연주 시작" #: ../quodlibet/cli.py:101 msgid "Turn up volume" msgstr "음량 증가" #: ../quodlibet/cli.py:102 msgid "Turn down volume" msgstr "음량 감소" #: ../quodlibet/cli.py:103 msgid "Print player status" msgstr "재생기 상태 표시" #: ../quodlibet/cli.py:104 msgid "Hide main window" msgstr "메인 창 숨기기" #: ../quodlibet/cli.py:105 msgid "Show main window" msgstr "메인 창 보이기" #: ../quodlibet/cli.py:106 msgid "Toggle main window visibility" msgstr "메인 창 표시 토글(Toggle)" #: ../quodlibet/cli.py:107 msgid "Focus the running player" msgstr "실행중인 재생기 강조" #: ../quodlibet/cli.py:108 msgid "Remove active browser filters" msgstr "" #: ../quodlibet/cli.py:109 #, fuzzy msgid "Refresh and rescan library" msgstr "라이브러리 새로고침" #: ../quodlibet/cli.py:110 #, fuzzy msgid "List available browsers" msgstr "브라우저 비활성" #: ../quodlibet/cli.py:111 msgid "Print the current playlist" msgstr "현재 재생목록 표시" #: ../quodlibet/cli.py:112 msgid "Print the contents of the queue" msgstr "대기열 내용 표시" #: ../quodlibet/cli.py:113 #, fuzzy msgid "Print the active text query" msgstr "대기열 내용 표시" #: ../quodlibet/cli.py:114 msgid "Start without plugins" msgstr "" #: ../quodlibet/cli.py:115 #, fuzzy msgid "Start Quod Libet if it isn't running" msgstr "Quod Libet 이 실행중이 아닙니다." #: ../quodlibet/cli.py:116 msgid "Exit Quod Libet" msgstr "Quod Libet 마침" #: ../quodlibet/cli.py:121 msgid "Seek within the playing song" msgstr "재생중인 노래에서 탐색" #: ../quodlibet/cli.py:121 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: ../quodlibet/cli.py:122 #, fuzzy msgid "Set or toggle shuffle mode" msgstr "재생/일시정지 토글(Toggle) 모드" #: ../quodlibet/cli.py:123 msgid "Turn repeat off, on, or toggle it" msgstr "반복 끄기, 켜기, 토글(Toggle)" #: ../quodlibet/cli.py:124 msgid "Set the volume" msgstr "음량 설정" #: ../quodlibet/cli.py:125 msgid "Search your audio library" msgstr "오디오 라이브러리 검색" #: ../quodlibet/cli.py:125 ../quodlibet/cli.py:137 ../quodlibet/cli.py:141 #: ../quodlibet/cli.py:143 msgid "query" msgstr "쿼리" #: ../quodlibet/cli.py:126 msgid "Play a file" msgstr "파일 재생" #: ../quodlibet/cli.py:126 ../quodlibet/cli.py:137 ../quodlibet/cli.py:143 #, fuzzy msgctxt "command" msgid "filename" msgstr "파일이름" #: ../quodlibet/cli.py:127 msgid "Rate the playing song" msgstr "재생율" #: ../quodlibet/cli.py:128 msgid "Set the current browser" msgstr "현재 브라우저 지정" #: ../quodlibet/cli.py:129 #, fuzzy msgid "Stop after the playing song" msgstr "재생율" #: ../quodlibet/cli.py:130 msgid "Open a new browser" msgstr "새 브라우저 열기" #: ../quodlibet/cli.py:131 msgid "Show or hide the queue" msgstr "대기열 보이기 및 숨기기" #: ../quodlibet/cli.py:133 #, fuzzy msgid "Show or hide the main song list (deprecated)" msgstr "메인 노래 목록 보이기 및 숨기기" #: ../quodlibet/cli.py:134 msgid "Filter on a random value" msgstr "임의의 값으로 필터" #: ../quodlibet/cli.py:134 #, fuzzy msgctxt "command" msgid "tag" msgstr "태그" #: ../quodlibet/cli.py:135 msgid "Filter on a tag value" msgstr "태그 값으로 필터" #: ../quodlibet/cli.py:135 msgid "tag=value" msgstr "tag=value" #: ../quodlibet/cli.py:136 msgid "Enqueue a file or query" msgstr "Enqueue a file or query" #: ../quodlibet/cli.py:138 msgid "Enqueue comma-separated files" msgstr "" #: ../quodlibet/cli.py:139 ../quodlibet/util/tags.py:147 msgid "filename" msgstr "파일이름" #: ../quodlibet/cli.py:140 msgid "Print filenames of results of query to stdout" msgstr "" #: ../quodlibet/cli.py:142 #, fuzzy msgid "Unqueue a file or query" msgstr "Enqueue a file or query" #: ../quodlibet/cli.py:203 #, fuzzy, python-format msgid "Invalid argument for '%s'." msgstr "에러: '%s' 에 유효하지 않은 인자." #: ../quodlibet/cli.py:204 ../quodlibet/util/__init__.py:190 #, fuzzy, python-format msgid "Try %s --help." msgstr "에러: %s --help 를 시도해 보십시오." #: ../quodlibet/devices/_base.py:65 #, fuzzy msgid "Unknown Device" msgstr "Unknown" #: ../quodlibet/devices/__init__.py:32 #, python-format msgid "Could not import %s, which is needed for device support." msgstr "" #: ../quodlibet/devices/__init__.py:153 #, fuzzy, python-format msgid "%r is not a supported device." msgstr "에러: '%s' 는 유일한 prefix 가 아닙니다." #: ../quodlibet/devices/__init__.py:245 ../quodlibet/devices/__init__.py:251 #, python-format msgid "Could not find '%s'." msgstr "" #: ../quodlibet/devices/__init__.py:450 #, fuzzy msgid "Initializing device backend." msgstr "유효하지 않은 값" #: ../quodlibet/devices/__init__.py:451 #, python-format msgid "Trying '%s'" msgstr "" #: ../quodlibet/devices/__init__.py:461 msgid "Couldn't connect to a device backend." msgstr "" #: ../quodlibet/devices/__init__.py:463 msgid "Device backend initialized." msgstr "" #: ../quodlibet/devices/storage.py:57 #, fuzzy msgid "_Filename pattern:" msgstr "파일이름" #: ../quodlibet/devices/storage.py:61 #, fuzzy msgid "Copy _album covers" msgstr "앨범 표지 보이기" #: ../quodlibet/devices/storage.py:65 msgid "_Remove unused covers and directories" msgstr "" #: ../quodlibet/errorreport/ui.py:60 msgid "An Error Occurred" msgstr "" #: ../quodlibet/errorreport/ui.py:62 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:72 msgid "File Bug Report" msgstr "" #: ../quodlibet/errorreport/ui.py:74 ../quodlibet/errorreport/ui.py:90 msgid "Submit Error Report" msgstr "" #: ../quodlibet/errorreport/ui.py:75 msgid "Quit Program" msgstr "" #: ../quodlibet/errorreport/ui.py:76 #, fuzzy msgid "Ignore Error" msgstr "에러 보이기" #: ../quodlibet/errorreport/ui.py:80 msgid "Error details:" msgstr "" #: ../quodlibet/errorreport/ui.py:92 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:100 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "" #: ../quodlibet/errorreport/ui.py:109 msgid "_Send" msgstr "" #: ../quodlibet/errorreport/ui.py:115 #, fuzzy msgid "Short description…" msgstr "설명" #: ../quodlibet/errorreport/ui.py:118 msgid "Data to be sent:" msgstr "" #: ../quodlibet/exfalso.py:34 msgid "an audio tag editor" msgstr "오디오 태그 편집기" #: ../quodlibet/exfalso.py:34 ../quodlibet/util/tags.py:148 msgid "directory" msgstr "디렉토리" #: ../quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "" #: ../quodlibet/ext/covers/artwork_url.py:20 msgid "" "Downloads covers linked to by the artwork_url tag.This works with the " "Soundcloud browser." msgstr "" #: ../quodlibet/ext/covers/discogs.py:25 #, fuzzy msgid "Discogs Cover Source" msgstr "MusicBrainz track ID" #: ../quodlibet/ext/covers/discogs.py:26 msgid "Downloads covers from Discogs." msgstr "" #: ../quodlibet/ext/covers/lastfm.py:22 msgid "Last.fm Cover Source" msgstr "" #: ../quodlibet/ext/covers/lastfm.py:23 msgid "Downloads covers from Last.fm's cover art archive." msgstr "" #: ../quodlibet/ext/covers/musicbrainz.py:19 #, fuzzy msgid "MusicBrainz Cover Source" msgstr "MusicBrainz track ID" #: ../quodlibet/ext/covers/musicbrainz.py:20 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:25 msgid "Kana/Kanji Simple Inverter" msgstr "" #: ../quodlibet/ext/editing/kakasi.py:26 msgid "Converts kana/kanji to romaji before renaming." msgstr "" #: ../quodlibet/ext/editing/kakasi.py:35 msgid "Romanize _Japanese text" msgstr "" #: ../quodlibet/ext/editing/kakasi.py:63 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:19 msgid "" "Allows arbitrary regex substitutions (s///) 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 "_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:69 #, fuzzy msgid "Advanced Preferences" msgstr "Paned Browser 설정" #: ../quodlibet/ext/events/advanced_preferences.py:70 msgid "Allow editing of advanced config settings." msgstr "" #: ../quodlibet/ext/events/advanced_preferences.py:162 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:153 msgid "Top of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:154 msgid "Middle of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:155 msgid "Bottom of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:158 msgid "_Position:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:171 #, fuzzy msgid "_Cover size:" msgstr "총 크기:" #: ../quodlibet/ext/events/animosd/prefs.py:177 #: ../quodlibet/ext/events/lyricswindow.py:334 ../quodlibet/qltk/prefs.py:266 #, fuzzy msgid "Display" msgstr "Edit Display" #: ../quodlibet/ext/events/animosd/prefs.py:190 msgid "_Font:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:195 msgid "Left" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:196 msgid "Center" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:197 #, fuzzy msgid "Right" msgstr "무게" #: ../quodlibet/ext/events/animosd/prefs.py:200 msgid "_Align text:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:206 msgid "Text" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:217 msgid "_Text:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:227 msgid "_Fill:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:232 #: ../quodlibet/ext/events/synchronizedlyrics.py:63 msgid "Colors" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:240 msgid "_Shadows" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:241 msgid "_Outline" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:242 msgid "Rou_nded Corners" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:258 msgid "_Delay:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:264 #: ../quodlibet/qltk/pluginwin.py:172 msgid "Effects" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:270 #, fuzzy msgid "Ed_it Display Pattern…" msgstr "Edit Display" #: ../quodlibet/ext/events/animosd/prefs.py:274 #: ../quodlibet/ext/events/trayicon/prefs.py:78 #, fuzzy msgid "Preview" msgstr "미리보기" #: ../quodlibet/ext/events/auto_library_update.py:136 msgid "Automatic Library Update" msgstr "" #: ../quodlibet/ext/events/auto_library_update.py:137 #, python-format msgid "Keeps your library up to date with inotify. Requires %s." 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 by Brian Nelson." 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/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:97 msgid "Equalizer" msgstr "" #: ../quodlibet/ext/events/equalizer.py:98 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:132 msgid "The current backend does not support equalization." msgstr "" #: ../quodlibet/ext/events/equalizer.py:138 #, python-format msgid "%.1f kHz" msgstr "" #: ../quodlibet/ext/events/equalizer.py:139 #: ../quodlibet/ext/gstreamer/crossfeed.py:93 #: ../quodlibet/ext/gstreamer/karaoke.py:95 #, python-format msgid "%d Hz" msgstr "" #: ../quodlibet/ext/events/equalizer.py:173 #: ../quodlibet/ext/gstreamer/crossfeed.py:112 #, fuzzy, python-format msgid "%.1f dB" msgstr "%d 초" #: ../quodlibet/ext/events/equalizer.py:192 #: ../quodlibet/ext/gstreamer/crossfeed.py:31 #, fuzzy msgid "Custom" msgstr "_Custom" #: ../quodlibet/ext/events/equalizer.py:199 #, fuzzy msgid "_Clear" msgstr "플러그인 에러" #. Translators: statuses relating to Instant Messenger apps #: ../quodlibet/ext/events/gajim_status.py:27 msgid "online" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:28 msgid "offline" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:29 msgid "chat" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:30 msgid "away" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:31 msgid "xa" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:32 msgid "invisible" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:37 msgid "Gajim Status Message" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:38 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:45 #: ../quodlibet/ext/events/telepathy_status.py:69 msgid "paused" 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:160 msgid "Add '[paused]'" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:163 msgid "If checked, '[paused]' will be added to status message on pause." msgstr "" #: ../quodlibet/ext/events/gajim_status.py:187 msgid "Statuses for which message will be changed" msgstr "" #: ../quodlibet/ext/events/headphonemon.py:156 msgid "Pause on Headphone Unplug" msgstr "" #: ../quodlibet/ext/events/headphonemon.py:157 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" #: ../quodlibet/ext/events/inhibit.py:41 msgid "Inhibit Screensaver" msgstr "" #: ../quodlibet/ext/events/inhibit.py:42 msgid "Prevents the GNOME screensaver from activating while a song is playing." msgstr "" #: ../quodlibet/ext/events/inhibit.py:51 #, fuzzy msgid "Music is playing" msgstr "음악 재생기" #: ../quodlibet/ext/events/iradiolog.py:16 #, fuzzy msgid "Internet Radio Log" msgstr "인터넷 라디오" #: ../quodlibet/ext/events/iradiolog.py:17 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" #: ../quodlibet/ext/events/jep118.py:29 msgid "JEP-118" msgstr "" #: ../quodlibet/ext/events/jep118.py:30 msgid "Outputs a Jabber User Tunes file to ~/.quodlibet/jabber." 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 msgid "A restart is required for any changes to take effect" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:199 #, fuzzy msgid "No active song" msgstr "노래를 저장할 수 없습니다" #: ../quodlibet/ext/events/lyricswindow.py:215 #, fuzzy msgid "No lyrics found" msgstr "발견된 플러그인이 없습니다" #: ../quodlibet/ext/events/lyricswindow.py:227 #, fuzzy msgid "Lyrics:" msgstr "가사" #: ../quodlibet/ext/events/lyricswindow.py:284 msgid "_Zoom level:" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:302 msgid "URL:" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:307 msgid "Revert to default" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:322 msgid "Search via above URL if the lyrics couldn't be found in LyricsWikia." msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:339 #, fuzzy msgid "Alternate search" msgstr "검색 초기화" #: ../quodlibet/ext/events/lyricswindow.py:347 #, fuzzy msgid "Lyrics Window" msgstr "가사" #: ../quodlibet/ext/events/lyricswindow.py:348 msgid "Shows a window containing lyrics of the playing song." msgstr "" #: ../quodlibet/ext/events/mediaserver.py:38 msgid "UPnP AV Media Server" msgstr "" #: ../quodlibet/ext/events/mediaserver.py:39 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." 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:39 msgid "" "Allows control of Quod Libet using the MPRIS 1.0/2.0 D-Bus Interface " "Specification." msgstr "" #: ../quodlibet/ext/events/mpris/__init__.py:45 #: ../quodlibet/ext/events/trayicon/prefs.py:30 #, fuzzy msgid "Hide main window on close" msgstr "메인 창 숨기기" #: ../quodlibet/ext/events/mpris/__init__.py:48 #: ../quodlibet/ext/events/themeswitcher.py:84 #: ../quodlibet/ext/gstreamer/compressor.py:99 #: ../quodlibet/ext/gstreamer/crossfeed.py:136 #: ../quodlibet/ext/gstreamer/karaoke.py:99 #: ../quodlibet/ext/gstreamer/pitch.py:83 ../quodlibet/qltk/prefs.py:688 #, fuzzy msgid "Preferences" msgstr "설정" #: ../quodlibet/ext/events/mqtt.py:50 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/mqtt.py:56 msgid "MQTT Publisher" msgstr "" #: ../quodlibet/ext/events/mqtt.py:57 msgid "Publishes status messages to an MQTT topic." msgstr "" #: ../quodlibet/ext/events/mqtt.py:122 msgid "Broker hostname" msgstr "" #: ../quodlibet/ext/events/mqtt.py:122 msgid "broker hostname / IP" msgstr "" #: ../quodlibet/ext/events/mqtt.py:124 msgid "Broker port" msgstr "" #: ../quodlibet/ext/events/mqtt.py:124 msgid "broker port" msgstr "" #: ../quodlibet/ext/events/mqtt.py:126 msgid "Topic" msgstr "" #: ../quodlibet/ext/events/mqtt.py:128 #, fuzzy msgid "Playing Pattern" msgstr "양식" #: ../quodlibet/ext/events/mqtt.py:130 msgid "Status text when a song is started." msgstr "" #: ../quodlibet/ext/events/mqtt.py:132 #, fuzzy msgid "Paused Pattern" msgstr "양식" #: ../quodlibet/ext/events/mqtt.py:134 msgid "Text when a song is paused." msgstr "" #: ../quodlibet/ext/events/mqtt.py:136 #, fuzzy msgid "No-song Text" msgstr "%d 곡" #: ../quodlibet/ext/events/mqtt.py:138 msgid "Plain text for when there is no current song" msgstr "" #: ../quodlibet/ext/events/mqtt.py:149 #, fuzzy msgid "MQTT Configuration" msgstr "정보" #: ../quodlibet/ext/events/mqtt.py:153 #, fuzzy msgid "Status Text" msgstr "양식" #: ../quodlibet/ext/events/mqtt.py:185 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "" #: ../quodlibet/ext/events/mqtt.py:189 #, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s" msgstr "" #: ../quodlibet/ext/events/mqtt.py:192 #, fuzzy msgid "Connection error" msgstr "주소" #: ../quodlibet/ext/events/notify.py:80 msgid "Notification text" msgstr "" #: ../quodlibet/ext/events/notify.py:88 #, fuzzy msgid "_Title:" msgstr "제목" #: ../quodlibet/ext/events/notify.py:99 ../quodlibet/ext/events/notify.py:128 msgid "Revert to default pattern" msgstr "" #: ../quodlibet/ext/events/notify.py:118 msgid "_Body:" msgstr "" #: ../quodlibet/ext/events/notify.py:138 msgid "_Show notification" msgstr "" #: ../quodlibet/ext/events/notify.py:156 msgid "Show notifications" msgstr "" #: ../quodlibet/ext/events/notify.py:162 msgid "Only on <i>_manual</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:170 msgid "Only on <i>_automatic</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:178 msgid "On <i>a_ll</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:196 msgid "Only when the main window is not _focused" msgstr "" #: ../quodlibet/ext/events/notify.py:204 msgid "Show \"_Next\" button" msgstr "" #: ../quodlibet/ext/events/notify.py:236 msgid "Connection Error" msgstr "" #: ../quodlibet/ext/events/notify.py:237 ../quodlibet/ext/events/notify.py:391 #: ../quodlibet/ext/events/notify.py:433 msgid "Couldn't connect to notification daemon." msgstr "" #: ../quodlibet/ext/events/notify.py:251 msgid "Song Notifications" msgstr "" #: ../quodlibet/ext/events/notify.py:252 msgid "Displays a notification when the song changes." msgstr "" #: ../quodlibet/ext/events/notify.py:415 ../quodlibet/qltk/unity.py:65 msgid "Next" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:178 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:254 #, python-format msgid "Could not contact service '%s'." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:260 msgid "Authentication failed: invalid URL." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:277 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:282 msgid "Client is banned. Contact the author." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:286 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:351 msgid "AudioScrobbler Submission" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:352 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:450 msgid "Authentication successful." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:462 msgid "_Service:" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:462 msgid "_URL:" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:462 #, fuzzy msgid "User_name:" msgstr "이름:" #: ../quodlibet/ext/events/qlscrobbler.py:463 msgid "_Password:" msgstr "" #. Translators: Other service #: ../quodlibet/ext/events/qlscrobbler.py:479 #, fuzzy msgid "Other…" msgstr "_Others:" #. verify data #: ../quodlibet/ext/events/qlscrobbler.py:517 msgid "_Verify account data" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:522 #: ../quodlibet/ext/songsmenu/lastfmsync.py:304 msgid "Account" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:530 #, fuzzy msgid "_Artist pattern:" msgstr "아티스트" #: ../quodlibet/ext/events/qlscrobbler.py:530 #, fuzzy msgid "_Title pattern:" msgstr "파일이름" #: ../quodlibet/ext/events/qlscrobbler.py:531 msgid "Exclude _filter:" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:549 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:559 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:568 msgid "Songs matching this filter will not be submitted." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:576 msgid "_Offline mode (don't submit anything)" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:580 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:27 #, fuzzy msgid "Random Album Playback" msgstr "임의의 앨범" #: ../quodlibet/ext/events/randomalbum.py:28 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:38 msgid "Rated higher" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:39 msgid "Played more often" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:40 msgid "Skipped more often" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:41 msgid "Played more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:42 msgid "Started more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:43 msgid "Added more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:44 #, fuzzy msgid "Longer albums" msgstr "앨범" #: ../quodlibet/ext/events/randomalbum.py:83 msgid "seconds before starting next album" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:87 #, fuzzy msgid "Weights" msgstr "무게" #: ../quodlibet/ext/events/randomalbum.py:89 msgid "Play some albums more than others" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:103 msgid "avoid" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:114 msgid "prefer" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:201 #, fuzzy msgid "Random Album" msgstr "임의의 앨범" #: ../quodlibet/ext/events/randomalbum.py:202 #, python-format msgid "Waiting to start %s" msgstr "" #: ../quodlibet/ext/events/rbimport.py:114 #, fuzzy msgid "Import Failed" msgstr "재생목록 가져오기" #: ../quodlibet/ext/events/rbimport.py:119 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "" #: ../quodlibet/ext/events/rbimport.py:127 msgid "Rhythmbox Import" msgstr "" #: ../quodlibet/ext/events/rbimport.py:128 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "" #: ../quodlibet/ext/events/rbimport.py:132 #, fuzzy msgid "Start Import" msgstr "가져오기" #: ../quodlibet/ext/events/screensaver.py:25 msgid "Screensaver Pause" msgstr "" #: ../quodlibet/ext/events/screensaver.py:26 msgid "Pauses playback while the GNOME screensaver is active." msgstr "" #: ../quodlibet/ext/events/searchprovider.py:73 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "" #: ../quodlibet/ext/events/searchprovider.py:79 msgid "GNOME Search Provider" msgstr "" #: ../quodlibet/ext/events/searchprovider.py:80 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/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:29 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:57 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:58 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:34 #, fuzzy msgid "Synchronized Lyrics" msgstr "가사" #: ../quodlibet/ext/events/synchronizedlyrics.py:35 msgid "Shows synchronized lyrics from .lrc file with same name as the track." msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:66 msgid "Text:" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:76 msgid "Background:" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:87 msgid "Font" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:90 msgid "Size (px):" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:62 msgid "Telepathy Status Messages" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:63 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:122 #, fuzzy msgid "Playing:" msgstr "Not playing" #: ../quodlibet/ext/events/telepathy_status.py:123 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:139 msgid "Paused:" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:140 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:156 msgid "Plain text for status when there is no current song" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:157 #, fuzzy msgid "No song:" msgstr "%d 곡" #. Frame #: ../quodlibet/ext/events/telepathy_status.py:164 #, 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/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:77 #: ../quodlibet/ext/events/trayicon/prefs.py:98 #: ../quodlibet/ext/events/trayicon/systemtray.py:177 #: ../quodlibet/qltk/info.py:47 msgid "Not playing" msgstr "Not playing" #: ../quodlibet/ext/events/trayicon/__init__.py:53 msgid "Tray Icon" msgstr "" #: ../quodlibet/ext/events/trayicon/__init__.py:54 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:183 #: ../quodlibet/qltk/quodlibetwindow.py:1046 #: ../quodlibet/qltk/quodlibetwindow.py:1238 #, fuzzy msgid "_Play" msgstr "재생목록" #: ../quodlibet/ext/events/trayicon/menu.py:63 #: ../quodlibet/qltk/quodlibetwindow.py:185 #: ../quodlibet/qltk/quodlibetwindow.py:1240 ../quodlibet/qltk/wlw.py:51 #, fuzzy msgid "P_ause" msgstr "재생기" #: ../quodlibet/ext/events/trayicon/menu.py:68 #: ../quodlibet/qltk/quodlibetwindow.py:190 #: ../quodlibet/qltk/quodlibetwindow.py:1041 #, fuzzy msgid "Pre_vious" msgstr "미리보기" #: ../quodlibet/ext/events/trayicon/menu.py:71 #: ../quodlibet/qltk/quodlibetwindow.py:194 #: ../quodlibet/qltk/quodlibetwindow.py:1051 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:1012 #, fuzzy msgid "Open _Browser" msgstr "새 브라우저 열기" #: ../quodlibet/ext/events/trayicon/menu.py:103 #: ../quodlibet/qltk/quodlibetwindow.py:1031 ../quodlibet/qltk/songsmenu.py:411 msgid "Edit _Tags" msgstr "태그 편집" #: ../quodlibet/ext/events/trayicon/menu.py:112 #: ../quodlibet/qltk/quodlibetwindow.py:975 ../quodlibet/qltk/songsmenu.py:424 msgid "_Information" msgstr "정보" #: ../quodlibet/ext/events/trayicon/menu.py:114 #: ../quodlibet/qltk/songsmenu.py:340 #, fuzzy msgid "Play_lists" msgstr "재생목록" #: ../quodlibet/ext/events/trayicon/menu.py:132 #: ../quodlibet/qltk/quodlibetwindow.py:1026 msgid "_Quit" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:32 ../quodlibet/qltk/prefs.py:69 msgid "Behavior" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:42 msgid "Scroll wheel adjusts volume" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel changes song" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll _Wheel" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:84 #, fuzzy msgid "Tooltip Display" msgstr "Edit Display" #: ../quodlibet/ext/events/viewlyrics.py:23 #, fuzzy msgid "View Lyrics" msgstr "가사" #: ../quodlibet/ext/events/viewlyrics.py:24 msgid "Automatically displays lyrics beneath the song list in the main window." msgstr "" #: ../quodlibet/ext/events/viewlyrics.py:29 #, fuzzy msgid "_Lyrics" 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:406 msgid "Waveform Seek Bar" msgstr "" #: ../quodlibet/ext/events/waveformseekbar.py:410 msgid "A seekbar in the shape of the waveform of the current song." msgstr "" #: ../quodlibet/ext/events/waveformseekbar.py:443 msgid "Override foreground color:" msgstr "" #: ../quodlibet/ext/events/write_cover.py:32 msgid "Picture Saver" msgstr "" #: ../quodlibet/ext/events/write_cover.py:33 msgid "Saves the cover image of the current song to a file." msgstr "" #: ../quodlibet/ext/events/write_cover.py:66 #, fuzzy msgid "File:" msgstr "파일" #: ../quodlibet/ext/gstreamer/compressor.py:20 msgid "_Threshold:" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:21 msgid "Threshold until the filter is activated" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:22 msgid "R_atio:" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:22 msgid "Compression ratio" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:74 #: ../quodlibet/ext/gstreamer/karaoke.py:91 #, python-format msgid "%d %%" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:105 msgid "Audio Compressor" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:106 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:19 #, fuzzy msgid "_Preset:" msgstr "미리보기" #: ../quodlibet/ext/gstreamer/crossfeed.py:19 #, fuzzy msgid "Filter preset" msgstr "아티스트 필터" #: ../quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Frequency cut:" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Low-pass filter cut frequency" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed _level:" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed level" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:25 msgid "Default" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Chu Moy" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Jan Meier" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:31 #, fuzzy msgid "Custom settings" msgstr "_Custom" #: ../quodlibet/ext/gstreamer/crossfeed.py:152 msgid "Crossfeed" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:153 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:20 #, fuzzy msgid "Filter _band:" msgstr "장르 필터" #: ../quodlibet/ext/gstreamer/karaoke.py:21 msgid "The Frequency band of the filter" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:22 #, fuzzy msgid "Filter _width:" msgstr "아티스트 필터" #: ../quodlibet/ext/gstreamer/karaoke.py:23 msgid "The Frequency width of the filter" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:24 msgid "_Level:" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:24 msgid "Level of the effect" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:105 msgid "Karaoke" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:106 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:20 msgid "R_ate:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:21 msgid "_Tempo:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:22 msgid "_Pitch:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:89 #, fuzzy msgid "Audio Pitch / Speed" msgstr "오디오 피드" #: ../quodlibet/ext/gstreamer/pitch.py:90 #, fuzzy msgid "Controls the pitch of an audio stream." msgstr "오디오 피드의 주소를 입력하십시오:" #: ../quodlibet/ext/playlist/export_to_folder.py:29 #: ../quodlibet/ext/playlist/export_to_folder.py:97 #: ../quodlibet/ext/playlist/export_to_folder.py:138 #, fuzzy msgid "Export Playlist to Folder" msgstr "재생목록 가져오기" #: ../quodlibet/ext/playlist/export_to_folder.py:38 #, fuzzy msgid "_Export" msgstr "가져오기" #: ../quodlibet/ext/playlist/export_to_folder.py:43 #, fuzzy msgid "Destination folder:" msgstr "발견된 방송국이 없습니다" #: ../quodlibet/ext/playlist/export_to_folder.py:58 #, 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:156 #, fuzzy msgid "Default filename pattern:" msgstr "파일이름" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:23 msgid "Export to Squeezebox" msgstr "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:25 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 "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Export playlist to Squeezebox" msgstr "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:80 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 "" "Playback follows your selection, or the next song in the list once exhausted." msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:22 msgid "Playcount Equalizer" msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:23 msgid "Shuffle, preferring songs with fewer total plays." msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:25 #, fuzzy msgid "Prefer less played" msgstr "마지막 재생" #: ../quodlibet/ext/playorder/queue.py:19 #, fuzzy msgid "Queue Only" msgstr "대기열" #: ../quodlibet/ext/playorder/queue.py:21 msgid "" "Limits playing of songs to the queue. Select this play order in the main " "window, then double-clicking any song will enqueue it instead of playing." msgstr "" #: ../quodlibet/ext/playorder/reverse.py:14 #, fuzzy msgid "Reverse" msgstr "Never" #: ../quodlibet/ext/playorder/reverse.py:16 msgid "Reverses the play order of songs." msgstr "" #: ../quodlibet/ext/playorder/skip_songs.py:25 #, fuzzy msgid "Skip Songs" msgstr "No Songs" #: ../quodlibet/ext/playorder/skip_songs.py:27 msgid "" "Playback skips over songs with a rating equal or below a given threshold." msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:30 msgid "Repeat Each Track" msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:32 msgid "Shuffle songs, but repeat every track a set number of times." msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:51 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. Syntax is '@(if: " "condition, then, else)'." msgstr "" #: ../quodlibet/ext/query/pythonexpression.py:14 msgid "Python Query" msgstr "" #: ../quodlibet/ext/query/pythonexpression.py:15 msgid "" "Use Python expressions in queries. Syntax is '@(python: expression)'. The " "variable 's' is the song being matched." msgstr "" #: ../quodlibet/ext/query/savedsearch.py:19 #, fuzzy msgid "Include Saved Search" msgstr "저장된 값" #: ../quodlibet/ext/query/savedsearch.py:20 msgid "" "Include the results of a saved search as part of another query. Syntax is " "'@(saved: search name)'." 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:116 msgid "Port:" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:121 #, fuzzy msgid "Username:" msgstr "이름 바꾸기" #: ../quodlibet/ext/_shared/squeezebox/base.py:126 msgid "Password:" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:130 msgid "Library directory the server connects to." msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:132 #, fuzzy msgid "Library path:" msgstr "라이브러리" #. Add verify button #: ../quodlibet/ext/_shared/squeezebox/base.py:141 msgid "_Verify settings" msgstr "" #. Server settings Frame #: ../quodlibet/ext/_shared/squeezebox/base.py:147 msgid "Squeezebox Server" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:150 msgid "Debug" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:26 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:28 msgid "unidentified Squeezebox server" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:37 #, 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:20 #: ../quodlibet/ext/songsmenu/importexport.py:34 #: ../quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:329 #, fuzzy msgid "Fit image to _window" msgstr "메인 창 숨기기" #. Both labels #: ../quodlibet/ext/songsmenu/albumart.py:338 msgid "_Program:" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:343 msgid "_Edit image after saving" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:345 #, fuzzy msgid "File_name:" msgstr "파일이름" #: ../quodlibet/ext/songsmenu/albumart.py:457 msgid "Saving failed" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:458 #, fuzzy, python-format msgid "Unable to save \"%s\"." msgstr "노래를 저장할 수 없습니다" #: ../quodlibet/ext/songsmenu/albumart.py:556 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:613 #, fuzzy msgid "Album Art Downloader" msgstr "앨범 목록" #: ../quodlibet/ext/songsmenu/albumart.py:666 #, python-format msgid "from %(source)s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:669 #, python-format msgid "Resolution: %s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:672 #, fuzzy, python-format msgid "Size: %s" msgstr "크기" #: ../quodlibet/ext/songsmenu/albumart.py:690 #, fuzzy msgid "_Search" msgstr "검색:" #: ../quodlibet/ext/songsmenu/albumart.py:741 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:451 #, fuzzy msgid "Searching…" msgstr "검색" #: ../quodlibet/ext/songsmenu/albumart.py:804 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:922 #, fuzzy msgid "Download Album Art" msgstr "앨범 목록" #: ../quodlibet/ext/songsmenu/albumart.py:923 msgid "Downloads album covers from various websites." msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:936 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 "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 #: ../quodlibet/qltk/downloader.py:52 msgid "Filename" msgstr "파일이름" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:130 #, fuzzy msgid "Disc" msgstr "디스크" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:131 #: ../quodlibet/ext/songsmenu/replaygain.py:404 #: ../quodlibet/qltk/tracknumbers.py:92 msgid "Track" msgstr "트랙" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:132 #, 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 #, 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:447 msgid "Please enter a query." msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:465 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:496 msgid "Error encountered. Please retry." msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:472 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:488 msgid "Loading result…" msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:475 #, fuzzy msgid "No results found." msgstr "발견된 플러그인이 없습니다" #: ../quodlibet/ext/songsmenu/browsefolders.py:159 #, fuzzy msgid "Browse Folders" msgstr "브라우저" #: ../quodlibet/ext/songsmenu/browsefolders.py:160 msgid "Opens the songs' folders in a file manager." msgstr "" #: ../quodlibet/ext/songsmenu/browsefolders.py:172 #, fuzzy msgid "Unable to open folders" msgstr "폴더를 생성할 수 없습니다" #: ../quodlibet/ext/songsmenu/browsefolders.py:173 msgid "No program available to open folders." msgstr "" #: ../quodlibet/ext/songsmenu/console.py:40 msgid "Python Console" msgstr "" #: ../quodlibet/ext/songsmenu/console.py:41 msgid "Interactive Python console." msgstr "" #: ../quodlibet/ext/songsmenu/console.py:72 msgid "You can access the following objects by default:" msgstr "" #: ../quodlibet/ext/songsmenu/console.py:82 msgid "Your current working directory is:" 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:55 #, fuzzy msgid "pattern" 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:91 #, fuzzy msgid "Input value" msgstr "유효하지 않은 값" #: ../quodlibet/ext/songsmenu/custom_commands.py:92 #, python-format msgid "Value for %s?" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:136 #, fuzzy msgid "Custom Commands" msgstr "_Custom" #: ../quodlibet/ext/songsmenu/custom_commands.py:137 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:188 #: ../quodlibet/ext/songsmenu/custom_commands.py:198 #: ../quodlibet/ext/songsmenu/custom_commands.py:252 msgid "Edit Custom Commands" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:199 msgid "" "Supports QL patterns\n" "eg <tt><~artist~title></tt>" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:283 #, fuzzy, python-format msgid "Unable to run custom command %s" msgstr "노래를 복사할 수 없습니다" #: ../quodlibet/ext/songsmenu/duplicates.py:290 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "" #: ../quodlibet/ext/songsmenu/duplicates.py:343 msgid "Collapse / Expand all" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:347 #, python-format msgid "Duplicate key expression is '%s'" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:363 #, fuzzy msgid "Duplicates Browser" msgstr "브라우저 비활성" #: ../quodlibet/ext/songsmenu/duplicates.py:364 msgid "Finds and displays similarly tagged versions of songs." msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:407 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:409 msgid "_Group duplicates by:" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:414 msgid "Duplicate Key" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:419 msgid "Remove _Whitespace" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:420 #, fuzzy msgid "Remove _Diacritics" msgstr "재생율" #: ../quodlibet/ext/songsmenu/duplicates.py:421 #, fuzzy msgid "Remove _Punctuation" msgstr "재생율" #: ../quodlibet/ext/songsmenu/duplicates.py:422 msgid "Case _Insensitive" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:430 msgid "Matching options" msgstr "" #. Create a dialog. #: ../quodlibet/ext/songsmenu/editplaycount.py:19 #: ../quodlibet/ext/songsmenu/editplaycount.py:41 #, fuzzy msgid "Edit Playcount" msgstr "Edit Display" #: ../quodlibet/ext/songsmenu/editplaycount.py:20 msgid "" "Edit a song's ~#playcount and ~#skipcount.\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's ~#playcount to 0, the ~#lastplayed and ~#laststarted " "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:68 msgid "Play Count" msgstr "" #: ../quodlibet/ext/songsmenu/editplaycount.py:69 msgid "Skip Count" msgstr "" #: ../quodlibet/ext/songsmenu/embedded.py:24 msgid "Edit Embedded Images" msgstr "" #: ../quodlibet/ext/songsmenu/embedded.py:25 msgid "Removes or replaces embedded images." msgstr "" #: ../quodlibet/ext/songsmenu/embedded.py:78 #, fuzzy msgid "_Remove all Images" msgstr "재생율" #: ../quodlibet/ext/songsmenu/embedded.py:82 msgid "_Embed Current 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:41 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 #: ../quodlibet/qltk/downloader.py:67 #, 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 "쓰기" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" 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 #, 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:49 msgid "Generating fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:63 msgid "_Details" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:85 msgid "_Submit" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:115 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:118 msgid "Fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Songs with MBIDs:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with sufficient tags:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs to submit:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:162 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:178 msgid "Submitting fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:186 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/id3tlen.py:21 msgid "Fix MP3 Duration" msgstr "" #: ../quodlibet/ext/songsmenu/id3tlen.py:22 msgid "" "Removes TLEN frames from ID3 tags which can be the cause for invalid song " "durations." msgstr "" #: ../quodlibet/ext/songsmenu/ifp.py:20 msgid "Send to iFP" msgstr "" #: ../quodlibet/ext/songsmenu/ifp.py:21 msgid "Uploads songs to an iRiver iFP device." msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:51 msgid "Export Metadata" msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:52 msgid "Exports metadata of selected songs as a .tags file." msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:92 #, fuzzy msgid "Import Metadata" msgstr "재생목록 가져오기" #: ../quodlibet/ext/songsmenu/importexport.py:93 msgid "Imports metadata for selected songs from a .tags file." msgstr "" #: ../quodlibet/ext/songsmenu/k3b.py:23 msgid "Burn CD" msgstr "" #: ../quodlibet/ext/songsmenu/k3b.py:24 msgid "Burns CDs with K3b, Brasero or xfburn." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:96 msgid "Updating chart list." msgstr "" #. No charts to fetch, no update scheduled. #: ../quodlibet/ext/songsmenu/lastfmsync.py:114 msgid "Already up-to-date." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:121 #, python-format msgid "Fetching chart for week of %s." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:143 msgid "Sync complete." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:149 msgid "Error during sync" msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:214 #: ../quodlibet/ext/songsmenu/lastfmsync.py:244 msgid "Last.fm Sync" msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:245 msgid "Updates your library's statistics from your Last.fm profile." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:293 #, 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 "" #. Create a dialog. #: ../quodlibet/ext/songsmenu/migratemetadata.py:29 #: ../quodlibet/ext/songsmenu/migratemetadata.py:38 #, fuzzy msgid "Migrate Metadata" msgstr "재생목록 가져오기" #: ../quodlibet/ext/songsmenu/migratemetadata.py:32 msgid "Copies the quodlibet-specific metadata between songs." msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:45 msgid "_Copy" msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:47 msgid "_Paste" msgstr "" #. Create the tag table. #: ../quodlibet/ext/songsmenu/migratemetadata.py:57 #, fuzzy msgid "Information to copy/paste" msgstr "정보" #. Create the indexing box. #: ../quodlibet/ext/songsmenu/migratemetadata.py:79 msgid "Map tracks by disc and track number" msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:80 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 "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:96 #, python-format msgid "There is %d stored track." msgid_plural "There are %d stored tracks." msgstr[0] "" #: ../quodlibet/ext/songsmenu/playlist.py:31 #, fuzzy msgid "Export as Playlist" msgstr "재생목록 가져오기" #: ../quodlibet/ext/songsmenu/playlist.py:32 msgid "Exports songs to an M3U or PLS playlist." msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:77 msgid "Use relative paths" msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:77 msgid "Use absolute paths" msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:132 #, fuzzy msgid "Unable to export playlist" msgstr "재생목록을 가져올 수 없습니다" #: ../quodlibet/ext/songsmenu/playlist.py:133 #, fuzzy, python-format msgid "Writing to <b>%s</b> 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:362 msgid "ReplayGain Analyzer" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:418 msgid "Progress" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:433 msgid "Gain" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:448 msgid "Peak" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:463 #, python-format msgid "There is <b>%(to-process)s</b> album to update (of %(all)s)" msgid_plural "There are <b>%(to-process)s</b> albums to update (of %(all)s)" msgstr[0] "" #: ../quodlibet/ext/songsmenu/replaygain.py:578 msgid "Replay Gain" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:579 msgid "" "Analyzes and updates ReplayGain information, using GStreamer. Results are " "grouped by album." msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:617 msgid "always" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:618 msgid "if <b>any</b> RG tags are missing" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:620 msgid "if <b>album</b> RG tags are missing" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:637 msgid "_Process albums:" msgstr "" #. Server settings Frame #: ../quodlibet/ext/songsmenu/replaygain.py:649 #, 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 "" #. TRANSLATORS: BPM mean "beats per minute" #: ../quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "" #: ../quodlibet/ext/songsmenu/tapbpm.py:32 #: ../quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" 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:172 #: ../quodlibet/ext/songsmenu/tapbpm.py:179 msgid "Tap BPM" msgstr "" #: ../quodlibet/ext/songsmenu/tapbpm.py:173 #, fuzzy msgid "Tap BPM for the selected song." msgstr "노래를 추가할 수 없습니다" #: ../quodlibet/ext/songsmenu/website_search.py:35 #, fuzzy msgid "Website Search" msgstr "검색" #: ../quodlibet/ext/songsmenu/website_search.py:36 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern-example)s." msgstr "" #: ../quodlibet/ext/songsmenu/website_search.py:78 #, fuzzy msgid "Search URL patterns" msgstr "양식" #: ../quodlibet/ext/songsmenu/website_search.py:88 #, fuzzy msgid "Edit search URLs" msgstr "저장된 값 편집..." #. Add link to editor #: ../quodlibet/ext/songsmenu/website_search.py:114 #, fuzzy msgid "Configure Searches…" msgstr "검색 용어에 색깔" #: ../quodlibet/ext/songsmenu/wikipedia.py:46 #, python-format msgid "Search at %(website)s" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:63 msgid "Search Artist in Wikipedia" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:64 msgid "" "Opens a browser window with Wikipedia article on the playing song artist." msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:71 msgid "Search Album in Wikipedia" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:72 msgid "" "Opens a browser window with Wikipedia article on the playing song album." msgstr "" #. then (try to) load all new files #: ../quodlibet/library/libraries.py:650 ../quodlibet/library/libraries.py:660 #: ../quodlibet/library/libraries.py:726 ../quodlibet/library/libraries.py:745 #: ../quodlibet/qltk/information.py:268 ../quodlibet/qltk/prefs.py:639 #: ../quodlibet/util/library.py:124 msgid "Library" msgstr "라이브러리" #: ../quodlibet/library/libraries.py:650 msgid "Checking mount points" msgstr "마운트 지점 확인" #: ../quodlibet/library/libraries.py:660 msgid "Scanning library" msgstr "라이브러리 스캐닝" #: ../quodlibet/library/libraries.py:725 #, python-format msgid "Scanning %s" msgstr "스캐닝 %s" #: ../quodlibet/library/libraries.py:745 msgid "Loading files" msgstr "" #: ../quodlibet/operon/base.py:70 #, python-format msgid "Failed to load file: %r" msgstr "" #: ../quodlibet/operon/commands.py:37 msgid "List tags" msgstr "" #: ../quodlibet/operon/commands.py:42 ../quodlibet/operon/commands.py:81 #: ../quodlibet/operon/commands.py:461 msgid "Print terse output" msgstr "" #: ../quodlibet/operon/commands.py:44 ../quodlibet/operon/commands.py:83 #: ../quodlibet/operon/commands.py:463 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "" #: ../quodlibet/operon/commands.py:47 ../quodlibet/operon/commands.py:86 #, fuzzy msgid "Also list programmatic tags" msgstr "Show _programmatic tags" #: ../quodlibet/operon/commands.py:51 ../quodlibet/operon/commands.py:129 #: ../quodlibet/operon/commands.py:220 ../quodlibet/operon/commands.py:293 #: ../quodlibet/operon/commands.py:336 ../quodlibet/operon/commands.py:340 #: ../quodlibet/operon/commands.py:391 ../quodlibet/operon/commands.py:394 #: ../quodlibet/operon/commands.py:433 ../quodlibet/operon/commands.py:468 #: ../quodlibet/operon/commands.py:508 ../quodlibet/operon/commands.py:543 #: ../quodlibet/operon/commands.py:585 msgid "Not enough arguments" msgstr "" #: ../quodlibet/operon/commands.py:53 ../quodlibet/operon/commands.py:90 #: ../quodlibet/operon/commands.py:131 ../quodlibet/operon/commands.py:222 #: ../quodlibet/operon/commands.py:470 msgid "Too many arguments" msgstr "" #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:92 #: ../quodlibet/operon/commands.py:475 ../quodlibet/qltk/data_editors.py:363 #, fuzzy msgid "Description" msgstr "설명" #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:475 #: ../quodlibet/qltk/edittags.py:454 msgid "Value" msgstr "값" #: ../quodlibet/operon/commands.py:76 msgid "List all common tags" msgstr "" #: ../quodlibet/operon/commands.py:118 msgid "Copy tags from one file to another" msgstr "" #: ../quodlibet/operon/commands.py:123 ../quodlibet/operon/commands.py:164 #: ../quodlibet/operon/commands.py:289 ../quodlibet/operon/commands.py:324 #: ../quodlibet/operon/commands.py:384 msgid "Show changes, don't apply them" msgstr "" #: ../quodlibet/operon/commands.py:125 msgid "Skip tags that can't be written" msgstr "" #: ../quodlibet/operon/commands.py:145 #, python-format msgid "Can't copy tag %r to file: %r" 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:304 ../quodlibet/operon/commands.py:444 #: ../quodlibet/operon/commands.py:676 #, python-format msgid "Can not set %r" msgstr "" #: ../quodlibet/operon/commands.py:319 msgid "Remove tags" msgstr "" #: ../quodlibet/operon/commands.py:326 ../quodlibet/operon/commands.py:386 msgid "Value is a regular expression" msgstr "" #: ../quodlibet/operon/commands.py:328 msgid "Remove all tags" msgstr "" #: ../quodlibet/operon/commands.py:332 msgid "Can't combine '--all' with '--regexp'" msgstr "" #: ../quodlibet/operon/commands.py:366 #, python-format msgid "Can't remove %r from %r" msgstr "" #: ../quodlibet/operon/commands.py:379 #, fuzzy msgid "Remove a tag value" msgstr "태그 값으로 필터" #: ../quodlibet/operon/commands.py:428 #, fuzzy msgid "Add a tag value" msgstr "태그 값으로 필터" #: ../quodlibet/operon/commands.py:456 #, fuzzy msgid "List file information" msgstr "정보에 시간이 없습니다" #: ../quodlibet/operon/commands.py:502 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" #: ../quodlibet/operon/commands.py:515 #, fuzzy, python-format msgid "Failed to load image file: %r" msgstr "파일이름 변경을 할 수 없습니다" #: ../quodlibet/operon/commands.py:522 ../quodlibet/operon/commands.py:551 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" #: ../quodlibet/operon/commands.py:538 msgid "Remove all embedded images" msgstr "" #: ../quodlibet/operon/commands.py:568 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "" #: ../quodlibet/operon/commands.py:580 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" #: ../quodlibet/operon/commands.py:639 msgid "Rename files based on tags" msgstr "" #: ../quodlibet/operon/commands.py:654 msgid "Fill tags based on the file path" msgstr "" #: ../quodlibet/operon/commands.py:704 ../quodlibet/qltk/information.py:305 #: ../quodlibet/qltk/properties.py:84 ../quodlibet/qltk/renamefiles.py:176 #: ../quodlibet/qltk/tagsfrompath.py:229 ../quodlibet/qltk/tracknumbers.py:79 msgid "File" msgstr "파일" #: ../quodlibet/operon/commands.py:712 msgid "Fill tracknumbers for all files" msgstr "" #: ../quodlibet/operon/commands.py:731 msgid "Print tags based on the given pattern" msgstr "" #: ../quodlibet/operon/commands.py:768 #, fuzzy msgid "Display help information" msgstr "사용 정보 개요 표시" #: ../quodlibet/operon/util.py:40 #, 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:30 #, fuzzy msgid "_Unknown" msgstr "Unknown" #: ../quodlibet/order/__init__.py:142 msgid "In Order" msgstr "순서대로" #: ../quodlibet/order/__init__.py:143 msgid "_In Order" msgstr "순서대로" #: ../quodlibet/order/reorder.py:23 #, fuzzy msgid "Random" msgstr "임의로" #: ../quodlibet/order/reorder.py:24 ../quodlibet/qltk/queue.py:119 msgid "_Random" msgstr "임의로" #: ../quodlibet/order/reorder.py:39 ../quodlibet/order/reorder.py:40 msgid "Prefer higher rated" msgstr "" #: ../quodlibet/order/repeat.py:43 ../quodlibet/order/repeat.py:44 msgid "Repeat this track" msgstr "" #: ../quodlibet/order/repeat.py:57 ../quodlibet/order/repeat.py:58 #, fuzzy msgid "Repeat all" msgstr "반복" #: ../quodlibet/order/repeat.py:73 ../quodlibet/order/repeat.py:74 msgid "One Song" msgstr "선택한 노래" #: ../quodlibet/player/gstbe/player.py:98 msgid "Stream" msgstr "" #: ../quodlibet/player/gstbe/player.py:98 msgid "Buffering" msgstr "" #: ../quodlibet/player/gstbe/player.py:319 msgid "Could not create GStreamer pipeline" msgstr "" #: ../quodlibet/player/gstbe/player.py:560 msgid "No GStreamer element found to handle media format" msgstr "" #: ../quodlibet/player/gstbe/player.py:561 #, 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:25 msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. In case the pipeline contains a sink, it will be used instead of " "the default one." msgstr "" #: ../quodlibet/player/gstbe/prefs.py:36 msgid "_Output pipeline:" msgstr "" #: ../quodlibet/player/gstbe/prefs.py:43 #, fuzzy, python-format msgid "%.1f seconds" msgstr "%d 초" #: ../quodlibet/player/gstbe/prefs.py:57 msgid "_Buffer duration:" msgstr "" #: ../quodlibet/player/gstbe/prefs.py:66 msgid "Disable _gapless playback" msgstr "" #: ../quodlibet/player/gstbe/prefs.py:70 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions." msgstr "" #: ../quodlibet/player/gstbe/util.py:93 #, fuzzy msgid "No GStreamer audio sink found" msgstr "발견된 방송국이 없습니다" #: ../quodlibet/player/gstbe/util.py:112 msgid "Invalid GStreamer output pipeline" msgstr "" #: ../quodlibet/player/xinebe/player.py:90 #, fuzzy msgid "Unable to create audio output" msgstr "폴더를 생성할 수 없습니다" #: ../quodlibet/player/xinebe/player.py:91 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "" #: ../quodlibet/plugins/__init__.py:62 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" #: ../quodlibet/plugins/__init__.py:71 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "" #: ../quodlibet/plugins/playlist.py:30 #, 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:41 ../quodlibet/qltk/songsmenu.py:46 #: ../quodlibet/qltk/songsmenu.py:74 #, fuzzy msgid "_Run Plugin" msgstr "플러그인" #: ../quodlibet/qltk/about.py:40 #, python-format msgid "Supported formats: %s" msgstr "지원 포맷: %s" #: ../quodlibet/qltk/about.py:43 #, python-format msgid "Audio device: %s" msgstr "오디오 장치: %s" #. 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:207 ../quodlibet/qltk/information.py:131 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 "" #: ../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 "" #: ../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 곡이 재생되었습니다" #: ../quodlibet/qltk/cbes.py:48 ../quodlibet/qltk/edittags.py:311 msgid "_Value:" msgstr "값:" #: ../quodlibet/qltk/cbes.py:262 msgid "Saved Values" msgstr "저장된 값" #: ../quodlibet/qltk/cbes.py:263 #, fuzzy msgid "Edit saved values…" msgstr "저장된 값 편집..." #: ../quodlibet/qltk/controls.py:111 msgid "Auto_matic" msgstr "" #: ../quodlibet/qltk/controls.py:112 #, fuzzy msgid "_Track Mode" msgstr "_Track Headers" #: ../quodlibet/qltk/controls.py:113 #, fuzzy msgid "_Album Mode" msgstr "_Album Headers" #. Translators: player state, no action #: ../quodlibet/qltk/controls.py:122 msgid "_Mute" msgstr "" #: ../quodlibet/qltk/controls.py:128 #, fuzzy msgid "_Replay Gain Mode" msgstr "_Replay Gain volume adjustment" #. Translators: New Command/Entry/Item/... #: ../quodlibet/qltk/data_editors.py:119 #, python-format msgid "New %s" msgstr "" #: ../quodlibet/qltk/data_editors.py:218 #, fuzzy msgid "(unknown)" msgstr "Unknown" #: ../quodlibet/qltk/data_editors.py:355 msgid "Tag expression" msgstr "" #: ../quodlibet/qltk/data_editors.py:382 msgid "Tag expression e.g. people:real or ~album~year." msgstr "" #: ../quodlibet/qltk/data_editors.py:383 #, fuzzy msgid "Enter new tag" 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] "" #: ../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] "" #: ../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/downloader.py:38 msgid "Downloads" msgstr "내려받기" #: ../quodlibet/qltk/downloader.py:62 msgid "Size" msgstr "크기" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: ../quodlibet/qltk/downloader.py:94 ../quodlibet/qltk/renamefiles.py:265 #: ../quodlibet/qltk/wlw.py:50 msgid "_Stop" msgstr "" #: ../quodlibet/qltk/edittags.py:63 ../quodlibet/qltk/edittags.py:74 #, python-format msgid "missing from %d song" msgid_plural "missing from %d songs" msgstr[0] "missing from %d song" #: ../quodlibet/qltk/edittags.py:67 ../quodlibet/qltk/edittags.py:71 #, python-format msgid "different across %d song" msgid_plural "different across %d songs" msgstr[0] "different across %d song" #: ../quodlibet/qltk/edittags.py:193 msgid "Split into _Multiple Values" msgstr "Split into _Multiple Values" #: ../quodlibet/qltk/edittags.py:211 msgid "Split Disc out of _Album" msgstr "Split Disc out of _Album" #: ../quodlibet/qltk/edittags.py:228 msgid "Split _Version out of Title" msgstr "Split _Version out of Title" #: ../quodlibet/qltk/edittags.py:259 msgid "Split Arranger out of Ar_tist" msgstr "Split Arranger out of Ar_tist" #: ../quodlibet/qltk/edittags.py:264 msgid "Split _Performer out of Artist" msgstr "Split _Performer out of Artist" #: ../quodlibet/qltk/edittags.py:270 #, fuzzy msgid "Split _Performer out of Title" msgstr "Split _Performer out of Artist" #: ../quodlibet/qltk/edittags.py:276 #, fuzzy msgid "Split _Originalartist out of Title" msgstr "Split _Version out of Title" #: ../quodlibet/qltk/edittags.py:283 msgid "Add a Tag" msgstr "태그 추가" #: ../quodlibet/qltk/edittags.py:302 msgid "_Tag:" msgstr "태그:" #: ../quodlibet/qltk/edittags.py:404 msgid "Edit Tags" msgstr "태그 편집:" #: ../quodlibet/qltk/edittags.py:477 msgid "Show _programmatic tags" msgstr "Show _programmatic tags" #: ../quodlibet/qltk/edittags.py:478 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" #. Translators: Revert button in the tag editor #: ../quodlibet/qltk/edittags.py:508 #, fuzzy msgctxt "edittags" msgid "_Revert" msgstr "Never" #. Translators: Save button in the tag editor #: ../quodlibet/qltk/edittags.py:513 msgctxt "edittags" msgid "_Save" msgstr "" #: ../quodlibet/qltk/edittags.py:659 msgid "Unable to add tag" msgstr "태그를 추가할 수 없습니다" #: ../quodlibet/qltk/edittags.py:660 #, fuzzy, python-format msgid "Unable to add <b>%s</b>" msgstr "노래를 추가할 수 없습니다" #: ../quodlibet/qltk/edittags.py:662 #, fuzzy, python-format msgid "" "The files currently selected do not support multiple values for <b>%s</b>." msgstr "" "<b>%s</b> 태그를 추가할 수 없습니다\n" "\n" "지금 선택한 파일은 복수값을 지원하지 않습니다." #. Can't add the new tag. #: ../quodlibet/qltk/edittags.py:689 ../quodlibet/qltk/edittags.py:856 #: ../quodlibet/qltk/tagsfrompath.py:212 ../quodlibet/util/__init__.py:554 #: ../quodlibet/util/tags.py:231 msgid "Invalid tag" msgstr "유효하지 않은 태그" #: ../quodlibet/qltk/edittags.py:690 ../quodlibet/qltk/edittags.py:857 #: ../quodlibet/qltk/tagsfrompath.py:213 #, python-format msgid "" "Invalid tag <b>%s</b>\n" "\n" "The files currently selected do not support editing this tag." msgstr "" "유효하지 않은 태그 <b>%s</b>\n" "\n" "지금 선택한 파일은 이러한 태그의 편집을 지원하지 않습니다." #: ../quodlibet/qltk/edittags.py:828 ../quodlibet/qltk/edittags.py:868 msgid "Invalid value" msgstr "유효하지 않은 값" #: ../quodlibet/qltk/edittags.py:829 ../quodlibet/qltk/edittags.py:869 #, python-format msgid "" "Invalid value: <b>%(value)s</b>\n" "\n" "%(error)s" msgstr "" "Invalid value: <b>%(value)s</b>\n" "\n" "%(error)s" #: ../quodlibet/qltk/_editutils.py:28 msgid "Tag may not be accurate" msgstr "태그에 결함이 있습니다" #: ../quodlibet/qltk/_editutils.py:31 #, 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" "어쨌든 이 노래를저장할까요?" #: ../quodlibet/qltk/_editutils.py:47 msgid "Unable to save song" msgstr "노래를 저장할 수 없습니다" #: ../quodlibet/qltk/_editutils.py:50 #, 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:142 #, 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:95 #: ../quodlibet/qltk/quodlibetwindow.py:1066 msgid "_About" msgstr "" #: ../quodlibet/qltk/exfalsowindow.py:99 #: ../quodlibet/qltk/quodlibetwindow.py:1088 msgid "_Check for Updates…" msgstr "" #: ../quodlibet/qltk/exfalsowindow.py:105 #: ../quodlibet/qltk/quodlibetwindow.py:1021 ../quodlibet/qltk/songsmenu.py:304 msgid "_Plugins" msgstr "플러그인" #: ../quodlibet/qltk/exfalsowindow.py:267 #, 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" #: ../quodlibet/qltk/exfalsowindow.py:279 msgid "Ex Falso Preferences" msgstr "Ex Falso 설정" #: ../quodlibet/qltk/exfalsowindow.py:289 ../quodlibet/qltk/prefs.py:598 msgid "Split _on:" msgstr "Split _on:" #: ../quodlibet/qltk/exfalsowindow.py:295 ../quodlibet/qltk/prefs.py:613 msgid "Tag Editing" msgstr "태그 편집" #: ../quodlibet/qltk/filesel.py:210 msgid "Folders" msgstr "폴더" #: ../quodlibet/qltk/filesel.py:253 #, fuzzy msgid "_New Folder…" msgstr "새 폴더" #: ../quodlibet/qltk/filesel.py:262 #, fuzzy msgid "_Select all Sub-Folders" msgstr "하위폴더 모두 선택" #: ../quodlibet/qltk/filesel.py:374 msgid "New Folder" msgstr "새 폴더" #: ../quodlibet/qltk/filesel.py:374 msgid "Enter a name for the new folder:" msgstr "새 폴더 이름을 입력하십시오:" #: ../quodlibet/qltk/filesel.py:387 msgid "Unable to create folder" msgstr "폴더를 생성할 수 없습니다" #: ../quodlibet/qltk/filesel.py:404 msgid "Unable to delete folder" msgstr "폴더를 지울 수 없습니다" #: ../quodlibet/qltk/filesel.py:519 ../quodlibet/qltk/pluginwin.py:167 msgid "Songs" msgstr "노래" #. Translators: As in "by Artist Name" #: ../quodlibet/qltk/info.py:42 #, python-format msgid "by %s" msgstr "아티스트: %s" #: ../quodlibet/qltk/info.py:43 ../quodlibet/qltk/information.py:167 #: ../quodlibet/qltk/information.py:448 #, python-format msgid "Disc %s" msgstr "%s 디스크" #: ../quodlibet/qltk/info.py:44 ../quodlibet/qltk/information.py:172 #, python-format msgid "Track %s" msgstr "%s 트랙" #: ../quodlibet/qltk/info.py:108 #, fuzzy msgid "_Edit Display…" msgstr "Edit Display" #: ../quodlibet/qltk/information.py:105 msgid "No songs are selected." msgstr "선택한 노래가 없습니다." #: ../quodlibet/qltk/information.py:106 msgid "No Songs" msgstr "No Songs" #: ../quodlibet/qltk/information.py:121 ../quodlibet/qltk/information.py:338 #: ../quodlibet/qltk/information.py:471 ../quodlibet/qltk/information.py:531 msgid "Information" msgstr "정보" #: ../quodlibet/qltk/information.py:126 msgid "Lyrics" msgstr "가사" #: ../quodlibet/qltk/information.py:184 ../quodlibet/qltk/information.py:396 #, python-format msgid "Produced by %s" msgstr "기획: %s" #: ../quodlibet/qltk/information.py:199 ../quodlibet/util/tags.py:76 msgid "artist" msgstr "아티스트" #: ../quodlibet/qltk/information.py:200 ../quodlibet/qltk/information.py:561 #: ../quodlibet/util/tags.py:76 msgid "artists" msgstr "아티스트" #. for backwards compat #: ../quodlibet/qltk/information.py:221 ../quodlibet/util/tags.py:86 #: ../quodlibet/util/tags.py:114 msgid "performers" msgstr "연주" #: ../quodlibet/qltk/information.py:235 ../quodlibet/qltk/information.py:248 #: ../quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "Never" #: ../quodlibet/qltk/information.py:236 #, fuzzy, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "%d 회" #: ../quodlibet/qltk/information.py:254 ../quodlibet/util/tags.py:139 msgid "added" msgstr "추가" #: ../quodlibet/qltk/information.py:255 ../quodlibet/util/tags.py:140 msgid "last played" msgstr "마지막 재생" #: ../quodlibet/qltk/information.py:256 ../quodlibet/util/tags.py:150 msgid "plays" msgstr "재생" #: ../quodlibet/qltk/information.py:257 ../quodlibet/util/tags.py:151 msgid "skips" msgstr "통과" #: ../quodlibet/qltk/information.py:258 ../quodlibet/util/tags.py:156 msgid "rating" msgstr "재생율" #: ../quodlibet/qltk/information.py:287 msgid "path" msgstr "" #: ../quodlibet/qltk/information.py:288 ../quodlibet/util/tags.py:154 msgid "length" msgstr "길이" #: ../quodlibet/qltk/information.py:289 #, fuzzy msgid "format" msgstr "정보" #: ../quodlibet/qltk/information.py:290 ../quodlibet/util/tags.py:163 msgid "codec" msgstr "" #: ../quodlibet/qltk/information.py:291 ../quodlibet/util/tags.py:164 #, fuzzy msgid "encoding" msgstr "[유효하지 않은 인코딩]" #: ../quodlibet/qltk/information.py:292 ../quodlibet/util/tags.py:160 msgid "bitrate" msgstr "비트율" #: ../quodlibet/qltk/information.py:293 ../quodlibet/util/tags.py:161 msgid "file size" msgstr "파일 크기" #: ../quodlibet/qltk/information.py:294 ../quodlibet/util/tags.py:149 msgid "modified" msgstr "수정" #: ../quodlibet/qltk/information.py:331 msgid "Additional" msgstr "" #: ../quodlibet/qltk/information.py:383 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d 선택" #: ../quodlibet/qltk/information.py:458 msgid "Track unavailable" msgstr "트랙을 이용할 수 없습니다" #: ../quodlibet/qltk/information.py:464 msgid "Track List" msgstr "트랙 목록" #: ../quodlibet/qltk/information.py:505 ../quodlibet/qltk/information.py:578 #, python-format msgid "%d song with no album" msgid_plural "%d songs with no album" msgstr[0] "앨범이 없는 노래 %d 곡" #: ../quodlibet/qltk/information.py:508 msgid "Selected Discography" msgstr "Selected Discography" #: ../quodlibet/qltk/information.py:558 #, python-format msgid "%d song with no artist" msgid_plural "%d songs with no artist" msgstr[0] "아티스트가 없는 노래 %d 곡" #: ../quodlibet/qltk/information.py:586 ../quodlibet/util/tags.py:74 msgid "albums" msgstr "앨범" #: ../quodlibet/qltk/information.py:599 msgid "Total length:" msgstr "총 길이:" #: ../quodlibet/qltk/information.py:603 msgid "Total size:" msgstr "총 크기:" #: ../quodlibet/qltk/information.py:606 msgid "Files" msgstr "파일" #: ../quodlibet/qltk/lyrics.py:37 msgid "_Download" msgstr "내려받기" #: ../quodlibet/qltk/lyrics.py:40 #, fuzzy msgid "_Edit" msgstr "_Edit Display..." #. buffer.set_text(_("No lyrics found.\n\nYou can click the " #. "Download button to have Quod Libet search " #. "for lyrics online. You can also enter them " #. "yourself and click save.")) #: ../quodlibet/qltk/lyrics.py:73 ../quodlibet/qltk/lyrics.py:109 msgid "No lyrics found for this song." msgstr "이 노래를 위한 가사가 없습니다" #: ../quodlibet/qltk/lyrics.py:82 #, fuzzy msgid "Searching for lyrics…" 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/msg.py:41 msgid "Discard tag changes?" msgstr "변경된 태그를 버릴까요?" #: ../quodlibet/qltk/msg.py:42 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "" "태그가 변경되었으나 저장되지 않았습니다. 이 파일을 저장할까요? 아니면 변경사" "항을 무시하고 이전으로 되돌릴까요?" #: ../quodlibet/qltk/msg.py:55 ../quodlibet/qltk/prefs.py:595 #: ../quodlibet/qltk/textedit.py:64 ../quodlibet/qltk/tracknumbers.py:117 #, fuzzy msgid "_Revert" msgstr "Never" #: ../quodlibet/qltk/msg.py:86 #, fuzzy msgid "File exists" msgstr "파일 시스템" #: ../quodlibet/qltk/msg.py:88 #, python-format msgid "Replace %(file-name)s?" msgstr "" #: ../quodlibet/qltk/msg.py:94 #, fuzzy msgid "_Replace File" msgstr "파일이름 바꾸기" #: ../quodlibet/qltk/notif.py:182 msgid "Active tasks" msgstr "" #: ../quodlibet/qltk/notif.py:188 #, python-format msgid "%d tasks running" msgstr "" #: ../quodlibet/qltk/playorder.py:254 #, fuzzy msgid "Toggle shuffle mode" msgstr "재생/일시정지 토글(Toggle) 모드" #: ../quodlibet/qltk/playorder.py:270 #, fuzzy msgid "Toggle repeat mode" msgstr "재생/일시정지 토글(Toggle) 모드" #: ../quodlibet/qltk/pluginwin.py:44 msgid "Plugin Errors" msgstr "플러그인 에러" #: ../quodlibet/qltk/pluginwin.py:124 msgid "Enabled" msgstr "" #: ../quodlibet/qltk/pluginwin.py:125 #, fuzzy msgid "Disabled" msgstr "브라우저 비활성" #: ../quodlibet/qltk/pluginwin.py:131 msgid "No category" msgstr "" #: ../quodlibet/qltk/pluginwin.py:169 msgid "Events" msgstr "" #: ../quodlibet/qltk/pluginwin.py:170 #, fuzzy msgid "Play Order" msgstr "재생순서:" #: ../quodlibet/qltk/pluginwin.py:171 #, fuzzy msgid "Editing" msgstr "태그 편집" #: ../quodlibet/qltk/pluginwin.py:173 #, fuzzy msgid "Covers" msgstr "총 크기:" #: ../quodlibet/qltk/pluginwin.py:309 msgid "No plugins found." msgstr "발견된 플러그인이 없습니다" #: ../quodlibet/qltk/pluginwin.py:358 #, fuzzy msgid "Plugins" msgstr "플러그인" #: ../quodlibet/qltk/pluginwin.py:402 msgid "Show _Errors" msgstr "에러 보이기" #: ../quodlibet/qltk/prefs.py:45 msgid "_Disc" msgstr "디스크" #: ../quodlibet/qltk/prefs.py:46 msgid "_Track" msgstr "트랙" #: ../quodlibet/qltk/prefs.py:47 #, fuzzy msgid "Grou_ping" msgstr "그룹" #: ../quodlibet/qltk/prefs.py:50 msgid "Al_bum" msgstr "앨범" #: ../quodlibet/qltk/prefs.py:55 msgid "_Filename" msgstr "파일이름" #: ../quodlibet/qltk/prefs.py:57 msgid "_Length" msgstr "길이" #: ../quodlibet/qltk/prefs.py:64 msgid "_Jump to playing song automatically" msgstr "자동으로 현재 재생중인 노래로 가기" #: ../quodlibet/qltk/prefs.py:66 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:82 msgid "_Others:" msgstr "_Others:" #: ../quodlibet/qltk/prefs.py:88 #, fuzzy msgid "_Edit…" msgstr "_Edit Display..." #: ../quodlibet/qltk/prefs.py:91 msgid "Add or remove additional column headers" msgstr "" #: ../quodlibet/qltk/prefs.py:101 msgid "Visible Columns" msgstr "칼럼 표시" #: ../quodlibet/qltk/prefs.py:104 msgid "Title includes _version" msgstr "버전을 포함하는 제목" #: ../quodlibet/qltk/prefs.py:106 #, fuzzy msgid "Artist includes all _people" msgstr "버전을 포함하는 제목" #: ../quodlibet/qltk/prefs.py:108 #, fuzzy msgid "Album includes _disc subtitle" msgstr "파트(part)를 포함하는 앨범" #: ../quodlibet/qltk/prefs.py:110 msgid "Filename includes _folder" msgstr "폴더를 포함하는 파일이름" #: ../quodlibet/qltk/prefs.py:123 #, fuzzy msgid "Column Preferences" msgstr "설정" #: ../quodlibet/qltk/prefs.py:129 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "" #: ../quodlibet/qltk/prefs.py:142 ../quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "노래 목록" #: ../quodlibet/qltk/prefs.py:222 #, fuzzy msgid "Edit Columns" msgstr "칼럼 표시" #: ../quodlibet/qltk/prefs.py:259 msgid "Duration totals" msgstr "" #: ../quodlibet/qltk/prefs.py:271 msgid "_Global filter:" msgstr "전역 필터:" #: ../quodlibet/qltk/prefs.py:277 msgid "Apply this query in addition to all others" msgstr "" #. Translators: The heading of the preference group, no action #: ../quodlibet/qltk/prefs.py:283 #, fuzzy msgctxt "heading" msgid "Search" msgstr "검색" #: ../quodlibet/qltk/prefs.py:287 ../quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "브라우저" #: ../quodlibet/qltk/prefs.py:293 msgid "Confirm _multiple ratings" msgstr "" #: ../quodlibet/qltk/prefs.py:295 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "" #: ../quodlibet/qltk/prefs.py:298 msgid "Enable _one-click ratings" msgstr "" #: ../quodlibet/qltk/prefs.py:300 #, 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:306 ../quodlibet/qltk/prefs.py:616 #, fuzzy msgid "Ratings" msgstr "재생율" #. Filename choice algorithm config #: ../quodlibet/qltk/prefs.py:312 msgid "Prefer _embedded art" msgstr "" #: ../quodlibet/qltk/prefs.py:314 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" #: ../quodlibet/qltk/prefs.py:319 msgid "_Fixed image filename:" msgstr "" #: ../quodlibet/qltk/prefs.py:321 msgid "The single image filename to use if selected" msgstr "" #: ../quodlibet/qltk/prefs.py:327 msgid "The album art image file to use when forced" msgstr "" #: ../quodlibet/qltk/prefs.py:336 #, fuzzy msgid "Album Art" msgstr "앨범 목록" #: ../quodlibet/qltk/prefs.py:357 #, fuzzy msgid "Playback" msgstr "연주 일시정지" #: ../quodlibet/qltk/prefs.py:362 msgid "Output Configuration" msgstr "" #: ../quodlibet/qltk/prefs.py:373 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" #: ../quodlibet/qltk/prefs.py:376 msgid "_Fall-back gain (dB):" msgstr "" #: ../quodlibet/qltk/prefs.py:387 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "" #: ../quodlibet/qltk/prefs.py:390 msgid "_Pre-amp gain (dB):" msgstr "" #: ../quodlibet/qltk/prefs.py:395 #, fuzzy msgid "_Enable Replay Gain volume adjustment" msgstr "_Replay Gain volume adjustment" #: ../quodlibet/qltk/prefs.py:420 #, fuzzy msgid "Replay Gain Volume Adjustment" msgstr "_Replay Gain volume adjustment" #: ../quodlibet/qltk/prefs.py:450 msgid "_Default rating:" msgstr "" #: ../quodlibet/qltk/prefs.py:493 #, fuzzy msgid "Rating _scale:" msgstr "재생율" #: ../quodlibet/qltk/prefs.py:542 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:547 msgid "_Bayesian averaging amount:" msgstr "" #: ../quodlibet/qltk/prefs.py:556 #, fuzzy msgid "Save ratings and play _counts" msgstr "Save ratings and play counts" #: ../quodlibet/qltk/prefs.py:560 msgid "_Email:" msgstr "전자메일:" #: ../quodlibet/qltk/prefs.py:562 msgid "Ratings and play counts will be set for this email address" msgstr "Ratings and play counts will be set for this email address" #: ../quodlibet/qltk/prefs.py:577 #, fuzzy msgid "Auto-save tag changes" msgstr "변경된 태그를 버릴까요?" #: ../quodlibet/qltk/prefs.py:579 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "" #: ../quodlibet/qltk/prefs.py:587 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:610 #, fuzzy msgid "Tags" msgstr "태그 편집:" #: ../quodlibet/qltk/prefs.py:631 #, fuzzy msgid "Updating for new ratings" msgstr "새 방송국" #: ../quodlibet/qltk/prefs.py:641 #, fuzzy msgid "Scan library _on start" msgstr "라이브러리 새로고침" #: ../quodlibet/qltk/prefs.py:651 ../quodlibet/qltk/quodlibetwindow.py:1100 #, fuzzy msgid "_Scan Library" msgstr "라이브러리 검색" #: ../quodlibet/qltk/prefs.py:653 ../quodlibet/qltk/quodlibetwindow.py:1162 msgid "Check for changes in your library" msgstr "라이브러리 변경 체크" #: ../quodlibet/qltk/prefs.py:658 #, fuzzy msgid "Re_build Library" msgstr "라이브러리 새로불러오기" #: ../quodlibet/qltk/prefs.py:661 #, fuzzy msgid "Reload all songs in your library. This can take a long time." msgstr "라이브러리의 모든 노래를 새로불러오기" #: ../quodlibet/qltk/prefs.py:671 #, fuzzy msgid "Scan Directories" msgstr "디렉토리 스캔" #: ../quodlibet/qltk/prefs.py:677 #, fuzzy msgid "Hidden Songs" msgstr "No Songs" #: ../quodlibet/qltk/properties.py:158 ../quodlibet/util/collection.py:398 #, 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" #: ../quodlibet/qltk/properties.py:162 ../quodlibet/qltk/properties.py:164 msgid "Properties" msgstr "등록정보" #: ../quodlibet/qltk/queue.py:101 msgid "_Queue" msgstr "대기열" #: ../quodlibet/qltk/queue.py:126 msgid "Stop Once Empty" msgstr "" #: ../quodlibet/qltk/queue.py:130 #, fuzzy msgid "_Clear Queue" msgstr "플러그인 에러" #: ../quodlibet/qltk/queue.py:242 #, 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:198 msgid "_Browse Library" msgstr "라이브러리 브라우저" #: ../quodlibet/qltk/quodlibetwindow.py:395 #, fuzzy msgid "Toggle queue visibility" msgstr "메인 창 표시 토글(Toggle)" #: ../quodlibet/qltk/quodlibetwindow.py:516 #, fuzzy msgid "Playback Error" msgstr "연주 일시정지" #: ../quodlibet/qltk/quodlibetwindow.py:524 #, fuzzy msgid "Set up library directories?" msgstr "디렉토리 선택" #: ../quodlibet/qltk/quodlibetwindow.py:525 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:531 msgid "_Not Now" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:532 msgid "_Set Up" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:956 msgid "Unable to add songs" msgstr "노래를 추가할 수 없습니다" #: ../quodlibet/qltk/quodlibetwindow.py:957 #: ../quodlibet/qltk/quodlibetwindow.py:1364 #, fuzzy, python-format msgid "%s uses an unsupported protocol." msgstr "<b>%s</b> 는 지원하지 않는 프로토콜을 사용하고 있습니다." #: ../quodlibet/qltk/quodlibetwindow.py:980 msgid "_Jump to Playing Song" msgstr "현재 재생중인 노래로 가기" #: ../quodlibet/qltk/quodlibetwindow.py:986 #, fuzzy msgid "_File" msgstr "파일" #: ../quodlibet/qltk/quodlibetwindow.py:987 #, fuzzy msgid "_Song" msgstr "노래" #: ../quodlibet/qltk/quodlibetwindow.py:988 msgid "_View" msgstr "보기" #: ../quodlibet/qltk/quodlibetwindow.py:989 #, fuzzy msgid "_Browse" msgstr "브라우저" #: ../quodlibet/qltk/quodlibetwindow.py:990 msgid "_Control" msgstr "조정" #: ../quodlibet/qltk/quodlibetwindow.py:991 msgid "_Help" msgstr "도움말" #: ../quodlibet/qltk/quodlibetwindow.py:997 #, fuzzy msgid "_Add a Folder…" msgstr "폴더 추가..." #: ../quodlibet/qltk/quodlibetwindow.py:1002 #, fuzzy msgid "_Add a File…" msgstr "파일 추가..." #: ../quodlibet/qltk/quodlibetwindow.py:1007 #, fuzzy msgid "_Add a Location…" msgstr "주소 추가" #: ../quodlibet/qltk/quodlibetwindow.py:1036 #, fuzzy msgid "Edit Bookmarks…" msgstr "북마크 편집" #: ../quodlibet/qltk/quodlibetwindow.py:1056 #, fuzzy msgid "Stop After This Song" msgstr "이 노래 후 정지" #: ../quodlibet/qltk/quodlibetwindow.py:1062 msgid "_Keyboard Shortcuts" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:1071 msgid "Online Help" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:1080 #, fuzzy msgid "Search Help" msgstr "검색" #: ../quodlibet/qltk/quodlibetwindow.py:1352 msgid "Add a Location" msgstr "주소 추가" #: ../quodlibet/qltk/quodlibetwindow.py:1353 msgid "Enter the location of an audio file:" msgstr "오디오 파일의 주소를 입력하십시오:" #: ../quodlibet/qltk/quodlibetwindow.py:1358 #: ../quodlibet/qltk/quodlibetwindow.py:1363 msgid "Unable to add location" msgstr "주소를 추가할 수 없습니다" #: ../quodlibet/qltk/quodlibetwindow.py:1359 #, fuzzy, python-format msgid "%s is not a valid location." msgstr "<b>%s</b> 는 유효하지 않은 주소입니다." #: ../quodlibet/qltk/quodlibetwindow.py:1372 #: ../quodlibet/qltk/quodlibetwindow.py:1381 msgid "Add Music" msgstr "음악 추가" #: ../quodlibet/qltk/quodlibetwindow.py:1372 ../quodlibet/qltk/scanbox.py:99 #, fuzzy msgid "_Add Folders" msgstr "폴더 추가..." #: ../quodlibet/qltk/quodlibetwindow.py:1379 #, fuzzy msgid "Music Files" msgstr "음악 재생기" #: ../quodlibet/qltk/quodlibetwindow.py:1381 #, fuzzy msgid "_Add Files" msgstr "파일 추가..." #: ../quodlibet/qltk/ratingsmenu.py:24 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "" #: ../quodlibet/qltk/ratingsmenu.py:26 msgid "The saved ratings will be removed" msgstr "" #: ../quodlibet/qltk/ratingsmenu.py:27 #, python-format msgid "The rating of all selected songs will be changed to '%s'" msgstr "" #: ../quodlibet/qltk/ratingsmenu.py:57 ../quodlibet/qltk/ratingsmenu.py:111 #, fuzzy msgid "_Remove Rating" msgstr "재생율" #: ../quodlibet/qltk/ratingsmenu.py:98 #, fuzzy msgid "Change _Rating" msgstr "재생율" #: ../quodlibet/qltk/renamefiles.py:46 msgid "Replace spaces with _underscores" msgstr "Replace spaces with _underscores" #: ../quodlibet/qltk/renamefiles.py:56 msgid "Strip _Windows-incompatible characters" msgstr "Strip _Windows-incompatible characters" #: ../quodlibet/qltk/renamefiles.py:74 msgid "Strip _diacritical marks" msgstr "Strip _diacritical marks" #: ../quodlibet/qltk/renamefiles.py:85 msgid "Strip non-_ASCII characters" msgstr "Strip non-_ASCII characters" #: ../quodlibet/qltk/renamefiles.py:95 msgid "Use only _lowercase characters" msgstr "" #: ../quodlibet/qltk/renamefiles.py:123 msgid "Rename Files" msgstr "파일이름 바꾸기" #: ../quodlibet/qltk/renamefiles.py:139 ../quodlibet/qltk/tagsfrompath.py:116 #, fuzzy msgid "Path Patterns" msgstr "양식" #: ../quodlibet/qltk/renamefiles.py:140 ../quodlibet/qltk/tagsfrompath.py:117 #, fuzzy msgid "Edit saved patterns…" msgstr "저장된 값 편집..." #: ../quodlibet/qltk/renamefiles.py:143 ../quodlibet/qltk/tagsfrompath.py:120 #: ../quodlibet/qltk/tracknumbers.py:58 msgid "_Preview" msgstr "미리보기" #: ../quodlibet/qltk/renamefiles.py:190 msgid "New Name" msgstr "새 이름" #: ../quodlibet/qltk/renamefiles.py:255 msgid "Unable to rename file" msgstr "파일이름 변경을 할 수 없습니다" #: ../quodlibet/qltk/renamefiles.py:256 #, fuzzy, python-format msgid "" "Renaming <b>%(old-name)s</b> to <b>%(new-name)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." msgstr "" "<b>%s</b> 를 <b>%s</b> 로 이름 변경을 할 수 없습니다. 변경하려는목적지 파일" "이 이미 존재하거나 파일로의 접근이 거부되었습니다." #: ../quodlibet/qltk/renamefiles.py:264 #, fuzzy msgid "Ignore _All Errors" msgstr "에러 보이기" #: ../quodlibet/qltk/renamefiles.py:267 msgid "_Continue" msgstr "계속" #: ../quodlibet/qltk/renamefiles.py:296 msgid "Path is not absolute" msgstr "절대경로가 아닙니다" #: ../quodlibet/qltk/renamefiles.py:297 #, python-format msgid "" "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 ~/." msgstr "" "아래 양식\n" "\t<b>%s</b>\n" "는 root 에서 시작하지않은 / 를포함하고 있습니다.폴더의 잘못된 이름을 피하려" "면, / 또는 ~/ 으로 시작하는 양식을취하십시오." #: ../quodlibet/qltk/scanbox.py:47 #, 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:99 msgid "Select Directories" msgstr "디렉토리 선택" #: ../quodlibet/qltk/searchbar.py:52 #, fuzzy msgid "Saved Searches" msgstr "저장된 값" #: ../quodlibet/qltk/searchbar.py:53 #, fuzzy msgid "Edit saved searches…" msgstr "저장된 값 편집..." #: ../quodlibet/qltk/searchbar.py:74 msgid "Search your library, using free text or QL queries" msgstr "" #: ../quodlibet/qltk/searchbar.py:129 #, fuzzy msgid "Search after _typing" msgstr "이 노래 후 정지" #: ../quodlibet/qltk/searchbar.py:132 msgid "Show search results after the user stops typing." msgstr "" #: ../quodlibet/qltk/searchbar.py:187 msgid "_Limit:" msgstr "제한:" #: ../quodlibet/qltk/searchbar.py:200 msgid "_Weight" 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 ../quodlibet/qltk/shortcuts.py:41 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: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:377 #, python-format msgid "_Filter on %s" msgstr "_Filter on %s" #: ../quodlibet/qltk/songlist.py:1094 #, fuzzy msgid "All _Headers" msgstr "_Album Headers" #: ../quodlibet/qltk/songlist.py:1095 msgid "_Track Headers" msgstr "_Track Headers" #: ../quodlibet/qltk/songlist.py:1096 msgid "_Album Headers" msgstr "_Album Headers" #: ../quodlibet/qltk/songlist.py:1097 msgid "_People Headers" msgstr "_People Headers" #: ../quodlibet/qltk/songlist.py:1098 msgid "_Date Headers" msgstr "_Date Headers" #: ../quodlibet/qltk/songlist.py:1099 msgid "_File Headers" msgstr "_File Headers" #: ../quodlibet/qltk/songlist.py:1100 msgid "_Production Headers" msgstr "_Production Headers" #: ../quodlibet/qltk/songlist.py:1115 #, fuzzy msgid "_Customize Headers…" msgstr "_Customize Headers..." #: ../quodlibet/qltk/songlist.py:1120 msgid "_Expand Column" msgstr "" #: ../quodlibet/qltk/songsmenu.py:36 #, 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:64 #, 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:149 #, fuzzy msgid "Configure Plugins…" msgstr "검색 용어에 색깔" #: ../quodlibet/qltk/songsmenu.py:345 msgid "Add to _Queue" msgstr "대기열 추가" #: ../quodlibet/qltk/songsmenu.py:368 msgid "_Copy to Device" msgstr "" #: ../quodlibet/qltk/songsmenu.py:379 #, fuzzy msgid "_Remove from Library" msgstr "재생목록으로부터 제거" #: ../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:101 msgid "Tags From Path" msgstr "Tags From Path" #: ../quodlibet/qltk/tagsfrompath.py:138 msgid "Tags replace existing ones" msgstr "Tags replace existing ones" #: ../quodlibet/qltk/tagsfrompath.py:139 msgid "Tags are added to existing ones" msgstr "Tags are added to existing ones" #. Save button #: ../quodlibet/qltk/tagsfrompath.py:153 msgid "Save" msgstr "" #: ../quodlibet/qltk/tagsfrompath.py:195 #, python-format msgid "" "The pattern\n" "\t<b>%s</b>\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/tagsfrompath.py:216 msgid "Invalid tags" msgstr "유효하지 않은 태그" #: ../quodlibet/qltk/tagsfrompath.py:217 #, 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" "지금 선택한 파일은 이러한 태그의 편집을 지원하지 않습니다." #: ../quodlibet/qltk/textedit.py:142 #, 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:158 msgid "Edit Display" msgstr "Edit Display" #: ../quodlibet/qltk/tracknumbers.py:39 msgid "Track Numbers" msgstr "트랙 번호" #: ../quodlibet/qltk/tracknumbers.py:42 msgid "Start fro_m:" msgstr "시작:" #: ../quodlibet/qltk/tracknumbers.py:51 msgid "_Total tracks:" msgstr "총 트랙:" #: ../quodlibet/qltk/unity.py:52 #, fuzzy msgid "Play/Pause" msgstr "재생기" #: ../quodlibet/qltk/unity.py:75 #, fuzzy msgid "Previous" msgstr "미리보기" #: ../quodlibet/qltk/views.py:923 #, fuzzy, python-format msgid "and %d more…" msgstr "and %d more..." #: ../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:89 #, fuzzy msgid "Checking for Updates" msgstr "마운트 지점 확인" #: ../quodlibet/update.py:124 #, fuzzy msgid "Connection failed" msgstr "주소" #: ../quodlibet/update.py:133 #, python-format msgid "You are already using the newest version %(version)s" msgstr "" #: ../quodlibet/update.py:136 #, 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:420 msgid "Playlists must have a name" msgstr "" #: ../quodlibet/util/collection.py:603 #, python-format msgid "A playlist named %s already exists." msgstr "%s 재생목록은 이미 존재합니다." #: ../quodlibet/util/cover/built_in.py:26 #, fuzzy msgid "Embedded album covers" msgstr "앨범 표지 보이기" #: ../quodlibet/util/cover/built_in.py:27 msgid "Uses covers embedded into audio files." msgstr "" #: ../quodlibet/util/cover/built_in.py:49 #, fuzzy msgid "Filesystem cover" msgstr "파일 시스템" #: ../quodlibet/util/cover/built_in.py:50 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "" #: ../quodlibet/util/__init__.py:93 msgid "Display brief usage information" msgstr "사용 정보 개요 표시" #: ../quodlibet/util/__init__.py:95 msgid "Display version and copyright" msgstr "버전 및 저작권 표시" #: ../quodlibet/util/__init__.py:135 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "" #: ../quodlibet/util/__init__.py:137 msgid "[options]" msgstr "[옵션]" #: ../quodlibet/util/__init__.py:182 #, fuzzy, python-format msgid "Option %r not recognized." msgstr "에러: '%s' 는 알 수 없는 옵션입니다." #: ../quodlibet/util/__init__.py:185 #, fuzzy, python-format msgid "Option %r requires an argument." msgstr "에러: '%s' 는 인자를 요구하는 옵션입니다." #: ../quodlibet/util/__init__.py:188 #, fuzzy, python-format msgid "%r is not a unique prefix." msgstr "에러: '%s' 는 유일한 prefix 가 아닙니다." #: ../quodlibet/util/__init__.py:364 #, python-format msgid "%d kbps" msgstr "%d kbps" #: ../quodlibet/util/__init__.py:419 #, fuzzy, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%d 초" #: ../quodlibet/util/__init__.py:432 msgid "No time information" msgstr "정보에 시간이 없습니다" #: ../quodlibet/util/__init__.py:435 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d 초" #: ../quodlibet/util/__init__.py:436 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d 분" #: ../quodlibet/util/__init__.py:437 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d 시간" #: ../quodlibet/util/__init__.py:438 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d 일" #: ../quodlibet/util/__init__.py:439 #, 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:563 #, 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 msgid "Unable to edit song" msgstr "노래를 편집할 수 없습니다" #: ../quodlibet/util/songwrapper.py:113 #, python-format msgid "" "Saving <b>%s</b> 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:34 #: ../quodlibet/util/string/__init__.py:44 msgid "[Invalid Encoding]" msgstr "[유효하지 않은 인코딩]" #: ../quodlibet/util/tags.py:74 msgid "album" msgstr "앨범" #: ../quodlibet/util/tags.py:75 msgid "arranger" msgstr "편곡" #: ../quodlibet/util/tags.py:75 msgid "arrangers" msgstr "편곡" #: ../quodlibet/util/tags.py:75 #, fuzzy msgid "arrangement" msgstr "편곡" #: ../quodlibet/util/tags.py:77 msgid "author" msgstr "작가" #: ../quodlibet/util/tags.py:77 msgid "authors" msgstr "작가" #: ../quodlibet/util/tags.py:78 msgid "composer" msgstr "작곡" #: ../quodlibet/util/tags.py:78 msgid "composers" msgstr "작곡" #: ../quodlibet/util/tags.py:78 #, fuzzy msgid "composition" msgstr "작곡" #. Translators: conducting as in conducting a musical performance #: ../quodlibet/util/tags.py:80 msgid "conductor" msgstr "지휘" #: ../quodlibet/util/tags.py:80 msgid "conductors" msgstr "지휘" #: ../quodlibet/util/tags.py:80 #, fuzzy msgid "conducting" msgstr "지휘" #: ../quodlibet/util/tags.py:81 msgid "contact" msgstr "연락" #: ../quodlibet/util/tags.py:82 msgid "copyright" msgstr "저작권" #: ../quodlibet/util/tags.py:83 msgid "date" msgstr "날짜" #: ../quodlibet/util/tags.py:84 msgid "description" msgstr "설명" #: ../quodlibet/util/tags.py:85 msgid "genre" msgstr "장르" #: ../quodlibet/util/tags.py:85 #, fuzzy msgid "genres" msgstr "장르" #: ../quodlibet/util/tags.py:86 msgid "performer" msgstr "연주" #: ../quodlibet/util/tags.py:87 msgid "grouping" msgstr "그룹" #: ../quodlibet/util/tags.py:88 msgid "language" msgstr "언어" #: ../quodlibet/util/tags.py:89 msgid "license" msgstr "라이센스" #: ../quodlibet/util/tags.py:90 msgid "location" msgstr "주소" #: ../quodlibet/util/tags.py:91 msgid "lyricist" msgstr "작사" #: ../quodlibet/util/tags.py:91 msgid "lyricists" msgstr "작사" #: ../quodlibet/util/tags.py:91 #, fuzzy msgid "lyrics" msgstr "작사" #. Translators: Also e.g. "record label", "publisher" #: ../quodlibet/util/tags.py:93 msgid "organization" msgstr "조직" #: ../quodlibet/util/tags.py:94 msgid "title" msgstr "제목" #: ../quodlibet/util/tags.py:95 msgid "version" msgstr "버전" #: ../quodlibet/util/tags.py:96 msgid "website" msgstr "웹사이트" #: ../quodlibet/util/tags.py:98 msgid "album artist" msgstr "앨범 아티스트" #: ../quodlibet/util/tags.py:99 msgid "BPM" msgstr "BPM" #. Translators: This used to be called "part". #: ../quodlibet/util/tags.py:102 ../quodlibet/util/tags.py:103 msgid "disc subtitle" msgstr "" #: ../quodlibet/util/tags.py:104 ../quodlibet/util/tags.py:141 msgid "disc" msgstr "디스크" #: ../quodlibet/util/tags.py:105 ../quodlibet/util/tags.py:143 msgid "track" msgstr "트랙" #: ../quodlibet/util/tags.py:106 msgid "label ID" msgstr "라벨 ID" #: ../quodlibet/util/tags.py:107 msgid "original release date" msgstr "오리지널 출시 날짜" #: ../quodlibet/util/tags.py:108 msgid "original album" msgstr "오리지널 앨범" #: ../quodlibet/util/tags.py:109 msgid "original artist" msgstr "오리지널 아티스트" #: ../quodlibet/util/tags.py:110 msgid "recording date" msgstr "녹음 날짜" #: ../quodlibet/util/tags.py:111 msgid "release country" 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:120 #, fuzzy msgid "MusicBrainz recording ID" msgstr "MusicBrainz track ID" #: ../quodlibet/util/tags.py:121 #, fuzzy msgid "MusicBrainz release track ID" msgstr "MusicBrainz track ID" #: ../quodlibet/util/tags.py:122 #, fuzzy msgid "MusicBrainz release ID" msgstr "MusicBrainz track ID" #: ../quodlibet/util/tags.py:123 #, fuzzy msgid "MusicBrainz artist ID" msgstr "MusicBrainz artist ID" #: ../quodlibet/util/tags.py:124 #, fuzzy msgid "MusicBrainz release artist ID" msgstr "MusicBrainz track ID" #: ../quodlibet/util/tags.py:125 msgid "MusicBrainz TRM ID" msgstr "MusicBrainz TRM ID" #: ../quodlibet/util/tags.py:126 msgid "MusicIP PUID" msgstr "MusicIP PUID" #: ../quodlibet/util/tags.py:127 msgid "MusicBrainz album status" msgstr "MusicBrainz album status" #: ../quodlibet/util/tags.py:128 msgid "MusicBrainz album type" msgstr "MusicBrainz album type" #: ../quodlibet/util/tags.py:129 #, fuzzy msgid "MusicBrainz release group ID" msgstr "MusicBrainz track ID" #. Translators: "gain" means a volume adjustment, not "to acquire". #: ../quodlibet/util/tags.py:132 msgid "track gain" msgstr "track gain" #: ../quodlibet/util/tags.py:133 msgid "track peak" msgstr "track peak" #. Translators: "gain" means a volume adjustment, not "to acquire". #: ../quodlibet/util/tags.py:135 msgid "album gain" msgstr "album gain" #: ../quodlibet/util/tags.py:136 msgid "album peak" msgstr "album peak" #: ../quodlibet/util/tags.py:137 #, fuzzy msgid "reference loudness" msgstr "설정" #: ../quodlibet/util/tags.py:142 msgid "discs" msgstr "디스크" #: ../quodlibet/util/tags.py:144 msgid "tracks" msgstr "트랙" #: ../quodlibet/util/tags.py:145 msgid "last started" msgstr "마지막 시작" #: ../quodlibet/util/tags.py:146 msgid "full name" msgstr "성명(FullName)" #: ../quodlibet/util/tags.py:153 msgid "mount point" msgstr "마운트 지점" #: ../quodlibet/util/tags.py:155 msgid "people" msgstr "가수" #: ../quodlibet/util/tags.py:157 msgid "year" msgstr "년" #: ../quodlibet/util/tags.py:158 #, fuzzy msgid "original release year" msgstr "오리지널 출시 날짜" #: ../quodlibet/util/tags.py:159 #, fuzzy msgid "bookmark" msgstr "북마크" #: ../quodlibet/util/tags.py:162 #, fuzzy msgid "file format" msgstr "포맷" #: ../quodlibet/util/tags.py:165 #, fuzzy msgid "playlists" msgstr "재생목록" #: ../quodlibet/util/tags.py:166 msgid "channel count" msgstr "" #. Translators: e.g. "artist (sort)" #: ../quodlibet/util/tags.py:256 msgid "sort" msgstr "" #. Translators: e.g. "performer (roles)" #: ../quodlibet/util/tags.py:264 msgid "roles" msgstr "" #, fuzzy #~ msgid "browsers" #~ msgstr "브라우저" #~ msgid "Unable to download lyrics." #~ msgstr "가사를 내려받을 수 없습니다" #~ msgid "Remove all songs from the queue" #~ msgstr "대기열의 모든 노래 지우기" #~ msgid "Watch this folder for new songs" #~ 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 "Unable to open input files" #~ 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 "_Select" #~ 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 "Choose New Stations" #~ msgstr "새 방송국을 선택하십시오" #~ msgid "Add" #~ msgstr "추가" #, fuzzy #~ msgid "Bitrate" #~ msgstr "비트율" #~ msgid "_Stations..." #~ msgstr "방송국..." #, fuzzy #~ msgid "Quod Libet" #~ msgstr "Quod Libet 마침" #~ 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9671857 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/po/lt.po����������������������������������������������������������������������������0000644�0001750�0001750�00000550221�00000000000�014100� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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: 2017-05-17 18:58+0200\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" #: ../data/exfalso.appdata.xml.in.h:1 ../data/exfalso.desktop.in.h:2 msgid "Edit tags in your audio files" msgstr "Redaguoti Jūsų garso failų žymes" #: ../data/exfalso.appdata.xml.in.h:2 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/exfalso.appdata.xml.in.h:3 ../data/quodlibet.appdata.xml.in.h:3 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/exfalso.desktop.in.h:1 msgid "Audio tag editor" msgstr "Garso žymių redaktorius" #: ../data/quodlibet.appdata.xml.in.h:1 ../data/quodlibet.desktop.in.h:2 msgid "Listen to, browse, or edit your audio collection" msgstr "Klausykite, naršykite ar redaguokite savo muzikos kolekciją" #: ../data/quodlibet.appdata.xml.in.h:2 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 "" #: ../data/quodlibet.desktop.in.h:1 msgid "Music Player" msgstr "Muzikos grotuvas" #: ../quodlibet/browsers/albums/main.py:168 #: ../quodlibet/browsers/covergrid/main.py:54 msgid "_Title" msgstr "Pa_vadinimas" #: ../quodlibet/browsers/albums/main.py:169 #: ../quodlibet/browsers/covergrid/main.py:55 ../quodlibet/qltk/prefs.py:49 msgid "_Artist" msgstr "_Atlikėjas" #: ../quodlibet/browsers/albums/main.py:170 #: ../quodlibet/browsers/covergrid/main.py:56 ../quodlibet/qltk/prefs.py:54 msgid "_Date" msgstr "_Data" #: ../quodlibet/browsers/albums/main.py:171 #: ../quodlibet/browsers/covergrid/main.py:57 ../quodlibet/qltk/prefs.py:53 msgid "_Genre" msgstr "_Žanras" #: ../quodlibet/browsers/albums/main.py:172 #: ../quodlibet/browsers/covergrid/main.py:58 ../quodlibet/qltk/prefs.py:58 #: ../quodlibet/qltk/ratingsmenu.py:39 msgid "_Rating" msgstr "Į_vertis" #: ../quodlibet/browsers/albums/main.py:178 #: ../quodlibet/browsers/covergrid/main.py:64 #, fuzzy msgid "Sort _by…" msgstr "Rikiuoti _pagal..." #: ../quodlibet/browsers/albums/main.py:199 #: ../quodlibet/browsers/covergrid/main.py:85 #: ../quodlibet/browsers/paned/prefs.py:166 #: ../quodlibet/browsers/playlists/main.py:629 #: ../quodlibet/qltk/exfalsowindow.py:109 ../quodlibet/qltk/pluginwin.py:341 #: ../quodlibet/qltk/quodlibetwindow.py:1016 msgid "_Preferences" msgstr "_Nuostatos" #: ../quodlibet/browsers/albums/main.py:361 msgid "Album List" msgstr "Albumų sąrašas" #: ../quodlibet/browsers/albums/main.py:362 msgid "_Album List" msgstr "_Albumų sąrašas" #: ../quodlibet/browsers/albums/main.py:472 #: ../quodlibet/browsers/covergrid/main.py:279 #: ../quodlibet/browsers/covergrid/main.py:488 msgid "All Albums" msgstr "Visi albumai" #: ../quodlibet/browsers/albums/main.py:473 #: ../quodlibet/browsers/covergrid/main.py:280 #: ../quodlibet/browsers/covergrid/main.py:489 #, 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:650 #: ../quodlibet/browsers/covergrid/main.py:467 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:381 ../quodlibet/util/collection.py:245 #, 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:379 ../quodlibet/util/collection.py:249 #, 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:120 #, fuzzy msgid "Options" msgstr "[pasirinktys]" #: ../quodlibet/browsers/albums/prefs.py:74 #: ../quodlibet/browsers/covergrid/prefs.py:123 msgid "Album Display" msgstr "Albumo vaizdas" #: ../quodlibet/browsers/albums/prefs.py:78 #: ../quodlibet/browsers/covergrid/prefs.py:127 #: ../quodlibet/browsers/media.py:39 #: ../quodlibet/browsers/playlists/prefs.py:56 #: ../quodlibet/ext/songsmenu/albumart.py:326 #: ../quodlibet/ext/songsmenu/duplicates.py:350 #: ../quodlibet/ext/songsmenu/filterall.py:48 #: ../quodlibet/qltk/bookmarks.py:101 ../quodlibet/qltk/cbes.py:93 #: ../quodlibet/qltk/data_editors.py:99 ../quodlibet/qltk/data_editors.py:324 #: ../quodlibet/qltk/exfalsowindow.py:297 ../quodlibet/qltk/pluginwin.py:79 #: ../quodlibet/qltk/pluginwin.py:427 ../quodlibet/qltk/prefs.py:707 #: ../quodlibet/qltk/textedit.py:164 ../quodlibet/update.py:148 msgid "_Close" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:55 #: ../quodlibet/browsers/audiofeeds.py:67 #: ../quodlibet/browsers/audiofeeds.py:69 #: ../quodlibet/browsers/audiofeeds.py:159 #: ../quodlibet/browsers/paned/models.py:86 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:46 #: ../quodlibet/formats/_audio.py:495 ../quodlibet/order/__init__.py:27 #: ../quodlibet/qltk/information.py:240 ../quodlibet/qltk/information.py:247 #: ../quodlibet/qltk/information.py:273 ../quodlibet/qltk/wlw.py:70 msgid "Unknown" msgstr "Nežinoma" #: ../quodlibet/browsers/audiofeeds.py:246 msgid "New Feed" msgstr "Naujas kanalas" #: ../quodlibet/browsers/audiofeeds.py:247 msgid "Enter the location of an audio feed:" msgstr "Įveskite garso kanalo vietą:" #: ../quodlibet/browsers/audiofeeds.py:248 #: ../quodlibet/browsers/collection/prefs.py:90 #: ../quodlibet/browsers/iradio.py:341 ../quodlibet/browsers/paned/prefs.py:78 #: ../quodlibet/browsers/playlists/menu.py:96 #: ../quodlibet/browsers/playlists/util.py:52 ../quodlibet/qltk/bookmarks.py:62 #: ../quodlibet/qltk/cbes.py:55 ../quodlibet/qltk/data_editors.py:311 #: ../quodlibet/qltk/edittags.py:288 ../quodlibet/qltk/edittags.py:488 #: ../quodlibet/qltk/quodlibetwindow.py:1354 ../quodlibet/qltk/scanbox.py:61 msgid "_Add" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:265 msgid "Audio Feeds" msgstr "Audio kanalai" #: ../quodlibet/browsers/audiofeeds.py:266 msgid "_Audio Feeds" msgstr "_Audio kanalai" #: ../quodlibet/browsers/audiofeeds.py:345 #: ../quodlibet/browsers/audiofeeds.py:350 #, fuzzy msgid "_Download…" msgstr "_Atsisiųsti" #: ../quodlibet/browsers/audiofeeds.py:359 msgid "Download Files" msgstr "Atsiųsti failus" #. Save button #: ../quodlibet/browsers/audiofeeds.py:359 #: ../quodlibet/browsers/audiofeeds.py:371 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:81 #: ../quodlibet/ext/songsmenu/albumart.py:322 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:355 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:278 #: ../quodlibet/ext/songsmenu/html.py:76 #: ../quodlibet/ext/songsmenu/lastfmsync.py:216 #: ../quodlibet/ext/songsmenu/playlist.py:51 #: ../quodlibet/ext/songsmenu/replaygain.py:365 #: ../quodlibet/ext/songsmenu/tapbpm.py:182 ../quodlibet/qltk/_editutils.py:39 #: ../quodlibet/qltk/lyrics.py:38 ../quodlibet/qltk/msg.py:52 #: ../quodlibet/qltk/renamefiles.py:168 ../quodlibet/qltk/tracknumbers.py:113 msgid "_Save" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:371 msgid "Download File" msgstr "Atsiųsti failą" #: ../quodlibet/browsers/audiofeeds.py:394 #: ../quodlibet/browsers/playlists/main.py:213 #: ../quodlibet/qltk/data_editors.py:96 msgid "_New" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:454 #: ../quodlibet/browsers/audiofeeds.py:513 msgid "Unable to add feed" msgstr "Negalima pridėti kanalo" #: ../quodlibet/browsers/audiofeeds.py:455 #: ../quodlibet/browsers/audiofeeds.py:514 #, fuzzy, python-format msgid "" "%s could not be added. The server may be down, or the location may not be an " "audio feed." msgstr "" "<b>%s</b> negali būti pridėta. Serveris gali neveikti arba nurodyta vieta " "nėra garso kanalas." #. refresh button #: ../quodlibet/browsers/audiofeeds.py:462 ../quodlibet/browsers/media.py:217 #: ../quodlibet/browsers/media.py:386 ../quodlibet/qltk/filesel.py:259 #: ../quodlibet/qltk/pluginwin.py:413 #, fuzzy msgid "_Refresh" msgstr "Atnaujinti biblioteką" #: ../quodlibet/browsers/audiofeeds.py:463 #: ../quodlibet/browsers/playlists/main.py:457 #: ../quodlibet/browsers/playlists/util.py:43 ../quodlibet/qltk/delete.py:143 #: ../quodlibet/qltk/filesel.py:256 ../quodlibet/qltk/lyrics.py:39 #: ../quodlibet/qltk/maskedbox.py:28 ../quodlibet/qltk/songsmenu.py:392 #, fuzzy msgid "_Delete" msgstr "Ištrinti failus" #: ../quodlibet/browsers/audiofeeds.py:530 msgid "" "The current audio backend does not support URLs, Audio Feeds browser " "disabled." msgstr "" "Dabartinė garso posistemė nepalaiko URL adresų. Audio kanalų naršyklė " "išjungta." #: ../quodlibet/browsers/_base.py:147 ../quodlibet/browsers/_base.py:150 msgid "Library Browser" msgstr "Bibliotekos naršyklė" #: ../quodlibet/browsers/_base.py:274 ../quodlibet/ext/songsmenu/refresh.py:30 #: ../quodlibet/qltk/exfalsowindow.py:241 ../quodlibet/qltk/information.py:542 #: ../quodlibet/qltk/maskedbox.py:68 ../quodlibet/util/collection.py:527 #, 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:402 ../quodlibet/browsers/_base.py:407 #: ../quodlibet/qltk/tagsfrompath.py:194 ../quodlibet/qltk/textedit.py:141 #: ../quodlibet/util/__init__.py:622 msgid "Invalid pattern" msgstr "Netaisyklingas šablonas" #: ../quodlibet/browsers/collection/main.py:78 msgid "Album Collection" msgstr "Albumų kolekcija" #: ../quodlibet/browsers/collection/main.py:79 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:66 #: ../quodlibet/browsers/paned/prefs.py:51 msgid "_Custom" msgstr "_Individualus" #. Remove button #: ../quodlibet/browsers/collection/prefs.py:94 #: ../quodlibet/browsers/paned/prefs.py:82 #: ../quodlibet/browsers/playlists/menu.py:97 #: ../quodlibet/ext/playlist/remove_duplicates.py:60 #: ../quodlibet/qltk/bookmarks.py:97 ../quodlibet/qltk/bookmarks.py:127 #: ../quodlibet/qltk/cbes.py:82 ../quodlibet/qltk/cbes.py:89 #: ../quodlibet/qltk/data_editors.py:81 ../quodlibet/qltk/data_editors.py:94 #: ../quodlibet/qltk/data_editors.py:301 ../quodlibet/qltk/data_editors.py:314 #: ../quodlibet/qltk/data_editors.py:322 ../quodlibet/qltk/edittags.py:494 #: ../quodlibet/qltk/edittags.py:634 ../quodlibet/qltk/maskedbox.py:48 #: ../quodlibet/qltk/maskedbox.py:88 ../quodlibet/qltk/queue.py:350 #: ../quodlibet/qltk/scanbox.py:36 ../quodlibet/qltk/scanbox.py:63 #, fuzzy msgid "_Remove" msgstr "Pašalinti pasikartojančias dainas" #: ../quodlibet/browsers/collection/prefs.py:122 #: ../quodlibet/ext/songsmenu/filterall.py:34 #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:92 #: ../quodlibet/qltk/edittags.py:431 msgid "Tag" msgstr "Žymė" #: ../quodlibet/browsers/collection/prefs.py:128 msgid "Merge" msgstr "Sulieti" #: ../quodlibet/browsers/collection/prefs.py:188 msgid "Album Collection Preferences" msgstr "Albumų sąrašo nuostatos" #: ../quodlibet/browsers/collection/prefs.py:195 #: ../quodlibet/browsers/paned/prefs.py:209 #: ../quodlibet/ext/songsmenu/editplaycount.py:45 #: ../quodlibet/ext/songsmenu/exact_rating.py:38 #: ../quodlibet/player/gstbe/prefs.py:40 ../quodlibet/qltk/prefs.py:127 #: ../quodlibet/qltk/textedit.py:65 msgid "_Apply" msgstr "" #: ../quodlibet/browsers/collection/prefs.py:198 #: ../quodlibet/browsers/paned/prefs.py:213 #: ../quodlibet/browsers/playlists/menu.py:95 #: ../quodlibet/browsers/playlists/util.py:42 #: ../quodlibet/errorreport/ui.py:108 #: ../quodlibet/ext/playlist/export_to_folder.py:37 #: ../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:44 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:281 #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:88 #: ../quodlibet/ext/songsmenu/importexport.py:35 #: ../quodlibet/ext/songsmenu/lastfmsync.py:215 #: ../quodlibet/ext/songsmenu/playlist.py:50 #: ../quodlibet/ext/songsmenu/replaygain.py:364 #: ../quodlibet/ext/songsmenu/tapbpm.py:181 ../quodlibet/plugins/playlist.py:39 #: ../quodlibet/qltk/chooser.py:184 ../quodlibet/qltk/chooser.py:205 #: ../quodlibet/qltk/chooser.py:229 ../quodlibet/qltk/chooser.py:253 #: ../quodlibet/qltk/delete.py:90 ../quodlibet/qltk/delete.py:133 #: ../quodlibet/qltk/edittags.py:287 ../quodlibet/qltk/_editutils.py:38 #: ../quodlibet/qltk/getstring.py:28 ../quodlibet/qltk/maskedbox.py:27 #: ../quodlibet/qltk/msg.py:54 ../quodlibet/qltk/msg.py:93 #: ../quodlibet/qltk/ratingsmenu.py:33 ../quodlibet/qltk/songsmenu.py:45 #: ../quodlibet/qltk/songsmenu.py:73 ../quodlibet/update.py:94 msgid "_Cancel" msgstr "" #: ../quodlibet/browsers/covergrid/main.py:125 #, fuzzy msgid "Cover Grid" msgstr "Visas dydis:" #: ../quodlibet/browsers/covergrid/main.py:126 #, 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:71 #, fuzzy msgid "Show \"All Albums\" Item" msgstr "Visi albumai" #: ../quodlibet/browsers/covergrid/prefs.py:78 msgid "Vertical Split" msgstr "" #: ../quodlibet/browsers/covergrid/prefs.py:110 #: ../quodlibet/browsers/covergrid/prefs.py:111 #, fuzzy msgid "Cover Magnification" msgstr "organizacija" #: ../quodlibet/browsers/filesystem.py:40 msgid "File System" msgstr "Failų sistema" #: ../quodlibet/browsers/filesystem.py:41 msgid "_File System" msgstr "_Failų sistema" #: ../quodlibet/browsers/filesystem.py:113 ../quodlibet/browsers/media.py:491 #: ../quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "Negalima kopijuoti dainų" #: ../quodlibet/browsers/filesystem.py:114 ../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:189 msgid "_Add to Library" msgstr "_Pridėti į biblioteką" #: ../quodlibet/browsers/iradio.py:178 msgid "Unsupported file type" msgstr "Nepalaikomas failo tipas" #: ../quodlibet/browsers/iradio.py:179 #, 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:219 ../quodlibet/browsers/iradio.py:232 #: ../quodlibet/browsers/iradio.py:810 msgid "Unable to add station" msgstr "Negalima pridėti stoties" #: ../quodlibet/browsers/iradio.py:243 ../quodlibet/browsers/iradio.py:471 msgid "Internet Radio" msgstr "Interneto radijas" #: ../quodlibet/browsers/iradio.py:243 msgid "Downloading station list" msgstr "Atsiunčiamas stočių sąrašas" #: ../quodlibet/browsers/iradio.py:339 msgid "New Station" msgstr "Nauja stotis" #: ../quodlibet/browsers/iradio.py:340 msgid "Enter the location of an Internet radio station:" msgstr "Įveskite Interneto radijo stočių adresą:" #: ../quodlibet/browsers/iradio.py:358 msgid "Electronic" msgstr "Elektroninė" #: ../quodlibet/browsers/iradio.py:361 msgid "Hip Hop / Rap" msgstr "Hiphopas / Repas" #: ../quodlibet/browsers/iradio.py:362 msgid "Oldies" msgstr "Senesnė muzika" #: ../quodlibet/browsers/iradio.py:363 msgid "R&B" msgstr "R&B" #: ../quodlibet/browsers/iradio.py:364 msgid "Japanese" msgstr "Japonų" #: ../quodlibet/browsers/iradio.py:365 msgid "Indian" msgstr "Indų" #: ../quodlibet/browsers/iradio.py:367 msgid "Religious" msgstr "Religinė" #: ../quodlibet/browsers/iradio.py:369 msgid "Charts" msgstr "Topai" #: ../quodlibet/browsers/iradio.py:370 msgid "Turkish" msgstr "Turkų" #: ../quodlibet/browsers/iradio.py:371 msgid "Reggae / Dancehall" msgstr "Regis / „Šokių salės“ regis" #: ../quodlibet/browsers/iradio.py:372 msgid "Latin" msgstr "Lotynų" #: ../quodlibet/browsers/iradio.py:373 msgid "College Radio" msgstr "Koledžų radijo stotys" #: ../quodlibet/browsers/iradio.py:374 msgid "Talk / News" msgstr "Pokalbiai / Žinios" #: ../quodlibet/browsers/iradio.py:375 msgid "Ambient" msgstr "Ambientinė" #: ../quodlibet/browsers/iradio.py:376 msgid "Jazz" msgstr "Džiazas" #: ../quodlibet/browsers/iradio.py:377 ../quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "Klasikinė" #: ../quodlibet/browsers/iradio.py:378 ../quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "Pop" #: ../quodlibet/browsers/iradio.py:379 msgid "Alternative" msgstr "Alternatyvioji" #: ../quodlibet/browsers/iradio.py:380 msgid "Metal" msgstr "Metalas" #: ../quodlibet/browsers/iradio.py:381 msgid "Country" msgstr "Kantri" #: ../quodlibet/browsers/iradio.py:382 msgid "News" msgstr "Žinios" #: ../quodlibet/browsers/iradio.py:383 msgid "Schlager" msgstr "Šlageriai" #: ../quodlibet/browsers/iradio.py:384 msgid "Funk" msgstr "Fank" #: ../quodlibet/browsers/iradio.py:385 msgid "Indie" msgstr "Indie" #: ../quodlibet/browsers/iradio.py:386 msgid "Blues" msgstr "Bliuzas" #: ../quodlibet/browsers/iradio.py:387 msgid "Soul" msgstr "Soul" #: ../quodlibet/browsers/iradio.py:388 msgid "Lounge" msgstr "Lounge" #: ../quodlibet/browsers/iradio.py:389 msgid "Punk" msgstr "Pank" #: ../quodlibet/browsers/iradio.py:390 msgid "Reggaeton" msgstr "Regetonas" #: ../quodlibet/browsers/iradio.py:392 msgid "Slavic" msgstr "Slavų" #: ../quodlibet/browsers/iradio.py:394 msgid "Greek" msgstr "Graikų" #: ../quodlibet/browsers/iradio.py:395 msgid "Gothic" msgstr "Gotikinė" #: ../quodlibet/browsers/iradio.py:396 ../quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "Rokas" #: ../quodlibet/browsers/iradio.py:449 msgid "Would you like to load a list of popular radio stations?" msgstr "" #: ../quodlibet/browsers/iradio.py:455 #, fuzzy msgid "_Load Stations" msgstr "_Atnaujinti stotis" #: ../quodlibet/browsers/iradio.py:472 msgid "_Internet Radio" msgstr "_Interneto radijas" #: ../quodlibet/browsers/iradio.py:538 #, fuzzy msgid "_New Station…" msgstr "Nauja stotis" #: ../quodlibet/browsers/iradio.py:541 msgid "_Update Stations" msgstr "_Atnaujinti stotis" #: ../quodlibet/browsers/iradio.py:568 msgid "All Stations" msgstr "Visos stotys" #. TODO: support for ~#rating=!None etc (#1940) #: ../quodlibet/browsers/iradio.py:572 #: ../quodlibet/browsers/soundcloud/main.py:64 msgid "Favorites" msgstr "Mėgstamiausios" #: ../quodlibet/browsers/iradio.py:580 msgid "No Category" msgstr "Be kategorijos" #: ../quodlibet/browsers/iradio.py:802 msgid "No stations found" msgstr "Nerasta stočių" #: ../quodlibet/browsers/iradio.py:803 #, python-format msgid "No Internet radio stations were found at %s." msgstr "Jokių Interneto radijo stočių nerasta %s." #: ../quodlibet/browsers/iradio.py:811 msgid "All stations listed are already in your library." msgstr "Visos šios stotys jau yra Jūsų bibliotekoje." #: ../quodlibet/browsers/iradio.py:828 msgid "Add to Favorites" msgstr "Pridėti prie Mėgstamiausių" #: ../quodlibet/browsers/iradio.py:832 msgid "Remove from Favorites" msgstr "Pašalinti iš Mėgstamiausių" #: ../quodlibet/browsers/iradio.py:932 #, 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/media.py:36 msgid "Device Properties" msgstr "Įrenginio savybės" #: ../quodlibet/browsers/media.py:52 msgid "Device:" msgstr "Įrenginys:" #: ../quodlibet/browsers/media.py:54 msgid "Not mounted" msgstr "Neprijungtas" #: ../quodlibet/browsers/media.py:55 #, fuzzy msgid "Mount point:" msgstr "Prijungimo taškas:" #: ../quodlibet/browsers/media.py:61 ../quodlibet/qltk/cbes.py:40 msgid "_Name:" msgstr "_Vardas:" #: ../quodlibet/browsers/media.py:135 msgid "Media Devices" msgstr "Medijos įrenginiai" #: ../quodlibet/browsers/media.py:136 msgid "_Media Devices" msgstr "_Medijos įrenginiai" #. eject button #: ../quodlibet/browsers/media.py:224 ../quodlibet/browsers/media.py:378 msgid "_Eject" msgstr "At_jungti" #: ../quodlibet/browsers/media.py:360 #, fuzzy msgid "_Properties" msgstr "Savybės" #: ../quodlibet/browsers/media.py:365 #: ../quodlibet/browsers/playlists/main.py:464 msgid "_Rename" msgstr "Per_vadinti" #: ../quodlibet/browsers/media.py:461 #, fuzzy, python-format msgid "%(used-size)s used, %(free-size)s available" msgstr "<b>%s</b> naudojama, <b>%s</b> prieinama" #: ../quodlibet/browsers/media.py:479 #, fuzzy, python-format msgid "%s is not connected." msgstr "<b>%s</b> nėra prijungtas." #: ../quodlibet/browsers/media.py:499 #, fuzzy, python-format msgid "Copying %(song)s" msgstr "Kopijuojama <b>%(song)s</b>" #: ../quodlibet/browsers/media.py:513 ../quodlibet/browsers/media.py:529 msgid "Unable to copy song" msgstr "Negalima kopijuoti dainos" #: ../quodlibet/browsers/media.py:514 msgid "There is not enough free space for this song." msgstr "Šiai dainai nepakanka laisvos vietos." #: ../quodlibet/browsers/media.py:526 #, fuzzy, python-format msgid "%s could not be copied." msgstr "<b>%s</b> nepavyko nukopijuoti." #: ../quodlibet/browsers/media.py:545 msgid "Unable to delete songs" msgstr "Negalima ištrinti dainų" #: ../quodlibet/browsers/media.py:557 #, fuzzy, python-format msgid "Deleting %(song)s" msgstr "Nepavyko ištrinti <b>%(song)s</b>." #: ../quodlibet/browsers/media.py:575 #, fuzzy, python-format msgid "%s could not be deleted." msgstr "Nepavyko ištrinti „<b>%s</b>“." #: ../quodlibet/browsers/media.py:579 msgid "Unable to delete song" msgstr "Negalima ištrinti dainos" #: ../quodlibet/browsers/media.py:594 #, fuzzy, python-format msgid "Ejecting %s failed." msgstr "Nepavyko atjungti <b>%s</b>." #: ../quodlibet/browsers/media.py:597 msgid "Unable to eject device" msgstr "Negalima atjungti įrenginio" #: ../quodlibet/browsers/media.py:603 msgid "No device backend, Media Devices browser disabled." msgstr "" "Nerasta jokių įrenginių posistemių, įvairialypės terpės naršyklė išjungta." #: ../quodlibet/browsers/paned/main.py:40 ../quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "Langų naršyklė" #: ../quodlibet/browsers/paned/main.py:41 msgid "_Paned Browser" msgstr "_Langų naršyklė" #: ../quodlibet/browsers/paned/main.py:90 msgid "Select _All" msgstr "P_asirinkti viską" #: ../quodlibet/browsers/paned/models.py:104 ../quodlibet/qltk/pluginwin.py:122 #: ../quodlibet/qltk/pluginwin.py:164 msgid "All" msgstr "Viskas" #: ../quodlibet/browsers/paned/prefs.py:67 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "<tt>%s</tt>" msgstr "" #: ../quodlibet/browsers/paned/prefs.py:162 msgid "_Wide Mode" msgstr "" #: ../quodlibet/browsers/paned/prefs.py:197 msgid "Paned Browser Preferences" msgstr "Langų naršyklės nuostatos" #: ../quodlibet/browsers/paned/prefs.py:204 msgid "Equal pane width" msgstr "" #: ../quodlibet/browsers/playlists/main.py:48 #: ../quodlibet/browsers/playlists/main.py:575 #: ../quodlibet/qltk/pluginwin.py:168 msgid "Playlists" msgstr "Grojaraščiai" #: ../quodlibet/browsers/playlists/main.py:49 msgid "_Playlists" msgstr "_Grojaraščiai" #: ../quodlibet/browsers/playlists/main.py:152 msgid "_Remove from Playlist" msgstr "_Pašalinti iš grojaraščio" #: ../quodlibet/browsers/playlists/main.py:215 #: ../quodlibet/browsers/playlists/main.py:576 msgid "_Import" msgstr "_Importuoti" #: ../quodlibet/browsers/playlists/main.py:391 #: ../quodlibet/browsers/playlists/util.py:50 #: ../quodlibet/util/collection.py:570 msgid "New Playlist" msgstr "Naujas grojaraštis" #: ../quodlibet/browsers/playlists/main.py:413 msgid "Unable to import playlist" msgstr "Negalima importuoti grojaraščio" #: ../quodlibet/browsers/playlists/main.py:414 msgid "Quod Libet can only import playlists in the M3U and PLS formats." msgstr "Quod Libet gali importuoti tik M3U ir PLS formato grojaraščius." #: ../quodlibet/browsers/playlists/main.py:565 msgid "Unable to rename playlist" msgstr "Negalima pervadinti grojaraščio" #: ../quodlibet/browsers/playlists/main.py:576 msgid "Import Playlist" msgstr "Importuoti grojaraštį" #: ../quodlibet/browsers/playlists/menu.py:25 #, fuzzy msgid "_New Playlist…" msgstr "_Naujas grojaraštis" #: ../quodlibet/browsers/playlists/menu.py:86 #, 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:90 #, 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:33 #, 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:35 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:51 msgid "Enter a name for the new playlist:" msgstr "Įveskite naujo grojaraščio pavadinimą:" #: ../quodlibet/browsers/playlists/util.py:102 #, 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/search.py:33 msgid "_Limit Results" msgstr "Ap_riboti rezultatus" #: ../quodlibet/browsers/search.py:48 msgid "Search Library" msgstr "Paieška bibliotekoje" #: ../quodlibet/browsers/search.py:49 msgid "_Search Library" msgstr "Pa_ieška bibliotekoje" #: ../quodlibet/browsers/soundcloud/main.py:38 #, fuzzy msgid "Soundcloud Browser" msgstr "Langų naršyklė" #: ../quodlibet/browsers/soundcloud/main.py:39 msgid "Sound_cloud" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:59 #: ../quodlibet/qltk/searchbar.py:73 msgid "Search" msgstr "Ieškoti" #: ../quodlibet/browsers/soundcloud/main.py:136 #, python-format msgid "Go to %s" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:380 #, fuzzy msgid "Connected" msgstr "vieta" #: ../quodlibet/browsers/soundcloud/main.py:381 #, python-format msgid "Quod Libet is now connected, <b>%s</b>!" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:393 #, python-format msgid "Log out of %s" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:395 msgid "Enter code…" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:396 #, python-format msgid "Log in to %s" msgstr "" #: ../quodlibet/browsers/soundcloud/util.py:86 msgid "Soundcloud authorisation" msgstr "" #: ../quodlibet/browsers/soundcloud/util.py:87 msgid "Enter Soundcloud auth code:" msgstr "" #: ../quodlibet/cli.py:50 #, fuzzy msgid "Quod Libet is not running (add '--run' to start it)" msgstr "Quod Libet nėra paleistas." #: ../quodlibet/cli.py:85 msgid "a music library and player" msgstr "muzikos biblioteka ir grotuvas" #: ../quodlibet/cli.py:86 msgid "[option]" msgstr "[pasirinktis]" #: ../quodlibet/cli.py:88 msgid "Print the playing song and exit" msgstr "Parašyti dabar grojamos dainos pavadinimą ir išeiti" #: ../quodlibet/cli.py:89 msgid "Begin playing immediately" msgstr "Iškart pradėti groti" #: ../quodlibet/cli.py:90 msgid "Don't show any windows on start" msgstr "" #: ../quodlibet/cli.py:93 msgid "Jump to next song" msgstr "Peršokti į kitą dainą" #: ../quodlibet/cli.py:95 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:96 msgid "Jump to previous song" msgstr "Peršokti į praėjusią dainą" #: ../quodlibet/cli.py:97 msgid "Start playback" msgstr "Pradėti grojimą" #: ../quodlibet/cli.py:98 msgid "Pause playback" msgstr "Pristabdyti grojimą" #: ../quodlibet/cli.py:99 msgid "Toggle play/pause mode" msgstr "Perjungti grojimo/pauzės režimą" #: ../quodlibet/cli.py:100 msgid "Stop playback" msgstr "Sustabdyti grojimą" #: ../quodlibet/cli.py:101 msgid "Turn up volume" msgstr "Pagarsinti" #: ../quodlibet/cli.py:102 msgid "Turn down volume" msgstr "Pritildyti" #: ../quodlibet/cli.py:103 msgid "Print player status" msgstr "Parašyti apie grotuvo būseną" #: ../quodlibet/cli.py:104 msgid "Hide main window" msgstr "Slėpti pagrindinį langą" #: ../quodlibet/cli.py:105 msgid "Show main window" msgstr "Rodyti pagrindinį langą" #: ../quodlibet/cli.py:106 msgid "Toggle main window visibility" msgstr "Perjungti pagrindinio lango matomumą" #: ../quodlibet/cli.py:107 msgid "Focus the running player" msgstr "Fokusuoti grojantį grotuvą" #: ../quodlibet/cli.py:108 msgid "Remove active browser filters" msgstr "Naikinti aktyvius naršyklių filtrus" #: ../quodlibet/cli.py:109 msgid "Refresh and rescan library" msgstr "Atnaujinti biblioteką" #: ../quodlibet/cli.py:110 #, fuzzy msgid "List available browsers" msgstr "Išjungti naršyklę" #: ../quodlibet/cli.py:111 msgid "Print the current playlist" msgstr "Parašyti dabartinį grojaraštį" #: ../quodlibet/cli.py:112 msgid "Print the contents of the queue" msgstr "Parašyti eilės turinį" #: ../quodlibet/cli.py:113 #, fuzzy msgid "Print the active text query" msgstr "Parašyti eilės turinį" #: ../quodlibet/cli.py:114 msgid "Start without plugins" msgstr "Paleisti be įskiepių" #: ../quodlibet/cli.py:115 #, fuzzy msgid "Start Quod Libet if it isn't running" msgstr "Quod Libet nėra paleistas." #: ../quodlibet/cli.py:116 msgid "Exit Quod Libet" msgstr "Išjungti Quod Libet" #: ../quodlibet/cli.py:121 msgid "Seek within the playing song" msgstr "Peršokti grojamoje dainoje" #: ../quodlibet/cli.py:121 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: ../quodlibet/cli.py:122 #, fuzzy msgid "Set or toggle shuffle mode" msgstr "Perjungti grojimo/pauzės režimą" #: ../quodlibet/cli.py:123 msgid "Turn repeat off, on, or toggle it" msgstr "Išjungti/įjungti kartojimo veikseną" #: ../quodlibet/cli.py:124 msgid "Set the volume" msgstr "Nustatyti garsumą" #: ../quodlibet/cli.py:125 msgid "Search your audio library" msgstr "Ieškoti jūsų garsų bibliotekoje" #: ../quodlibet/cli.py:125 ../quodlibet/cli.py:137 ../quodlibet/cli.py:141 #: ../quodlibet/cli.py:143 msgid "query" msgstr "užklausa" #: ../quodlibet/cli.py:126 msgid "Play a file" msgstr "Groti failą" #: ../quodlibet/cli.py:126 ../quodlibet/cli.py:137 ../quodlibet/cli.py:143 #, fuzzy msgctxt "command" msgid "filename" msgstr "failo vardas" #: ../quodlibet/cli.py:127 msgid "Rate the playing song" msgstr "Įvertinti grojamą dainą" #: ../quodlibet/cli.py:128 msgid "Set the current browser" msgstr "Nustatyti dabartinę naršyklę" #: ../quodlibet/cli.py:129 #, fuzzy msgid "Stop after the playing song" msgstr "Įvertinti grojamą dainą" #: ../quodlibet/cli.py:130 msgid "Open a new browser" msgstr "Atverti naują naršyklę" #: ../quodlibet/cli.py:131 msgid "Show or hide the queue" msgstr "Rodyti ar slepti eilę" #: ../quodlibet/cli.py:133 #, fuzzy msgid "Show or hide the main song list (deprecated)" msgstr "Rodyti ar slėpti pagrindinį dainų sąrašą" #: ../quodlibet/cli.py:134 msgid "Filter on a random value" msgstr "Filtruoti pagal atsitiktinę reikšmę" #: ../quodlibet/cli.py:134 #, fuzzy msgctxt "command" msgid "tag" msgstr "Žymė" #: ../quodlibet/cli.py:135 msgid "Filter on a tag value" msgstr "Filtruoti pagal žymės reikšmę" #: ../quodlibet/cli.py:135 msgid "tag=value" msgstr "žymė=reikšmė" #: ../quodlibet/cli.py:136 msgid "Enqueue a file or query" msgstr "Pridėti į eilę failą ar užklausą" #: ../quodlibet/cli.py:138 msgid "Enqueue comma-separated files" msgstr "Pridėti į eilę kableliu atskirtus failus" #: ../quodlibet/cli.py:139 ../quodlibet/util/tags.py:147 msgid "filename" msgstr "failo vardas" #: ../quodlibet/cli.py:140 msgid "Print filenames of results of query to stdout" msgstr "Spausdinti užklausų rezultatų failų vardus į standartinę išvestį" #: ../quodlibet/cli.py:142 msgid "Unqueue a file or query" msgstr "Pašalinti iš eilės failą ar užklausą" #: ../quodlibet/cli.py:203 #, python-format msgid "Invalid argument for '%s'." msgstr "Netaisyklingas „%s“ argumentas." #: ../quodlibet/cli.py:204 ../quodlibet/util/__init__.py:190 #, python-format msgid "Try %s --help." msgstr "Pamėginkite „%s“ --help." #: ../quodlibet/devices/_base.py:65 msgid "Unknown Device" msgstr "Nežinomas įrenginys" #: ../quodlibet/devices/__init__.py:32 #, python-format msgid "Could not import %s, which is needed for device support." msgstr "Nepavyko įkelti %s, kuri yra būtina įrenginio palaikymui." #: ../quodlibet/devices/__init__.py:153 #, python-format msgid "%r is not a supported device." msgstr "„%r“ nėra palaikomas įrenginys." #: ../quodlibet/devices/__init__.py:245 ../quodlibet/devices/__init__.py:251 #, fuzzy, python-format msgid "Could not find '%s'." msgstr "%s: Nepavyko rasti %s." #: ../quodlibet/devices/__init__.py:450 msgid "Initializing device backend." msgstr "Inicijuojama garso posistemė." #: ../quodlibet/devices/__init__.py:451 #, python-format msgid "Trying '%s'" msgstr "Bandoma '%s'" #: ../quodlibet/devices/__init__.py:461 msgid "Couldn't connect to a device backend." msgstr "Nepavyko prisijungti prie įrenginio posistemės." #: ../quodlibet/devices/__init__.py:463 msgid "Device backend initialized." msgstr "Įrenginio posistemė inicijuota." #: ../quodlibet/devices/storage.py:57 #, fuzzy msgid "_Filename pattern:" msgstr "Failo _vardo šablonas:" #: ../quodlibet/devices/storage.py:61 msgid "Copy _album covers" msgstr "Kopijuoti albumų _viršelius" #: ../quodlibet/devices/storage.py:65 msgid "_Remove unused covers and directories" msgstr "Šalinti nenaudojamus vi_ršelius bei aplankus" #: ../quodlibet/errorreport/ui.py:60 #, fuzzy msgid "An Error Occurred" msgstr "Įvyko klaida" #: ../quodlibet/errorreport/ui.py:62 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:72 msgid "File Bug Report" msgstr "" #: ../quodlibet/errorreport/ui.py:74 ../quodlibet/errorreport/ui.py:90 msgid "Submit Error Report" msgstr "" #: ../quodlibet/errorreport/ui.py:75 msgid "Quit Program" msgstr "" #: ../quodlibet/errorreport/ui.py:76 #, fuzzy msgid "Ignore Error" msgstr "Ignoruoti vis_as klaidas" #: ../quodlibet/errorreport/ui.py:80 msgid "Error details:" msgstr "" #: ../quodlibet/errorreport/ui.py:92 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:100 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "" #: ../quodlibet/errorreport/ui.py:109 msgid "_Send" msgstr "" #: ../quodlibet/errorreport/ui.py:115 #, fuzzy msgid "Short description…" msgstr "aprašymas" #: ../quodlibet/errorreport/ui.py:118 msgid "Data to be sent:" msgstr "" #: ../quodlibet/exfalso.py:34 msgid "an audio tag editor" msgstr "audio žymių redaktorius" #: ../quodlibet/exfalso.py:34 ../quodlibet/util/tags.py:148 msgid "directory" msgstr "aplankas" #: ../quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "" #: ../quodlibet/ext/covers/artwork_url.py:20 msgid "" "Downloads covers linked to by the artwork_url tag.This works with the " "Soundcloud browser." msgstr "" #: ../quodlibet/ext/covers/discogs.py:25 #, fuzzy msgid "Discogs Cover Source" msgstr "„MusicBrainz“ takelio ID" #: ../quodlibet/ext/covers/discogs.py:26 msgid "Downloads covers from Discogs." msgstr "" #: ../quodlibet/ext/covers/lastfm.py:22 msgid "Last.fm Cover Source" msgstr "" #: ../quodlibet/ext/covers/lastfm.py:23 msgid "Downloads covers from Last.fm's cover art archive." msgstr "" #: ../quodlibet/ext/covers/musicbrainz.py:19 #, fuzzy msgid "MusicBrainz Cover Source" msgstr "„MusicBrainz“ takelio ID" #: ../quodlibet/ext/covers/musicbrainz.py:20 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:25 msgid "Kana/Kanji Simple Inverter" msgstr "" #: ../quodlibet/ext/editing/kakasi.py:26 msgid "Converts kana/kanji to romaji before renaming." msgstr "" #: ../quodlibet/ext/editing/kakasi.py:35 msgid "Romanize _Japanese text" msgstr "" #: ../quodlibet/ext/editing/kakasi.py:63 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:19 msgid "" "Allows arbitrary regex substitutions (s///) 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:69 #, fuzzy msgid "Advanced Preferences" msgstr "Langų naršyklės nuostatos" #: ../quodlibet/ext/events/advanced_preferences.py:70 msgid "Allow editing of advanced config settings." msgstr "" #: ../quodlibet/ext/events/advanced_preferences.py:162 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:153 msgid "Top of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:154 msgid "Middle of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:155 msgid "Bottom of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:158 msgid "_Position:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:171 #, fuzzy msgid "_Cover size:" msgstr "Visas dydis:" #: ../quodlibet/ext/events/animosd/prefs.py:177 #: ../quodlibet/ext/events/lyricswindow.py:334 ../quodlibet/qltk/prefs.py:266 #, fuzzy msgid "Display" msgstr "Redaguoti rodymą" #: ../quodlibet/ext/events/animosd/prefs.py:190 msgid "_Font:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:195 msgid "Left" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:196 msgid "Center" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:197 #, fuzzy msgid "Right" msgstr "_Svoris" #: ../quodlibet/ext/events/animosd/prefs.py:200 msgid "_Align text:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:206 msgid "Text" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:217 msgid "_Text:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:227 msgid "_Fill:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:232 #: ../quodlibet/ext/events/synchronizedlyrics.py:63 msgid "Colors" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:240 msgid "_Shadows" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:241 #, fuzzy msgid "_Outline" msgstr "_Išvestis:" #: ../quodlibet/ext/events/animosd/prefs.py:242 msgid "Rou_nded Corners" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:258 msgid "_Delay:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:264 #: ../quodlibet/qltk/pluginwin.py:172 msgid "Effects" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:270 #, fuzzy msgid "Ed_it Display Pattern…" msgstr "Redaguoti rodomą informaciją" #: ../quodlibet/ext/events/animosd/prefs.py:274 #: ../quodlibet/ext/events/trayicon/prefs.py:78 #, fuzzy msgid "Preview" msgstr "Perž_iūra" #: ../quodlibet/ext/events/auto_library_update.py:136 msgid "Automatic Library Update" msgstr "" #: ../quodlibet/ext/events/auto_library_update.py:137 #, python-format msgid "Keeps your library up to date with inotify. Requires %s." msgstr "" #: ../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 by Brian Nelson." 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/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:97 msgid "Equalizer" msgstr "" #: ../quodlibet/ext/events/equalizer.py:98 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:132 #, 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:138 #, python-format msgid "%.1f kHz" msgstr "" #: ../quodlibet/ext/events/equalizer.py:139 #: ../quodlibet/ext/gstreamer/crossfeed.py:93 #: ../quodlibet/ext/gstreamer/karaoke.py:95 #, python-format msgid "%d Hz" msgstr "" #: ../quodlibet/ext/events/equalizer.py:173 #: ../quodlibet/ext/gstreamer/crossfeed.py:112 #, fuzzy, python-format msgid "%.1f dB" msgstr "%.1f sekundė" #: ../quodlibet/ext/events/equalizer.py:192 #: ../quodlibet/ext/gstreamer/crossfeed.py:31 #, fuzzy msgid "Custom" msgstr "_Individualus" #: ../quodlibet/ext/events/equalizer.py:199 #, fuzzy msgid "_Clear" msgstr "Valyti _klaidas" #. Translators: statuses relating to Instant Messenger apps #: ../quodlibet/ext/events/gajim_status.py:27 msgid "online" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:28 msgid "offline" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:29 msgid "chat" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:30 msgid "away" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:31 msgid "xa" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:32 msgid "invisible" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:37 msgid "Gajim Status Message" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:38 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:45 #: ../quodlibet/ext/events/telepathy_status.py:69 msgid "paused" 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:160 msgid "Add '[paused]'" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:163 msgid "If checked, '[paused]' will be added to status message on pause." msgstr "" #: ../quodlibet/ext/events/gajim_status.py:187 msgid "Statuses for which message will be changed" msgstr "" #: ../quodlibet/ext/events/headphonemon.py:156 msgid "Pause on Headphone Unplug" msgstr "" #: ../quodlibet/ext/events/headphonemon.py:157 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" #: ../quodlibet/ext/events/inhibit.py:41 msgid "Inhibit Screensaver" msgstr "" #: ../quodlibet/ext/events/inhibit.py:42 msgid "Prevents the GNOME screensaver from activating while a song is playing." msgstr "" #: ../quodlibet/ext/events/inhibit.py:51 #, fuzzy msgid "Music is playing" msgstr "Muzikos grotuvas" #: ../quodlibet/ext/events/iradiolog.py:16 #, fuzzy msgid "Internet Radio Log" msgstr "Interneto radijas" #: ../quodlibet/ext/events/iradiolog.py:17 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" #: ../quodlibet/ext/events/jep118.py:29 msgid "JEP-118" msgstr "" #: ../quodlibet/ext/events/jep118.py:30 msgid "Outputs a Jabber User Tunes file to ~/.quodlibet/jabber." 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 msgid "A restart is required for any changes to take effect" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:199 #, fuzzy msgid "No active song" msgstr "Negalima išsaugoti dainos" #: ../quodlibet/ext/events/lyricswindow.py:215 #, fuzzy msgid "No lyrics found" msgstr "Nerasta priedų." #: ../quodlibet/ext/events/lyricswindow.py:227 #, fuzzy msgid "Lyrics:" msgstr "Dainos žodžiai" #: ../quodlibet/ext/events/lyricswindow.py:284 msgid "_Zoom level:" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:302 msgid "URL:" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:307 msgid "Revert to default" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:322 msgid "Search via above URL if the lyrics couldn't be found in LyricsWikia." msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:339 #, fuzzy msgid "Alternate search" msgstr "Išvalyti paiešką" #: ../quodlibet/ext/events/lyricswindow.py:347 #, fuzzy msgid "Lyrics Window" msgstr "Dainos žodžiai" #: ../quodlibet/ext/events/lyricswindow.py:348 msgid "Shows a window containing lyrics of the playing song." msgstr "" #: ../quodlibet/ext/events/mediaserver.py:38 msgid "UPnP AV Media Server" msgstr "" #: ../quodlibet/ext/events/mediaserver.py:39 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." 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:39 msgid "" "Allows control of Quod Libet using the MPRIS 1.0/2.0 D-Bus Interface " "Specification." msgstr "" #: ../quodlibet/ext/events/mpris/__init__.py:45 #: ../quodlibet/ext/events/trayicon/prefs.py:30 #, fuzzy msgid "Hide main window on close" msgstr "Slėpti pagrindinį langą" #: ../quodlibet/ext/events/mpris/__init__.py:48 #: ../quodlibet/ext/events/themeswitcher.py:84 #: ../quodlibet/ext/gstreamer/compressor.py:99 #: ../quodlibet/ext/gstreamer/crossfeed.py:136 #: ../quodlibet/ext/gstreamer/karaoke.py:99 #: ../quodlibet/ext/gstreamer/pitch.py:83 ../quodlibet/qltk/prefs.py:688 msgid "Preferences" msgstr "Nuostatos" #: ../quodlibet/ext/events/mqtt.py:50 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/mqtt.py:56 msgid "MQTT Publisher" msgstr "" #: ../quodlibet/ext/events/mqtt.py:57 msgid "Publishes status messages to an MQTT topic." msgstr "" #: ../quodlibet/ext/events/mqtt.py:122 msgid "Broker hostname" msgstr "" #: ../quodlibet/ext/events/mqtt.py:122 msgid "broker hostname / IP" msgstr "" #: ../quodlibet/ext/events/mqtt.py:124 msgid "Broker port" msgstr "" #: ../quodlibet/ext/events/mqtt.py:124 msgid "broker port" msgstr "" #: ../quodlibet/ext/events/mqtt.py:126 msgid "Topic" msgstr "" #: ../quodlibet/ext/events/mqtt.py:128 #, fuzzy msgid "Playing Pattern" msgstr "Kelio šablonai" #: ../quodlibet/ext/events/mqtt.py:130 msgid "Status text when a song is started." msgstr "" #: ../quodlibet/ext/events/mqtt.py:132 #, fuzzy msgid "Paused Pattern" msgstr "Kelio šablonai" #: ../quodlibet/ext/events/mqtt.py:134 msgid "Text when a song is paused." msgstr "" #: ../quodlibet/ext/events/mqtt.py:136 #, fuzzy msgid "No-song Text" msgstr "%d daina" #: ../quodlibet/ext/events/mqtt.py:138 msgid "Plain text for when there is no current song" msgstr "" #: ../quodlibet/ext/events/mqtt.py:149 #, fuzzy msgid "MQTT Configuration" msgstr "Išvesties sąranka" #: ../quodlibet/ext/events/mqtt.py:153 #, fuzzy msgid "Status Text" msgstr "Kelio šablonai" #: ../quodlibet/ext/events/mqtt.py:185 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "" #: ../quodlibet/ext/events/mqtt.py:189 #, 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:192 #, fuzzy msgid "Connection error" msgstr "vieta" #: ../quodlibet/ext/events/notify.py:80 msgid "Notification text" msgstr "" #: ../quodlibet/ext/events/notify.py:88 #, fuzzy msgid "_Title:" msgstr "Pa_vadinimas" #: ../quodlibet/ext/events/notify.py:99 ../quodlibet/ext/events/notify.py:128 msgid "Revert to default pattern" msgstr "" #: ../quodlibet/ext/events/notify.py:118 msgid "_Body:" msgstr "" #: ../quodlibet/ext/events/notify.py:138 msgid "_Show notification" msgstr "" #: ../quodlibet/ext/events/notify.py:156 msgid "Show notifications" msgstr "" #: ../quodlibet/ext/events/notify.py:162 msgid "Only on <i>_manual</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:170 msgid "Only on <i>_automatic</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:178 msgid "On <i>a_ll</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:196 msgid "Only when the main window is not _focused" msgstr "" #: ../quodlibet/ext/events/notify.py:204 msgid "Show \"_Next\" button" msgstr "" #: ../quodlibet/ext/events/notify.py:236 msgid "Connection Error" msgstr "" #: ../quodlibet/ext/events/notify.py:237 ../quodlibet/ext/events/notify.py:391 #: ../quodlibet/ext/events/notify.py:433 #, fuzzy msgid "Couldn't connect to notification daemon." msgstr "Nepavyko prisijungti prie įrenginio posistemės." #: ../quodlibet/ext/events/notify.py:251 msgid "Song Notifications" msgstr "" #: ../quodlibet/ext/events/notify.py:252 msgid "Displays a notification when the song changes." msgstr "" #: ../quodlibet/ext/events/notify.py:415 ../quodlibet/qltk/unity.py:65 msgid "Next" msgstr "Kita" #: ../quodlibet/ext/events/qlscrobbler.py:178 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:254 #, fuzzy, python-format msgid "Could not contact service '%s'." msgstr "Nepavyko prisijungti prie įrenginio posistemės." #: ../quodlibet/ext/events/qlscrobbler.py:260 msgid "Authentication failed: invalid URL." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:277 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:282 msgid "Client is banned. Contact the author." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:286 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:351 msgid "AudioScrobbler Submission" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:352 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:450 msgid "Authentication successful." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:462 #, fuzzy msgid "_Service:" msgstr "Įrenginys:" #: ../quodlibet/ext/events/qlscrobbler.py:462 msgid "_URL:" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:462 #, fuzzy msgid "User_name:" msgstr "_Vardas:" #: ../quodlibet/ext/events/qlscrobbler.py:463 msgid "_Password:" msgstr "" #. Translators: Other service #: ../quodlibet/ext/events/qlscrobbler.py:479 #, fuzzy msgid "Other…" msgstr "_Kita:" #. verify data #: ../quodlibet/ext/events/qlscrobbler.py:517 msgid "_Verify account data" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:522 #: ../quodlibet/ext/songsmenu/lastfmsync.py:304 msgid "Account" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:530 #, fuzzy msgid "_Artist pattern:" msgstr "_Atlikėjas" #: ../quodlibet/ext/events/qlscrobbler.py:530 #, fuzzy msgid "_Title pattern:" msgstr "Failo _vardo šablonas:" #: ../quodlibet/ext/events/qlscrobbler.py:531 msgid "Exclude _filter:" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:549 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:559 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:568 msgid "Songs matching this filter will not be submitted." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:576 msgid "_Offline mode (don't submit anything)" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:580 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:27 #, fuzzy msgid "Random Album Playback" msgstr "Atsitiktinis a_lbumas" #: ../quodlibet/ext/events/randomalbum.py:28 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:38 msgid "Rated higher" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:39 msgid "Played more often" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:40 msgid "Skipped more often" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:41 msgid "Played more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:42 msgid "Started more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:43 msgid "Added more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:44 #, fuzzy msgid "Longer albums" msgstr "albumai" #: ../quodlibet/ext/events/randomalbum.py:83 msgid "seconds before starting next album" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:87 #, fuzzy msgid "Weights" msgstr "_Svoris" #: ../quodlibet/ext/events/randomalbum.py:89 msgid "Play some albums more than others" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:103 msgid "avoid" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:114 msgid "prefer" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:201 #, fuzzy msgid "Random Album" msgstr "Atsitiktinis a_lbumas" #: ../quodlibet/ext/events/randomalbum.py:202 #, python-format msgid "Waiting to start %s" msgstr "" #: ../quodlibet/ext/events/rbimport.py:114 #, fuzzy msgid "Import Failed" msgstr "Importuoti grojaraštį" #: ../quodlibet/ext/events/rbimport.py:119 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "" #: ../quodlibet/ext/events/rbimport.py:127 msgid "Rhythmbox Import" msgstr "" #: ../quodlibet/ext/events/rbimport.py:128 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "" #: ../quodlibet/ext/events/rbimport.py:132 #, fuzzy msgid "Start Import" msgstr "_Importuoti" #: ../quodlibet/ext/events/screensaver.py:25 msgid "Screensaver Pause" msgstr "" #: ../quodlibet/ext/events/screensaver.py:26 msgid "Pauses playback while the GNOME screensaver is active." msgstr "" #: ../quodlibet/ext/events/searchprovider.py:73 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "" #: ../quodlibet/ext/events/searchprovider.py:79 msgid "GNOME Search Provider" msgstr "" #: ../quodlibet/ext/events/searchprovider.py:80 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/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:29 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:57 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:58 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:34 #, fuzzy msgid "Synchronized Lyrics" msgstr "Dainos žodžiai" #: ../quodlibet/ext/events/synchronizedlyrics.py:35 msgid "Shows synchronized lyrics from .lrc file with same name as the track." msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:66 msgid "Text:" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:76 msgid "Background:" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:87 msgid "Font" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:90 msgid "Size (px):" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:62 msgid "Telepathy Status Messages" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:63 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:122 #, fuzzy msgid "Playing:" msgstr "Negrojama" #: ../quodlibet/ext/events/telepathy_status.py:123 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:139 msgid "Paused:" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:140 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:156 msgid "Plain text for status when there is no current song" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:157 #, fuzzy msgid "No song:" msgstr "%d daina" #. Frame #: ../quodlibet/ext/events/telepathy_status.py:164 #, 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/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:77 #: ../quodlibet/ext/events/trayicon/prefs.py:98 #: ../quodlibet/ext/events/trayicon/systemtray.py:177 #: ../quodlibet/qltk/info.py:47 msgid "Not playing" msgstr "Negrojama" #: ../quodlibet/ext/events/trayicon/__init__.py:53 msgid "Tray Icon" msgstr "" #: ../quodlibet/ext/events/trayicon/__init__.py:54 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:183 #: ../quodlibet/qltk/quodlibetwindow.py:1046 #: ../quodlibet/qltk/quodlibetwindow.py:1238 #, fuzzy msgid "_Play" msgstr "_Grojaraščiai" #: ../quodlibet/ext/events/trayicon/menu.py:63 #: ../quodlibet/qltk/quodlibetwindow.py:185 #: ../quodlibet/qltk/quodlibetwindow.py:1240 ../quodlibet/qltk/wlw.py:51 #, fuzzy msgid "P_ause" msgstr "Groti/Pristabdyti" #: ../quodlibet/ext/events/trayicon/menu.py:68 #: ../quodlibet/qltk/quodlibetwindow.py:190 #: ../quodlibet/qltk/quodlibetwindow.py:1041 #, fuzzy msgid "Pre_vious" msgstr "Ankstesnė" #: ../quodlibet/ext/events/trayicon/menu.py:71 #: ../quodlibet/qltk/quodlibetwindow.py:194 #: ../quodlibet/qltk/quodlibetwindow.py:1051 #, 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:1012 #, fuzzy msgid "Open _Browser" msgstr "Atverti naują naršyklę" #: ../quodlibet/ext/events/trayicon/menu.py:103 #: ../quodlibet/qltk/quodlibetwindow.py:1031 ../quodlibet/qltk/songsmenu.py:411 msgid "Edit _Tags" msgstr "_Redaguoti žymes" #: ../quodlibet/ext/events/trayicon/menu.py:112 #: ../quodlibet/qltk/quodlibetwindow.py:975 ../quodlibet/qltk/songsmenu.py:424 #, fuzzy msgid "_Information" msgstr "Informacija" #: ../quodlibet/ext/events/trayicon/menu.py:114 #: ../quodlibet/qltk/songsmenu.py:340 #, fuzzy msgid "Play_lists" msgstr "Grojaraščiai" #: ../quodlibet/ext/events/trayicon/menu.py:132 #: ../quodlibet/qltk/quodlibetwindow.py:1026 msgid "_Quit" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:32 ../quodlibet/qltk/prefs.py:69 msgid "Behavior" msgstr "Elgsena" #: ../quodlibet/ext/events/trayicon/prefs.py:42 msgid "Scroll wheel adjusts volume" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel changes song" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll _Wheel" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:84 #, fuzzy msgid "Tooltip Display" msgstr "Redaguoti rodomą informaciją" #: ../quodlibet/ext/events/viewlyrics.py:23 #, fuzzy msgid "View Lyrics" msgstr "Dainos žodžiai" #: ../quodlibet/ext/events/viewlyrics.py:24 msgid "Automatically displays lyrics beneath the song list in the main window." msgstr "" #: ../quodlibet/ext/events/viewlyrics.py:29 #, fuzzy msgid "_Lyrics" msgstr "Dainos žodžiai" #: ../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:406 #, fuzzy msgid "Waveform Seek Bar" msgstr "Alternatyvioji" #: ../quodlibet/ext/events/waveformseekbar.py:410 msgid "A seekbar in the shape of the waveform of the current song." msgstr "" #: ../quodlibet/ext/events/waveformseekbar.py:443 msgid "Override foreground color:" msgstr "" #: ../quodlibet/ext/events/write_cover.py:32 msgid "Picture Saver" msgstr "" #: ../quodlibet/ext/events/write_cover.py:33 msgid "Saves the cover image of the current song to a file." msgstr "" #: ../quodlibet/ext/events/write_cover.py:66 #, fuzzy msgid "File:" msgstr "Failų" #: ../quodlibet/ext/gstreamer/compressor.py:20 msgid "_Threshold:" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:21 msgid "Threshold until the filter is activated" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:22 msgid "R_atio:" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:22 msgid "Compression ratio" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:74 #: ../quodlibet/ext/gstreamer/karaoke.py:91 #, python-format msgid "%d %%" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:105 msgid "Audio Compressor" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:106 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:19 #, fuzzy msgid "_Preset:" msgstr "Perž_iūra" #: ../quodlibet/ext/gstreamer/crossfeed.py:19 #, fuzzy msgid "Filter preset" msgstr "Filtras _atlikėjui" #: ../quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Frequency cut:" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Low-pass filter cut frequency" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed _level:" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed level" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:25 #, fuzzy msgid "Default" msgstr "Numatytasis" #: ../quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Chu Moy" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Jan Meier" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:31 #, fuzzy msgid "Custom settings" msgstr "Individualizuotas rikiavimas" #: ../quodlibet/ext/gstreamer/crossfeed.py:152 msgid "Crossfeed" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:153 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:20 #, fuzzy msgid "Filter _band:" msgstr "Filtras _žanrui" #: ../quodlibet/ext/gstreamer/karaoke.py:21 msgid "The Frequency band of the filter" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:22 #, fuzzy msgid "Filter _width:" msgstr "Filtras _atlikėjui" #: ../quodlibet/ext/gstreamer/karaoke.py:23 msgid "The Frequency width of the filter" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:24 msgid "_Level:" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:24 msgid "Level of the effect" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:105 msgid "Karaoke" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:106 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:20 msgid "R_ate:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:21 msgid "_Tempo:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:22 msgid "_Pitch:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:89 #, fuzzy msgid "Audio Pitch / Speed" msgstr "Audio kanalai" #: ../quodlibet/ext/gstreamer/pitch.py:90 #, fuzzy msgid "Controls the pitch of an audio stream." msgstr "Įveskite garso kanalo vietą:" #: ../quodlibet/ext/playlist/export_to_folder.py:29 #: ../quodlibet/ext/playlist/export_to_folder.py:97 #: ../quodlibet/ext/playlist/export_to_folder.py:138 #, fuzzy msgid "Export Playlist to Folder" msgstr "Importuoti grojaraštį" #: ../quodlibet/ext/playlist/export_to_folder.py:38 #, fuzzy msgid "_Export" msgstr "_Importuoti" #: ../quodlibet/ext/playlist/export_to_folder.py:43 #, fuzzy msgid "Destination folder:" msgstr "Nerasta stočių" #: ../quodlibet/ext/playlist/export_to_folder.py:58 #, 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:156 #, fuzzy msgid "Default filename pattern:" msgstr "Failo _vardo šablonas:" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:23 msgid "Export to Squeezebox" msgstr "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:25 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 "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Export playlist to Squeezebox" msgstr "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:80 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 "" "Playback follows your selection, or the next song in the list once exhausted." msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:22 msgid "Playcount Equalizer" msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:23 msgid "Shuffle, preferring songs with fewer total plays." msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:25 #, fuzzy msgid "Prefer less played" msgstr "paskutinį kartą grota" #: ../quodlibet/ext/playorder/queue.py:19 #, fuzzy msgid "Queue Only" msgstr "Eilėje" #: ../quodlibet/ext/playorder/queue.py:21 msgid "" "Limits playing of songs to the queue. Select this play order in the main " "window, then double-clicking any song will enqueue it instead of playing." msgstr "" #: ../quodlibet/ext/playorder/reverse.py:14 #, fuzzy msgid "Reverse" msgstr "Niekada" #: ../quodlibet/ext/playorder/reverse.py:16 msgid "Reverses the play order of songs." msgstr "" #: ../quodlibet/ext/playorder/skip_songs.py:25 #, fuzzy msgid "Skip Songs" msgstr "Nėra dainų" #: ../quodlibet/ext/playorder/skip_songs.py:27 msgid "" "Playback skips over songs with a rating equal or below a given threshold." msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:30 msgid "Repeat Each Track" msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:32 msgid "Shuffle songs, but repeat every track a set number of times." msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:51 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. Syntax is '@(if: " "condition, then, else)'." msgstr "" #: ../quodlibet/ext/query/pythonexpression.py:14 msgid "Python Query" msgstr "" #: ../quodlibet/ext/query/pythonexpression.py:15 msgid "" "Use Python expressions in queries. Syntax is '@(python: expression)'. The " "variable 's' is the song being matched." msgstr "" #: ../quodlibet/ext/query/savedsearch.py:19 #, fuzzy msgid "Include Saved Search" msgstr "Išsaugotos paieškos reikšmės" #: ../quodlibet/ext/query/savedsearch.py:20 msgid "" "Include the results of a saved search as part of another query. Syntax is " "'@(saved: search name)'." 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:116 msgid "Port:" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:121 #, fuzzy msgid "Username:" msgstr "Per_vadinti" #: ../quodlibet/ext/_shared/squeezebox/base.py:126 msgid "Password:" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:130 msgid "Library directory the server connects to." msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:132 #, fuzzy msgid "Library path:" msgstr "Biblioteka" #. Add verify button #: ../quodlibet/ext/_shared/squeezebox/base.py:141 msgid "_Verify settings" msgstr "" #. Server settings Frame #: ../quodlibet/ext/_shared/squeezebox/base.py:147 msgid "Squeezebox Server" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:150 msgid "Debug" msgstr "Derinimas" #: ../quodlibet/ext/_shared/squeezebox/server.py:26 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:28 msgid "unidentified Squeezebox server" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:37 #, 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:20 #: ../quodlibet/ext/songsmenu/importexport.py:34 #: ../quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:329 #, fuzzy msgid "Fit image to _window" msgstr "Slėpti pagrindinį langą" #. Both labels #: ../quodlibet/ext/songsmenu/albumart.py:338 msgid "_Program:" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:343 msgid "_Edit image after saving" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:345 #, fuzzy msgid "File_name:" msgstr "Failo vardas" #: ../quodlibet/ext/songsmenu/albumart.py:457 msgid "Saving failed" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:458 #, fuzzy, python-format msgid "Unable to save \"%s\"." msgstr "Negalima išsaugoti dainos" #: ../quodlibet/ext/songsmenu/albumart.py:556 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:613 #, fuzzy msgid "Album Art Downloader" msgstr "Albumų viršeliai" #: ../quodlibet/ext/songsmenu/albumart.py:666 #, python-format msgid "from %(source)s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:669 #, python-format msgid "Resolution: %s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:672 #, fuzzy, python-format msgid "Size: %s" msgstr "Dydis" #: ../quodlibet/ext/songsmenu/albumart.py:690 #, fuzzy msgid "_Search" msgstr "_Paieška:" #: ../quodlibet/ext/songsmenu/albumart.py:741 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:451 #, fuzzy msgid "Searching…" msgstr "Ieškoti" #: ../quodlibet/ext/songsmenu/albumart.py:804 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:922 #, fuzzy msgid "Download Album Art" msgstr "Albumų viršeliai" #: ../quodlibet/ext/songsmenu/albumart.py:923 msgid "Downloads album covers from various websites." msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:936 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 #: ../quodlibet/qltk/downloader.py:52 msgid "Filename" msgstr "Failo vardas" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:130 #, fuzzy msgid "Disc" msgstr "_Diskas" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:131 #: ../quodlibet/ext/songsmenu/replaygain.py:404 #: ../quodlibet/qltk/tracknumbers.py:92 msgid "Track" msgstr "Takelis" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:132 #, 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:447 msgid "Please enter a query." msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:465 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:496 msgid "Error encountered. Please retry." msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:472 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:488 msgid "Loading result…" msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:475 #, fuzzy msgid "No results found." msgstr "Nerasta priedų." #: ../quodlibet/ext/songsmenu/browsefolders.py:159 #, fuzzy msgid "Browse Folders" msgstr "Naršyklės" #: ../quodlibet/ext/songsmenu/browsefolders.py:160 msgid "Opens the songs' folders in a file manager." msgstr "" #: ../quodlibet/ext/songsmenu/browsefolders.py:172 #, fuzzy msgid "Unable to open folders" msgstr "Negalima sukurti aplanko" #: ../quodlibet/ext/songsmenu/browsefolders.py:173 msgid "No program available to open folders." msgstr "" #: ../quodlibet/ext/songsmenu/console.py:40 msgid "Python Console" msgstr "" #: ../quodlibet/ext/songsmenu/console.py:41 msgid "Interactive Python console." msgstr "" #: ../quodlibet/ext/songsmenu/console.py:72 msgid "You can access the following objects by default:" msgstr "" #: ../quodlibet/ext/songsmenu/console.py:82 msgid "Your current working directory is:" 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:55 #, fuzzy msgid "pattern" msgstr "Netaisyklingas šablonas" #: ../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:91 #, fuzzy msgid "Input value" msgstr "Netaisyklinga reikšmė" #: ../quodlibet/ext/songsmenu/custom_commands.py:92 #, python-format msgid "Value for %s?" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:136 #, fuzzy msgid "Custom Commands" msgstr "Individualizuotas rikiavimas" #: ../quodlibet/ext/songsmenu/custom_commands.py:137 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:188 #: ../quodlibet/ext/songsmenu/custom_commands.py:198 #: ../quodlibet/ext/songsmenu/custom_commands.py:252 msgid "Edit Custom Commands" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:199 msgid "" "Supports QL patterns\n" "eg <tt><~artist~title></tt>" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:283 #, fuzzy, python-format msgid "Unable to run custom command %s" msgstr "Negalima kopijuoti dainų" #: ../quodlibet/ext/songsmenu/duplicates.py:290 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: ../quodlibet/ext/songsmenu/duplicates.py:343 msgid "Collapse / Expand all" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:347 #, python-format msgid "Duplicate key expression is '%s'" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:363 #, fuzzy msgid "Duplicates Browser" msgstr "Išjungti naršyklę" #: ../quodlibet/ext/songsmenu/duplicates.py:364 msgid "Finds and displays similarly tagged versions of songs." msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:407 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:409 msgid "_Group duplicates by:" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:414 #, fuzzy msgid "Duplicate Key" msgstr "Pašalinti pasikartojančias dainas" #: ../quodlibet/ext/songsmenu/duplicates.py:419 #, fuzzy msgid "Remove _Whitespace" msgstr "Pašalinti pasikartojančias dainas" #: ../quodlibet/ext/songsmenu/duplicates.py:420 #, fuzzy msgid "Remove _Diacritics" msgstr "Pašalinti pasikartojančias dainas" #: ../quodlibet/ext/songsmenu/duplicates.py:421 #, fuzzy msgid "Remove _Punctuation" msgstr "Pašalinti pasikartojančias dainas" #: ../quodlibet/ext/songsmenu/duplicates.py:422 msgid "Case _Insensitive" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:430 msgid "Matching options" msgstr "" #. Create a dialog. #: ../quodlibet/ext/songsmenu/editplaycount.py:19 #: ../quodlibet/ext/songsmenu/editplaycount.py:41 #, fuzzy msgid "Edit Playcount" msgstr "Redaguoti rodomą informaciją" #: ../quodlibet/ext/songsmenu/editplaycount.py:20 msgid "" "Edit a song's ~#playcount and ~#skipcount.\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's ~#playcount to 0, the ~#lastplayed and ~#laststarted " "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:68 msgid "Play Count" msgstr "" #: ../quodlibet/ext/songsmenu/editplaycount.py:69 msgid "Skip Count" msgstr "" #: ../quodlibet/ext/songsmenu/embedded.py:24 #, fuzzy msgid "Edit Embedded Images" msgstr "Pašalinti pasikartojančias dainas" #: ../quodlibet/ext/songsmenu/embedded.py:25 #, fuzzy msgid "Removes or replaces embedded images." msgstr "Pašalinti pasikartojančias dainas" #: ../quodlibet/ext/songsmenu/embedded.py:78 #, fuzzy msgid "_Remove all Images" msgstr "Pašalinti pasikartojančias dainas" #: ../quodlibet/ext/songsmenu/embedded.py:82 #, fuzzy msgid "_Embed Current Image" msgstr "Pašalinti pasikartojančias dainas" #: ../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:41 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 #: ../quodlibet/qltk/downloader.py:67 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" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" 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“ 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:49 msgid "Generating fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:63 msgid "_Details" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:85 msgid "_Submit" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:115 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:118 msgid "Fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Songs with MBIDs:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with sufficient tags:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs to submit:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:162 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:178 msgid "Submitting fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:186 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/id3tlen.py:21 msgid "Fix MP3 Duration" msgstr "" #: ../quodlibet/ext/songsmenu/id3tlen.py:22 msgid "" "Removes TLEN frames from ID3 tags which can be the cause for invalid song " "durations." msgstr "" #: ../quodlibet/ext/songsmenu/ifp.py:20 msgid "Send to iFP" msgstr "" #: ../quodlibet/ext/songsmenu/ifp.py:21 msgid "Uploads songs to an iRiver iFP device." msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:51 msgid "Export Metadata" msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:52 msgid "Exports metadata of selected songs as a .tags file." msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:92 #, fuzzy msgid "Import Metadata" msgstr "Importuoti grojaraštį" #: ../quodlibet/ext/songsmenu/importexport.py:93 msgid "Imports metadata for selected songs from a .tags file." msgstr "" #: ../quodlibet/ext/songsmenu/k3b.py:23 msgid "Burn CD" msgstr "" #: ../quodlibet/ext/songsmenu/k3b.py:24 msgid "Burns CDs with K3b, Brasero or xfburn." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:96 msgid "Updating chart list." msgstr "" #. No charts to fetch, no update scheduled. #: ../quodlibet/ext/songsmenu/lastfmsync.py:114 msgid "Already up-to-date." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:121 #, python-format msgid "Fetching chart for week of %s." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:143 msgid "Sync complete." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:149 #, fuzzy msgid "Error during sync" msgstr "Klaida įkeliant %r" #: ../quodlibet/ext/songsmenu/lastfmsync.py:214 #: ../quodlibet/ext/songsmenu/lastfmsync.py:244 msgid "Last.fm Sync" msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:245 msgid "Updates your library's statistics from your Last.fm profile." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:293 #, 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 "" #. Create a dialog. #: ../quodlibet/ext/songsmenu/migratemetadata.py:29 #: ../quodlibet/ext/songsmenu/migratemetadata.py:38 #, fuzzy msgid "Migrate Metadata" msgstr "Importuoti grojaraštį" #: ../quodlibet/ext/songsmenu/migratemetadata.py:32 msgid "Copies the quodlibet-specific metadata between songs." msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:45 msgid "_Copy" msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:47 msgid "_Paste" msgstr "" #. Create the tag table. #: ../quodlibet/ext/songsmenu/migratemetadata.py:57 #, fuzzy msgid "Information to copy/paste" msgstr "Informacija" #. Create the indexing box. #: ../quodlibet/ext/songsmenu/migratemetadata.py:79 msgid "Map tracks by disc and track number" msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:80 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 "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:96 #, python-format msgid "There is %d stored track." msgid_plural "There are %d stored tracks." msgstr[0] "" msgstr[1] "" msgstr[2] "" #: ../quodlibet/ext/songsmenu/playlist.py:31 #, fuzzy msgid "Export as Playlist" msgstr "Importuoti grojaraštį" #: ../quodlibet/ext/songsmenu/playlist.py:32 msgid "Exports songs to an M3U or PLS playlist." msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:77 msgid "Use relative paths" msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:77 msgid "Use absolute paths" msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:132 #, fuzzy msgid "Unable to export playlist" msgstr "Negalima importuoti grojaraščio" #: ../quodlibet/ext/songsmenu/playlist.py:133 #, fuzzy, python-format msgid "Writing to <b>%s</b> 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:362 msgid "ReplayGain Analyzer" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:418 msgid "Progress" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:433 msgid "Gain" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:448 msgid "Peak" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:463 #, python-format msgid "There is <b>%(to-process)s</b> album to update (of %(all)s)" msgid_plural "There are <b>%(to-process)s</b> albums to update (of %(all)s)" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: ../quodlibet/ext/songsmenu/replaygain.py:578 msgid "Replay Gain" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:579 msgid "" "Analyzes and updates ReplayGain information, using GStreamer. Results are " "grouped by album." msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:617 msgid "always" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:618 msgid "if <b>any</b> RG tags are missing" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:620 msgid "if <b>album</b> RG tags are missing" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:637 msgid "_Process albums:" msgstr "" #. Server settings Frame #: ../quodlibet/ext/songsmenu/replaygain.py:649 #, 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 "" #. TRANSLATORS: BPM mean "beats per minute" #: ../quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "" #: ../quodlibet/ext/songsmenu/tapbpm.py:32 #: ../quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" 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:172 #: ../quodlibet/ext/songsmenu/tapbpm.py:179 msgid "Tap BPM" msgstr "" #: ../quodlibet/ext/songsmenu/tapbpm.py:173 #, fuzzy msgid "Tap BPM for the selected song." msgstr "Negalima ištrinti dainų" #: ../quodlibet/ext/songsmenu/website_search.py:35 #, fuzzy msgid "Website Search" msgstr "Ieškoti" #: ../quodlibet/ext/songsmenu/website_search.py:36 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern-example)s." msgstr "" #: ../quodlibet/ext/songsmenu/website_search.py:78 #, fuzzy msgid "Search URL patterns" msgstr "Kelio šablonai" #: ../quodlibet/ext/songsmenu/website_search.py:88 #, fuzzy msgid "Edit search URLs" msgstr "Redaguoti išsaugotas paieškos reikšmes..." #. Add link to editor #: ../quodlibet/ext/songsmenu/website_search.py:114 #, fuzzy msgid "Configure Searches…" msgstr "Nus_palvinti paieškos žodžius" #: ../quodlibet/ext/songsmenu/wikipedia.py:46 #, python-format msgid "Search at %(website)s" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:63 msgid "Search Artist in Wikipedia" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:64 msgid "" "Opens a browser window with Wikipedia article on the playing song artist." msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:71 msgid "Search Album in Wikipedia" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:72 msgid "" "Opens a browser window with Wikipedia article on the playing song album." msgstr "" #. then (try to) load all new files #: ../quodlibet/library/libraries.py:650 ../quodlibet/library/libraries.py:660 #: ../quodlibet/library/libraries.py:726 ../quodlibet/library/libraries.py:745 #: ../quodlibet/qltk/information.py:268 ../quodlibet/qltk/prefs.py:639 #: ../quodlibet/util/library.py:124 msgid "Library" msgstr "Biblioteka" #: ../quodlibet/library/libraries.py:650 msgid "Checking mount points" msgstr "Tikrinami prijungimo taškai" #: ../quodlibet/library/libraries.py:660 msgid "Scanning library" msgstr "Peržvelgiama biblioteka" #: ../quodlibet/library/libraries.py:725 #, python-format msgid "Scanning %s" msgstr "Peržvelgiama %s" #: ../quodlibet/library/libraries.py:745 msgid "Loading files" msgstr "" #: ../quodlibet/operon/base.py:70 #, python-format msgid "Failed to load file: %r" msgstr "" #: ../quodlibet/operon/commands.py:37 msgid "List tags" msgstr "" #: ../quodlibet/operon/commands.py:42 ../quodlibet/operon/commands.py:81 #: ../quodlibet/operon/commands.py:461 msgid "Print terse output" msgstr "" #: ../quodlibet/operon/commands.py:44 ../quodlibet/operon/commands.py:83 #: ../quodlibet/operon/commands.py:463 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "" #: ../quodlibet/operon/commands.py:47 ../quodlibet/operon/commands.py:86 #, fuzzy msgid "Also list programmatic tags" msgstr "Rodyti su_generuotas programines žymes" #: ../quodlibet/operon/commands.py:51 ../quodlibet/operon/commands.py:129 #: ../quodlibet/operon/commands.py:220 ../quodlibet/operon/commands.py:293 #: ../quodlibet/operon/commands.py:336 ../quodlibet/operon/commands.py:340 #: ../quodlibet/operon/commands.py:391 ../quodlibet/operon/commands.py:394 #: ../quodlibet/operon/commands.py:433 ../quodlibet/operon/commands.py:468 #: ../quodlibet/operon/commands.py:508 ../quodlibet/operon/commands.py:543 #: ../quodlibet/operon/commands.py:585 msgid "Not enough arguments" msgstr "" #: ../quodlibet/operon/commands.py:53 ../quodlibet/operon/commands.py:90 #: ../quodlibet/operon/commands.py:131 ../quodlibet/operon/commands.py:222 #: ../quodlibet/operon/commands.py:470 #, fuzzy msgid "Too many arguments" msgstr "Per daug klaidų" #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:92 #: ../quodlibet/operon/commands.py:475 ../quodlibet/qltk/data_editors.py:363 #, fuzzy msgid "Description" msgstr "aprašymas" #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:475 #: ../quodlibet/qltk/edittags.py:454 msgid "Value" msgstr "Reikšmė" #: ../quodlibet/operon/commands.py:76 msgid "List all common tags" msgstr "" #: ../quodlibet/operon/commands.py:118 msgid "Copy tags from one file to another" msgstr "" #: ../quodlibet/operon/commands.py:123 ../quodlibet/operon/commands.py:164 #: ../quodlibet/operon/commands.py:289 ../quodlibet/operon/commands.py:324 #: ../quodlibet/operon/commands.py:384 msgid "Show changes, don't apply them" msgstr "" #: ../quodlibet/operon/commands.py:125 msgid "Skip tags that can't be written" msgstr "" #: ../quodlibet/operon/commands.py:145 #, python-format msgid "Can't copy tag %r to file: %r" 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:304 ../quodlibet/operon/commands.py:444 #: ../quodlibet/operon/commands.py:676 #, python-format msgid "Can not set %r" msgstr "" #: ../quodlibet/operon/commands.py:319 #, fuzzy msgid "Remove tags" msgstr "Pašalinti pasikartojančias dainas" #: ../quodlibet/operon/commands.py:326 ../quodlibet/operon/commands.py:386 msgid "Value is a regular expression" msgstr "" #: ../quodlibet/operon/commands.py:328 #, fuzzy msgid "Remove all tags" msgstr "Pašalinti pasikartojančias dainas" #: ../quodlibet/operon/commands.py:332 msgid "Can't combine '--all' with '--regexp'" msgstr "" #: ../quodlibet/operon/commands.py:366 #, python-format msgid "Can't remove %r from %r" msgstr "" #: ../quodlibet/operon/commands.py:379 #, fuzzy msgid "Remove a tag value" msgstr "Filtruoti pagal žymės reikšmę" #: ../quodlibet/operon/commands.py:428 #, fuzzy msgid "Add a tag value" msgstr "Filtruoti pagal žymės reikšmę" #: ../quodlibet/operon/commands.py:456 #, fuzzy msgid "List file information" msgstr "Nėra laiko informacijos" #: ../quodlibet/operon/commands.py:502 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" #: ../quodlibet/operon/commands.py:515 #, fuzzy, python-format msgid "Failed to load image file: %r" msgstr "Negalima pervadinti failo" #: ../quodlibet/operon/commands.py:522 ../quodlibet/operon/commands.py:551 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" #: ../quodlibet/operon/commands.py:538 #, fuzzy msgid "Remove all embedded images" msgstr "Pašalinti pasikartojančias dainas" #: ../quodlibet/operon/commands.py:568 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "" #: ../quodlibet/operon/commands.py:580 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" #: ../quodlibet/operon/commands.py:639 msgid "Rename files based on tags" msgstr "" #: ../quodlibet/operon/commands.py:654 msgid "Fill tags based on the file path" msgstr "" #: ../quodlibet/operon/commands.py:704 ../quodlibet/qltk/information.py:305 #: ../quodlibet/qltk/properties.py:84 ../quodlibet/qltk/renamefiles.py:176 #: ../quodlibet/qltk/tagsfrompath.py:229 ../quodlibet/qltk/tracknumbers.py:79 msgid "File" msgstr "Failas" #: ../quodlibet/operon/commands.py:712 msgid "Fill tracknumbers for all files" msgstr "" #: ../quodlibet/operon/commands.py:731 msgid "Print tags based on the given pattern" msgstr "" #: ../quodlibet/operon/commands.py:768 #, fuzzy msgid "Display help information" msgstr "Rodyti bendrą vartojimo informaciją" #: ../quodlibet/operon/util.py:40 #, 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:30 msgid "_Unknown" msgstr "Nežinoma" #: ../quodlibet/order/__init__.py:142 msgid "In Order" msgstr "Iš eilės" #: ../quodlibet/order/__init__.py:143 msgid "_In Order" msgstr "Iš _eilės" #: ../quodlibet/order/reorder.py:23 #, fuzzy msgid "Random" msgstr "_Atsitiktine tvarka" #: ../quodlibet/order/reorder.py:24 ../quodlibet/qltk/queue.py:119 msgid "_Random" msgstr "_Atsitiktine tvarka" #: ../quodlibet/order/reorder.py:39 ../quodlibet/order/reorder.py:40 msgid "Prefer higher rated" msgstr "" #: ../quodlibet/order/repeat.py:43 ../quodlibet/order/repeat.py:44 msgid "Repeat this track" msgstr "" #: ../quodlibet/order/repeat.py:57 ../quodlibet/order/repeat.py:58 #, fuzzy msgid "Repeat all" msgstr "_Kartoti" #: ../quodlibet/order/repeat.py:73 ../quodlibet/order/repeat.py:74 msgid "One Song" msgstr "Viena daina" #: ../quodlibet/player/gstbe/player.py:98 msgid "Stream" msgstr "Srautas" #: ../quodlibet/player/gstbe/player.py:98 msgid "Buffering" msgstr "Buferizuojama" #: ../quodlibet/player/gstbe/player.py:319 #, fuzzy msgid "Could not create GStreamer pipeline" msgstr "Nepavyko sukurti GStreamer išvesties." #: ../quodlibet/player/gstbe/player.py:560 msgid "No GStreamer element found to handle media format" msgstr "" #: ../quodlibet/player/gstbe/player.py:561 #, 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:25 #, fuzzy msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. In case 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:36 msgid "_Output pipeline:" msgstr "_Išvestis:" #: ../quodlibet/player/gstbe/prefs.py:43 #, python-format msgid "%.1f seconds" msgstr "%.1f sekundė" #: ../quodlibet/player/gstbe/prefs.py:57 msgid "_Buffer duration:" msgstr "_Buferizavimo trukmė:" #: ../quodlibet/player/gstbe/prefs.py:66 msgid "Disable _gapless playback" msgstr "" #: ../quodlibet/player/gstbe/prefs.py:70 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions." msgstr "" #: ../quodlibet/player/gstbe/util.py:93 #, fuzzy msgid "No GStreamer audio sink found" msgstr "Nerasta stočių" #: ../quodlibet/player/gstbe/util.py:112 #, fuzzy msgid "Invalid GStreamer output pipeline" msgstr "Netaisyklinga GStreamer išvestis, bandoma naudoti numatytąją." #: ../quodlibet/player/xinebe/player.py:90 msgid "Unable to create audio output" msgstr "Negalima sukurti garso išvesties" #: ../quodlibet/player/xinebe/player.py:91 #, 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:62 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" #: ../quodlibet/plugins/__init__.py:71 #, fuzzy, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "Nepavyko susieti GStreamer išvesties: '%s'" #: ../quodlibet/plugins/playlist.py:30 #, 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:41 ../quodlibet/qltk/songsmenu.py:46 #: ../quodlibet/qltk/songsmenu.py:74 #, fuzzy msgid "_Run Plugin" msgstr "_Priedai" #: ../quodlibet/qltk/about.py:40 #, python-format msgid "Supported formats: %s" msgstr "Palaikomi formatai: %s" #: ../quodlibet/qltk/about.py:43 #, python-format msgid "Audio device: %s" msgstr "Garso įrenginys: %s" #. 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:207 ../quodlibet/qltk/information.py:131 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:48 ../quodlibet/qltk/edittags.py:311 msgid "_Value:" msgstr "_Reikšmė:" #: ../quodlibet/qltk/cbes.py:262 msgid "Saved Values" msgstr "Išsaugotos reikšmės" #: ../quodlibet/qltk/cbes.py:263 #, fuzzy msgid "Edit saved values…" msgstr "Redaguoti išsaugotas reikšmes..." #: ../quodlibet/qltk/controls.py:111 msgid "Auto_matic" msgstr "Auto_matinis" #: ../quodlibet/qltk/controls.py:112 msgid "_Track Mode" msgstr "_Takelio režimas" #: ../quodlibet/qltk/controls.py:113 msgid "_Album Mode" msgstr "_Albumo režimas" #. Translators: player state, no action #: ../quodlibet/qltk/controls.py:122 msgid "_Mute" msgstr "" #: ../quodlibet/qltk/controls.py:128 #, fuzzy msgid "_Replay Gain Mode" msgstr "Garsumo derinimas (Replay Gain)" #. Translators: New Command/Entry/Item/... #: ../quodlibet/qltk/data_editors.py:119 #, python-format msgid "New %s" msgstr "" #: ../quodlibet/qltk/data_editors.py:218 #, fuzzy msgid "(unknown)" msgstr "Nežinoma" #: ../quodlibet/qltk/data_editors.py:355 msgid "Tag expression" msgstr "" #: ../quodlibet/qltk/data_editors.py:382 msgid "Tag expression e.g. people:real or ~album~year." msgstr "" #: ../quodlibet/qltk/data_editors.py:383 #, fuzzy msgid "Enter new tag" msgstr "Filtruoti pagal žymės reikšmę" #: ../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/downloader.py:38 msgid "Downloads" msgstr "Atsiuntimai" #: ../quodlibet/qltk/downloader.py:62 msgid "Size" msgstr "Dydis" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: ../quodlibet/qltk/downloader.py:94 ../quodlibet/qltk/renamefiles.py:265 #: ../quodlibet/qltk/wlw.py:50 msgid "_Stop" msgstr "" #: ../quodlibet/qltk/edittags.py:63 ../quodlibet/qltk/edittags.py:74 #, 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:67 ../quodlibet/qltk/edittags.py:71 #, 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:193 msgid "Split into _Multiple Values" msgstr "Iš_skaidyti į keletą reikšmių" #: ../quodlibet/qltk/edittags.py:211 msgid "Split Disc out of _Album" msgstr "Išskaidyti diską iš _albumo" #: ../quodlibet/qltk/edittags.py:228 msgid "Split _Version out of Title" msgstr "Išskaidyti _versiją iš pavadinimo" #: ../quodlibet/qltk/edittags.py:259 msgid "Split Arranger out of Ar_tist" msgstr "Išskaidyti aranžuotoją iš a_tlikėjo" #: ../quodlibet/qltk/edittags.py:264 msgid "Split _Performer out of Artist" msgstr "Išskaidyti muzikantą iš atlikėjo" #: ../quodlibet/qltk/edittags.py:270 msgid "Split _Performer out of Title" msgstr "Išskaidyti _Muzikantą iš Pavadinimo žymės" #: ../quodlibet/qltk/edittags.py:276 msgid "Split _Originalartist out of Title" msgstr "Išskaidyti _Originalo atlikėją iš Pavadinimo žymės" #: ../quodlibet/qltk/edittags.py:283 msgid "Add a Tag" msgstr "Pridėti žymę" #: ../quodlibet/qltk/edittags.py:302 msgid "_Tag:" msgstr "Žy_mė:" #: ../quodlibet/qltk/edittags.py:404 msgid "Edit Tags" msgstr "Redaguoti žymes" #: ../quodlibet/qltk/edittags.py:477 msgid "Show _programmatic tags" msgstr "Rodyti su_generuotas programines žymes" #: ../quodlibet/qltk/edittags.py:478 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" #. Translators: Revert button in the tag editor #: ../quodlibet/qltk/edittags.py:508 #, fuzzy msgctxt "edittags" msgid "_Revert" msgstr "Niekada" #. Translators: Save button in the tag editor #: ../quodlibet/qltk/edittags.py:513 msgctxt "edittags" msgid "_Save" msgstr "" #: ../quodlibet/qltk/edittags.py:659 msgid "Unable to add tag" msgstr "Negalima pridėti žymės" #: ../quodlibet/qltk/edittags.py:660 #, fuzzy, python-format msgid "Unable to add <b>%s</b>" msgstr "Negalima pridėti dainos" #: ../quodlibet/qltk/edittags.py:662 #, fuzzy, python-format msgid "" "The files currently selected do not support multiple values for <b>%s</b>." 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:689 ../quodlibet/qltk/edittags.py:856 #: ../quodlibet/qltk/tagsfrompath.py:212 ../quodlibet/util/__init__.py:554 #: ../quodlibet/util/tags.py:231 msgid "Invalid tag" msgstr "Netaisyklinga žymė" #: ../quodlibet/qltk/edittags.py:690 ../quodlibet/qltk/edittags.py:857 #: ../quodlibet/qltk/tagsfrompath.py:213 #, python-format msgid "" "Invalid tag <b>%s</b>\n" "\n" "The files currently selected do not support editing this tag." msgstr "" "Netaisyklinga žymė <b>%s</b>\n" "\n" "Failai, kuriuos pasirinkote, nepalaiko šios žymės redagavimo." #: ../quodlibet/qltk/edittags.py:828 ../quodlibet/qltk/edittags.py:868 msgid "Invalid value" msgstr "Netaisyklinga reikšmė" #: ../quodlibet/qltk/edittags.py:829 ../quodlibet/qltk/edittags.py:869 #, python-format msgid "" "Invalid value: <b>%(value)s</b>\n" "\n" "%(error)s" msgstr "" "Netaisyklinga reikšmė: <b>%(value)s</b>\n" "\n" "%(error)s" #: ../quodlibet/qltk/_editutils.py:28 msgid "Tag may not be accurate" msgstr "Žymė gali būti netiksli" #: ../quodlibet/qltk/_editutils.py:31 #, 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:47 msgid "Unable to save song" msgstr "Negalima išsaugoti dainos" #: ../quodlibet/qltk/_editutils.py:50 #, 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:142 #, 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:95 #: ../quodlibet/qltk/quodlibetwindow.py:1066 msgid "_About" msgstr "" #: ../quodlibet/qltk/exfalsowindow.py:99 #: ../quodlibet/qltk/quodlibetwindow.py:1088 msgid "_Check for Updates…" msgstr "" #: ../quodlibet/qltk/exfalsowindow.py:105 #: ../quodlibet/qltk/quodlibetwindow.py:1021 ../quodlibet/qltk/songsmenu.py:304 msgid "_Plugins" msgstr "_Priedai" #: ../quodlibet/qltk/exfalsowindow.py:267 #, 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:279 msgid "Ex Falso Preferences" msgstr "Ex Falso nuostatos" #: ../quodlibet/qltk/exfalsowindow.py:289 ../quodlibet/qltk/prefs.py:598 msgid "Split _on:" msgstr "At_skirti ties:" #: ../quodlibet/qltk/exfalsowindow.py:295 ../quodlibet/qltk/prefs.py:613 msgid "Tag Editing" msgstr "Žymių redagavimas" #: ../quodlibet/qltk/filesel.py:210 msgid "Folders" msgstr "Aplankai" #: ../quodlibet/qltk/filesel.py:253 #, fuzzy msgid "_New Folder…" msgstr "Naujas aplankas" #: ../quodlibet/qltk/filesel.py:262 #, fuzzy msgid "_Select all Sub-Folders" msgstr "_Pasirinkti visus poaplankius" #: ../quodlibet/qltk/filesel.py:374 msgid "New Folder" msgstr "Naujas aplankas" #: ../quodlibet/qltk/filesel.py:374 msgid "Enter a name for the new folder:" msgstr "Įveskite naujo aplanko vardą:" #: ../quodlibet/qltk/filesel.py:387 msgid "Unable to create folder" msgstr "Negalima sukurti aplanko" #: ../quodlibet/qltk/filesel.py:404 msgid "Unable to delete folder" msgstr "Negalima ištrinti aplanko" #: ../quodlibet/qltk/filesel.py:519 ../quodlibet/qltk/pluginwin.py:167 msgid "Songs" msgstr "Dainos" #. Translators: As in "by Artist Name" #: ../quodlibet/qltk/info.py:42 #, python-format msgid "by %s" msgstr "atliko %s" #: ../quodlibet/qltk/info.py:43 ../quodlibet/qltk/information.py:167 #: ../quodlibet/qltk/information.py:448 #, python-format msgid "Disc %s" msgstr "Diskas %s" #: ../quodlibet/qltk/info.py:44 ../quodlibet/qltk/information.py:172 #, python-format msgid "Track %s" msgstr "Takelis %s" #: ../quodlibet/qltk/info.py:108 #, fuzzy msgid "_Edit Display…" msgstr "Redaguoti rodomą informaciją" #: ../quodlibet/qltk/information.py:105 msgid "No songs are selected." msgstr "Nepasirinkta jokių dainų." #: ../quodlibet/qltk/information.py:106 msgid "No Songs" msgstr "Nėra dainų" #: ../quodlibet/qltk/information.py:121 ../quodlibet/qltk/information.py:338 #: ../quodlibet/qltk/information.py:471 ../quodlibet/qltk/information.py:531 msgid "Information" msgstr "Informacija" #: ../quodlibet/qltk/information.py:126 msgid "Lyrics" msgstr "Dainos žodžiai" #: ../quodlibet/qltk/information.py:184 ../quodlibet/qltk/information.py:396 #, python-format msgid "Produced by %s" msgstr "Prodiusavo %s" #: ../quodlibet/qltk/information.py:199 ../quodlibet/util/tags.py:76 msgid "artist" msgstr "atlikėjas" #: ../quodlibet/qltk/information.py:200 ../quodlibet/qltk/information.py:561 #: ../quodlibet/util/tags.py:76 msgid "artists" msgstr "atlikėjai" #. for backwards compat #: ../quodlibet/qltk/information.py:221 ../quodlibet/util/tags.py:86 #: ../quodlibet/util/tags.py:114 msgid "performers" msgstr "muzikantai" #: ../quodlibet/qltk/information.py:235 ../quodlibet/qltk/information.py:248 #: ../quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "Niekada" #: ../quodlibet/qltk/information.py:236 #, 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:254 ../quodlibet/util/tags.py:139 msgid "added" msgstr "pridėta" #: ../quodlibet/qltk/information.py:255 ../quodlibet/util/tags.py:140 msgid "last played" msgstr "paskutinį kartą grota" #: ../quodlibet/qltk/information.py:256 ../quodlibet/util/tags.py:150 msgid "plays" msgstr "grota" #: ../quodlibet/qltk/information.py:257 ../quodlibet/util/tags.py:151 msgid "skips" msgstr "praleista" #: ../quodlibet/qltk/information.py:258 ../quodlibet/util/tags.py:156 msgid "rating" msgstr "įvertis" #: ../quodlibet/qltk/information.py:287 msgid "path" msgstr "" #: ../quodlibet/qltk/information.py:288 ../quodlibet/util/tags.py:154 msgid "length" msgstr "trukmė" #: ../quodlibet/qltk/information.py:289 #, fuzzy msgid "format" msgstr "Informacija" #: ../quodlibet/qltk/information.py:290 ../quodlibet/util/tags.py:163 msgid "codec" msgstr "" #: ../quodlibet/qltk/information.py:291 ../quodlibet/util/tags.py:164 #, fuzzy msgid "encoding" msgstr "Didėjančia tvarka" #: ../quodlibet/qltk/information.py:292 ../quodlibet/util/tags.py:160 msgid "bitrate" msgstr "bitų dažnis" #: ../quodlibet/qltk/information.py:293 ../quodlibet/util/tags.py:161 msgid "file size" msgstr "failo dydis" #: ../quodlibet/qltk/information.py:294 ../quodlibet/util/tags.py:149 msgid "modified" msgstr "paskutinį kartą pakeista" #: ../quodlibet/qltk/information.py:331 msgid "Additional" msgstr "" #: ../quodlibet/qltk/information.py:383 #, 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:458 msgid "Track unavailable" msgstr "Takelis neprieinamas" #: ../quodlibet/qltk/information.py:464 msgid "Track List" msgstr "Takelių sąrašas" #: ../quodlibet/qltk/information.py:505 ../quodlibet/qltk/information.py:578 #, 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:508 msgid "Selected Discography" msgstr "Pasirinkta diskografija" #: ../quodlibet/qltk/information.py:558 #, 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:586 ../quodlibet/util/tags.py:74 msgid "albums" msgstr "albumai" #: ../quodlibet/qltk/information.py:599 msgid "Total length:" msgstr "Visa trukmė:" #: ../quodlibet/qltk/information.py:603 msgid "Total size:" msgstr "Visas dydis:" #: ../quodlibet/qltk/information.py:606 msgid "Files" msgstr "Failų" #: ../quodlibet/qltk/lyrics.py:37 msgid "_Download" msgstr "_Atsisiųsti" #: ../quodlibet/qltk/lyrics.py:40 #, fuzzy msgid "_Edit" msgstr "_Redaguoti vaizdą..." #. buffer.set_text(_("No lyrics found.\n\nYou can click the " #. "Download button to have Quod Libet search " #. "for lyrics online. You can also enter them " #. "yourself and click save.")) #: ../quodlibet/qltk/lyrics.py:73 ../quodlibet/qltk/lyrics.py:109 msgid "No lyrics found for this song." msgstr "Nerasta dainos žodžių šiai dainai." #: ../quodlibet/qltk/lyrics.py:82 #, fuzzy msgid "Searching for lyrics…" msgstr "Ieškoma dainos žodžių..." #: ../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/msg.py:41 msgid "Discard tag changes?" msgstr "Atšaukti žymių pakeitimus?" #: ../quodlibet/qltk/msg.py:42 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:55 ../quodlibet/qltk/prefs.py:595 #: ../quodlibet/qltk/textedit.py:64 ../quodlibet/qltk/tracknumbers.py:117 #, fuzzy msgid "_Revert" msgstr "Niekada" #: ../quodlibet/qltk/msg.py:86 msgid "File exists" msgstr "Failas egzistuoja" #: ../quodlibet/qltk/msg.py:88 #, python-format msgid "Replace %(file-name)s?" msgstr "" #: ../quodlibet/qltk/msg.py:94 #, fuzzy msgid "_Replace File" msgstr "Pervadinti failus" #: ../quodlibet/qltk/notif.py:182 msgid "Active tasks" msgstr "Aktyvios užduotys" #: ../quodlibet/qltk/notif.py:188 #, python-format msgid "%d tasks running" msgstr "%d užduotys vykdomos" #: ../quodlibet/qltk/playorder.py:254 #, fuzzy msgid "Toggle shuffle mode" msgstr "Perjungti grojimo/pauzės režimą" #: ../quodlibet/qltk/playorder.py:270 #, fuzzy msgid "Toggle repeat mode" msgstr "Perjungti grojimo/pauzės režimą" #: ../quodlibet/qltk/pluginwin.py:44 msgid "Plugin Errors" msgstr "Priedų klaidos" #: ../quodlibet/qltk/pluginwin.py:124 msgid "Enabled" msgstr "Įjungta" #: ../quodlibet/qltk/pluginwin.py:125 msgid "Disabled" msgstr "Išjungta" #: ../quodlibet/qltk/pluginwin.py:131 msgid "No category" msgstr "Be kategorijos" #: ../quodlibet/qltk/pluginwin.py:169 msgid "Events" msgstr "" #: ../quodlibet/qltk/pluginwin.py:170 #, fuzzy msgid "Play Order" msgstr "_Tvarka:" #: ../quodlibet/qltk/pluginwin.py:171 #, fuzzy msgid "Editing" msgstr "Žymių redagavimas" #: ../quodlibet/qltk/pluginwin.py:173 #, fuzzy msgid "Covers" msgstr "Visas dydis:" #: ../quodlibet/qltk/pluginwin.py:309 msgid "No plugins found." msgstr "Nerasta priedų." #: ../quodlibet/qltk/pluginwin.py:358 msgid "Plugins" msgstr "Priedai" #: ../quodlibet/qltk/pluginwin.py:402 msgid "Show _Errors" msgstr "Rodyti klaidas" #: ../quodlibet/qltk/prefs.py:45 msgid "_Disc" msgstr "_Diskas" #: ../quodlibet/qltk/prefs.py:46 msgid "_Track" msgstr "_Takelio nr." #: ../quodlibet/qltk/prefs.py:47 #, fuzzy msgid "Grou_ping" msgstr "grupavimas" #: ../quodlibet/qltk/prefs.py:50 msgid "Al_bum" msgstr "Al_bumas" #: ../quodlibet/qltk/prefs.py:55 msgid "_Filename" msgstr "Failo _vardas" #: ../quodlibet/qltk/prefs.py:57 msgid "_Length" msgstr "T_rukmė" #: ../quodlibet/qltk/prefs.py:64 msgid "_Jump to playing song automatically" msgstr "_Automatiškai peršokti prie grojamos dainos" #: ../quodlibet/qltk/prefs.py:66 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:82 msgid "_Others:" msgstr "_Kita:" #: ../quodlibet/qltk/prefs.py:88 #, fuzzy msgid "_Edit…" msgstr "_Redaguoti vaizdą..." #: ../quodlibet/qltk/prefs.py:91 msgid "Add or remove additional column headers" msgstr "" #: ../quodlibet/qltk/prefs.py:101 msgid "Visible Columns" msgstr "Matomi stulpeliai" #: ../quodlibet/qltk/prefs.py:104 msgid "Title includes _version" msgstr "Pavadinime yra dainos versija" #: ../quodlibet/qltk/prefs.py:106 #, fuzzy msgid "Artist includes all _people" msgstr "Į paiešką įtraukti atlikėju_s" #: ../quodlibet/qltk/prefs.py:108 msgid "Album includes _disc subtitle" msgstr "Albumo pavadinime yra disko _dalis" #: ../quodlibet/qltk/prefs.py:110 msgid "Filename includes _folder" msgstr "Failo varde yra _aplanko vardas" #: ../quodlibet/qltk/prefs.py:123 #, fuzzy msgid "Column Preferences" msgstr "Nuostatos" #: ../quodlibet/qltk/prefs.py:129 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "" #: ../quodlibet/qltk/prefs.py:142 ../quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Dainų sąrašas" #: ../quodlibet/qltk/prefs.py:222 #, fuzzy msgid "Edit Columns" msgstr "Matomi stulpeliai" #: ../quodlibet/qltk/prefs.py:259 msgid "Duration totals" msgstr "" #: ../quodlibet/qltk/prefs.py:271 msgid "_Global filter:" msgstr "_Bendras filtras:" #: ../quodlibet/qltk/prefs.py:277 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:283 #, fuzzy msgctxt "heading" msgid "Search" msgstr "Ieškoti" #: ../quodlibet/qltk/prefs.py:287 ../quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Naršyklės" #: ../quodlibet/qltk/prefs.py:293 msgid "Confirm _multiple ratings" msgstr "Patvirtinti su_dėtinius įverčius" #: ../quodlibet/qltk/prefs.py:295 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:298 msgid "Enable _one-click ratings" msgstr "Įjungti vien_o paspaudimo įverčius" #: ../quodlibet/qltk/prefs.py:300 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:306 ../quodlibet/qltk/prefs.py:616 msgid "Ratings" msgstr "Įverčiai" #. Filename choice algorithm config #: ../quodlibet/qltk/prefs.py:312 msgid "Prefer _embedded art" msgstr "Pageidautina naudoti į_terptinius albumų viršelius" #: ../quodlibet/qltk/prefs.py:314 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:319 #, fuzzy msgid "_Fixed image filename:" msgstr "_Priverstinai naudotino paveikslėlio failo vardas:" #: ../quodlibet/qltk/prefs.py:321 #, fuzzy msgid "The single image filename to use if selected" msgstr "" "Naudotino albumo viršelio paveikslėlio failo vardas (esant keliems galimiems " "variantams)" #: ../quodlibet/qltk/prefs.py:327 msgid "The album art image file to use when forced" msgstr "" "Naudotino albumo viršelio paveikslėlio failo vardas (esant keliems galimiems " "variantams)" #: ../quodlibet/qltk/prefs.py:336 msgid "Album Art" msgstr "Albumų viršeliai" #: ../quodlibet/qltk/prefs.py:357 msgid "Playback" msgstr "Grojimas" #: ../quodlibet/qltk/prefs.py:362 msgid "Output Configuration" msgstr "Išvesties sąranka" #: ../quodlibet/qltk/prefs.py:373 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:376 msgid "_Fall-back gain (dB):" msgstr "_Numatytasis derinimas (dB):" #: ../quodlibet/qltk/prefs.py:387 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:390 msgid "_Pre-amp gain (dB):" msgstr "_Pirminis derinimas (dB):" #: ../quodlibet/qltk/prefs.py:395 msgid "_Enable Replay Gain volume adjustment" msgstr "Įjungti Replay Gain garso d_erinimą" #: ../quodlibet/qltk/prefs.py:420 msgid "Replay Gain Volume Adjustment" msgstr "Garsumo derinimas (Replay Gain)" #: ../quodlibet/qltk/prefs.py:450 #, fuzzy msgid "_Default rating:" msgstr "Numatytasis" #: ../quodlibet/qltk/prefs.py:493 #, fuzzy msgid "Rating _scale:" msgstr "Įverčiai" #: ../quodlibet/qltk/prefs.py:542 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:547 msgid "_Bayesian averaging amount:" msgstr "" #: ../quodlibet/qltk/prefs.py:556 msgid "Save ratings and play _counts" msgstr "Saugoti įverčius bei grojimo _kartų vertes" #: ../quodlibet/qltk/prefs.py:560 msgid "_Email:" msgstr "_El. paštas:" #: ../quodlibet/qltk/prefs.py:562 msgid "Ratings and play counts will be set for this email address" msgstr "" "Įverčiai bei grojimo kartų vertės bus susietos su šiuo el. pašto adresu" #: ../quodlibet/qltk/prefs.py:577 msgid "Auto-save tag changes" msgstr "Automatiškai išsaugoti žymių pakeitimus" #: ../quodlibet/qltk/prefs.py:579 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:587 #, 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:610 msgid "Tags" msgstr "Žymės" #: ../quodlibet/qltk/prefs.py:631 #, fuzzy msgid "Updating for new ratings" msgstr "_Atnaujinti stotis" #: ../quodlibet/qltk/prefs.py:641 #, fuzzy msgid "Scan library _on start" msgstr "At_naujinti biblioteką paleidus programą" #: ../quodlibet/qltk/prefs.py:651 ../quodlibet/qltk/quodlibetwindow.py:1100 #, fuzzy msgid "_Scan Library" msgstr "Pa_ieška bibliotekoje" #: ../quodlibet/qltk/prefs.py:653 ../quodlibet/qltk/quodlibetwindow.py:1162 msgid "Check for changes in your library" msgstr "Ieškoti pasikeitimų bibliotekoje" #: ../quodlibet/qltk/prefs.py:658 #, fuzzy msgid "Re_build Library" msgstr "Iš naujo įkelti _biblioteką" #: ../quodlibet/qltk/prefs.py:661 #, 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:671 msgid "Scan Directories" msgstr "Peržvelgiami aplankai" #: ../quodlibet/qltk/prefs.py:677 #, fuzzy msgid "Hidden Songs" msgstr "Nėra dainų" #: ../quodlibet/qltk/properties.py:158 ../quodlibet/util/collection.py:398 #, 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:162 ../quodlibet/qltk/properties.py:164 msgid "Properties" msgstr "Savybės" #: ../quodlibet/qltk/queue.py:101 msgid "_Queue" msgstr "_Eilė" #: ../quodlibet/qltk/queue.py:126 msgid "Stop Once Empty" msgstr "" #: ../quodlibet/qltk/queue.py:130 #, fuzzy msgid "_Clear Queue" msgstr "Valyti _klaidas" #: ../quodlibet/qltk/queue.py:242 #, 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:198 msgid "_Browse Library" msgstr "_Naršyti bibliotekoje" #: ../quodlibet/qltk/quodlibetwindow.py:395 #, fuzzy msgid "Toggle queue visibility" msgstr "Perjungti pagrindinio lango matomumą" #: ../quodlibet/qltk/quodlibetwindow.py:516 #, fuzzy msgid "Playback Error" msgstr "Grojimas" #: ../quodlibet/qltk/quodlibetwindow.py:524 #, fuzzy msgid "Set up library directories?" msgstr "Pasirinkti aplankus" #: ../quodlibet/qltk/quodlibetwindow.py:525 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:531 msgid "_Not Now" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:532 msgid "_Set Up" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:956 msgid "Unable to add songs" msgstr "Negalima pridėti dainų" #: ../quodlibet/qltk/quodlibetwindow.py:957 #: ../quodlibet/qltk/quodlibetwindow.py:1364 #, fuzzy, python-format msgid "%s uses an unsupported protocol." msgstr "<b>%s</b> naudoja nepalaikomą protokolą." #: ../quodlibet/qltk/quodlibetwindow.py:980 msgid "_Jump to Playing Song" msgstr "_Peršokti ties grojama daina" #: ../quodlibet/qltk/quodlibetwindow.py:986 #, fuzzy msgid "_File" msgstr "Failas" #: ../quodlibet/qltk/quodlibetwindow.py:987 #, fuzzy msgid "_Song" msgstr "Dainos" #: ../quodlibet/qltk/quodlibetwindow.py:988 msgid "_View" msgstr "_Rodymas" #: ../quodlibet/qltk/quodlibetwindow.py:989 #, fuzzy msgid "_Browse" msgstr "Naršyklės" #: ../quodlibet/qltk/quodlibetwindow.py:990 msgid "_Control" msgstr "_Valdymas" #: ../quodlibet/qltk/quodlibetwindow.py:991 msgid "_Help" msgstr "_Pagalba" #: ../quodlibet/qltk/quodlibetwindow.py:997 #, fuzzy msgid "_Add a Folder…" msgstr "_Pridėti aplanką..." #: ../quodlibet/qltk/quodlibetwindow.py:1002 #, fuzzy msgid "_Add a File…" msgstr "_Pridėti failą..." #: ../quodlibet/qltk/quodlibetwindow.py:1007 #, fuzzy msgid "_Add a Location…" msgstr "Pridėti vietą" #: ../quodlibet/qltk/quodlibetwindow.py:1036 #, fuzzy msgid "Edit Bookmarks…" msgstr "Redaguoti _žymes..." #: ../quodlibet/qltk/quodlibetwindow.py:1056 #, fuzzy msgid "Stop After This Song" msgstr "Po šios dainos sustabdyti" #: ../quodlibet/qltk/quodlibetwindow.py:1062 msgid "_Keyboard Shortcuts" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:1071 msgid "Online Help" msgstr "Pagalba Internete" #: ../quodlibet/qltk/quodlibetwindow.py:1080 msgid "Search Help" msgstr "Paieškos bibliotekoje pagalba" #: ../quodlibet/qltk/quodlibetwindow.py:1352 msgid "Add a Location" msgstr "Pridėti vietą" #: ../quodlibet/qltk/quodlibetwindow.py:1353 msgid "Enter the location of an audio file:" msgstr "Įveskite garso failo vietą:" #: ../quodlibet/qltk/quodlibetwindow.py:1358 #: ../quodlibet/qltk/quodlibetwindow.py:1363 msgid "Unable to add location" msgstr "Negalima pridėti vietos" #: ../quodlibet/qltk/quodlibetwindow.py:1359 #, fuzzy, python-format msgid "%s is not a valid location." msgstr "<b>%s</b> nėra tinkama vieta." #: ../quodlibet/qltk/quodlibetwindow.py:1372 #: ../quodlibet/qltk/quodlibetwindow.py:1381 msgid "Add Music" msgstr "Pridėti muziką" #: ../quodlibet/qltk/quodlibetwindow.py:1372 ../quodlibet/qltk/scanbox.py:99 #, fuzzy msgid "_Add Folders" msgstr "_Pridėti aplanką..." #: ../quodlibet/qltk/quodlibetwindow.py:1379 #, fuzzy msgid "Music Files" msgstr "Muzikos grotuvas" #: ../quodlibet/qltk/quodlibetwindow.py:1381 #, fuzzy msgid "_Add Files" msgstr "_Pridėti failą..." #: ../quodlibet/qltk/ratingsmenu.py:24 #, 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:26 #, fuzzy msgid "The saved ratings will be removed" msgstr "Pasikartojančios dainos bus pašalintos iš grojaraščio '%s'." #: ../quodlibet/qltk/ratingsmenu.py:27 #, 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:57 ../quodlibet/qltk/ratingsmenu.py:111 #, fuzzy msgid "_Remove Rating" msgstr "Pašalinti pasikartojančias dainas" #: ../quodlibet/qltk/ratingsmenu.py:98 #, fuzzy msgid "Change _Rating" msgstr "Į_vertis" #: ../quodlibet/qltk/renamefiles.py:46 msgid "Replace spaces with _underscores" msgstr "Pakeisti tarpus „_“ simboliu" #: ../quodlibet/qltk/renamefiles.py:56 msgid "Strip _Windows-incompatible characters" msgstr "Pašalinti su _Windows nesuderinamus simbolius" #: ../quodlibet/qltk/renamefiles.py:74 msgid "Strip _diacritical marks" msgstr "Pašalinti _diakritinius ženklus" #: ../quodlibet/qltk/renamefiles.py:85 msgid "Strip non-_ASCII characters" msgstr "Pašalinti ne _ASCII simbolius" #: ../quodlibet/qltk/renamefiles.py:95 msgid "Use only _lowercase characters" msgstr "Naudoti tik _mažąsias raides" #: ../quodlibet/qltk/renamefiles.py:123 msgid "Rename Files" msgstr "Pervadinti failus" #: ../quodlibet/qltk/renamefiles.py:139 ../quodlibet/qltk/tagsfrompath.py:116 msgid "Path Patterns" msgstr "Kelio šablonai" #: ../quodlibet/qltk/renamefiles.py:140 ../quodlibet/qltk/tagsfrompath.py:117 #, fuzzy msgid "Edit saved patterns…" msgstr "Redaguoti išsaugotus šablonus..." #: ../quodlibet/qltk/renamefiles.py:143 ../quodlibet/qltk/tagsfrompath.py:120 #: ../quodlibet/qltk/tracknumbers.py:58 msgid "_Preview" msgstr "Perž_iūra" #: ../quodlibet/qltk/renamefiles.py:190 msgid "New Name" msgstr "Naujas vardas" #: ../quodlibet/qltk/renamefiles.py:255 msgid "Unable to rename file" msgstr "Negalima pervadinti failo" #: ../quodlibet/qltk/renamefiles.py:256 #, fuzzy, python-format msgid "" "Renaming <b>%(old-name)s</b> to <b>%(new-name)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." 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:264 msgid "Ignore _All Errors" msgstr "Ignoruoti vis_as klaidas" #: ../quodlibet/qltk/renamefiles.py:267 msgid "_Continue" msgstr "_Tęsti" #: ../quodlibet/qltk/renamefiles.py:296 msgid "Path is not absolute" msgstr "Kelias neabsoliutus" #: ../quodlibet/qltk/renamefiles.py:297 #, python-format msgid "" "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 ~/." 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:47 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:99 msgid "Select Directories" msgstr "Pasirinkti aplankus" #: ../quodlibet/qltk/searchbar.py:52 msgid "Saved Searches" msgstr "Išsaugotos paieškos reikšmės" #: ../quodlibet/qltk/searchbar.py:53 #, fuzzy msgid "Edit saved searches…" msgstr "Redaguoti išsaugotas paieškos reikšmes..." #: ../quodlibet/qltk/searchbar.py:74 msgid "Search your library, using free text or QL queries" msgstr "" #: ../quodlibet/qltk/searchbar.py:129 msgid "Search after _typing" msgstr "Ieško_ti bevedant užklausą" #: ../quodlibet/qltk/searchbar.py:132 msgid "Show search results after the user stops typing" msgstr "Rodyti paieškos rezultatus vartotojui baigus įvesti užklausą" #: ../quodlibet/qltk/searchbar.py:187 msgid "_Limit:" msgstr "_Riba:" #: ../quodlibet/qltk/searchbar.py:200 msgid "_Weight" msgstr "_Svoris" #: ../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 ../quodlibet/qltk/shortcuts.py:41 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: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:377 #, python-format msgid "_Filter on %s" msgstr "_Filtras laukui „%s“" #: ../quodlibet/qltk/songlist.py:1094 msgid "All _Headers" msgstr "_Visos antraštės" #: ../quodlibet/qltk/songlist.py:1095 msgid "_Track Headers" msgstr "_Takelio antraštės" #: ../quodlibet/qltk/songlist.py:1096 msgid "_Album Headers" msgstr "_Albumo antraštės" #: ../quodlibet/qltk/songlist.py:1097 msgid "_People Headers" msgstr "A_tlikėjų antraštės" #: ../quodlibet/qltk/songlist.py:1098 msgid "_Date Headers" msgstr "Dat_os antraštės" #: ../quodlibet/qltk/songlist.py:1099 msgid "_File Headers" msgstr "_Failo antraštės" #: ../quodlibet/qltk/songlist.py:1100 msgid "_Production Headers" msgstr "_Produkcijos antraštės" #: ../quodlibet/qltk/songlist.py:1115 #, fuzzy msgid "_Customize Headers…" msgstr "_Individualizuoti antraštes..." #: ../quodlibet/qltk/songlist.py:1120 msgid "_Expand Column" msgstr "" #: ../quodlibet/qltk/songsmenu.py:36 #, 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:64 #, 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:149 #, fuzzy msgid "Configure Plugins…" msgstr "Nus_palvinti paieškos žodžius" #: ../quodlibet/qltk/songsmenu.py:345 msgid "Add to _Queue" msgstr "Pridėti į _eilę" #: ../quodlibet/qltk/songsmenu.py:368 msgid "_Copy to Device" msgstr "_Kopijuoti į įrenginį" #: ../quodlibet/qltk/songsmenu.py:379 #, fuzzy msgid "_Remove from Library" msgstr "_Pašalinti iš bibliotekos" #: ../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:101 msgid "Tags From Path" msgstr "Žymės pagal kelią" #: ../quodlibet/qltk/tagsfrompath.py:138 msgid "Tags replace existing ones" msgstr "Žymės pakeičia jau esamas" #: ../quodlibet/qltk/tagsfrompath.py:139 msgid "Tags are added to existing ones" msgstr "Žymės pridedamos prie esamų" #. Save button #: ../quodlibet/qltk/tagsfrompath.py:153 msgid "Save" msgstr "" #: ../quodlibet/qltk/tagsfrompath.py:195 #, python-format msgid "" "The pattern\n" "\t<b>%s</b>\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/tagsfrompath.py:216 msgid "Invalid tags" msgstr "Netaisyklingos žymės" #: ../quodlibet/qltk/tagsfrompath.py:217 #, 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." #: ../quodlibet/qltk/textedit.py:142 #, 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:158 msgid "Edit Display" msgstr "Redaguoti rodomą informaciją" #: ../quodlibet/qltk/tracknumbers.py:39 msgid "Track Numbers" msgstr "Takelių numeriai" #: ../quodlibet/qltk/tracknumbers.py:42 msgid "Start fro_m:" msgstr "Pradėti _nuo:" #: ../quodlibet/qltk/tracknumbers.py:51 msgid "_Total tracks:" msgstr "Iš _viso takelių:" #: ../quodlibet/qltk/unity.py:52 msgid "Play/Pause" msgstr "Groti/Pristabdyti" #: ../quodlibet/qltk/unity.py:75 msgid "Previous" msgstr "Ankstesnė" #: ../quodlibet/qltk/views.py:923 #, 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:89 #, fuzzy msgid "Checking for Updates" msgstr "Tikrinami prijungimo taškai" #: ../quodlibet/update.py:124 #, fuzzy msgid "Connection failed" msgstr "vieta" #: ../quodlibet/update.py:133 #, python-format msgid "You are already using the newest version %(version)s" msgstr "" #: ../quodlibet/update.py:136 #, 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:420 msgid "Playlists must have a name" msgstr "" #: ../quodlibet/util/collection.py:603 #, python-format msgid "A playlist named %s already exists." msgstr "Grojaraštis vardu %s jau egzistuoja." #: ../quodlibet/util/cover/built_in.py:26 #, fuzzy msgid "Embedded album covers" msgstr "Atnaujinti albumo _viršelį" #: ../quodlibet/util/cover/built_in.py:27 msgid "Uses covers embedded into audio files." msgstr "" #: ../quodlibet/util/cover/built_in.py:49 #, fuzzy msgid "Filesystem cover" msgstr "Failų sistema" #: ../quodlibet/util/cover/built_in.py:50 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "" #: ../quodlibet/util/__init__.py:93 msgid "Display brief usage information" msgstr "Rodyti bendrą vartojimo informaciją" #: ../quodlibet/util/__init__.py:95 msgid "Display version and copyright" msgstr "Rodyti versijos numerį ir autorių teises" #: ../quodlibet/util/__init__.py:135 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "" #: ../quodlibet/util/__init__.py:137 msgid "[options]" msgstr "[pasirinktys]" #: ../quodlibet/util/__init__.py:182 #, python-format msgid "Option %r not recognized." msgstr "Pasirinkimas „%r“ neatpažintas." #: ../quodlibet/util/__init__.py:185 #, python-format msgid "Option %r requires an argument." msgstr "Pasirinkimas „%r“ reikalauja argumento." #: ../quodlibet/util/__init__.py:188 #, python-format msgid "%r is not a unique prefix." msgstr "„%r“ nėra unikalus priešdėlis." #: ../quodlibet/util/__init__.py:364 #, python-format msgid "%d kbps" msgstr "%d kbps" #: ../quodlibet/util/__init__.py:419 #, 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:432 msgid "No time information" msgstr "Nėra laiko informacijos" #: ../quodlibet/util/__init__.py:435 #, 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:436 #, 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:437 #, 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:438 #, 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:439 #, 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:563 #, 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 msgid "Unable to edit song" msgstr "Negalima redaguoti dainos" #: ../quodlibet/util/songwrapper.py:113 #, python-format msgid "" "Saving <b>%s</b> 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:34 #: ../quodlibet/util/string/__init__.py:44 msgid "[Invalid Encoding]" msgstr "[Netaisyklinga koduotė]" #: ../quodlibet/util/tags.py:74 msgid "album" msgstr "albumas" #: ../quodlibet/util/tags.py:75 msgid "arranger" msgstr "aranžuotojas" #: ../quodlibet/util/tags.py:75 msgid "arrangers" msgstr "aranžuotojai" #: ../quodlibet/util/tags.py:75 #, fuzzy msgid "arrangement" msgstr "aranžuotojas" #: ../quodlibet/util/tags.py:77 msgid "author" msgstr "autorius" #: ../quodlibet/util/tags.py:77 msgid "authors" msgstr "autoriai" #: ../quodlibet/util/tags.py:78 msgid "composer" msgstr "kompozitorius" #: ../quodlibet/util/tags.py:78 msgid "composers" msgstr "kompozitoriai" #: ../quodlibet/util/tags.py:78 #, fuzzy msgid "composition" msgstr "kompozitorius" #. Translators: conducting as in conducting a musical performance #: ../quodlibet/util/tags.py:80 msgid "conductor" msgstr "dirigentas" #: ../quodlibet/util/tags.py:80 msgid "conductors" msgstr "dirigentai" #: ../quodlibet/util/tags.py:80 #, fuzzy msgid "conducting" msgstr "dirigentas" #: ../quodlibet/util/tags.py:81 msgid "contact" msgstr "kontaktai" #: ../quodlibet/util/tags.py:82 msgid "copyright" msgstr "autorių teisės" #: ../quodlibet/util/tags.py:83 msgid "date" msgstr "data" #: ../quodlibet/util/tags.py:84 msgid "description" msgstr "aprašymas" #: ../quodlibet/util/tags.py:85 msgid "genre" msgstr "žanras" #: ../quodlibet/util/tags.py:85 #, fuzzy msgid "genres" msgstr "žanras" #: ../quodlibet/util/tags.py:86 msgid "performer" msgstr "muzikantas" #: ../quodlibet/util/tags.py:87 msgid "grouping" msgstr "grupavimas" #: ../quodlibet/util/tags.py:88 msgid "language" msgstr "kalba" #: ../quodlibet/util/tags.py:89 msgid "license" msgstr "licencija" #: ../quodlibet/util/tags.py:90 msgid "location" msgstr "vieta" #: ../quodlibet/util/tags.py:91 msgid "lyricist" msgstr "dainos ž. autorius" #: ../quodlibet/util/tags.py:91 msgid "lyricists" msgstr "dainos ž. autoriai" #: ../quodlibet/util/tags.py:91 #, fuzzy msgid "lyrics" msgstr "dainos ž. autorius" #. Translators: Also e.g. "record label", "publisher" #: ../quodlibet/util/tags.py:93 msgid "organization" msgstr "organizacija" #: ../quodlibet/util/tags.py:94 msgid "title" msgstr "pavadinimas" #: ../quodlibet/util/tags.py:95 msgid "version" msgstr "versija" #: ../quodlibet/util/tags.py:96 msgid "website" msgstr "tinklalapis" #: ../quodlibet/util/tags.py:98 msgid "album artist" msgstr "albumo atlikėjas" #: ../quodlibet/util/tags.py:99 msgid "BPM" msgstr "BPM" #. Translators: This used to be called "part". #: ../quodlibet/util/tags.py:102 ../quodlibet/util/tags.py:103 msgid "disc subtitle" msgstr "disko dalis" #: ../quodlibet/util/tags.py:104 ../quodlibet/util/tags.py:141 msgid "disc" msgstr "diskas" #: ../quodlibet/util/tags.py:105 ../quodlibet/util/tags.py:143 msgid "track" msgstr "takelio nr." #: ../quodlibet/util/tags.py:106 msgid "label ID" msgstr "leidinio ID" #: ../quodlibet/util/tags.py:107 msgid "original release date" msgstr "originalo išleidimo data" #: ../quodlibet/util/tags.py:108 msgid "original album" msgstr "originalus albumas" #: ../quodlibet/util/tags.py:109 msgid "original artist" msgstr "originalus atlikėjas" #: ../quodlibet/util/tags.py:110 msgid "recording date" msgstr "įrašymo data" #: ../quodlibet/util/tags.py:111 msgid "release country" msgstr "išleidimo šalis" #. 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:120 #, fuzzy msgid "MusicBrainz recording ID" msgstr "„MusicBrainz“ takelio ID" #: ../quodlibet/util/tags.py:121 #, fuzzy msgid "MusicBrainz release track ID" msgstr "„MusicBrainz“ leidimo ID" #: ../quodlibet/util/tags.py:122 msgid "MusicBrainz release ID" msgstr "„MusicBrainz“ leidimo ID" #: ../quodlibet/util/tags.py:123 #, fuzzy msgid "MusicBrainz artist ID" msgstr "„MusicBrainz“ atlikėjo ID" #: ../quodlibet/util/tags.py:124 #, fuzzy msgid "MusicBrainz release artist ID" msgstr "„MusicBrainz“ leidimo ID" #: ../quodlibet/util/tags.py:125 msgid "MusicBrainz TRM ID" msgstr "„MusicBrainz“ TRM ID" #: ../quodlibet/util/tags.py:126 msgid "MusicIP PUID" msgstr "„MusicIP“ PUID" #: ../quodlibet/util/tags.py:127 msgid "MusicBrainz album status" msgstr "„MusicBrainz“ albumo statusas" #: ../quodlibet/util/tags.py:128 msgid "MusicBrainz album type" msgstr "„MusicBrainz“ albumo tipas" #: ../quodlibet/util/tags.py:129 #, fuzzy msgid "MusicBrainz release group ID" msgstr "„MusicBrainz“ leidimo ID" #. Translators: "gain" means a volume adjustment, not "to acquire". #: ../quodlibet/util/tags.py:132 msgid "track gain" msgstr "takelio garso lygis" #: ../quodlibet/util/tags.py:133 msgid "track peak" msgstr "takelio maks. garsumo lygis" #. Translators: "gain" means a volume adjustment, not "to acquire". #: ../quodlibet/util/tags.py:135 msgid "album gain" msgstr "albumo garso lygis" #: ../quodlibet/util/tags.py:136 msgid "album peak" msgstr "albumo maks. garsumo lygis" #: ../quodlibet/util/tags.py:137 msgid "reference loudness" msgstr "garsumo etalonas" #: ../quodlibet/util/tags.py:142 msgid "discs" msgstr "diskai" #: ../quodlibet/util/tags.py:144 msgid "tracks" msgstr "takeliai" #: ../quodlibet/util/tags.py:145 msgid "last started" msgstr "paskutinį kartą grota" #: ../quodlibet/util/tags.py:146 msgid "full name" msgstr "pilnas vardas" #: ../quodlibet/util/tags.py:153 msgid "mount point" msgstr "prijungimo taškas" #: ../quodlibet/util/tags.py:155 msgid "people" msgstr "atlikėjai" #: ../quodlibet/util/tags.py:157 msgid "year" msgstr "metai" #: ../quodlibet/util/tags.py:158 msgid "original release year" msgstr "originalo išleidimo metai" #: ../quodlibet/util/tags.py:159 msgid "bookmark" msgstr "žymė" #: ../quodlibet/util/tags.py:162 msgid "file format" msgstr "failo formatas" #: ../quodlibet/util/tags.py:165 #, fuzzy msgid "playlists" msgstr "Grojaraščiai" #: ../quodlibet/util/tags.py:166 msgid "channel count" msgstr "" #. Translators: e.g. "artist (sort)" #: ../quodlibet/util/tags.py:256 msgid "sort" msgstr "" #. Translators: e.g. "performer (roles)" #: ../quodlibet/util/tags.py:264 msgid "roles" msgstr "" #, 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 "Remove all songs from the queue" #~ msgstr "Iš eilės pašalinti visas dainas" #~ msgid "Watch this folder for new songs" #~ msgstr "Stebėti šį aplanką dėl naujų dainų" #~ 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 "Model:" #~ msgstr "Modelis:" #~ msgid "Capacity:" #~ msgstr "Talpa:" #~ msgid "Firmware:" #~ msgstr "Programinė įranga:" #~ msgid "Removing orphaned iPod track" #~ msgstr "Šalinamas vienišas takelis iPod grotuve" #, 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 "Unable to open input files" #~ msgstr "Negalima atverti įvesties failų" #~ 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 "General" #~ msgstr "Bendrasis" #~ 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 "_Select" #~ msgstr "_Pasirinkti" #~ 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 "Choose New Stations" #~ msgstr "Pasirinkite naujas stotis" #~ msgid "Add" #~ msgstr "Pridėti" #~ msgid "Bitrate" #~ msgstr "Bitų dažnis" #~ msgid "_Stations..." #~ msgstr "_Stotys..." #~ msgid "Quod Libet" #~ msgstr "Quod Libet" #~ 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9671857 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/po/lv.po����������������������������������������������������������������������������0000644�0001750�0001750�00000542350�00000000000�014106� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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: 2017-05-17 18:58+0200\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" #: ../data/exfalso.appdata.xml.in.h:1 ../data/exfalso.desktop.in.h:2 msgid "Edit tags in your audio files" msgstr "Rediģē tagus jūsu audio failos" #: ../data/exfalso.appdata.xml.in.h:2 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/exfalso.appdata.xml.in.h:3 ../data/quodlibet.appdata.xml.in.h:3 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/exfalso.desktop.in.h:1 msgid "Audio tag editor" msgstr "Audio tagu redaktors" #: ../data/quodlibet.appdata.xml.in.h:1 ../data/quodlibet.desktop.in.h:2 msgid "Listen to, browse, or edit your audio collection" msgstr "Atskaņo, pārlūko vai rediģē jūsu audio kolekciju" #: ../data/quodlibet.appdata.xml.in.h:2 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 "" #: ../data/quodlibet.desktop.in.h:1 msgid "Music Player" msgstr "Mūzikas atskaņotājs" #: ../quodlibet/browsers/albums/main.py:168 #: ../quodlibet/browsers/covergrid/main.py:54 #, fuzzy msgid "_Title" msgstr "Nosaukums" #: ../quodlibet/browsers/albums/main.py:169 #: ../quodlibet/browsers/covergrid/main.py:55 ../quodlibet/qltk/prefs.py:49 msgid "_Artist" msgstr "_Mākslinieks" #: ../quodlibet/browsers/albums/main.py:170 #: ../quodlibet/browsers/covergrid/main.py:56 ../quodlibet/qltk/prefs.py:54 msgid "_Date" msgstr "_Datums" #: ../quodlibet/browsers/albums/main.py:171 #: ../quodlibet/browsers/covergrid/main.py:57 ../quodlibet/qltk/prefs.py:53 #, fuzzy msgid "_Genre" msgstr "Žanrs" #: ../quodlibet/browsers/albums/main.py:172 #: ../quodlibet/browsers/covergrid/main.py:58 ../quodlibet/qltk/prefs.py:58 #: ../quodlibet/qltk/ratingsmenu.py:39 msgid "_Rating" msgstr "_Vērtējums" #: ../quodlibet/browsers/albums/main.py:178 #: ../quodlibet/browsers/covergrid/main.py:64 #, fuzzy msgid "Sort _by…" msgstr "_Kārtot pēc:" #: ../quodlibet/browsers/albums/main.py:199 #: ../quodlibet/browsers/covergrid/main.py:85 #: ../quodlibet/browsers/paned/prefs.py:166 #: ../quodlibet/browsers/playlists/main.py:629 #: ../quodlibet/qltk/exfalsowindow.py:109 ../quodlibet/qltk/pluginwin.py:341 #: ../quodlibet/qltk/quodlibetwindow.py:1016 #, fuzzy msgid "_Preferences" msgstr "Iestatījumi" #: ../quodlibet/browsers/albums/main.py:361 msgid "Album List" msgstr "Albumu saraksts" #: ../quodlibet/browsers/albums/main.py:362 msgid "_Album List" msgstr "_Albumu saraksts" #: ../quodlibet/browsers/albums/main.py:472 #: ../quodlibet/browsers/covergrid/main.py:279 #: ../quodlibet/browsers/covergrid/main.py:488 msgid "All Albums" msgstr "Visi albumi" #: ../quodlibet/browsers/albums/main.py:473 #: ../quodlibet/browsers/covergrid/main.py:280 #: ../quodlibet/browsers/covergrid/main.py:489 #, 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:650 #: ../quodlibet/browsers/covergrid/main.py:467 #, 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:381 ../quodlibet/util/collection.py:245 #, 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:379 ../quodlibet/util/collection.py:249 #, 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:120 #, fuzzy msgid "Options" msgstr "[opcijas]" #: ../quodlibet/browsers/albums/prefs.py:74 #: ../quodlibet/browsers/covergrid/prefs.py:123 msgid "Album Display" msgstr "Albuma attēlojums" #: ../quodlibet/browsers/albums/prefs.py:78 #: ../quodlibet/browsers/covergrid/prefs.py:127 #: ../quodlibet/browsers/media.py:39 #: ../quodlibet/browsers/playlists/prefs.py:56 #: ../quodlibet/ext/songsmenu/albumart.py:326 #: ../quodlibet/ext/songsmenu/duplicates.py:350 #: ../quodlibet/ext/songsmenu/filterall.py:48 #: ../quodlibet/qltk/bookmarks.py:101 ../quodlibet/qltk/cbes.py:93 #: ../quodlibet/qltk/data_editors.py:99 ../quodlibet/qltk/data_editors.py:324 #: ../quodlibet/qltk/exfalsowindow.py:297 ../quodlibet/qltk/pluginwin.py:79 #: ../quodlibet/qltk/pluginwin.py:427 ../quodlibet/qltk/prefs.py:707 #: ../quodlibet/qltk/textedit.py:164 ../quodlibet/update.py:148 msgid "_Close" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:55 #: ../quodlibet/browsers/audiofeeds.py:67 #: ../quodlibet/browsers/audiofeeds.py:69 #: ../quodlibet/browsers/audiofeeds.py:159 #: ../quodlibet/browsers/paned/models.py:86 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:46 #: ../quodlibet/formats/_audio.py:495 ../quodlibet/order/__init__.py:27 #: ../quodlibet/qltk/information.py:240 ../quodlibet/qltk/information.py:247 #: ../quodlibet/qltk/information.py:273 ../quodlibet/qltk/wlw.py:70 msgid "Unknown" msgstr "Nezināms" #: ../quodlibet/browsers/audiofeeds.py:246 msgid "New Feed" msgstr "Jauna barotne" #: ../quodlibet/browsers/audiofeeds.py:247 msgid "Enter the location of an audio feed:" msgstr "Ievadiet audio barotnes adresi:" #: ../quodlibet/browsers/audiofeeds.py:248 #: ../quodlibet/browsers/collection/prefs.py:90 #: ../quodlibet/browsers/iradio.py:341 ../quodlibet/browsers/paned/prefs.py:78 #: ../quodlibet/browsers/playlists/menu.py:96 #: ../quodlibet/browsers/playlists/util.py:52 ../quodlibet/qltk/bookmarks.py:62 #: ../quodlibet/qltk/cbes.py:55 ../quodlibet/qltk/data_editors.py:311 #: ../quodlibet/qltk/edittags.py:288 ../quodlibet/qltk/edittags.py:488 #: ../quodlibet/qltk/quodlibetwindow.py:1354 ../quodlibet/qltk/scanbox.py:61 msgid "_Add" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:265 msgid "Audio Feeds" msgstr "Audio barotnes" #: ../quodlibet/browsers/audiofeeds.py:266 msgid "_Audio Feeds" msgstr "_Audio barotnes" #: ../quodlibet/browsers/audiofeeds.py:345 #: ../quodlibet/browsers/audiofeeds.py:350 #, fuzzy msgid "_Download…" msgstr "Lejupielā_dēt" #: ../quodlibet/browsers/audiofeeds.py:359 msgid "Download Files" msgstr "Lejupielādēt failus" #. Save button #: ../quodlibet/browsers/audiofeeds.py:359 #: ../quodlibet/browsers/audiofeeds.py:371 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:81 #: ../quodlibet/ext/songsmenu/albumart.py:322 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:355 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:278 #: ../quodlibet/ext/songsmenu/html.py:76 #: ../quodlibet/ext/songsmenu/lastfmsync.py:216 #: ../quodlibet/ext/songsmenu/playlist.py:51 #: ../quodlibet/ext/songsmenu/replaygain.py:365 #: ../quodlibet/ext/songsmenu/tapbpm.py:182 ../quodlibet/qltk/_editutils.py:39 #: ../quodlibet/qltk/lyrics.py:38 ../quodlibet/qltk/msg.py:52 #: ../quodlibet/qltk/renamefiles.py:168 ../quodlibet/qltk/tracknumbers.py:113 msgid "_Save" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:371 msgid "Download File" msgstr "Lejupielādēt failu" #: ../quodlibet/browsers/audiofeeds.py:394 #: ../quodlibet/browsers/playlists/main.py:213 #: ../quodlibet/qltk/data_editors.py:96 msgid "_New" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:454 #: ../quodlibet/browsers/audiofeeds.py:513 msgid "Unable to add feed" msgstr "Neizdevās pievienot barotni" #: ../quodlibet/browsers/audiofeeds.py:455 #: ../quodlibet/browsers/audiofeeds.py:514 #, fuzzy, python-format msgid "" "%s could not be added. The server may be down, or the location may not be an " "audio feed." msgstr "" "<b>%s</b> neizdevās pievienot. Iespējams, nedarbojas serveris, vai arī " "ievadītā adrese nav audio barotne." #. refresh button #: ../quodlibet/browsers/audiofeeds.py:462 ../quodlibet/browsers/media.py:217 #: ../quodlibet/browsers/media.py:386 ../quodlibet/qltk/filesel.py:259 #: ../quodlibet/qltk/pluginwin.py:413 #, fuzzy msgid "_Refresh" msgstr "_Atsvaidzināt bibliotēku" #: ../quodlibet/browsers/audiofeeds.py:463 #: ../quodlibet/browsers/playlists/main.py:457 #: ../quodlibet/browsers/playlists/util.py:43 ../quodlibet/qltk/delete.py:143 #: ../quodlibet/qltk/filesel.py:256 ../quodlibet/qltk/lyrics.py:39 #: ../quodlibet/qltk/maskedbox.py:28 ../quodlibet/qltk/songsmenu.py:392 #, fuzzy msgid "_Delete" msgstr "Dzēst failus" #: ../quodlibet/browsers/audiofeeds.py:530 msgid "" "The current audio backend does not support URLs, Audio Feeds browser " "disabled." msgstr "" "Pašreizējā audio aizmugure neatbalsta URL, audio barotņu pārlūks tiks " "atslēgts." #: ../quodlibet/browsers/_base.py:147 ../quodlibet/browsers/_base.py:150 msgid "Library Browser" msgstr "Bibliotēkas pārlūks" #: ../quodlibet/browsers/_base.py:274 ../quodlibet/ext/songsmenu/refresh.py:30 #: ../quodlibet/qltk/exfalsowindow.py:241 ../quodlibet/qltk/information.py:542 #: ../quodlibet/qltk/maskedbox.py:68 ../quodlibet/util/collection.py:527 #, 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:402 ../quodlibet/browsers/_base.py:407 #: ../quodlibet/qltk/tagsfrompath.py:194 ../quodlibet/qltk/textedit.py:141 #: ../quodlibet/util/__init__.py:622 msgid "Invalid pattern" msgstr "Nederīgs paraugs" #: ../quodlibet/browsers/collection/main.py:78 msgid "Album Collection" msgstr "" #: ../quodlibet/browsers/collection/main.py:79 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:66 #: ../quodlibet/browsers/paned/prefs.py:51 msgid "_Custom" msgstr "_Pielāgots" #. Remove button #: ../quodlibet/browsers/collection/prefs.py:94 #: ../quodlibet/browsers/paned/prefs.py:82 #: ../quodlibet/browsers/playlists/menu.py:97 #: ../quodlibet/ext/playlist/remove_duplicates.py:60 #: ../quodlibet/qltk/bookmarks.py:97 ../quodlibet/qltk/bookmarks.py:127 #: ../quodlibet/qltk/cbes.py:82 ../quodlibet/qltk/cbes.py:89 #: ../quodlibet/qltk/data_editors.py:81 ../quodlibet/qltk/data_editors.py:94 #: ../quodlibet/qltk/data_editors.py:301 ../quodlibet/qltk/data_editors.py:314 #: ../quodlibet/qltk/data_editors.py:322 ../quodlibet/qltk/edittags.py:494 #: ../quodlibet/qltk/edittags.py:634 ../quodlibet/qltk/maskedbox.py:48 #: ../quodlibet/qltk/maskedbox.py:88 ../quodlibet/qltk/queue.py:350 #: ../quodlibet/qltk/scanbox.py:36 ../quodlibet/qltk/scanbox.py:63 #, fuzzy msgid "_Remove" msgstr "_Vērtējums" #: ../quodlibet/browsers/collection/prefs.py:122 #: ../quodlibet/ext/songsmenu/filterall.py:34 #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:92 #: ../quodlibet/qltk/edittags.py:431 msgid "Tag" msgstr "Tags" #: ../quodlibet/browsers/collection/prefs.py:128 msgid "Merge" msgstr "" #: ../quodlibet/browsers/collection/prefs.py:188 #, fuzzy msgid "Album Collection Preferences" msgstr "Albumu saraksta iestatījumi" #: ../quodlibet/browsers/collection/prefs.py:195 #: ../quodlibet/browsers/paned/prefs.py:209 #: ../quodlibet/ext/songsmenu/editplaycount.py:45 #: ../quodlibet/ext/songsmenu/exact_rating.py:38 #: ../quodlibet/player/gstbe/prefs.py:40 ../quodlibet/qltk/prefs.py:127 #: ../quodlibet/qltk/textedit.py:65 msgid "_Apply" msgstr "" #: ../quodlibet/browsers/collection/prefs.py:198 #: ../quodlibet/browsers/paned/prefs.py:213 #: ../quodlibet/browsers/playlists/menu.py:95 #: ../quodlibet/browsers/playlists/util.py:42 #: ../quodlibet/errorreport/ui.py:108 #: ../quodlibet/ext/playlist/export_to_folder.py:37 #: ../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:44 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:281 #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:88 #: ../quodlibet/ext/songsmenu/importexport.py:35 #: ../quodlibet/ext/songsmenu/lastfmsync.py:215 #: ../quodlibet/ext/songsmenu/playlist.py:50 #: ../quodlibet/ext/songsmenu/replaygain.py:364 #: ../quodlibet/ext/songsmenu/tapbpm.py:181 ../quodlibet/plugins/playlist.py:39 #: ../quodlibet/qltk/chooser.py:184 ../quodlibet/qltk/chooser.py:205 #: ../quodlibet/qltk/chooser.py:229 ../quodlibet/qltk/chooser.py:253 #: ../quodlibet/qltk/delete.py:90 ../quodlibet/qltk/delete.py:133 #: ../quodlibet/qltk/edittags.py:287 ../quodlibet/qltk/_editutils.py:38 #: ../quodlibet/qltk/getstring.py:28 ../quodlibet/qltk/maskedbox.py:27 #: ../quodlibet/qltk/msg.py:54 ../quodlibet/qltk/msg.py:93 #: ../quodlibet/qltk/ratingsmenu.py:33 ../quodlibet/qltk/songsmenu.py:45 #: ../quodlibet/qltk/songsmenu.py:73 ../quodlibet/update.py:94 msgid "_Cancel" msgstr "" #: ../quodlibet/browsers/covergrid/main.py:125 #, fuzzy msgid "Cover Grid" msgstr "Kopējais izmērs:" #: ../quodlibet/browsers/covergrid/main.py:126 #, 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:71 #, fuzzy msgid "Show \"All Albums\" Item" msgstr "Visi albumi" #: ../quodlibet/browsers/covergrid/prefs.py:78 msgid "Vertical Split" msgstr "" #: ../quodlibet/browsers/covergrid/prefs.py:110 #: ../quodlibet/browsers/covergrid/prefs.py:111 #, fuzzy msgid "Cover Magnification" msgstr "organizācija" #: ../quodlibet/browsers/filesystem.py:40 msgid "File System" msgstr "Failu sistēma" #: ../quodlibet/browsers/filesystem.py:41 msgid "_File System" msgstr "_Failu sistēma" #: ../quodlibet/browsers/filesystem.py:113 ../quodlibet/browsers/media.py:491 #: ../quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "Neizdevās pārkopēt dziesmas" #: ../quodlibet/browsers/filesystem.py:114 ../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:189 msgid "_Add to Library" msgstr "Pievienot bibliotēk_ai" #: ../quodlibet/browsers/iradio.py:178 msgid "Unsupported file type" msgstr "Neatbalstīts faila tips" #: ../quodlibet/browsers/iradio.py:179 #, 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:219 ../quodlibet/browsers/iradio.py:232 #: ../quodlibet/browsers/iradio.py:810 msgid "Unable to add station" msgstr "Neizdevās pievienot staciju" #: ../quodlibet/browsers/iradio.py:243 ../quodlibet/browsers/iradio.py:471 msgid "Internet Radio" msgstr "Interneta radio" #: ../quodlibet/browsers/iradio.py:243 #, fuzzy msgid "Downloading station list" msgstr "Lejupielādēt failus" #: ../quodlibet/browsers/iradio.py:339 msgid "New Station" msgstr "Jauna stacija" #: ../quodlibet/browsers/iradio.py:340 msgid "Enter the location of an Internet radio station:" msgstr "Ievadiet interneta radiostacijas adresi:" #: ../quodlibet/browsers/iradio.py:358 msgid "Electronic" msgstr "" #: ../quodlibet/browsers/iradio.py:361 msgid "Hip Hop / Rap" msgstr "" #: ../quodlibet/browsers/iradio.py:362 msgid "Oldies" msgstr "" #: ../quodlibet/browsers/iradio.py:363 msgid "R&B" msgstr "" #: ../quodlibet/browsers/iradio.py:364 msgid "Japanese" msgstr "" #: ../quodlibet/browsers/iradio.py:365 msgid "Indian" msgstr "" #: ../quodlibet/browsers/iradio.py:367 msgid "Religious" msgstr "" #: ../quodlibet/browsers/iradio.py:369 msgid "Charts" msgstr "" #: ../quodlibet/browsers/iradio.py:370 msgid "Turkish" msgstr "" #: ../quodlibet/browsers/iradio.py:371 msgid "Reggae / Dancehall" msgstr "" #: ../quodlibet/browsers/iradio.py:372 #, fuzzy msgid "Latin" msgstr "vērtējums" #: ../quodlibet/browsers/iradio.py:373 msgid "College Radio" msgstr "" #: ../quodlibet/browsers/iradio.py:374 msgid "Talk / News" msgstr "" #: ../quodlibet/browsers/iradio.py:375 msgid "Ambient" msgstr "" #: ../quodlibet/browsers/iradio.py:376 msgid "Jazz" msgstr "" #: ../quodlibet/browsers/iradio.py:377 ../quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "" #: ../quodlibet/browsers/iradio.py:378 ../quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "" #: ../quodlibet/browsers/iradio.py:379 msgid "Alternative" msgstr "" #: ../quodlibet/browsers/iradio.py:380 msgid "Metal" msgstr "" #: ../quodlibet/browsers/iradio.py:381 msgid "Country" msgstr "" #: ../quodlibet/browsers/iradio.py:382 msgid "News" msgstr "" #: ../quodlibet/browsers/iradio.py:383 msgid "Schlager" msgstr "" #: ../quodlibet/browsers/iradio.py:384 msgid "Funk" msgstr "" #: ../quodlibet/browsers/iradio.py:385 msgid "Indie" msgstr "" #: ../quodlibet/browsers/iradio.py:386 msgid "Blues" msgstr "" #: ../quodlibet/browsers/iradio.py:387 msgid "Soul" msgstr "" #: ../quodlibet/browsers/iradio.py:388 msgid "Lounge" msgstr "" #: ../quodlibet/browsers/iradio.py:389 msgid "Punk" msgstr "" #: ../quodlibet/browsers/iradio.py:390 msgid "Reggaeton" msgstr "" #: ../quodlibet/browsers/iradio.py:392 msgid "Slavic" msgstr "" #: ../quodlibet/browsers/iradio.py:394 msgid "Greek" msgstr "" #: ../quodlibet/browsers/iradio.py:395 msgid "Gothic" msgstr "" #: ../quodlibet/browsers/iradio.py:396 ../quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "" #: ../quodlibet/browsers/iradio.py:449 msgid "Would you like to load a list of popular radio stations?" msgstr "" #: ../quodlibet/browsers/iradio.py:455 #, fuzzy msgid "_Load Stations" msgstr "Jau_na stacija" #: ../quodlibet/browsers/iradio.py:472 msgid "_Internet Radio" msgstr "_Interneta radio" #: ../quodlibet/browsers/iradio.py:538 #, fuzzy msgid "_New Station…" msgstr "Jauna stacija" #: ../quodlibet/browsers/iradio.py:541 #, fuzzy msgid "_Update Stations" msgstr "Jau_na stacija" #: ../quodlibet/browsers/iradio.py:568 #, fuzzy msgid "All Stations" msgstr "Jauna stacija" #. TODO: support for ~#rating=!None etc (#1940) #: ../quodlibet/browsers/iradio.py:572 #: ../quodlibet/browsers/soundcloud/main.py:64 msgid "Favorites" msgstr "" #: ../quodlibet/browsers/iradio.py:580 #, fuzzy msgid "No Category" msgstr "Bez kategorijas" #: ../quodlibet/browsers/iradio.py:802 msgid "No stations found" msgstr "Nav atrasta neviena stacija" #: ../quodlibet/browsers/iradio.py:803 #, python-format msgid "No Internet radio stations were found at %s." msgstr "Netika atrasta neviena interneta radiostacija ar adresi %s." #: ../quodlibet/browsers/iradio.py:811 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:828 #, fuzzy msgid "Add to Favorites" msgstr "Pievienot repertuār_am" #: ../quodlibet/browsers/iradio.py:832 #, fuzzy msgid "Remove from Favorites" msgstr "Izņemt no _repertuāra" #: ../quodlibet/browsers/iradio.py:932 #, 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/media.py:36 msgid "Device Properties" msgstr "Ierīces īpašības" #: ../quodlibet/browsers/media.py:52 msgid "Device:" msgstr "Ierīce:" #: ../quodlibet/browsers/media.py:54 msgid "Not mounted" msgstr "Nav piemontēta" #: ../quodlibet/browsers/media.py:55 #, fuzzy msgid "Mount point:" msgstr "Montēšanas punkts:" #: ../quodlibet/browsers/media.py:61 ../quodlibet/qltk/cbes.py:40 msgid "_Name:" msgstr "_Nosaukums:" #: ../quodlibet/browsers/media.py:135 msgid "Media Devices" msgstr "Multivides ierīces" #: ../quodlibet/browsers/media.py:136 msgid "_Media Devices" msgstr "_Multivides ierīces" #. eject button #: ../quodlibet/browsers/media.py:224 ../quodlibet/browsers/media.py:378 msgid "_Eject" msgstr "Izgrūz_t" #: ../quodlibet/browsers/media.py:360 #, fuzzy msgid "_Properties" msgstr "Īpašības" #: ../quodlibet/browsers/media.py:365 #: ../quodlibet/browsers/playlists/main.py:464 msgid "_Rename" msgstr "Pā_rdēvēt" #: ../quodlibet/browsers/media.py:461 #, fuzzy, python-format msgid "%(used-size)s used, %(free-size)s available" msgstr "<b>%s</b> izmantoti, <b>%s</b> pieejami" #: ../quodlibet/browsers/media.py:479 #, fuzzy, python-format msgid "%s is not connected." msgstr "<b>%s</b> nav pievienots." #: ../quodlibet/browsers/media.py:499 #, fuzzy, python-format msgid "Copying %(song)s" msgstr "Kopē <b>%(song)s</b>" #: ../quodlibet/browsers/media.py:513 ../quodlibet/browsers/media.py:529 msgid "Unable to copy song" msgstr "Neizdevās pārkopēt dziesmu" #: ../quodlibet/browsers/media.py:514 msgid "There is not enough free space for this song." msgstr "Nav pietiekami daudz brīvas vietas šajai dziesmai." #: ../quodlibet/browsers/media.py:526 #, fuzzy, python-format msgid "%s could not be copied." msgstr "<b>%s</b> nevarēja tikt pārkopēta." #: ../quodlibet/browsers/media.py:545 msgid "Unable to delete songs" msgstr "Neizdevās izdzēst dziesmas" #: ../quodlibet/browsers/media.py:557 #, fuzzy, python-format msgid "Deleting %(song)s" msgstr "Dzēš <b>%(song)s</b>" #: ../quodlibet/browsers/media.py:575 #, fuzzy, python-format msgid "%s could not be deleted." msgstr "<b>%s</b> nevarēja tikt izdzēsta." #: ../quodlibet/browsers/media.py:579 msgid "Unable to delete song" msgstr "Neizdevās izdzēst dziesmu" #: ../quodlibet/browsers/media.py:594 #, fuzzy, python-format msgid "Ejecting %s failed." msgstr "Neizdevās izgrūzt <b>%s</b>." #: ../quodlibet/browsers/media.py:597 msgid "Unable to eject device" msgstr "Neizdevās izgrūzt ierīci" #: ../quodlibet/browsers/media.py:603 msgid "No device backend, Media Devices browser disabled." msgstr "Nav ierīču aizmugures, multivides ierīču pārlūks atslēgts." #: ../quodlibet/browsers/paned/main.py:40 ../quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "Sadalītais pārlūks" #: ../quodlibet/browsers/paned/main.py:41 msgid "_Paned Browser" msgstr "Sadalītais _pārlūks" #: ../quodlibet/browsers/paned/main.py:90 msgid "Select _All" msgstr "Iezīmēt visus" #: ../quodlibet/browsers/paned/models.py:104 ../quodlibet/qltk/pluginwin.py:122 #: ../quodlibet/qltk/pluginwin.py:164 msgid "All" msgstr "Visi" #: ../quodlibet/browsers/paned/prefs.py:67 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "<tt>%s</tt>" msgstr "" #: ../quodlibet/browsers/paned/prefs.py:162 msgid "_Wide Mode" msgstr "" #: ../quodlibet/browsers/paned/prefs.py:197 msgid "Paned Browser Preferences" msgstr "Sadalītā pārlūka iestatījumi" #: ../quodlibet/browsers/paned/prefs.py:204 msgid "Equal pane width" msgstr "" #: ../quodlibet/browsers/playlists/main.py:48 #: ../quodlibet/browsers/playlists/main.py:575 #: ../quodlibet/qltk/pluginwin.py:168 msgid "Playlists" msgstr "Repertuāri" #: ../quodlibet/browsers/playlists/main.py:49 msgid "_Playlists" msgstr "Re_pertuāri" #: ../quodlibet/browsers/playlists/main.py:152 msgid "_Remove from Playlist" msgstr "Izņemt no _repertuāra" #: ../quodlibet/browsers/playlists/main.py:215 #: ../quodlibet/browsers/playlists/main.py:576 msgid "_Import" msgstr "_Importēt" #: ../quodlibet/browsers/playlists/main.py:391 #: ../quodlibet/browsers/playlists/util.py:50 #: ../quodlibet/util/collection.py:570 msgid "New Playlist" msgstr "Jauns repertuārs" #: ../quodlibet/browsers/playlists/main.py:413 msgid "Unable to import playlist" msgstr "Neizdevās importēt repertuāru" #: ../quodlibet/browsers/playlists/main.py:414 msgid "Quod Libet can only import playlists in the M3U and PLS formats." msgstr "Quod Libet var importēt repertuārus tikai M3U un PLS formātā." #: ../quodlibet/browsers/playlists/main.py:565 msgid "Unable to rename playlist" msgstr "Neizdevās pārdēvēt repertuāru" #: ../quodlibet/browsers/playlists/main.py:576 msgid "Import Playlist" msgstr "Importēt repertuāru" #: ../quodlibet/browsers/playlists/menu.py:25 #, fuzzy msgid "_New Playlist…" msgstr "Jau_ns repertuārs" #: ../quodlibet/browsers/playlists/menu.py:86 #, 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:90 #, 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:33 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "" #: ../quodlibet/browsers/playlists/util.py:35 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" #: ../quodlibet/browsers/playlists/util.py:51 #, fuzzy msgid "Enter a name for the new playlist:" msgstr "Ievadiet jaunās mapes nosaukumu:" #: ../quodlibet/browsers/playlists/util.py:102 #, 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/search.py:33 msgid "_Limit Results" msgstr "_Limitēt rezultātus" #: ../quodlibet/browsers/search.py:48 msgid "Search Library" msgstr "Meklēt bibliotēkā" #: ../quodlibet/browsers/search.py:49 msgid "_Search Library" msgstr "_Meklēt bibliotēkā" #: ../quodlibet/browsers/soundcloud/main.py:38 #, fuzzy msgid "Soundcloud Browser" msgstr "Sadalītais pārlūks" #: ../quodlibet/browsers/soundcloud/main.py:39 msgid "Sound_cloud" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:59 #: ../quodlibet/qltk/searchbar.py:73 msgid "Search" msgstr "Meklēt" #: ../quodlibet/browsers/soundcloud/main.py:136 #, python-format msgid "Go to %s" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:380 #, fuzzy msgid "Connected" msgstr "vieta" #: ../quodlibet/browsers/soundcloud/main.py:381 #, python-format msgid "Quod Libet is now connected, <b>%s</b>!" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:393 #, python-format msgid "Log out of %s" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:395 msgid "Enter code…" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:396 #, python-format msgid "Log in to %s" msgstr "" #: ../quodlibet/browsers/soundcloud/util.py:86 msgid "Soundcloud authorisation" msgstr "" #: ../quodlibet/browsers/soundcloud/util.py:87 msgid "Enter Soundcloud auth code:" msgstr "" #: ../quodlibet/cli.py:50 #, fuzzy msgid "Quod Libet is not running (add '--run' to start it)" msgstr "Quod Libet nav palaists." #: ../quodlibet/cli.py:85 msgid "a music library and player" msgstr "mūzikas bibliotēka un atskaņotājs" #: ../quodlibet/cli.py:86 #, fuzzy msgid "[option]" msgstr "[opcijas]" #: ../quodlibet/cli.py:88 msgid "Print the playing song and exit" msgstr "Izdrukā pašreiz atskaņoto dziesmu un iziet" #: ../quodlibet/cli.py:89 msgid "Begin playing immediately" msgstr "Nekavējoties uzsāk atskaņošanu" #: ../quodlibet/cli.py:90 msgid "Don't show any windows on start" msgstr "" #: ../quodlibet/cli.py:93 msgid "Jump to next song" msgstr "Pāriet uz nākamo dziesmu" #: ../quodlibet/cli.py:95 msgid "Jump to previous song or restart if near the beginning" msgstr "" #: ../quodlibet/cli.py:96 msgid "Jump to previous song" msgstr "Pāriet uz iepriekšējo dziesmu" #: ../quodlibet/cli.py:97 msgid "Start playback" msgstr "Sākt atskaņošanu" #: ../quodlibet/cli.py:98 msgid "Pause playback" msgstr "Pauzēt atskaņošanu" #: ../quodlibet/cli.py:99 msgid "Toggle play/pause mode" msgstr "Pārslēgt atskaņošanas/pauzes režīmu" #: ../quodlibet/cli.py:100 #, fuzzy msgid "Stop playback" msgstr "Sākt atskaņošanu" #: ../quodlibet/cli.py:101 msgid "Turn up volume" msgstr "Palielināt skaļumu" #: ../quodlibet/cli.py:102 msgid "Turn down volume" msgstr "Samazināt skaļumu" #: ../quodlibet/cli.py:103 msgid "Print player status" msgstr "Izdrukāt atskaņotāja statusu" #: ../quodlibet/cli.py:104 msgid "Hide main window" msgstr "Slēpt galveno logu" #: ../quodlibet/cli.py:105 msgid "Show main window" msgstr "Rādīt galveno logu" #: ../quodlibet/cli.py:106 msgid "Toggle main window visibility" msgstr "Pārslēgt galvenā loga redzamību" #: ../quodlibet/cli.py:107 msgid "Focus the running player" msgstr "Fokusēties uz darbojošos atskaņotāju" #: ../quodlibet/cli.py:108 msgid "Remove active browser filters" msgstr "Noņemt aktīvos pārlūka filtrus" #: ../quodlibet/cli.py:109 msgid "Refresh and rescan library" msgstr "Atsvaidzināt un pārskenēt bibliotēku" #: ../quodlibet/cli.py:110 #, fuzzy msgid "List available browsers" msgstr "Atslēgt pārlūku" #: ../quodlibet/cli.py:111 msgid "Print the current playlist" msgstr "Izdrukāt pašreizējo repertuāru" #: ../quodlibet/cli.py:112 msgid "Print the contents of the queue" msgstr "Izdrukāt rindas saturu" #: ../quodlibet/cli.py:113 #, fuzzy msgid "Print the active text query" msgstr "Izdrukāt rindas saturu" #: ../quodlibet/cli.py:114 msgid "Start without plugins" msgstr "" #: ../quodlibet/cli.py:115 #, fuzzy msgid "Start Quod Libet if it isn't running" msgstr "Quod Libet nav palaists." #: ../quodlibet/cli.py:116 msgid "Exit Quod Libet" msgstr "Iziet no Quod Libet" #: ../quodlibet/cli.py:121 msgid "Seek within the playing song" msgstr "Meklēt pašreizējā dziesmā" #: ../quodlibet/cli.py:121 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: ../quodlibet/cli.py:122 #, fuzzy msgid "Set or toggle shuffle mode" msgstr "Pārslēgt atskaņošanas/pauzes režīmu" #: ../quodlibet/cli.py:123 msgid "Turn repeat off, on, or toggle it" msgstr "Izslēgt, ieslēgt vai pārslēgt atkārtošanu" #: ../quodlibet/cli.py:124 msgid "Set the volume" msgstr "Iestatīt skaļumu" #: ../quodlibet/cli.py:125 msgid "Search your audio library" msgstr "Meklēt jūsu audio bibliotēkā" #: ../quodlibet/cli.py:125 ../quodlibet/cli.py:137 ../quodlibet/cli.py:141 #: ../quodlibet/cli.py:143 msgid "query" msgstr "vaicājums" #: ../quodlibet/cli.py:126 msgid "Play a file" msgstr "Atskaņot failu" #: ../quodlibet/cli.py:126 ../quodlibet/cli.py:137 ../quodlibet/cli.py:143 #, fuzzy msgctxt "command" msgid "filename" msgstr "faila nosaukums" #: ../quodlibet/cli.py:127 msgid "Rate the playing song" msgstr "Novērtēt pašreiz atskaņoto dziesmu" #: ../quodlibet/cli.py:128 msgid "Set the current browser" msgstr "Iestatīt pašreizējo pārlūku" #: ../quodlibet/cli.py:129 #, fuzzy msgid "Stop after the playing song" msgstr "Novērtēt pašreiz atskaņoto dziesmu" #: ../quodlibet/cli.py:130 msgid "Open a new browser" msgstr "Atvērt jaunu pārlūku" #: ../quodlibet/cli.py:131 msgid "Show or hide the queue" msgstr "Rādīt vai slēpt rindu" #: ../quodlibet/cli.py:133 #, fuzzy msgid "Show or hide the main song list (deprecated)" msgstr "Rādīt vai slēpt galveno dziesmu sarakstu" #: ../quodlibet/cli.py:134 msgid "Filter on a random value" msgstr "Filtrēt pēc nejaušas vērtības" #: ../quodlibet/cli.py:134 #, fuzzy msgctxt "command" msgid "tag" msgstr "Tags" #: ../quodlibet/cli.py:135 msgid "Filter on a tag value" msgstr "Filtrēt pēc taga vērtības" #: ../quodlibet/cli.py:135 msgid "tag=value" msgstr "tags=vērtība" #: ../quodlibet/cli.py:136 msgid "Enqueue a file or query" msgstr "Ierindot failu vai vaicājumu" #: ../quodlibet/cli.py:138 msgid "Enqueue comma-separated files" msgstr "" #: ../quodlibet/cli.py:139 ../quodlibet/util/tags.py:147 msgid "filename" msgstr "faila nosaukums" #: ../quodlibet/cli.py:140 msgid "Print filenames of results of query to stdout" msgstr "" #: ../quodlibet/cli.py:142 msgid "Unqueue a file or query" msgstr "Atrindot failu vai vaicājumu" #: ../quodlibet/cli.py:203 #, python-format msgid "Invalid argument for '%s'." msgstr "Nederīgs arguments priekš '%s'." #: ../quodlibet/cli.py:204 ../quodlibet/util/__init__.py:190 #, python-format msgid "Try %s --help." msgstr "Mēģiniet %s --help." #: ../quodlibet/devices/_base.py:65 msgid "Unknown Device" msgstr "Nezināma ierīce" #: ../quodlibet/devices/__init__.py:32 #, fuzzy, python-format 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." #: ../quodlibet/devices/__init__.py:153 #, python-format msgid "%r is not a supported device." msgstr "%r nav atbalstīta ierīce." #: ../quodlibet/devices/__init__.py:245 ../quodlibet/devices/__init__.py:251 #, fuzzy, python-format msgid "Could not find '%s'." msgstr "%s: neizdevās atrast media-player-info." #: ../quodlibet/devices/__init__.py:450 msgid "Initializing device backend." msgstr "Inicializē ierīces aizmuguri." #: ../quodlibet/devices/__init__.py:451 #, python-format msgid "Trying '%s'" msgstr "Mēģina '%s'" #: ../quodlibet/devices/__init__.py:461 msgid "Couldn't connect to a device backend." msgstr "Neizdevās pieslēgties ierīces aizmugurei." #: ../quodlibet/devices/__init__.py:463 msgid "Device backend initialized." msgstr "Ierīces aizmugure inicializēta." #: ../quodlibet/devices/storage.py:57 #, fuzzy msgid "_Filename pattern:" msgstr "_Faila nosaukuma paraugs:" #: ../quodlibet/devices/storage.py:61 msgid "Copy _album covers" msgstr "Kopēt _albumu vākus" #: ../quodlibet/devices/storage.py:65 msgid "_Remove unused covers and directories" msgstr "_Dzēst nevajadzīgos vākus un mapes" #: ../quodlibet/errorreport/ui.py:60 #, fuzzy msgid "An Error Occurred" msgstr "Gadījās kļūda" #: ../quodlibet/errorreport/ui.py:62 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:72 msgid "File Bug Report" msgstr "" #: ../quodlibet/errorreport/ui.py:74 ../quodlibet/errorreport/ui.py:90 msgid "Submit Error Report" msgstr "" #: ../quodlibet/errorreport/ui.py:75 msgid "Quit Program" msgstr "" #: ../quodlibet/errorreport/ui.py:76 #, fuzzy msgid "Ignore Error" msgstr "Ignorēt vis_as kļūdas" #: ../quodlibet/errorreport/ui.py:80 msgid "Error details:" msgstr "" #: ../quodlibet/errorreport/ui.py:92 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:100 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "" #: ../quodlibet/errorreport/ui.py:109 msgid "_Send" msgstr "" #: ../quodlibet/errorreport/ui.py:115 #, fuzzy msgid "Short description…" msgstr "apraksts" #: ../quodlibet/errorreport/ui.py:118 msgid "Data to be sent:" msgstr "" #: ../quodlibet/exfalso.py:34 msgid "an audio tag editor" msgstr "audio tagu redaktors" #: ../quodlibet/exfalso.py:34 ../quodlibet/util/tags.py:148 msgid "directory" msgstr "mape" #: ../quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "" #: ../quodlibet/ext/covers/artwork_url.py:20 msgid "" "Downloads covers linked to by the artwork_url tag.This works with the " "Soundcloud browser." msgstr "" #: ../quodlibet/ext/covers/discogs.py:25 #, fuzzy msgid "Discogs Cover Source" msgstr "MusicBrainz celiņa ID" #: ../quodlibet/ext/covers/discogs.py:26 msgid "Downloads covers from Discogs." msgstr "" #: ../quodlibet/ext/covers/lastfm.py:22 msgid "Last.fm Cover Source" msgstr "" #: ../quodlibet/ext/covers/lastfm.py:23 msgid "Downloads covers from Last.fm's cover art archive." msgstr "" #: ../quodlibet/ext/covers/musicbrainz.py:19 #, fuzzy msgid "MusicBrainz Cover Source" msgstr "MusicBrainz celiņa ID" #: ../quodlibet/ext/covers/musicbrainz.py:20 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:25 msgid "Kana/Kanji Simple Inverter" msgstr "" #: ../quodlibet/ext/editing/kakasi.py:26 msgid "Converts kana/kanji to romaji before renaming." msgstr "" #: ../quodlibet/ext/editing/kakasi.py:35 msgid "Romanize _Japanese text" msgstr "" #: ../quodlibet/ext/editing/kakasi.py:63 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:19 msgid "" "Allows arbitrary regex substitutions (s///) 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:69 #, fuzzy msgid "Advanced Preferences" msgstr "Sadalītā pārlūka iestatījumi" #: ../quodlibet/ext/events/advanced_preferences.py:70 msgid "Allow editing of advanced config settings." msgstr "" #: ../quodlibet/ext/events/advanced_preferences.py:162 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:153 msgid "Top of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:154 msgid "Middle of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:155 msgid "Bottom of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:158 msgid "_Position:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:171 #, fuzzy msgid "_Cover size:" msgstr "Kopējais izmērs:" #: ../quodlibet/ext/events/animosd/prefs.py:177 #: ../quodlibet/ext/events/lyricswindow.py:334 ../quodlibet/qltk/prefs.py:266 #, fuzzy msgid "Display" msgstr "Rediģēt rādāmo" #: ../quodlibet/ext/events/animosd/prefs.py:190 msgid "_Font:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:195 msgid "Left" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:196 msgid "Center" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:197 #, fuzzy msgid "Right" msgstr "S_vars" #: ../quodlibet/ext/events/animosd/prefs.py:200 msgid "_Align text:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:206 msgid "Text" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:217 msgid "_Text:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:227 msgid "_Fill:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:232 #: ../quodlibet/ext/events/synchronizedlyrics.py:63 msgid "Colors" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:240 msgid "_Shadows" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:241 #, fuzzy msgid "_Outline" msgstr "_Izvades līnija:" #: ../quodlibet/ext/events/animosd/prefs.py:242 msgid "Rou_nded Corners" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:258 msgid "_Delay:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:264 #: ../quodlibet/qltk/pluginwin.py:172 msgid "Effects" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:270 #, fuzzy msgid "Ed_it Display Pattern…" msgstr "Rediģēt rādāmo" #: ../quodlibet/ext/events/animosd/prefs.py:274 #: ../quodlibet/ext/events/trayicon/prefs.py:78 #, fuzzy msgid "Preview" msgstr "_Priekšskats" #: ../quodlibet/ext/events/auto_library_update.py:136 msgid "Automatic Library Update" msgstr "" #: ../quodlibet/ext/events/auto_library_update.py:137 #, python-format msgid "Keeps your library up to date with inotify. Requires %s." 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 by Brian Nelson." 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/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:97 msgid "Equalizer" msgstr "" #: ../quodlibet/ext/events/equalizer.py:98 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:132 #, 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:138 #, python-format msgid "%.1f kHz" msgstr "" #: ../quodlibet/ext/events/equalizer.py:139 #: ../quodlibet/ext/gstreamer/crossfeed.py:93 #: ../quodlibet/ext/gstreamer/karaoke.py:95 #, python-format msgid "%d Hz" msgstr "" #: ../quodlibet/ext/events/equalizer.py:173 #: ../quodlibet/ext/gstreamer/crossfeed.py:112 #, fuzzy, python-format msgid "%.1f dB" msgstr "%d sekunde" #: ../quodlibet/ext/events/equalizer.py:192 #: ../quodlibet/ext/gstreamer/crossfeed.py:31 #, fuzzy msgid "Custom" msgstr "_Pielāgots" #: ../quodlibet/ext/events/equalizer.py:199 #, fuzzy msgid "_Clear" msgstr "_Notīrīt kļūdas" #. Translators: statuses relating to Instant Messenger apps #: ../quodlibet/ext/events/gajim_status.py:27 msgid "online" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:28 msgid "offline" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:29 msgid "chat" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:30 msgid "away" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:31 msgid "xa" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:32 msgid "invisible" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:37 msgid "Gajim Status Message" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:38 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:45 #: ../quodlibet/ext/events/telepathy_status.py:69 msgid "paused" 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:160 msgid "Add '[paused]'" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:163 msgid "If checked, '[paused]' will be added to status message on pause." msgstr "" #: ../quodlibet/ext/events/gajim_status.py:187 msgid "Statuses for which message will be changed" msgstr "" #: ../quodlibet/ext/events/headphonemon.py:156 msgid "Pause on Headphone Unplug" msgstr "" #: ../quodlibet/ext/events/headphonemon.py:157 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" #: ../quodlibet/ext/events/inhibit.py:41 msgid "Inhibit Screensaver" msgstr "" #: ../quodlibet/ext/events/inhibit.py:42 msgid "Prevents the GNOME screensaver from activating while a song is playing." msgstr "" #: ../quodlibet/ext/events/inhibit.py:51 #, fuzzy msgid "Music is playing" msgstr "Mūzikas atskaņotājs" #: ../quodlibet/ext/events/iradiolog.py:16 #, fuzzy msgid "Internet Radio Log" msgstr "Interneta radio" #: ../quodlibet/ext/events/iradiolog.py:17 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" #: ../quodlibet/ext/events/jep118.py:29 msgid "JEP-118" msgstr "" #: ../quodlibet/ext/events/jep118.py:30 msgid "Outputs a Jabber User Tunes file to ~/.quodlibet/jabber." 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 msgid "A restart is required for any changes to take effect" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:199 #, fuzzy msgid "No active song" msgstr "Neizdevās saglabāt dziesmu" #: ../quodlibet/ext/events/lyricswindow.py:215 #, fuzzy msgid "No lyrics found" msgstr "Nav atrasts neviens spraudnis." #: ../quodlibet/ext/events/lyricswindow.py:227 #, fuzzy msgid "Lyrics:" msgstr "Dziesmas vārdi" #: ../quodlibet/ext/events/lyricswindow.py:284 msgid "_Zoom level:" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:302 msgid "URL:" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:307 msgid "Revert to default" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:322 msgid "Search via above URL if the lyrics couldn't be found in LyricsWikia." msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:339 #, fuzzy msgid "Alternate search" msgstr "Notīrīt meklējumu lauku" #: ../quodlibet/ext/events/lyricswindow.py:347 #, fuzzy msgid "Lyrics Window" msgstr "Dziesmas vārdi" #: ../quodlibet/ext/events/lyricswindow.py:348 msgid "Shows a window containing lyrics of the playing song." msgstr "" #: ../quodlibet/ext/events/mediaserver.py:38 msgid "UPnP AV Media Server" msgstr "" #: ../quodlibet/ext/events/mediaserver.py:39 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." 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:39 msgid "" "Allows control of Quod Libet using the MPRIS 1.0/2.0 D-Bus Interface " "Specification." msgstr "" #: ../quodlibet/ext/events/mpris/__init__.py:45 #: ../quodlibet/ext/events/trayicon/prefs.py:30 #, fuzzy msgid "Hide main window on close" msgstr "Slēpt galveno logu" #: ../quodlibet/ext/events/mpris/__init__.py:48 #: ../quodlibet/ext/events/themeswitcher.py:84 #: ../quodlibet/ext/gstreamer/compressor.py:99 #: ../quodlibet/ext/gstreamer/crossfeed.py:136 #: ../quodlibet/ext/gstreamer/karaoke.py:99 #: ../quodlibet/ext/gstreamer/pitch.py:83 ../quodlibet/qltk/prefs.py:688 #, fuzzy msgid "Preferences" msgstr "Iestatījumi" #: ../quodlibet/ext/events/mqtt.py:50 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/mqtt.py:56 msgid "MQTT Publisher" msgstr "" #: ../quodlibet/ext/events/mqtt.py:57 msgid "Publishes status messages to an MQTT topic." msgstr "" #: ../quodlibet/ext/events/mqtt.py:122 msgid "Broker hostname" msgstr "" #: ../quodlibet/ext/events/mqtt.py:122 msgid "broker hostname / IP" msgstr "" #: ../quodlibet/ext/events/mqtt.py:124 msgid "Broker port" msgstr "" #: ../quodlibet/ext/events/mqtt.py:124 msgid "broker port" msgstr "" #: ../quodlibet/ext/events/mqtt.py:126 msgid "Topic" msgstr "" #: ../quodlibet/ext/events/mqtt.py:128 #, fuzzy msgid "Playing Pattern" msgstr "paraugs" #: ../quodlibet/ext/events/mqtt.py:130 msgid "Status text when a song is started." msgstr "" #: ../quodlibet/ext/events/mqtt.py:132 #, fuzzy msgid "Paused Pattern" msgstr "paraugs" #: ../quodlibet/ext/events/mqtt.py:134 msgid "Text when a song is paused." msgstr "" #: ../quodlibet/ext/events/mqtt.py:136 #, fuzzy msgid "No-song Text" msgstr "%d dziesma" #: ../quodlibet/ext/events/mqtt.py:138 msgid "Plain text for when there is no current song" msgstr "" #: ../quodlibet/ext/events/mqtt.py:149 #, fuzzy msgid "MQTT Configuration" msgstr "Izvades žurnāls" #: ../quodlibet/ext/events/mqtt.py:153 #, fuzzy msgid "Status Text" msgstr "paraugs" #: ../quodlibet/ext/events/mqtt.py:185 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "" #: ../quodlibet/ext/events/mqtt.py:189 #, 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:192 #, fuzzy msgid "Connection error" msgstr "vieta" #: ../quodlibet/ext/events/notify.py:80 msgid "Notification text" msgstr "" #: ../quodlibet/ext/events/notify.py:88 #, fuzzy msgid "_Title:" msgstr "Nosaukums" #: ../quodlibet/ext/events/notify.py:99 ../quodlibet/ext/events/notify.py:128 msgid "Revert to default pattern" msgstr "" #: ../quodlibet/ext/events/notify.py:118 msgid "_Body:" msgstr "" #: ../quodlibet/ext/events/notify.py:138 msgid "_Show notification" msgstr "" #: ../quodlibet/ext/events/notify.py:156 msgid "Show notifications" msgstr "" #: ../quodlibet/ext/events/notify.py:162 msgid "Only on <i>_manual</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:170 msgid "Only on <i>_automatic</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:178 msgid "On <i>a_ll</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:196 msgid "Only when the main window is not _focused" msgstr "" #: ../quodlibet/ext/events/notify.py:204 msgid "Show \"_Next\" button" msgstr "" #: ../quodlibet/ext/events/notify.py:236 msgid "Connection Error" msgstr "" #: ../quodlibet/ext/events/notify.py:237 ../quodlibet/ext/events/notify.py:391 #: ../quodlibet/ext/events/notify.py:433 #, fuzzy msgid "Couldn't connect to notification daemon." msgstr "Neizdevās pieslēgties ierīces aizmugurei." #: ../quodlibet/ext/events/notify.py:251 msgid "Song Notifications" msgstr "" #: ../quodlibet/ext/events/notify.py:252 msgid "Displays a notification when the song changes." msgstr "" #: ../quodlibet/ext/events/notify.py:415 ../quodlibet/qltk/unity.py:65 msgid "Next" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:178 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:254 #, fuzzy, python-format msgid "Could not contact service '%s'." msgstr "Neizdevās pieslēgties ierīces aizmugurei." #: ../quodlibet/ext/events/qlscrobbler.py:260 msgid "Authentication failed: invalid URL." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:277 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:282 msgid "Client is banned. Contact the author." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:286 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:351 msgid "AudioScrobbler Submission" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:352 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:450 msgid "Authentication successful." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:462 #, fuzzy msgid "_Service:" msgstr "Ierīce:" #: ../quodlibet/ext/events/qlscrobbler.py:462 msgid "_URL:" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:462 #, fuzzy msgid "User_name:" msgstr "_Nosaukums:" #: ../quodlibet/ext/events/qlscrobbler.py:463 msgid "_Password:" msgstr "" #. Translators: Other service #: ../quodlibet/ext/events/qlscrobbler.py:479 #, fuzzy msgid "Other…" msgstr "C_iti:" #. verify data #: ../quodlibet/ext/events/qlscrobbler.py:517 msgid "_Verify account data" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:522 #: ../quodlibet/ext/songsmenu/lastfmsync.py:304 msgid "Account" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:530 #, fuzzy msgid "_Artist pattern:" msgstr "_Mākslinieks" #: ../quodlibet/ext/events/qlscrobbler.py:530 #, fuzzy msgid "_Title pattern:" msgstr "_Faila nosaukuma paraugs:" #: ../quodlibet/ext/events/qlscrobbler.py:531 msgid "Exclude _filter:" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:549 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:559 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:568 msgid "Songs matching this filter will not be submitted." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:576 msgid "_Offline mode (don't submit anything)" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:580 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:27 #, fuzzy msgid "Random Album Playback" msgstr "Nejaušs al_bums" #: ../quodlibet/ext/events/randomalbum.py:28 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:38 msgid "Rated higher" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:39 msgid "Played more often" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:40 msgid "Skipped more often" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:41 msgid "Played more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:42 msgid "Started more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:43 msgid "Added more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:44 #, fuzzy msgid "Longer albums" msgstr "albumi" #: ../quodlibet/ext/events/randomalbum.py:83 msgid "seconds before starting next album" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:87 #, fuzzy msgid "Weights" msgstr "S_vars" #: ../quodlibet/ext/events/randomalbum.py:89 msgid "Play some albums more than others" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:103 msgid "avoid" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:114 msgid "prefer" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:201 #, fuzzy msgid "Random Album" msgstr "Nejaušs al_bums" #: ../quodlibet/ext/events/randomalbum.py:202 #, python-format msgid "Waiting to start %s" msgstr "" #: ../quodlibet/ext/events/rbimport.py:114 #, fuzzy msgid "Import Failed" msgstr "Importēt repertuāru" #: ../quodlibet/ext/events/rbimport.py:119 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "" #: ../quodlibet/ext/events/rbimport.py:127 msgid "Rhythmbox Import" msgstr "" #: ../quodlibet/ext/events/rbimport.py:128 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "" #: ../quodlibet/ext/events/rbimport.py:132 #, fuzzy msgid "Start Import" msgstr "_Importēt" #: ../quodlibet/ext/events/screensaver.py:25 msgid "Screensaver Pause" msgstr "" #: ../quodlibet/ext/events/screensaver.py:26 msgid "Pauses playback while the GNOME screensaver is active." msgstr "" #: ../quodlibet/ext/events/searchprovider.py:73 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "" #: ../quodlibet/ext/events/searchprovider.py:79 msgid "GNOME Search Provider" msgstr "" #: ../quodlibet/ext/events/searchprovider.py:80 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/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:29 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:57 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:58 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:34 #, fuzzy msgid "Synchronized Lyrics" msgstr "Dziesmas vārdi" #: ../quodlibet/ext/events/synchronizedlyrics.py:35 msgid "Shows synchronized lyrics from .lrc file with same name as the track." msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:66 msgid "Text:" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:76 msgid "Background:" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:87 msgid "Font" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:90 msgid "Size (px):" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:62 msgid "Telepathy Status Messages" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:63 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:122 #, fuzzy msgid "Playing:" msgstr "Pašreiz neatskaņo" #: ../quodlibet/ext/events/telepathy_status.py:123 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:139 msgid "Paused:" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:140 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:156 msgid "Plain text for status when there is no current song" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:157 #, fuzzy msgid "No song:" msgstr "%d dziesma" #. Frame #: ../quodlibet/ext/events/telepathy_status.py:164 #, 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/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:77 #: ../quodlibet/ext/events/trayicon/prefs.py:98 #: ../quodlibet/ext/events/trayicon/systemtray.py:177 #: ../quodlibet/qltk/info.py:47 msgid "Not playing" msgstr "Pašreiz neatskaņo" #: ../quodlibet/ext/events/trayicon/__init__.py:53 msgid "Tray Icon" msgstr "" #: ../quodlibet/ext/events/trayicon/__init__.py:54 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:183 #: ../quodlibet/qltk/quodlibetwindow.py:1046 #: ../quodlibet/qltk/quodlibetwindow.py:1238 #, fuzzy msgid "_Play" msgstr "Re_pertuāri" #: ../quodlibet/ext/events/trayicon/menu.py:63 #: ../quodlibet/qltk/quodlibetwindow.py:185 #: ../quodlibet/qltk/quodlibetwindow.py:1240 ../quodlibet/qltk/wlw.py:51 #, fuzzy msgid "P_ause" msgstr "Atskaņotājs" #: ../quodlibet/ext/events/trayicon/menu.py:68 #: ../quodlibet/qltk/quodlibetwindow.py:190 #: ../quodlibet/qltk/quodlibetwindow.py:1041 #, fuzzy msgid "Pre_vious" msgstr "_Priekšskats" #: ../quodlibet/ext/events/trayicon/menu.py:71 #: ../quodlibet/qltk/quodlibetwindow.py:194 #: ../quodlibet/qltk/quodlibetwindow.py:1051 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:1012 #, fuzzy msgid "Open _Browser" msgstr "Atvērt jaunu pārlūku" #: ../quodlibet/ext/events/trayicon/menu.py:103 #: ../quodlibet/qltk/quodlibetwindow.py:1031 ../quodlibet/qltk/songsmenu.py:411 msgid "Edit _Tags" msgstr "Rediģēt _tagus" #: ../quodlibet/ext/events/trayicon/menu.py:112 #: ../quodlibet/qltk/quodlibetwindow.py:975 ../quodlibet/qltk/songsmenu.py:424 msgid "_Information" msgstr "_Informācija" #: ../quodlibet/ext/events/trayicon/menu.py:114 #: ../quodlibet/qltk/songsmenu.py:340 #, fuzzy msgid "Play_lists" msgstr "Repertuāri" #: ../quodlibet/ext/events/trayicon/menu.py:132 #: ../quodlibet/qltk/quodlibetwindow.py:1026 msgid "_Quit" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:32 ../quodlibet/qltk/prefs.py:69 msgid "Behavior" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:42 msgid "Scroll wheel adjusts volume" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel changes song" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll _Wheel" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:84 #, fuzzy msgid "Tooltip Display" msgstr "Rediģēt rādāmo" #: ../quodlibet/ext/events/viewlyrics.py:23 #, fuzzy msgid "View Lyrics" msgstr "Dziesmas vārdi" #: ../quodlibet/ext/events/viewlyrics.py:24 msgid "Automatically displays lyrics beneath the song list in the main window." msgstr "" #: ../quodlibet/ext/events/viewlyrics.py:29 #, fuzzy msgid "_Lyrics" msgstr "Dziesmas vārdi" #: ../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:406 msgid "Waveform Seek Bar" msgstr "" #: ../quodlibet/ext/events/waveformseekbar.py:410 msgid "A seekbar in the shape of the waveform of the current song." msgstr "" #: ../quodlibet/ext/events/waveformseekbar.py:443 msgid "Override foreground color:" msgstr "" #: ../quodlibet/ext/events/write_cover.py:32 msgid "Picture Saver" msgstr "" #: ../quodlibet/ext/events/write_cover.py:33 msgid "Saves the cover image of the current song to a file." msgstr "" #: ../quodlibet/ext/events/write_cover.py:66 #, fuzzy msgid "File:" msgstr "Faili" #: ../quodlibet/ext/gstreamer/compressor.py:20 msgid "_Threshold:" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:21 msgid "Threshold until the filter is activated" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:22 msgid "R_atio:" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:22 msgid "Compression ratio" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:74 #: ../quodlibet/ext/gstreamer/karaoke.py:91 #, python-format msgid "%d %%" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:105 msgid "Audio Compressor" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:106 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:19 #, fuzzy msgid "_Preset:" msgstr "_Priekšskats" #: ../quodlibet/ext/gstreamer/crossfeed.py:19 #, fuzzy msgid "Filter preset" msgstr "Filtrēt pēc māksliniek_a" #: ../quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Frequency cut:" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Low-pass filter cut frequency" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed _level:" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed level" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:25 msgid "Default" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Chu Moy" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Jan Meier" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:31 #, fuzzy msgid "Custom settings" msgstr "_Pielāgots" #: ../quodlibet/ext/gstreamer/crossfeed.py:152 msgid "Crossfeed" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:153 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:20 #, fuzzy msgid "Filter _band:" msgstr "Filtrēt pēc žanra" #: ../quodlibet/ext/gstreamer/karaoke.py:21 msgid "The Frequency band of the filter" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:22 #, fuzzy msgid "Filter _width:" msgstr "Filtrēt pēc māksliniek_a" #: ../quodlibet/ext/gstreamer/karaoke.py:23 msgid "The Frequency width of the filter" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:24 msgid "_Level:" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:24 msgid "Level of the effect" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:105 msgid "Karaoke" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:106 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:20 msgid "R_ate:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:21 msgid "_Tempo:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:22 msgid "_Pitch:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:89 #, fuzzy msgid "Audio Pitch / Speed" msgstr "Audio barotnes" #: ../quodlibet/ext/gstreamer/pitch.py:90 #, fuzzy msgid "Controls the pitch of an audio stream." msgstr "Ievadiet audio barotnes adresi:" #: ../quodlibet/ext/playlist/export_to_folder.py:29 #: ../quodlibet/ext/playlist/export_to_folder.py:97 #: ../quodlibet/ext/playlist/export_to_folder.py:138 #, fuzzy msgid "Export Playlist to Folder" msgstr "Importēt repertuāru" #: ../quodlibet/ext/playlist/export_to_folder.py:38 #, fuzzy msgid "_Export" msgstr "_Importēt" #: ../quodlibet/ext/playlist/export_to_folder.py:43 #, fuzzy msgid "Destination folder:" msgstr "Nav atrasta neviena stacija" #: ../quodlibet/ext/playlist/export_to_folder.py:58 #, 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:156 #, fuzzy msgid "Default filename pattern:" msgstr "_Faila nosaukuma paraugs:" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:23 msgid "Export to Squeezebox" msgstr "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:25 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 "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Export playlist to Squeezebox" msgstr "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:80 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 "" "Playback follows your selection, or the next song in the list once exhausted." msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:22 msgid "Playcount Equalizer" msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:23 msgid "Shuffle, preferring 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/queue.py:19 #, fuzzy msgid "Queue Only" msgstr "Ierindots" #: ../quodlibet/ext/playorder/queue.py:21 msgid "" "Limits playing of songs to the queue. Select this play order in the main " "window, then double-clicking any song will enqueue it instead of playing." msgstr "" #: ../quodlibet/ext/playorder/reverse.py:14 #, fuzzy msgid "Reverse" msgstr "Nekad" #: ../quodlibet/ext/playorder/reverse.py:16 msgid "Reverses the play order of songs." msgstr "" #: ../quodlibet/ext/playorder/skip_songs.py:25 #, fuzzy msgid "Skip Songs" msgstr "Nav dziesmu" #: ../quodlibet/ext/playorder/skip_songs.py:27 msgid "" "Playback skips over songs with a rating equal or below a given threshold." msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:30 msgid "Repeat Each Track" msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:32 msgid "Shuffle songs, but repeat every track a set number of times." msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:51 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. Syntax is '@(if: " "condition, then, else)'." msgstr "" #: ../quodlibet/ext/query/pythonexpression.py:14 msgid "Python Query" msgstr "" #: ../quodlibet/ext/query/pythonexpression.py:15 msgid "" "Use Python expressions in queries. Syntax is '@(python: expression)'. The " "variable 's' is the song being matched." msgstr "" #: ../quodlibet/ext/query/savedsearch.py:19 #, fuzzy msgid "Include Saved Search" msgstr "Saglabātās vērtības" #: ../quodlibet/ext/query/savedsearch.py:20 msgid "" "Include the results of a saved search as part of another query. Syntax is " "'@(saved: search name)'." 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:116 msgid "Port:" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:121 #, fuzzy msgid "Username:" msgstr "Pā_rdēvēt" #: ../quodlibet/ext/_shared/squeezebox/base.py:126 msgid "Password:" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:130 msgid "Library directory the server connects to." msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:132 #, fuzzy msgid "Library path:" msgstr "Bibliotēka" #. Add verify button #: ../quodlibet/ext/_shared/squeezebox/base.py:141 msgid "_Verify settings" msgstr "" #. Server settings Frame #: ../quodlibet/ext/_shared/squeezebox/base.py:147 msgid "Squeezebox Server" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:150 msgid "Debug" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:26 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:28 msgid "unidentified Squeezebox server" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:37 #, 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:20 #: ../quodlibet/ext/songsmenu/importexport.py:34 #: ../quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:329 #, fuzzy msgid "Fit image to _window" msgstr "Slēpt galveno logu" #. Both labels #: ../quodlibet/ext/songsmenu/albumart.py:338 msgid "_Program:" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:343 msgid "_Edit image after saving" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:345 #, fuzzy msgid "File_name:" msgstr "Faila nosaukums" #: ../quodlibet/ext/songsmenu/albumart.py:457 msgid "Saving failed" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:458 #, fuzzy, python-format msgid "Unable to save \"%s\"." msgstr "Neizdevās saglabāt dziesmu" #: ../quodlibet/ext/songsmenu/albumart.py:556 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:613 #, fuzzy msgid "Album Art Downloader" msgstr "Albumu saraksts" #: ../quodlibet/ext/songsmenu/albumart.py:666 #, python-format msgid "from %(source)s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:669 #, python-format msgid "Resolution: %s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:672 #, fuzzy, python-format msgid "Size: %s" msgstr "Izmērs" #: ../quodlibet/ext/songsmenu/albumart.py:690 #, fuzzy msgid "_Search" msgstr "_Meklēt:" #: ../quodlibet/ext/songsmenu/albumart.py:741 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:451 #, fuzzy msgid "Searching…" msgstr "Meklēt" #: ../quodlibet/ext/songsmenu/albumart.py:804 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:922 #, fuzzy msgid "Download Album Art" msgstr "Albumu saraksts" #: ../quodlibet/ext/songsmenu/albumart.py:923 msgid "Downloads album covers from various websites." msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:936 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 #: ../quodlibet/qltk/downloader.py:52 msgid "Filename" msgstr "Faila nosaukums" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:130 #, fuzzy msgid "Disc" msgstr "_Disks" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:131 #: ../quodlibet/ext/songsmenu/replaygain.py:404 #: ../quodlibet/qltk/tracknumbers.py:92 msgid "Track" msgstr "Celiņš" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:132 #, 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:447 msgid "Please enter a query." msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:465 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:496 msgid "Error encountered. Please retry." msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:472 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:488 msgid "Loading result…" msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:475 #, fuzzy msgid "No results found." msgstr "Nav atrasts neviens spraudnis." #: ../quodlibet/ext/songsmenu/browsefolders.py:159 #, fuzzy msgid "Browse Folders" msgstr "Pārlūki" #: ../quodlibet/ext/songsmenu/browsefolders.py:160 msgid "Opens the songs' folders in a file manager." msgstr "" #: ../quodlibet/ext/songsmenu/browsefolders.py:172 #, fuzzy msgid "Unable to open folders" msgstr "Neizdevās izveidot mapi" #: ../quodlibet/ext/songsmenu/browsefolders.py:173 msgid "No program available to open folders." msgstr "" #: ../quodlibet/ext/songsmenu/console.py:40 msgid "Python Console" msgstr "" #: ../quodlibet/ext/songsmenu/console.py:41 msgid "Interactive Python console." msgstr "" #: ../quodlibet/ext/songsmenu/console.py:72 msgid "You can access the following objects by default:" msgstr "" #: ../quodlibet/ext/songsmenu/console.py:82 msgid "Your current working directory is:" 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:55 #, fuzzy msgid "pattern" msgstr "Nederīgs paraugs" #: ../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:91 #, fuzzy msgid "Input value" msgstr "Nederīga vērtība" #: ../quodlibet/ext/songsmenu/custom_commands.py:92 #, python-format msgid "Value for %s?" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:136 #, fuzzy msgid "Custom Commands" msgstr "_Pielāgots" #: ../quodlibet/ext/songsmenu/custom_commands.py:137 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:188 #: ../quodlibet/ext/songsmenu/custom_commands.py:198 #: ../quodlibet/ext/songsmenu/custom_commands.py:252 msgid "Edit Custom Commands" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:199 msgid "" "Supports QL patterns\n" "eg <tt><~artist~title></tt>" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:283 #, fuzzy, python-format msgid "Unable to run custom command %s" msgstr "Neizdevās pārkopēt dziesmas" #: ../quodlibet/ext/songsmenu/duplicates.py:290 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: ../quodlibet/ext/songsmenu/duplicates.py:343 msgid "Collapse / Expand all" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:347 #, python-format msgid "Duplicate key expression is '%s'" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:363 #, fuzzy msgid "Duplicates Browser" msgstr "Atslēgt pārlūku" #: ../quodlibet/ext/songsmenu/duplicates.py:364 msgid "Finds and displays similarly tagged versions of songs." msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:407 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:409 msgid "_Group duplicates by:" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:414 msgid "Duplicate Key" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:419 msgid "Remove _Whitespace" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:420 #, fuzzy msgid "Remove _Diacritics" msgstr "_Vērtējums" #: ../quodlibet/ext/songsmenu/duplicates.py:421 #, fuzzy msgid "Remove _Punctuation" msgstr "_Vērtējums" #: ../quodlibet/ext/songsmenu/duplicates.py:422 msgid "Case _Insensitive" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:430 msgid "Matching options" msgstr "" #. Create a dialog. #: ../quodlibet/ext/songsmenu/editplaycount.py:19 #: ../quodlibet/ext/songsmenu/editplaycount.py:41 #, fuzzy msgid "Edit Playcount" msgstr "Rediģēt rādāmo" #: ../quodlibet/ext/songsmenu/editplaycount.py:20 msgid "" "Edit a song's ~#playcount and ~#skipcount.\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's ~#playcount to 0, the ~#lastplayed and ~#laststarted " "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:68 msgid "Play Count" msgstr "" #: ../quodlibet/ext/songsmenu/editplaycount.py:69 msgid "Skip Count" msgstr "" #: ../quodlibet/ext/songsmenu/embedded.py:24 msgid "Edit Embedded Images" msgstr "" #: ../quodlibet/ext/songsmenu/embedded.py:25 msgid "Removes or replaces embedded images." msgstr "" #: ../quodlibet/ext/songsmenu/embedded.py:78 #, fuzzy msgid "_Remove all Images" msgstr "_Vērtējums" #: ../quodlibet/ext/songsmenu/embedded.py:82 msgid "_Embed Current 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:41 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 #: ../quodlibet/qltk/downloader.py:67 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" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" 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 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:49 msgid "Generating fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:63 msgid "_Details" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:85 msgid "_Submit" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:115 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:118 msgid "Fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Songs with MBIDs:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with sufficient tags:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs to submit:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:162 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:178 msgid "Submitting fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:186 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/id3tlen.py:21 msgid "Fix MP3 Duration" msgstr "" #: ../quodlibet/ext/songsmenu/id3tlen.py:22 msgid "" "Removes TLEN frames from ID3 tags which can be the cause for invalid song " "durations." msgstr "" #: ../quodlibet/ext/songsmenu/ifp.py:20 msgid "Send to iFP" msgstr "" #: ../quodlibet/ext/songsmenu/ifp.py:21 msgid "Uploads songs to an iRiver iFP device." msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:51 msgid "Export Metadata" msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:52 msgid "Exports metadata of selected songs as a .tags file." msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:92 #, fuzzy msgid "Import Metadata" msgstr "Importēt repertuāru" #: ../quodlibet/ext/songsmenu/importexport.py:93 msgid "Imports metadata for selected songs from a .tags file." msgstr "" #: ../quodlibet/ext/songsmenu/k3b.py:23 msgid "Burn CD" msgstr "" #: ../quodlibet/ext/songsmenu/k3b.py:24 msgid "Burns CDs with K3b, Brasero or xfburn." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:96 msgid "Updating chart list." msgstr "" #. No charts to fetch, no update scheduled. #: ../quodlibet/ext/songsmenu/lastfmsync.py:114 msgid "Already up-to-date." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:121 #, python-format msgid "Fetching chart for week of %s." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:143 msgid "Sync complete." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:149 #, fuzzy msgid "Error during sync" msgstr "Kļūda ielādējot %r" #: ../quodlibet/ext/songsmenu/lastfmsync.py:214 #: ../quodlibet/ext/songsmenu/lastfmsync.py:244 msgid "Last.fm Sync" msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:245 msgid "Updates your library's statistics from your Last.fm profile." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:293 #, 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 "" #. Create a dialog. #: ../quodlibet/ext/songsmenu/migratemetadata.py:29 #: ../quodlibet/ext/songsmenu/migratemetadata.py:38 #, fuzzy msgid "Migrate Metadata" msgstr "Importēt repertuāru" #: ../quodlibet/ext/songsmenu/migratemetadata.py:32 msgid "Copies the quodlibet-specific metadata between songs." msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:45 msgid "_Copy" msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:47 msgid "_Paste" msgstr "" #. Create the tag table. #: ../quodlibet/ext/songsmenu/migratemetadata.py:57 #, fuzzy msgid "Information to copy/paste" msgstr "Informācija" #. Create the indexing box. #: ../quodlibet/ext/songsmenu/migratemetadata.py:79 msgid "Map tracks by disc and track number" msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:80 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 "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:96 #, python-format msgid "There is %d stored track." msgid_plural "There are %d stored tracks." msgstr[0] "" msgstr[1] "" msgstr[2] "" #: ../quodlibet/ext/songsmenu/playlist.py:31 #, fuzzy msgid "Export as Playlist" msgstr "Importēt repertuāru" #: ../quodlibet/ext/songsmenu/playlist.py:32 msgid "Exports songs to an M3U or PLS playlist." msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:77 msgid "Use relative paths" msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:77 msgid "Use absolute paths" msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:132 #, fuzzy msgid "Unable to export playlist" msgstr "Neizdevās importēt repertuāru" #: ../quodlibet/ext/songsmenu/playlist.py:133 #, fuzzy, python-format msgid "Writing to <b>%s</b> 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:362 msgid "ReplayGain Analyzer" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:418 msgid "Progress" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:433 msgid "Gain" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:448 msgid "Peak" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:463 #, python-format msgid "There is <b>%(to-process)s</b> album to update (of %(all)s)" msgid_plural "There are <b>%(to-process)s</b> albums to update (of %(all)s)" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: ../quodlibet/ext/songsmenu/replaygain.py:578 msgid "Replay Gain" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:579 msgid "" "Analyzes and updates ReplayGain information, using GStreamer. Results are " "grouped by album." msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:617 msgid "always" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:618 msgid "if <b>any</b> RG tags are missing" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:620 msgid "if <b>album</b> RG tags are missing" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:637 msgid "_Process albums:" msgstr "" #. Server settings Frame #: ../quodlibet/ext/songsmenu/replaygain.py:649 #, 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 "" #. TRANSLATORS: BPM mean "beats per minute" #: ../quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "" #: ../quodlibet/ext/songsmenu/tapbpm.py:32 #: ../quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" 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:172 #: ../quodlibet/ext/songsmenu/tapbpm.py:179 msgid "Tap BPM" msgstr "" #: ../quodlibet/ext/songsmenu/tapbpm.py:173 #, fuzzy msgid "Tap BPM for the selected song." msgstr "Neizdevās izdzēst dziesmas" #: ../quodlibet/ext/songsmenu/website_search.py:35 #, fuzzy msgid "Website Search" msgstr "Meklēt" #: ../quodlibet/ext/songsmenu/website_search.py:36 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern-example)s." msgstr "" #: ../quodlibet/ext/songsmenu/website_search.py:78 #, fuzzy msgid "Search URL patterns" msgstr "paraugs" #: ../quodlibet/ext/songsmenu/website_search.py:88 #, fuzzy msgid "Edit search URLs" msgstr "Rediģēt saglabātās vērtības..." #. Add link to editor #: ../quodlibet/ext/songsmenu/website_search.py:114 #, fuzzy msgid "Configure Searches…" msgstr "Iekrā_sot meklējamos terminus" #: ../quodlibet/ext/songsmenu/wikipedia.py:46 #, python-format msgid "Search at %(website)s" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:63 msgid "Search Artist in Wikipedia" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:64 msgid "" "Opens a browser window with Wikipedia article on the playing song artist." msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:71 msgid "Search Album in Wikipedia" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:72 msgid "" "Opens a browser window with Wikipedia article on the playing song album." msgstr "" #. then (try to) load all new files #: ../quodlibet/library/libraries.py:650 ../quodlibet/library/libraries.py:660 #: ../quodlibet/library/libraries.py:726 ../quodlibet/library/libraries.py:745 #: ../quodlibet/qltk/information.py:268 ../quodlibet/qltk/prefs.py:639 #: ../quodlibet/util/library.py:124 msgid "Library" msgstr "Bibliotēka" #: ../quodlibet/library/libraries.py:650 msgid "Checking mount points" msgstr "Pārbauda montēšanas punktus" #: ../quodlibet/library/libraries.py:660 msgid "Scanning library" msgstr "Skenē bibliotēku" #: ../quodlibet/library/libraries.py:725 #, python-format msgid "Scanning %s" msgstr "Skenē %s" #: ../quodlibet/library/libraries.py:745 msgid "Loading files" msgstr "" #: ../quodlibet/operon/base.py:70 #, python-format msgid "Failed to load file: %r" msgstr "" #: ../quodlibet/operon/commands.py:37 msgid "List tags" msgstr "" #: ../quodlibet/operon/commands.py:42 ../quodlibet/operon/commands.py:81 #: ../quodlibet/operon/commands.py:461 msgid "Print terse output" msgstr "" #: ../quodlibet/operon/commands.py:44 ../quodlibet/operon/commands.py:83 #: ../quodlibet/operon/commands.py:463 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "" #: ../quodlibet/operon/commands.py:47 ../quodlibet/operon/commands.py:86 #, fuzzy msgid "Also list programmatic tags" msgstr "Rādīt programmatūras _tagus" #: ../quodlibet/operon/commands.py:51 ../quodlibet/operon/commands.py:129 #: ../quodlibet/operon/commands.py:220 ../quodlibet/operon/commands.py:293 #: ../quodlibet/operon/commands.py:336 ../quodlibet/operon/commands.py:340 #: ../quodlibet/operon/commands.py:391 ../quodlibet/operon/commands.py:394 #: ../quodlibet/operon/commands.py:433 ../quodlibet/operon/commands.py:468 #: ../quodlibet/operon/commands.py:508 ../quodlibet/operon/commands.py:543 #: ../quodlibet/operon/commands.py:585 msgid "Not enough arguments" msgstr "" #: ../quodlibet/operon/commands.py:53 ../quodlibet/operon/commands.py:90 #: ../quodlibet/operon/commands.py:131 ../quodlibet/operon/commands.py:222 #: ../quodlibet/operon/commands.py:470 #, fuzzy msgid "Too many arguments" msgstr "Par daudz kļūdu" #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:92 #: ../quodlibet/operon/commands.py:475 ../quodlibet/qltk/data_editors.py:363 #, fuzzy msgid "Description" msgstr "apraksts" #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:475 #: ../quodlibet/qltk/edittags.py:454 msgid "Value" msgstr "Vērtība" #: ../quodlibet/operon/commands.py:76 msgid "List all common tags" msgstr "" #: ../quodlibet/operon/commands.py:118 msgid "Copy tags from one file to another" msgstr "" #: ../quodlibet/operon/commands.py:123 ../quodlibet/operon/commands.py:164 #: ../quodlibet/operon/commands.py:289 ../quodlibet/operon/commands.py:324 #: ../quodlibet/operon/commands.py:384 msgid "Show changes, don't apply them" msgstr "" #: ../quodlibet/operon/commands.py:125 msgid "Skip tags that can't be written" msgstr "" #: ../quodlibet/operon/commands.py:145 #, python-format msgid "Can't copy tag %r to file: %r" 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:304 ../quodlibet/operon/commands.py:444 #: ../quodlibet/operon/commands.py:676 #, python-format msgid "Can not set %r" msgstr "" #: ../quodlibet/operon/commands.py:319 msgid "Remove tags" msgstr "" #: ../quodlibet/operon/commands.py:326 ../quodlibet/operon/commands.py:386 msgid "Value is a regular expression" msgstr "" #: ../quodlibet/operon/commands.py:328 msgid "Remove all tags" msgstr "" #: ../quodlibet/operon/commands.py:332 msgid "Can't combine '--all' with '--regexp'" msgstr "" #: ../quodlibet/operon/commands.py:366 #, python-format msgid "Can't remove %r from %r" msgstr "" #: ../quodlibet/operon/commands.py:379 #, fuzzy msgid "Remove a tag value" msgstr "Filtrēt pēc taga vērtības" #: ../quodlibet/operon/commands.py:428 #, fuzzy msgid "Add a tag value" msgstr "Filtrēt pēc taga vērtības" #: ../quodlibet/operon/commands.py:456 #, fuzzy msgid "List file information" msgstr "Nav ilguma informācijas" #: ../quodlibet/operon/commands.py:502 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" #: ../quodlibet/operon/commands.py:515 #, fuzzy, python-format msgid "Failed to load image file: %r" msgstr "Neizdevās pārdēvēt failu" #: ../quodlibet/operon/commands.py:522 ../quodlibet/operon/commands.py:551 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" #: ../quodlibet/operon/commands.py:538 msgid "Remove all embedded images" msgstr "" #: ../quodlibet/operon/commands.py:568 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "" #: ../quodlibet/operon/commands.py:580 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" #: ../quodlibet/operon/commands.py:639 msgid "Rename files based on tags" msgstr "" #: ../quodlibet/operon/commands.py:654 msgid "Fill tags based on the file path" msgstr "" #: ../quodlibet/operon/commands.py:704 ../quodlibet/qltk/information.py:305 #: ../quodlibet/qltk/properties.py:84 ../quodlibet/qltk/renamefiles.py:176 #: ../quodlibet/qltk/tagsfrompath.py:229 ../quodlibet/qltk/tracknumbers.py:79 msgid "File" msgstr "Fails" #: ../quodlibet/operon/commands.py:712 msgid "Fill tracknumbers for all files" msgstr "" #: ../quodlibet/operon/commands.py:731 msgid "Print tags based on the given pattern" msgstr "" #: ../quodlibet/operon/commands.py:768 #, fuzzy msgid "Display help information" msgstr "Parādīt īsu lietošanas informāciju" #: ../quodlibet/operon/util.py:40 #, 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:30 msgid "_Unknown" msgstr "_Nezināms" #: ../quodlibet/order/__init__.py:142 msgid "In Order" msgstr "Pēc kārtības" #: ../quodlibet/order/__init__.py:143 msgid "_In Order" msgstr "Pē_c kārtības" #: ../quodlibet/order/reorder.py:23 #, fuzzy msgid "Random" msgstr "_Nejauši" #: ../quodlibet/order/reorder.py:24 ../quodlibet/qltk/queue.py:119 msgid "_Random" msgstr "_Nejauši" #: ../quodlibet/order/reorder.py:39 ../quodlibet/order/reorder.py:40 msgid "Prefer higher rated" msgstr "" #: ../quodlibet/order/repeat.py:43 ../quodlibet/order/repeat.py:44 msgid "Repeat this track" msgstr "" #: ../quodlibet/order/repeat.py:57 ../quodlibet/order/repeat.py:58 #, fuzzy msgid "Repeat all" msgstr "_Atkārtot" #: ../quodlibet/order/repeat.py:73 ../quodlibet/order/repeat.py:74 msgid "One Song" msgstr "Viena dziesma" #: ../quodlibet/player/gstbe/player.py:98 msgid "Stream" msgstr "" #: ../quodlibet/player/gstbe/player.py:98 msgid "Buffering" msgstr "" #: ../quodlibet/player/gstbe/player.py:319 msgid "Could not create GStreamer pipeline" msgstr "" #: ../quodlibet/player/gstbe/player.py:560 msgid "No GStreamer element found to handle media format" msgstr "" #: ../quodlibet/player/gstbe/player.py:561 #, 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:25 #, fuzzy msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. In case 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:36 msgid "_Output pipeline:" msgstr "_Izvades līnija:" #: ../quodlibet/player/gstbe/prefs.py:43 #, fuzzy, python-format msgid "%.1f seconds" msgstr "%d sekunde" #: ../quodlibet/player/gstbe/prefs.py:57 msgid "_Buffer duration:" msgstr "" #: ../quodlibet/player/gstbe/prefs.py:66 msgid "Disable _gapless playback" msgstr "" #: ../quodlibet/player/gstbe/prefs.py:70 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions." msgstr "" #: ../quodlibet/player/gstbe/util.py:93 #, fuzzy msgid "No GStreamer audio sink found" msgstr "Nav atrasta neviena stacija" #: ../quodlibet/player/gstbe/util.py:112 #, fuzzy msgid "Invalid GStreamer output pipeline" msgstr "Nederīga GStreamer izvades līnija, mēģina noklusēto." #: ../quodlibet/player/xinebe/player.py:90 msgid "Unable to create audio output" msgstr "Neizdevās izveidot audio izvadi" #: ../quodlibet/player/xinebe/player.py:91 #, 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:62 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" #: ../quodlibet/plugins/__init__.py:71 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "" #: ../quodlibet/plugins/playlist.py:30 #, 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:41 ../quodlibet/qltk/songsmenu.py:46 #: ../quodlibet/qltk/songsmenu.py:74 #, fuzzy msgid "_Run Plugin" msgstr "S_praudņi" #: ../quodlibet/qltk/about.py:40 #, python-format msgid "Supported formats: %s" msgstr "Atbalstītie formāti: %s" #: ../quodlibet/qltk/about.py:43 #, python-format msgid "Audio device: %s" msgstr "Audio ierīce: %s" #. 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:207 ../quodlibet/qltk/information.py:131 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:48 ../quodlibet/qltk/edittags.py:311 msgid "_Value:" msgstr "_Vērtība:" #: ../quodlibet/qltk/cbes.py:262 msgid "Saved Values" msgstr "Saglabātās vērtības" #: ../quodlibet/qltk/cbes.py:263 #, fuzzy msgid "Edit saved values…" msgstr "Rediģēt saglabātās vērtības..." #: ../quodlibet/qltk/controls.py:111 msgid "Auto_matic" msgstr "" #: ../quodlibet/qltk/controls.py:112 #, fuzzy msgid "_Track Mode" msgstr "_Celiņu galvenes" #: ../quodlibet/qltk/controls.py:113 #, fuzzy msgid "_Album Mode" msgstr "_Albumu galvenes" #. Translators: player state, no action #: ../quodlibet/qltk/controls.py:122 msgid "_Mute" msgstr "" #: ../quodlibet/qltk/controls.py:128 #, fuzzy msgid "_Replay Gain Mode" msgstr "Replay Gain skaļuma regulācija" #. Translators: New Command/Entry/Item/... #: ../quodlibet/qltk/data_editors.py:119 #, python-format msgid "New %s" msgstr "" #: ../quodlibet/qltk/data_editors.py:218 #, fuzzy msgid "(unknown)" msgstr "Nezināms" #: ../quodlibet/qltk/data_editors.py:355 msgid "Tag expression" msgstr "" #: ../quodlibet/qltk/data_editors.py:382 msgid "Tag expression e.g. people:real or ~album~year." msgstr "" #: ../quodlibet/qltk/data_editors.py:383 #, fuzzy msgid "Enter new tag" msgstr "Filtrēt pēc taga vērtības" #: ../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/downloader.py:38 msgid "Downloads" msgstr "Lejupielādes" #: ../quodlibet/qltk/downloader.py:62 msgid "Size" msgstr "Izmērs" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: ../quodlibet/qltk/downloader.py:94 ../quodlibet/qltk/renamefiles.py:265 #: ../quodlibet/qltk/wlw.py:50 msgid "_Stop" msgstr "" #: ../quodlibet/qltk/edittags.py:63 ../quodlibet/qltk/edittags.py:74 #, 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:67 ../quodlibet/qltk/edittags.py:71 #, 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:193 msgid "Split into _Multiple Values" msgstr "Sadalīt _vairākās vērtībās" #: ../quodlibet/qltk/edittags.py:211 msgid "Split Disc out of _Album" msgstr "Izdalīt disku no _albuma" #: ../quodlibet/qltk/edittags.py:228 msgid "Split _Version out of Title" msgstr "Izdalīt _versiju no nosaukuma" #: ../quodlibet/qltk/edittags.py:259 msgid "Split Arranger out of Ar_tist" msgstr "Izdalīt aranžētāju no izpildī_tāja" #: ../quodlibet/qltk/edittags.py:264 msgid "Split _Performer out of Artist" msgstr "Izdalīt iz_pildītāju no mākslinieka" #: ../quodlibet/qltk/edittags.py:270 #, fuzzy msgid "Split _Performer out of Title" msgstr "Izdalīt iz_pildītāju no mākslinieka" #: ../quodlibet/qltk/edittags.py:276 #, fuzzy msgid "Split _Originalartist out of Title" msgstr "Izdalīt _versiju no nosaukuma" #: ../quodlibet/qltk/edittags.py:283 msgid "Add a Tag" msgstr "Pievienot tagu" #: ../quodlibet/qltk/edittags.py:302 msgid "_Tag:" msgstr "_Tags:" #: ../quodlibet/qltk/edittags.py:404 msgid "Edit Tags" msgstr "Rediģēt tagus" #: ../quodlibet/qltk/edittags.py:477 msgid "Show _programmatic tags" msgstr "Rādīt programmatūras _tagus" #: ../quodlibet/qltk/edittags.py:478 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" #. Translators: Revert button in the tag editor #: ../quodlibet/qltk/edittags.py:508 #, fuzzy msgctxt "edittags" msgid "_Revert" msgstr "Nekad" #. Translators: Save button in the tag editor #: ../quodlibet/qltk/edittags.py:513 msgctxt "edittags" msgid "_Save" msgstr "" #: ../quodlibet/qltk/edittags.py:659 msgid "Unable to add tag" msgstr "Neizdevās pievienot tagu" #: ../quodlibet/qltk/edittags.py:660 #, fuzzy, python-format msgid "Unable to add <b>%s</b>" msgstr "Neizdevās pievienot dziesmu" #: ../quodlibet/qltk/edittags.py:662 #, fuzzy, python-format msgid "" "The files currently selected do not support multiple values for <b>%s</b>." 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:689 ../quodlibet/qltk/edittags.py:856 #: ../quodlibet/qltk/tagsfrompath.py:212 ../quodlibet/util/__init__.py:554 #: ../quodlibet/util/tags.py:231 msgid "Invalid tag" msgstr "Nederīgs tags" #: ../quodlibet/qltk/edittags.py:690 ../quodlibet/qltk/edittags.py:857 #: ../quodlibet/qltk/tagsfrompath.py:213 #, python-format msgid "" "Invalid tag <b>%s</b>\n" "\n" "The files currently selected do not support editing this tag." msgstr "" "Neatļauts tags <b>%s</b>\n" "\n" "Pašlaik izvēlētie faili neatbalsta šī taga rediģēšanu." #: ../quodlibet/qltk/edittags.py:828 ../quodlibet/qltk/edittags.py:868 msgid "Invalid value" msgstr "Nederīga vērtība" #: ../quodlibet/qltk/edittags.py:829 ../quodlibet/qltk/edittags.py:869 #, python-format msgid "" "Invalid value: <b>%(value)s</b>\n" "\n" "%(error)s" msgstr "" "Nederīga vērtība: <b>%(value)s</b>\n" "\n" "%(error)s" #: ../quodlibet/qltk/_editutils.py:28 msgid "Tag may not be accurate" msgstr "Tags var nebūt precīzs" #: ../quodlibet/qltk/_editutils.py:31 #, 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:47 msgid "Unable to save song" msgstr "Neizdevās saglabāt dziesmu" #: ../quodlibet/qltk/_editutils.py:50 #, 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:142 #, 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:95 #: ../quodlibet/qltk/quodlibetwindow.py:1066 msgid "_About" msgstr "" #: ../quodlibet/qltk/exfalsowindow.py:99 #: ../quodlibet/qltk/quodlibetwindow.py:1088 msgid "_Check for Updates…" msgstr "" #: ../quodlibet/qltk/exfalsowindow.py:105 #: ../quodlibet/qltk/quodlibetwindow.py:1021 ../quodlibet/qltk/songsmenu.py:304 msgid "_Plugins" msgstr "S_praudņi" #: ../quodlibet/qltk/exfalsowindow.py:267 #, 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:279 msgid "Ex Falso Preferences" msgstr "Ex Falso iestatījumi" #: ../quodlibet/qltk/exfalsowindow.py:289 ../quodlibet/qltk/prefs.py:598 msgid "Split _on:" msgstr "Sadalīt _pie:" #: ../quodlibet/qltk/exfalsowindow.py:295 ../quodlibet/qltk/prefs.py:613 msgid "Tag Editing" msgstr "Tagu rediģēšana" #: ../quodlibet/qltk/filesel.py:210 msgid "Folders" msgstr "Mapes" #: ../quodlibet/qltk/filesel.py:253 #, fuzzy msgid "_New Folder…" msgstr "Jauna mape" #: ../quodlibet/qltk/filesel.py:262 #, fuzzy msgid "_Select all Sub-Folders" msgstr "Izvēlēties vi_sas apakšmapes" #: ../quodlibet/qltk/filesel.py:374 msgid "New Folder" msgstr "Jauna mape" #: ../quodlibet/qltk/filesel.py:374 msgid "Enter a name for the new folder:" msgstr "Ievadiet jaunās mapes nosaukumu:" #: ../quodlibet/qltk/filesel.py:387 msgid "Unable to create folder" msgstr "Neizdevās izveidot mapi" #: ../quodlibet/qltk/filesel.py:404 msgid "Unable to delete folder" msgstr "Neizdevās izdzēst mapi" #: ../quodlibet/qltk/filesel.py:519 ../quodlibet/qltk/pluginwin.py:167 msgid "Songs" msgstr "Dziesmas" #. Translators: As in "by Artist Name" #: ../quodlibet/qltk/info.py:42 #, python-format msgid "by %s" msgstr "no %s" #: ../quodlibet/qltk/info.py:43 ../quodlibet/qltk/information.py:167 #: ../quodlibet/qltk/information.py:448 #, python-format msgid "Disc %s" msgstr "%s. disks" #: ../quodlibet/qltk/info.py:44 ../quodlibet/qltk/information.py:172 #, python-format msgid "Track %s" msgstr "%s. celiņš" #: ../quodlibet/qltk/info.py:108 #, fuzzy msgid "_Edit Display…" msgstr "Rediģēt rādāmo" #: ../quodlibet/qltk/information.py:105 msgid "No songs are selected." msgstr "Nav izvēlēta neviena dziesma." #: ../quodlibet/qltk/information.py:106 msgid "No Songs" msgstr "Nav dziesmu" #: ../quodlibet/qltk/information.py:121 ../quodlibet/qltk/information.py:338 #: ../quodlibet/qltk/information.py:471 ../quodlibet/qltk/information.py:531 msgid "Information" msgstr "Informācija" #: ../quodlibet/qltk/information.py:126 msgid "Lyrics" msgstr "Dziesmas vārdi" #: ../quodlibet/qltk/information.py:184 ../quodlibet/qltk/information.py:396 #, python-format msgid "Produced by %s" msgstr "Producējis %s" #: ../quodlibet/qltk/information.py:199 ../quodlibet/util/tags.py:76 msgid "artist" msgstr "mākslinieks" #: ../quodlibet/qltk/information.py:200 ../quodlibet/qltk/information.py:561 #: ../quodlibet/util/tags.py:76 msgid "artists" msgstr "mākslinieki" #. for backwards compat #: ../quodlibet/qltk/information.py:221 ../quodlibet/util/tags.py:86 #: ../quodlibet/util/tags.py:114 msgid "performers" msgstr "izpildītāji" #: ../quodlibet/qltk/information.py:235 ../quodlibet/qltk/information.py:248 #: ../quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "Nekad" #: ../quodlibet/qltk/information.py:236 #, 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:254 ../quodlibet/util/tags.py:139 msgid "added" msgstr "pievienots" #: ../quodlibet/qltk/information.py:255 ../quodlibet/util/tags.py:140 msgid "last played" msgstr "Pēdējo reizi atskaņots" #: ../quodlibet/qltk/information.py:256 ../quodlibet/util/tags.py:150 msgid "plays" msgstr "atskaņojumi" #: ../quodlibet/qltk/information.py:257 ../quodlibet/util/tags.py:151 msgid "skips" msgstr "izlaidumi" #: ../quodlibet/qltk/information.py:258 ../quodlibet/util/tags.py:156 msgid "rating" msgstr "vērtējums" #: ../quodlibet/qltk/information.py:287 msgid "path" msgstr "" #: ../quodlibet/qltk/information.py:288 ../quodlibet/util/tags.py:154 msgid "length" msgstr "ilgums" #: ../quodlibet/qltk/information.py:289 #, fuzzy msgid "format" msgstr "Informācija" #: ../quodlibet/qltk/information.py:290 ../quodlibet/util/tags.py:163 msgid "codec" msgstr "" #: ../quodlibet/qltk/information.py:291 ../quodlibet/util/tags.py:164 #, fuzzy msgid "encoding" msgstr "[Nederīgs kodējums]" #: ../quodlibet/qltk/information.py:292 ../quodlibet/util/tags.py:160 msgid "bitrate" msgstr "bitātrums" #: ../quodlibet/qltk/information.py:293 ../quodlibet/util/tags.py:161 msgid "file size" msgstr "faila izmērs" #: ../quodlibet/qltk/information.py:294 ../quodlibet/util/tags.py:149 msgid "modified" msgstr "mainīts" #: ../quodlibet/qltk/information.py:331 msgid "Additional" msgstr "" #: ../quodlibet/qltk/information.py:383 #, 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:458 msgid "Track unavailable" msgstr "Celiņš nav pieejams" #: ../quodlibet/qltk/information.py:464 msgid "Track List" msgstr "Celiņu saraksts" #: ../quodlibet/qltk/information.py:505 ../quodlibet/qltk/information.py:578 #, 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:508 msgid "Selected Discography" msgstr "Izvēlētā diskogrāfija" #: ../quodlibet/qltk/information.py:558 #, 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:586 ../quodlibet/util/tags.py:74 msgid "albums" msgstr "albumi" #: ../quodlibet/qltk/information.py:599 msgid "Total length:" msgstr "Kopējais ilgums:" #: ../quodlibet/qltk/information.py:603 msgid "Total size:" msgstr "Kopējais izmērs:" #: ../quodlibet/qltk/information.py:606 msgid "Files" msgstr "Faili" #: ../quodlibet/qltk/lyrics.py:37 msgid "_Download" msgstr "Lejupielā_dēt" #: ../quodlibet/qltk/lyrics.py:40 #, fuzzy msgid "_Edit" msgstr "R_ediģēt rādāmo..." #. buffer.set_text(_("No lyrics found.\n\nYou can click the " #. "Download button to have Quod Libet search " #. "for lyrics online. You can also enter them " #. "yourself and click save.")) #: ../quodlibet/qltk/lyrics.py:73 ../quodlibet/qltk/lyrics.py:109 msgid "No lyrics found for this song." msgstr "Šajai dziesmai vārdi netika atrasti." #: ../quodlibet/qltk/lyrics.py:82 #, fuzzy msgid "Searching for lyrics…" msgstr "Meklē dziesmas vārdus..." #: ../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/msg.py:41 msgid "Discard tag changes?" msgstr "Izmest tagu izmaiņas?" #: ../quodlibet/qltk/msg.py:42 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:55 ../quodlibet/qltk/prefs.py:595 #: ../quodlibet/qltk/textedit.py:64 ../quodlibet/qltk/tracknumbers.py:117 #, fuzzy msgid "_Revert" msgstr "Nekad" #: ../quodlibet/qltk/msg.py:86 msgid "File exists" msgstr "Fails pastāv" #: ../quodlibet/qltk/msg.py:88 #, python-format msgid "Replace %(file-name)s?" msgstr "" #: ../quodlibet/qltk/msg.py:94 #, fuzzy msgid "_Replace File" msgstr "Pārdēvēt failus" #: ../quodlibet/qltk/notif.py:182 msgid "Active tasks" msgstr "" #: ../quodlibet/qltk/notif.py:188 #, python-format msgid "%d tasks running" msgstr "" #: ../quodlibet/qltk/playorder.py:254 #, fuzzy msgid "Toggle shuffle mode" msgstr "Pārslēgt atskaņošanas/pauzes režīmu" #: ../quodlibet/qltk/playorder.py:270 #, fuzzy msgid "Toggle repeat mode" msgstr "Pārslēgt atskaņošanas/pauzes režīmu" #: ../quodlibet/qltk/pluginwin.py:44 msgid "Plugin Errors" msgstr "Spraudņu kļūdas" #: ../quodlibet/qltk/pluginwin.py:124 msgid "Enabled" msgstr "Ieslēgts" #: ../quodlibet/qltk/pluginwin.py:125 msgid "Disabled" msgstr "Izslēgts" #: ../quodlibet/qltk/pluginwin.py:131 msgid "No category" msgstr "Bez kategorijas" #: ../quodlibet/qltk/pluginwin.py:169 msgid "Events" msgstr "" #: ../quodlibet/qltk/pluginwin.py:170 #, fuzzy msgid "Play Order" msgstr "_Kārtība" #: ../quodlibet/qltk/pluginwin.py:171 #, fuzzy msgid "Editing" msgstr "Tagu rediģēšana" #: ../quodlibet/qltk/pluginwin.py:173 #, fuzzy msgid "Covers" msgstr "Kopējais izmērs:" #: ../quodlibet/qltk/pluginwin.py:309 msgid "No plugins found." msgstr "Nav atrasts neviens spraudnis." #: ../quodlibet/qltk/pluginwin.py:358 #, fuzzy msgid "Plugins" msgstr "S_praudņi" #: ../quodlibet/qltk/pluginwin.py:402 msgid "Show _Errors" msgstr "Rādīt _kļūdas" #: ../quodlibet/qltk/prefs.py:45 msgid "_Disc" msgstr "_Disks" #: ../quodlibet/qltk/prefs.py:46 msgid "_Track" msgstr "_Celiņš" #: ../quodlibet/qltk/prefs.py:47 #, fuzzy msgid "Grou_ping" msgstr "grupēšana" #: ../quodlibet/qltk/prefs.py:50 msgid "Al_bum" msgstr "Al_bums" #: ../quodlibet/qltk/prefs.py:55 msgid "_Filename" msgstr "_Faila nosaukums" #: ../quodlibet/qltk/prefs.py:57 msgid "_Length" msgstr "_Ilgums" #: ../quodlibet/qltk/prefs.py:64 msgid "_Jump to playing song automatically" msgstr "_Pārlēkt uz atskaņoto dziesmu automātiski" #: ../quodlibet/qltk/prefs.py:66 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:82 msgid "_Others:" msgstr "C_iti:" #: ../quodlibet/qltk/prefs.py:88 #, fuzzy msgid "_Edit…" msgstr "R_ediģēt rādāmo..." #: ../quodlibet/qltk/prefs.py:91 msgid "Add or remove additional column headers" msgstr "" #: ../quodlibet/qltk/prefs.py:101 msgid "Visible Columns" msgstr "Redzamās kolonnas" #: ../quodlibet/qltk/prefs.py:104 msgid "Title includes _version" msgstr "Nosaukums iekļauj _versiju" #: ../quodlibet/qltk/prefs.py:106 #, fuzzy msgid "Artist includes all _people" msgstr "Iegultajā _meklēšanā tiek iekļauti cilvēki" #: ../quodlibet/qltk/prefs.py:108 msgid "Album includes _disc subtitle" msgstr "Albums iekļauj _diska apakšnosaukumu" #: ../quodlibet/qltk/prefs.py:110 msgid "Filename includes _folder" msgstr "_Faila nosaukums iekļauj mapi" #: ../quodlibet/qltk/prefs.py:123 #, fuzzy msgid "Column Preferences" msgstr "Iestatījumi" #: ../quodlibet/qltk/prefs.py:129 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "" #: ../quodlibet/qltk/prefs.py:142 ../quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Dziesmu saraksts" #: ../quodlibet/qltk/prefs.py:222 #, fuzzy msgid "Edit Columns" msgstr "Redzamās kolonnas" #: ../quodlibet/qltk/prefs.py:259 msgid "Duration totals" msgstr "" #: ../quodlibet/qltk/prefs.py:271 msgid "_Global filter:" msgstr "_Globālais filtrs:" #: ../quodlibet/qltk/prefs.py:277 msgid "Apply this query in addition to all others" msgstr "" #. Translators: The heading of the preference group, no action #: ../quodlibet/qltk/prefs.py:283 #, fuzzy msgctxt "heading" msgid "Search" msgstr "Meklēt" #: ../quodlibet/qltk/prefs.py:287 ../quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Pārlūki" #: ../quodlibet/qltk/prefs.py:293 msgid "Confirm _multiple ratings" msgstr "Apstiprināt vairākus vērtēju_mus" #: ../quodlibet/qltk/prefs.py:295 #, 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:298 msgid "Enable _one-click ratings" msgstr "Ieslēgt viena klikšķa vērtējumus" #: ../quodlibet/qltk/prefs.py:300 #, 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:306 ../quodlibet/qltk/prefs.py:616 msgid "Ratings" msgstr "Vērtējumi" #. Filename choice algorithm config #: ../quodlibet/qltk/prefs.py:312 msgid "Prefer _embedded art" msgstr "" #: ../quodlibet/qltk/prefs.py:314 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" #: ../quodlibet/qltk/prefs.py:319 msgid "_Fixed image filename:" msgstr "" #: ../quodlibet/qltk/prefs.py:321 msgid "The single image filename to use if selected" msgstr "" #: ../quodlibet/qltk/prefs.py:327 msgid "The album art image file to use when forced" msgstr "" #: ../quodlibet/qltk/prefs.py:336 #, fuzzy msgid "Album Art" msgstr "Albumu saraksts" #: ../quodlibet/qltk/prefs.py:357 #, fuzzy msgid "Playback" msgstr "Pauzēt atskaņošanu" #: ../quodlibet/qltk/prefs.py:362 #, fuzzy msgid "Output Configuration" msgstr "Izvades žurnāls" #: ../quodlibet/qltk/prefs.py:373 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:376 #, fuzzy msgid "_Fall-back gain (dB):" msgstr "Atkāpšanās pastiprinājums (dB):" #: ../quodlibet/qltk/prefs.py:387 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:390 #, fuzzy msgid "_Pre-amp gain (dB):" msgstr "Priekšpastiprinājuma pastiprinājums (dB):" #: ../quodlibet/qltk/prefs.py:395 msgid "_Enable Replay Gain volume adjustment" msgstr "I_eslēgt Replay Gain skaļuma regulāciju" #: ../quodlibet/qltk/prefs.py:420 msgid "Replay Gain Volume Adjustment" msgstr "Replay Gain skaļuma regulācija" #: ../quodlibet/qltk/prefs.py:450 msgid "_Default rating:" msgstr "" #: ../quodlibet/qltk/prefs.py:493 #, fuzzy msgid "Rating _scale:" msgstr "Vērtējumi" #: ../quodlibet/qltk/prefs.py:542 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:547 msgid "_Bayesian averaging amount:" msgstr "" #: ../quodlibet/qltk/prefs.py:556 msgid "Save ratings and play _counts" msgstr "Saglabāt vērtējumus un _atskaņošanu skaitu" #: ../quodlibet/qltk/prefs.py:560 msgid "_Email:" msgstr "_E-pasts:" #: ../quodlibet/qltk/prefs.py:562 msgid "Ratings and play counts will be set for this email address" msgstr "Vērtējumi un atskaņošanu skaits tiks iestatīts šajai e-pasta adresei" #: ../quodlibet/qltk/prefs.py:577 #, fuzzy msgid "Auto-save tag changes" msgstr "Izmest tagu izmaiņas?" #: ../quodlibet/qltk/prefs.py:579 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "" #: ../quodlibet/qltk/prefs.py:587 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:610 #, fuzzy msgid "Tags" msgstr "Rediģēt tagus" #: ../quodlibet/qltk/prefs.py:631 #, fuzzy msgid "Updating for new ratings" msgstr "Jau_na stacija" #: ../quodlibet/qltk/prefs.py:641 #, fuzzy msgid "Scan library _on start" msgstr "A_tsvaidzināt bibliotēku, palaižot programmu" #: ../quodlibet/qltk/prefs.py:651 ../quodlibet/qltk/quodlibetwindow.py:1100 #, fuzzy msgid "_Scan Library" msgstr "_Meklēt bibliotēkā" #: ../quodlibet/qltk/prefs.py:653 ../quodlibet/qltk/quodlibetwindow.py:1162 msgid "Check for changes in your library" msgstr "Pārbaudīt izmaiņas jūsu bibliotēkā" #: ../quodlibet/qltk/prefs.py:658 #, fuzzy msgid "Re_build Library" msgstr "Pār_lādēt bibliotēku" #: ../quodlibet/qltk/prefs.py:661 #, 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:671 #, fuzzy msgid "Scan Directories" msgstr "Skenēt _mapes" #: ../quodlibet/qltk/prefs.py:677 #, fuzzy msgid "Hidden Songs" msgstr "Nav dziesmu" #: ../quodlibet/qltk/properties.py:158 ../quodlibet/util/collection.py:398 #, 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:162 ../quodlibet/qltk/properties.py:164 msgid "Properties" msgstr "Īpašības" #: ../quodlibet/qltk/queue.py:101 msgid "_Queue" msgstr "_Rinda" #: ../quodlibet/qltk/queue.py:126 msgid "Stop Once Empty" msgstr "" #: ../quodlibet/qltk/queue.py:130 #, fuzzy msgid "_Clear Queue" msgstr "_Notīrīt kļūdas" #: ../quodlibet/qltk/queue.py:242 #, 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:198 msgid "_Browse Library" msgstr "Pārlūkot _bibliotēku" #: ../quodlibet/qltk/quodlibetwindow.py:395 #, fuzzy msgid "Toggle queue visibility" msgstr "Pārslēgt galvenā loga redzamību" #: ../quodlibet/qltk/quodlibetwindow.py:516 #, fuzzy msgid "Playback Error" msgstr "Pauzēt atskaņošanu" #: ../quodlibet/qltk/quodlibetwindow.py:524 #, fuzzy msgid "Set up library directories?" msgstr "Izvēlieties mapes" #: ../quodlibet/qltk/quodlibetwindow.py:525 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:531 msgid "_Not Now" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:532 msgid "_Set Up" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:956 msgid "Unable to add songs" msgstr "Neizdevās pievienot dziesmas" #: ../quodlibet/qltk/quodlibetwindow.py:957 #: ../quodlibet/qltk/quodlibetwindow.py:1364 #, fuzzy, python-format msgid "%s uses an unsupported protocol." msgstr "<b>%s</b> izmanto neatbalstītu protokolu." #: ../quodlibet/qltk/quodlibetwindow.py:980 msgid "_Jump to Playing Song" msgstr "_Pārlēkt uz atskaņoto dziesmu" #: ../quodlibet/qltk/quodlibetwindow.py:986 #, fuzzy msgid "_File" msgstr "Fails" #: ../quodlibet/qltk/quodlibetwindow.py:987 #, fuzzy msgid "_Song" msgstr "Dziesmas" #: ../quodlibet/qltk/quodlibetwindow.py:988 msgid "_View" msgstr "_Skats" #: ../quodlibet/qltk/quodlibetwindow.py:989 #, fuzzy msgid "_Browse" msgstr "Pārlūki" #: ../quodlibet/qltk/quodlibetwindow.py:990 msgid "_Control" msgstr "_Vadība" #: ../quodlibet/qltk/quodlibetwindow.py:991 msgid "_Help" msgstr "_Palīdzība" #: ../quodlibet/qltk/quodlibetwindow.py:997 #, fuzzy msgid "_Add a Folder…" msgstr "_Pievienot mapi..." #: ../quodlibet/qltk/quodlibetwindow.py:1002 #, fuzzy msgid "_Add a File…" msgstr "Pievienot _failu..." #: ../quodlibet/qltk/quodlibetwindow.py:1007 #, fuzzy msgid "_Add a Location…" msgstr "Pievienot vietu" #: ../quodlibet/qltk/quodlibetwindow.py:1036 #, fuzzy msgid "Edit Bookmarks…" msgstr "R_ediģēt grāmatzīmes..." #: ../quodlibet/qltk/quodlibetwindow.py:1056 #, fuzzy msgid "Stop After This Song" msgstr "Apstāties pēc šīs dziesmas" #: ../quodlibet/qltk/quodlibetwindow.py:1062 msgid "_Keyboard Shortcuts" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:1071 msgid "Online Help" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:1080 #, fuzzy msgid "Search Help" msgstr "Meklēt" #: ../quodlibet/qltk/quodlibetwindow.py:1352 msgid "Add a Location" msgstr "Pievienot vietu" #: ../quodlibet/qltk/quodlibetwindow.py:1353 msgid "Enter the location of an audio file:" msgstr "Ievadiet audio faila atrašanās vietu:" #: ../quodlibet/qltk/quodlibetwindow.py:1358 #: ../quodlibet/qltk/quodlibetwindow.py:1363 msgid "Unable to add location" msgstr "Neizdevās pievienot vietu" #: ../quodlibet/qltk/quodlibetwindow.py:1359 #, fuzzy, python-format msgid "%s is not a valid location." msgstr "<b>%s</b> nav derīga vieta." #: ../quodlibet/qltk/quodlibetwindow.py:1372 #: ../quodlibet/qltk/quodlibetwindow.py:1381 msgid "Add Music" msgstr "Pievienot mūziku" #: ../quodlibet/qltk/quodlibetwindow.py:1372 ../quodlibet/qltk/scanbox.py:99 #, fuzzy msgid "_Add Folders" msgstr "_Pievienot mapi..." #: ../quodlibet/qltk/quodlibetwindow.py:1379 #, fuzzy msgid "Music Files" msgstr "Mūzikas atskaņotājs" #: ../quodlibet/qltk/quodlibetwindow.py:1381 #, fuzzy msgid "_Add Files" msgstr "Pievienot _failu..." #: ../quodlibet/qltk/ratingsmenu.py:24 #, 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:26 msgid "The saved ratings will be removed" msgstr "" #: ../quodlibet/qltk/ratingsmenu.py:27 #, python-format msgid "The rating of all selected songs will be changed to '%s'" msgstr "" #: ../quodlibet/qltk/ratingsmenu.py:57 ../quodlibet/qltk/ratingsmenu.py:111 #, fuzzy msgid "_Remove Rating" msgstr "_Vērtējums" #: ../quodlibet/qltk/ratingsmenu.py:98 #, fuzzy msgid "Change _Rating" msgstr "_Vērtējums" #: ../quodlibet/qltk/renamefiles.py:46 msgid "Replace spaces with _underscores" msgstr "Aizvietot atstarpes ar pa_svītrām" #: ../quodlibet/qltk/renamefiles.py:56 msgid "Strip _Windows-incompatible characters" msgstr "Izņemt ar Windows nesavietojamas rakstzīmes" #: ../quodlibet/qltk/renamefiles.py:74 msgid "Strip _diacritical marks" msgstr "Izņemt _diakritiskās zīmes" #: ../quodlibet/qltk/renamefiles.py:85 msgid "Strip non-_ASCII characters" msgstr "Izņemt ne-ASCII rakstzīmes" #: ../quodlibet/qltk/renamefiles.py:95 msgid "Use only _lowercase characters" msgstr "" #: ../quodlibet/qltk/renamefiles.py:123 msgid "Rename Files" msgstr "Pārdēvēt failus" #: ../quodlibet/qltk/renamefiles.py:139 ../quodlibet/qltk/tagsfrompath.py:116 #, fuzzy msgid "Path Patterns" msgstr "paraugs" #: ../quodlibet/qltk/renamefiles.py:140 ../quodlibet/qltk/tagsfrompath.py:117 #, fuzzy msgid "Edit saved patterns…" msgstr "Rediģēt saglabātās vērtības..." #: ../quodlibet/qltk/renamefiles.py:143 ../quodlibet/qltk/tagsfrompath.py:120 #: ../quodlibet/qltk/tracknumbers.py:58 msgid "_Preview" msgstr "_Priekšskats" #: ../quodlibet/qltk/renamefiles.py:190 msgid "New Name" msgstr "Jauns nosaukums" #: ../quodlibet/qltk/renamefiles.py:255 msgid "Unable to rename file" msgstr "Neizdevās pārdēvēt failu" #: ../quodlibet/qltk/renamefiles.py:256 #, fuzzy, python-format msgid "" "Renaming <b>%(old-name)s</b> to <b>%(new-name)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." 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:264 msgid "Ignore _All Errors" msgstr "Ignorēt vis_as kļūdas" #: ../quodlibet/qltk/renamefiles.py:267 msgid "_Continue" msgstr "_Turpināt" #: ../quodlibet/qltk/renamefiles.py:296 msgid "Path is not absolute" msgstr "Ceļš nav absolūts" #: ../quodlibet/qltk/renamefiles.py:297 #, python-format msgid "" "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 ~/." 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:47 #, 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:99 msgid "Select Directories" msgstr "Izvēlieties mapes" #: ../quodlibet/qltk/searchbar.py:52 #, fuzzy msgid "Saved Searches" msgstr "Saglabātās vērtības" #: ../quodlibet/qltk/searchbar.py:53 #, fuzzy msgid "Edit saved searches…" msgstr "Rediģēt saglabātās vērtības..." #: ../quodlibet/qltk/searchbar.py:74 msgid "Search your library, using free text or QL queries" msgstr "" #: ../quodlibet/qltk/searchbar.py:129 msgid "Search after _typing" msgstr "Meklēt pēc ieraks_tīšanas" #: ../quodlibet/qltk/searchbar.py:132 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:187 msgid "_Limit:" msgstr "_Limits:" #: ../quodlibet/qltk/searchbar.py:200 msgid "_Weight" msgstr "S_vars" #: ../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 ../quodlibet/qltk/shortcuts.py:41 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: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:377 #, python-format msgid "_Filter on %s" msgstr "_Filtrēt pēc %s" #: ../quodlibet/qltk/songlist.py:1094 #, fuzzy msgid "All _Headers" msgstr "_Albumu galvenes" #: ../quodlibet/qltk/songlist.py:1095 msgid "_Track Headers" msgstr "_Celiņu galvenes" #: ../quodlibet/qltk/songlist.py:1096 msgid "_Album Headers" msgstr "_Albumu galvenes" #: ../quodlibet/qltk/songlist.py:1097 msgid "_People Headers" msgstr "C_ilvēku galvenes" #: ../quodlibet/qltk/songlist.py:1098 msgid "_Date Headers" msgstr "_Datumu galvenes" #: ../quodlibet/qltk/songlist.py:1099 msgid "_File Headers" msgstr "_Failu galvenes" #: ../quodlibet/qltk/songlist.py:1100 msgid "_Production Headers" msgstr "_Producēšanas galvenes" #: ../quodlibet/qltk/songlist.py:1115 #, fuzzy msgid "_Customize Headers…" msgstr "Pielāg_ot galvenes..." #: ../quodlibet/qltk/songlist.py:1120 msgid "_Expand Column" msgstr "" #: ../quodlibet/qltk/songsmenu.py:36 #, 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:64 #, 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:149 #, fuzzy msgid "Configure Plugins…" msgstr "Iekrā_sot meklējamos terminus" #: ../quodlibet/qltk/songsmenu.py:345 msgid "Add to _Queue" msgstr "Pie_vienot rindai" #: ../quodlibet/qltk/songsmenu.py:368 msgid "_Copy to Device" msgstr "Kopēt uz ierī_ci" #: ../quodlibet/qltk/songsmenu.py:379 #, fuzzy msgid "_Remove from Library" msgstr "Izņemt no _repertuāra" #: ../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:101 msgid "Tags From Path" msgstr "Tagi no ceļa" #: ../quodlibet/qltk/tagsfrompath.py:138 msgid "Tags replace existing ones" msgstr "Tagi aizvieto pastāvošos tagus" #: ../quodlibet/qltk/tagsfrompath.py:139 msgid "Tags are added to existing ones" msgstr "Tagi tiek pievienoti pastāvošajiem tagiem" #. Save button #: ../quodlibet/qltk/tagsfrompath.py:153 msgid "Save" msgstr "" #: ../quodlibet/qltk/tagsfrompath.py:195 #, python-format msgid "" "The pattern\n" "\t<b>%s</b>\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/tagsfrompath.py:216 msgid "Invalid tags" msgstr "Nederīgi tagi" #: ../quodlibet/qltk/tagsfrompath.py:217 #, 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." #: ../quodlibet/qltk/textedit.py:142 #, 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:158 msgid "Edit Display" msgstr "Rediģēt rādāmo" #: ../quodlibet/qltk/tracknumbers.py:39 msgid "Track Numbers" msgstr "Celiņu numuri" #: ../quodlibet/qltk/tracknumbers.py:42 msgid "Start fro_m:" msgstr "Sākt _no:" #: ../quodlibet/qltk/tracknumbers.py:51 msgid "_Total tracks:" msgstr "_Celiņi kopā:" #: ../quodlibet/qltk/unity.py:52 #, fuzzy msgid "Play/Pause" msgstr "Atskaņotājs" #: ../quodlibet/qltk/unity.py:75 #, fuzzy msgid "Previous" msgstr "_Priekšskats" #: ../quodlibet/qltk/views.py:923 #, 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:89 #, fuzzy msgid "Checking for Updates" msgstr "Pārbauda montēšanas punktus" #: ../quodlibet/update.py:124 #, fuzzy msgid "Connection failed" msgstr "vieta" #: ../quodlibet/update.py:133 #, python-format msgid "You are already using the newest version %(version)s" msgstr "" #: ../quodlibet/update.py:136 #, 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:420 msgid "Playlists must have a name" msgstr "" #: ../quodlibet/util/collection.py:603 #, python-format msgid "A playlist named %s already exists." msgstr "Repertuārs ar nosaukumu %s jau pastāv." #: ../quodlibet/util/cover/built_in.py:26 #, fuzzy msgid "Embedded album covers" msgstr "Rādīt albumu _vākus" #: ../quodlibet/util/cover/built_in.py:27 msgid "Uses covers embedded into audio files." msgstr "" #: ../quodlibet/util/cover/built_in.py:49 #, fuzzy msgid "Filesystem cover" msgstr "Failu sistēma" #: ../quodlibet/util/cover/built_in.py:50 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "" #: ../quodlibet/util/__init__.py:93 msgid "Display brief usage information" msgstr "Parādīt īsu lietošanas informāciju" #: ../quodlibet/util/__init__.py:95 msgid "Display version and copyright" msgstr "Parādīt versiju un autortiesības" #: ../quodlibet/util/__init__.py:135 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "" #: ../quodlibet/util/__init__.py:137 msgid "[options]" msgstr "[opcijas]" #: ../quodlibet/util/__init__.py:182 #, python-format msgid "Option %r not recognized." msgstr "Opcija %r nav atpazīta." #: ../quodlibet/util/__init__.py:185 #, python-format msgid "Option %r requires an argument." msgstr "Opcijai %r nepieciešams arguments." #: ../quodlibet/util/__init__.py:188 #, python-format msgid "%r is not a unique prefix." msgstr "%r nav unikāls prefikss." #: ../quodlibet/util/__init__.py:364 #, python-format msgid "%d kbps" msgstr "%d kb/s" #: ../quodlibet/util/__init__.py:419 #, 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:432 msgid "No time information" msgstr "Nav ilguma informācijas" #: ../quodlibet/util/__init__.py:435 #, 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:436 #, 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:437 #, 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:438 #, 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:439 #, 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:563 #, 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 msgid "Unable to edit song" msgstr "Neizdevās rediģēt dziesmu" #: ../quodlibet/util/songwrapper.py:113 #, python-format msgid "" "Saving <b>%s</b> 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:34 #: ../quodlibet/util/string/__init__.py:44 msgid "[Invalid Encoding]" msgstr "[Nederīgs kodējums]" #: ../quodlibet/util/tags.py:74 msgid "album" msgstr "albums" #: ../quodlibet/util/tags.py:75 msgid "arranger" msgstr "aranžētājs" #: ../quodlibet/util/tags.py:75 msgid "arrangers" msgstr "aranžētāji" #: ../quodlibet/util/tags.py:75 #, fuzzy msgid "arrangement" msgstr "aranžētājs" #: ../quodlibet/util/tags.py:77 msgid "author" msgstr "autors" #: ../quodlibet/util/tags.py:77 msgid "authors" msgstr "autori" #: ../quodlibet/util/tags.py:78 msgid "composer" msgstr "komponists" #: ../quodlibet/util/tags.py:78 msgid "composers" msgstr "komponisti" #: ../quodlibet/util/tags.py:78 #, fuzzy msgid "composition" msgstr "komponists" #. Translators: conducting as in conducting a musical performance #: ../quodlibet/util/tags.py:80 msgid "conductor" msgstr "diriģents" #: ../quodlibet/util/tags.py:80 msgid "conductors" msgstr "diriģenti" #: ../quodlibet/util/tags.py:80 #, fuzzy msgid "conducting" msgstr "diriģents" #: ../quodlibet/util/tags.py:81 msgid "contact" msgstr "kontakts" #: ../quodlibet/util/tags.py:82 msgid "copyright" msgstr "autortiesības" #: ../quodlibet/util/tags.py:83 msgid "date" msgstr "datums" #: ../quodlibet/util/tags.py:84 msgid "description" msgstr "apraksts" #: ../quodlibet/util/tags.py:85 msgid "genre" msgstr "žanrs" #: ../quodlibet/util/tags.py:85 #, fuzzy msgid "genres" msgstr "žanrs" #: ../quodlibet/util/tags.py:86 msgid "performer" msgstr "izpildītājs" #: ../quodlibet/util/tags.py:87 msgid "grouping" msgstr "grupēšana" #: ../quodlibet/util/tags.py:88 msgid "language" msgstr "valoda" #: ../quodlibet/util/tags.py:89 msgid "license" msgstr "licence" #: ../quodlibet/util/tags.py:90 msgid "location" msgstr "vieta" #: ../quodlibet/util/tags.py:91 msgid "lyricist" msgstr "dziesmu vārdu autors" #: ../quodlibet/util/tags.py:91 msgid "lyricists" msgstr "vārdu autori" #: ../quodlibet/util/tags.py:91 #, fuzzy msgid "lyrics" msgstr "dziesmu vārdu autors" #. Translators: Also e.g. "record label", "publisher" #: ../quodlibet/util/tags.py:93 msgid "organization" msgstr "organizācija" #: ../quodlibet/util/tags.py:94 msgid "title" msgstr "nosaukums" #: ../quodlibet/util/tags.py:95 msgid "version" msgstr "versija" #: ../quodlibet/util/tags.py:96 msgid "website" msgstr "tīmekļa vietne" #: ../quodlibet/util/tags.py:98 msgid "album artist" msgstr "albuma mākslinieks" #: ../quodlibet/util/tags.py:99 msgid "BPM" msgstr "sit./min." #. Translators: This used to be called "part". #: ../quodlibet/util/tags.py:102 ../quodlibet/util/tags.py:103 msgid "disc subtitle" msgstr "diska apakšnosaukums" #: ../quodlibet/util/tags.py:104 ../quodlibet/util/tags.py:141 msgid "disc" msgstr "disks" #: ../quodlibet/util/tags.py:105 ../quodlibet/util/tags.py:143 msgid "track" msgstr "celiņš" #: ../quodlibet/util/tags.py:106 msgid "label ID" msgstr "izdevēja ID" #: ../quodlibet/util/tags.py:107 msgid "original release date" msgstr "oriģinālais izlaiduma datums" #: ../quodlibet/util/tags.py:108 msgid "original album" msgstr "oriģinālais albums" #: ../quodlibet/util/tags.py:109 msgid "original artist" msgstr "oriģinālais mākslinieks" #: ../quodlibet/util/tags.py:110 msgid "recording date" msgstr "ierakstīšanas datums" #: ../quodlibet/util/tags.py:111 msgid "release country" msgstr "izlaiduma valsts" #. 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:120 #, fuzzy msgid "MusicBrainz recording ID" msgstr "MusicBrainz celiņa ID" #: ../quodlibet/util/tags.py:121 #, fuzzy msgid "MusicBrainz release track ID" msgstr "MusicBrainz izlaiduma ID" #: ../quodlibet/util/tags.py:122 msgid "MusicBrainz release ID" msgstr "MusicBrainz izlaiduma ID" #: ../quodlibet/util/tags.py:123 #, fuzzy msgid "MusicBrainz artist ID" msgstr "MusicBrainz mākslinieka ID" #: ../quodlibet/util/tags.py:124 #, fuzzy msgid "MusicBrainz release artist ID" msgstr "MusicBrainz izlaiduma ID" #: ../quodlibet/util/tags.py:125 msgid "MusicBrainz TRM ID" msgstr "MusicBrainz TRM ID" #: ../quodlibet/util/tags.py:126 msgid "MusicIP PUID" msgstr "MusicIP PUID" #: ../quodlibet/util/tags.py:127 msgid "MusicBrainz album status" msgstr "MusicBrainz albuma statuss" #: ../quodlibet/util/tags.py:128 msgid "MusicBrainz album type" msgstr "MusicBrainz albuma tips" #: ../quodlibet/util/tags.py:129 #, fuzzy msgid "MusicBrainz release group ID" msgstr "MusicBrainz izlaiduma ID" #. Translators: "gain" means a volume adjustment, not "to acquire". #: ../quodlibet/util/tags.py:132 msgid "track gain" msgstr "celiņa pastiprinājums" #: ../quodlibet/util/tags.py:133 msgid "track peak" msgstr "celiņa maksimums" #. Translators: "gain" means a volume adjustment, not "to acquire". #: ../quodlibet/util/tags.py:135 msgid "album gain" msgstr "albuma pastiprinājums" #: ../quodlibet/util/tags.py:136 msgid "album peak" msgstr "albuma maksimums" #: ../quodlibet/util/tags.py:137 #, fuzzy msgid "reference loudness" msgstr "Iestatījumi" #: ../quodlibet/util/tags.py:142 msgid "discs" msgstr "diski" #: ../quodlibet/util/tags.py:144 msgid "tracks" msgstr "celiņi" #: ../quodlibet/util/tags.py:145 msgid "last started" msgstr "pēdējo reizi sākts" #: ../quodlibet/util/tags.py:146 msgid "full name" msgstr "pilns vārds" #: ../quodlibet/util/tags.py:153 msgid "mount point" msgstr "montēšanas punkts" #: ../quodlibet/util/tags.py:155 msgid "people" msgstr "cilvēki" #: ../quodlibet/util/tags.py:157 msgid "year" msgstr "gads" #: ../quodlibet/util/tags.py:158 #, fuzzy msgid "original release year" msgstr "oriģinālais izlaiduma datums" #: ../quodlibet/util/tags.py:159 msgid "bookmark" msgstr "grāmatzīme" #: ../quodlibet/util/tags.py:162 #, fuzzy msgid "file format" msgstr "Nav ilguma informācijas" #: ../quodlibet/util/tags.py:165 #, fuzzy msgid "playlists" msgstr "Repertuāri" #: ../quodlibet/util/tags.py:166 msgid "channel count" msgstr "" #. Translators: e.g. "artist (sort)" #: ../quodlibet/util/tags.py:256 msgid "sort" msgstr "" #. Translators: e.g. "performer (roles)" #: ../quodlibet/util/tags.py:264 msgid "roles" msgstr "" #, 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 "Remove all songs from the queue" #~ msgstr "Izņemt no rindas visas dziesmas" #~ msgid "Watch this folder for new songs" #~ msgstr "Vērot šo mapi" #~ 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 "Model:" #~ msgstr "Modelis:" #~ msgid "Capacity:" #~ msgstr "Ietilpība:" #~ msgid "Firmware:" #~ msgstr "Programmatūra:" #~ msgid "Removing orphaned iPod track" #~ msgstr "Dzēš nevajadzīgu iPod celiņu" #, 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 "Unable to open input files" #~ msgstr "Neizdevās atvērt ievades failus" #~ 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 "_Select" #~ msgstr "Izvēlētie_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 "Choose New Stations" #~ msgstr "Izvēlieties jaunas stacijas" #~ msgid "Add" #~ msgstr "Pievienot" #~ msgid "Bitrate" #~ msgstr "Bitātrums" #~ msgid "_Stations..." #~ msgstr "_Stacijas..." #~ msgid "Quod Libet" #~ msgstr "Quod Libet" #~ 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9711857 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/po/nb.po����������������������������������������������������������������������������0000644�0001750�0001750�00000622507�00000000000�014067� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Norwegian bokmål translation of Quod Libet # Copyright (C) 2004-2017 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. # msgid "" msgstr "" "Project-Id-Version: quodlibet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2018-04-19 18:25+0200\n" "PO-Revision-Date: 2018-04-19 18:37+0200\n" "Last-Translator: Åka Sikrom <a4 ætt hush dått com>\n" "Language-Team: Norwegian Bokmål\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 1.8.7.1\n" #: ../data/exfalso.appdata.xml.in.h:1 ../data/exfalso.desktop.in.h:2 msgid "Edit tags in your audio files" msgstr "Rediger tagger i lydfiler" #: ../data/exfalso.appdata.xml.in.h:2 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/exfalso.appdata.xml.in.h:3 ../data/quodlibet.appdata.xml.in.h:3 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/exfalso.desktop.in.h:1 msgid "Audio tag editor" msgstr "Lydtagg-behandler" #: ../data/quodlibet.appdata.xml.in.h:1 ../data/quodlibet.desktop.in.h:2 msgid "Listen to, browse, or edit your audio collection" msgstr "Lytt til, bla gjennom eller rediger lydsamling" #: ../data/quodlibet.appdata.xml.in.h:2 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." #: ../data/quodlibet.desktop.in.h:1 msgid "Music Player" msgstr "Musikkspiller" #: ../quodlibet/browsers/albums/main.py:186 #: ../quodlibet/browsers/covergrid/main.py:55 msgid "_Title" msgstr "_Tittel" #: ../quodlibet/browsers/albums/main.py:187 #: ../quodlibet/browsers/covergrid/main.py:56 ../quodlibet/qltk/prefs.py:50 msgid "_Artist" msgstr "_Artist" #: ../quodlibet/browsers/albums/main.py:188 #: ../quodlibet/browsers/covergrid/main.py:57 ../quodlibet/qltk/prefs.py:55 msgid "_Date" msgstr "_Dato" #: ../quodlibet/browsers/albums/main.py:189 #: ../quodlibet/browsers/covergrid/main.py:58 ../quodlibet/qltk/prefs.py:54 msgid "_Genre" msgstr "Sjan_ger" #: ../quodlibet/browsers/albums/main.py:190 #: ../quodlibet/browsers/covergrid/main.py:59 ../quodlibet/qltk/prefs.py:59 #: ../quodlibet/qltk/ratingsmenu.py:40 msgid "_Rating" msgstr "_Vurdering" #: ../quodlibet/browsers/albums/main.py:191 msgid "_Playcount" msgstr "_Antall avspillinger" #: ../quodlibet/browsers/albums/main.py:197 #: ../quodlibet/browsers/covergrid/main.py:65 msgid "Sort _by…" msgstr "Sorter _etter …" #: ../quodlibet/browsers/albums/main.py:218 #: ../quodlibet/browsers/covergrid/main.py:86 #: ../quodlibet/browsers/paned/prefs.py:167 #: ../quodlibet/browsers/playlists/main.py:638 #: ../quodlibet/qltk/exfalsowindow.py:110 ../quodlibet/qltk/pluginwin.py:342 #: ../quodlibet/qltk/quodlibetwindow.py:1053 msgid "_Preferences" msgstr "_Innstillinger" #: ../quodlibet/browsers/albums/main.py:384 msgid "Album List" msgstr "Albumliste" #: ../quodlibet/browsers/albums/main.py:385 msgid "_Album List" msgstr "_Albumliste" #: ../quodlibet/browsers/albums/main.py:495 #: ../quodlibet/browsers/covergrid/main.py:281 #: ../quodlibet/browsers/covergrid/main.py:491 msgid "All Albums" msgstr "Alle album" #: ../quodlibet/browsers/albums/main.py:496 #: ../quodlibet/browsers/covergrid/main.py:282 #: ../quodlibet/browsers/covergrid/main.py:492 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d album" msgstr[1] "%d album" #: ../quodlibet/browsers/albums/main.py:674 #: ../quodlibet/browsers/covergrid/main.py:470 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:29 #: ../quodlibet/browsers/collection/models.py:18 #: ../quodlibet/browsers/covergrid/prefs.py:31 msgid "Songs not in an album" msgstr "Låter uten album" #: ../quodlibet/browsers/albums/prefs.py:42 #: ../quodlibet/browsers/covergrid/prefs.py:44 #: ../quodlibet/browsers/playlists/prefs.py:36 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:100 #: ../quodlibet/qltk/information.py:386 ../quodlibet/util/collection.py:246 #, python-format msgid "%d track" msgid_plural "%d tracks" msgstr[0] "%d spor" msgstr[1] "%d spor" #: ../quodlibet/browsers/albums/prefs.py:43 #: ../quodlibet/browsers/covergrid/prefs.py:45 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:99 #: ../quodlibet/qltk/information.py:384 ../quodlibet/util/collection.py:250 #, python-format msgid "%d disc" msgid_plural "%d discs" msgstr[0] "%d plate" msgstr[1] "%d plater" #: ../quodlibet/browsers/albums/prefs.py:45 #: ../quodlibet/browsers/covergrid/prefs.py:47 msgid "An Example Album" msgstr "Et eksempelalbum" #: ../quodlibet/browsers/albums/prefs.py:53 msgid "Album List Preferences" msgstr "Innstillinger for albumliste" #: ../quodlibet/browsers/albums/prefs.py:62 msgid "Show album _covers" msgstr "Vis album_omslag" #: ../quodlibet/browsers/albums/prefs.py:68 msgid "Inline _search includes people" msgstr "_Søk inkluderer personer" #: ../quodlibet/browsers/albums/prefs.py:72 #: ../quodlibet/browsers/covergrid/prefs.py:121 #: ../quodlibet/ext/songsmenu/cover_download.py:243 msgid "Options" msgstr "Valg" #: ../quodlibet/browsers/albums/prefs.py:75 #: ../quodlibet/browsers/covergrid/prefs.py:124 msgid "Album Display" msgstr "Albumvisning" #: ../quodlibet/browsers/albums/prefs.py:79 #: ../quodlibet/browsers/covergrid/prefs.py:128 #: ../quodlibet/browsers/playlists/prefs.py:57 #: ../quodlibet/ext/songsmenu/albumart.py:328 #: ../quodlibet/ext/songsmenu/duplicates.py:349 #: ../quodlibet/ext/songsmenu/filterall.py:49 #: ../quodlibet/qltk/bookmarks.py:102 ../quodlibet/qltk/cbes.py:94 #: ../quodlibet/qltk/data_editors.py:98 ../quodlibet/qltk/data_editors.py:323 #: ../quodlibet/qltk/exfalsowindow.py:298 ../quodlibet/qltk/pluginwin.py:80 #: ../quodlibet/qltk/pluginwin.py:429 ../quodlibet/qltk/prefs.py:718 #: ../quodlibet/qltk/textedit.py:165 ../quodlibet/update.py:149 msgid "_Close" msgstr "_Lukk" #: ../quodlibet/browsers/audiofeeds.py:53 #: ../quodlibet/browsers/audiofeeds.py:65 #: ../quodlibet/browsers/audiofeeds.py:67 #: ../quodlibet/browsers/audiofeeds.py:157 #: ../quodlibet/browsers/paned/models.py:87 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:47 #: ../quodlibet/formats/_audio.py:501 ../quodlibet/order/__init__.py:28 #: ../quodlibet/qltk/information.py:245 ../quodlibet/qltk/information.py:252 #: ../quodlibet/qltk/information.py:278 ../quodlibet/qltk/wlw.py:71 msgid "Unknown" msgstr "Ukjent" #: ../quodlibet/browsers/audiofeeds.py:248 msgid "New Feed" msgstr "Ny kilde" #: ../quodlibet/browsers/audiofeeds.py:249 msgid "Enter the location of an audio feed:" msgstr "Skriv inn adressen til en lydkilde: " #: ../quodlibet/browsers/audiofeeds.py:250 #: ../quodlibet/browsers/collection/prefs.py:91 #: ../quodlibet/browsers/iradio.py:355 ../quodlibet/browsers/paned/prefs.py:79 #: ../quodlibet/browsers/playlists/menu.py:97 #: ../quodlibet/browsers/playlists/util.py:54 ../quodlibet/qltk/bookmarks.py:63 #: ../quodlibet/qltk/cbes.py:56 ../quodlibet/qltk/data_editors.py:310 #: ../quodlibet/qltk/edittags.py:289 ../quodlibet/qltk/edittags.py:489 #: ../quodlibet/qltk/quodlibetwindow.py:1388 ../quodlibet/qltk/scanbox.py:62 msgid "_Add" msgstr "L_egg til" #: ../quodlibet/browsers/audiofeeds.py:304 msgid "Audio Feeds" msgstr "Lydkilder" #: ../quodlibet/browsers/audiofeeds.py:305 msgid "_Audio Feeds" msgstr "_Lydkilder" #: ../quodlibet/browsers/audiofeeds.py:408 #: ../quodlibet/browsers/playlists/main.py:216 #: ../quodlibet/qltk/data_editors.py:95 msgid "_New" msgstr "_Ny" #: ../quodlibet/browsers/audiofeeds.py:468 #: ../quodlibet/browsers/audiofeeds.py:527 msgid "Unable to add feed" msgstr "Klarte ikke å legge til kilde" #: ../quodlibet/browsers/audiofeeds.py:469 #: ../quodlibet/browsers/audiofeeds.py:528 #, python-format msgid "" "%s could not be added. The server may be down, or the location may not be an " "audio feed." msgstr "" "Klarte ikke å legge til %s. Tjeneren kan være utilgjengelig, eller " "plasseringa er ikke en lydkilde." #: ../quodlibet/browsers/audiofeeds.py:476 ../quodlibet/qltk/filesel.py:272 #: ../quodlibet/qltk/pluginwin.py:415 msgid "_Refresh" msgstr "Oppdate_r" #: ../quodlibet/browsers/audiofeeds.py:477 #: ../quodlibet/browsers/playlists/main.py:459 #: ../quodlibet/browsers/playlists/util.py:45 ../quodlibet/qltk/delete.py:144 #: ../quodlibet/qltk/filesel.py:269 ../quodlibet/qltk/lyrics.py:36 #: ../quodlibet/qltk/maskedbox.py:29 ../quodlibet/qltk/songsmenu.py:363 msgid "_Delete" msgstr "Sle_tt" #: ../quodlibet/browsers/audiofeeds.py:544 msgid "" "The current audio backend does not support URLs, Audio Feeds browser " "disabled." msgstr "" "Gjeldende lyd-bakstykke støtter ikke nettadresser. Lydstrøm-utforsker slått " "av." #: ../quodlibet/browsers/_base.py:148 ../quodlibet/browsers/_base.py:151 msgid "Library Browser" msgstr "Bibliotekutforsker" #: ../quodlibet/browsers/_base.py:275 ../quodlibet/ext/songsmenu/console.py:47 #: ../quodlibet/ext/songsmenu/refresh.py:31 #: ../quodlibet/qltk/exfalsowindow.py:242 ../quodlibet/qltk/information.py:555 #: ../quodlibet/qltk/maskedbox.py:69 ../quodlibet/util/collection.py:532 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d låt" msgstr[1] "%d låter" #: ../quodlibet/browsers/_base.py:403 ../quodlibet/browsers/_base.py:408 #: ../quodlibet/qltk/tagsfrompath.py:195 ../quodlibet/qltk/textedit.py:142 #: ../quodlibet/util/__init__.py:574 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:25 #, python-format msgid "Unknown %s" msgstr "Ukjent %s" #: ../quodlibet/browsers/collection/models.py:26 #, python-format msgid "Multiple %s Values" msgstr "Flere %s verdier" #: ../quodlibet/browsers/collection/prefs.py:67 #: ../quodlibet/browsers/paned/prefs.py:52 msgid "_Custom" msgstr "_Selvvalgt" #. Remove button #: ../quodlibet/browsers/collection/prefs.py:95 #: ../quodlibet/browsers/paned/prefs.py:83 #: ../quodlibet/browsers/playlists/menu.py:98 #: ../quodlibet/ext/playlist/remove_duplicates.py:61 #: ../quodlibet/qltk/bookmarks.py:98 ../quodlibet/qltk/bookmarks.py:128 #: ../quodlibet/qltk/cbes.py:83 ../quodlibet/qltk/cbes.py:90 #: ../quodlibet/qltk/data_editors.py:80 ../quodlibet/qltk/data_editors.py:93 #: ../quodlibet/qltk/data_editors.py:300 ../quodlibet/qltk/data_editors.py:313 #: ../quodlibet/qltk/data_editors.py:321 ../quodlibet/qltk/edittags.py:495 #: ../quodlibet/qltk/edittags.py:635 ../quodlibet/qltk/maskedbox.py:49 #: ../quodlibet/qltk/maskedbox.py:89 ../quodlibet/qltk/queue.py:377 #: ../quodlibet/qltk/scanbox.py:37 ../quodlibet/qltk/scanbox.py:64 msgid "_Remove" msgstr "_Fjern" #: ../quodlibet/browsers/collection/prefs.py:123 #: ../quodlibet/ext/songsmenu/filterall.py:35 #: ../quodlibet/operon/commands.py:57 ../quodlibet/operon/commands.py:93 #: ../quodlibet/qltk/edittags.py:432 msgid "Tag" msgstr "Tagg" #: ../quodlibet/browsers/collection/prefs.py:129 msgid "Merge" msgstr "Slå sammen" #: ../quodlibet/browsers/collection/prefs.py:189 msgid "Album Collection Preferences" msgstr "Innstillinger for albumsamling" #: ../quodlibet/browsers/collection/prefs.py:196 #: ../quodlibet/browsers/paned/prefs.py:210 #: ../quodlibet/ext/songsmenu/editplaycount.py:46 #: ../quodlibet/ext/songsmenu/exact_rating.py:39 #: ../quodlibet/player/gstbe/prefs.py:41 ../quodlibet/qltk/prefs.py:128 #: ../quodlibet/qltk/textedit.py:66 msgid "_Apply" msgstr "_Bruk" #: ../quodlibet/browsers/collection/prefs.py:199 #: ../quodlibet/browsers/paned/prefs.py:214 #: ../quodlibet/browsers/playlists/menu.py:96 #: ../quodlibet/browsers/playlists/util.py:44 #: ../quodlibet/errorreport/ui.py:104 #: ../quodlibet/ext/playlist/export_to_folder.py:38 #: ../quodlibet/ext/playlist/remove_duplicates.py:60 #: ../quodlibet/ext/_shared/squeezebox/util.py:20 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:356 #: ../quodlibet/ext/songsmenu/editplaycount.py:45 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:282 #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:92 #: ../quodlibet/ext/songsmenu/importexport.py:40 #: ../quodlibet/ext/songsmenu/lastfmsync.py:219 #: ../quodlibet/ext/songsmenu/playlist.py:51 #: ../quodlibet/ext/songsmenu/replaygain.py:364 #: ../quodlibet/ext/songsmenu/tapbpm.py:182 ../quodlibet/qltk/chooser.py:189 #: ../quodlibet/qltk/chooser.py:210 ../quodlibet/qltk/chooser.py:234 #: ../quodlibet/qltk/chooser.py:258 ../quodlibet/qltk/delete.py:91 #: ../quodlibet/qltk/delete.py:134 ../quodlibet/qltk/edittags.py:288 #: ../quodlibet/qltk/_editutils.py:40 ../quodlibet/qltk/getstring.py:29 #: ../quodlibet/qltk/maskedbox.py:28 ../quodlibet/qltk/msg.py:55 #: ../quodlibet/qltk/msg.py:94 ../quodlibet/qltk/msg.py:112 #: ../quodlibet/qltk/ratingsmenu.py:34 ../quodlibet/update.py:95 msgid "_Cancel" msgstr "Avbr_yt" #: ../quodlibet/browsers/covergrid/main.py:127 msgid "Cover Grid" msgstr "Omslagsnett" #: ../quodlibet/browsers/covergrid/main.py:128 msgid "_Cover Grid" msgstr "_Omslagsnett" #: ../quodlibet/browsers/covergrid/prefs.py:55 msgid "Cover Grid Preferences" msgstr "Omslagsnett-innstillinger" #: ../quodlibet/browsers/covergrid/prefs.py:65 msgid "Show album _text" msgstr "Vis album_tekst" #: ../quodlibet/browsers/covergrid/prefs.py:72 msgid "Show \"All Albums\" Item" msgstr "Vis elementet «alle album»" #: ../quodlibet/browsers/covergrid/prefs.py:79 msgid "Wide Mode" msgstr "Bred modus" #: ../quodlibet/browsers/covergrid/prefs.py:111 #: ../quodlibet/browsers/covergrid/prefs.py:112 msgid "Cover Magnification" msgstr "Omslagsforstørrelse" #: ../quodlibet/browsers/filesystem.py:41 msgid "File System" msgstr "Filsystem" #: ../quodlibet/browsers/filesystem.py:42 msgid "_File System" msgstr "_Filsystem" #: ../quodlibet/browsers/filesystem.py:126 ../quodlibet/qltk/songlist.py:256 msgid "Unable to copy songs" msgstr "Klarte ikke å legge til låter" #: ../quodlibet/browsers/filesystem.py:127 ../quodlibet/qltk/songlist.py:257 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:199 msgid "_Add to Library" msgstr "_Legg til i bibliotek" #: ../quodlibet/browsers/iradio.py:182 msgid "Unsupported file type" msgstr "Gjeldende filtype støttes ikke" #: ../quodlibet/browsers/iradio.py:183 #, 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:228 ../quodlibet/browsers/iradio.py:241 #: ../quodlibet/browsers/iradio.py:824 msgid "Unable to add station" msgstr "Klarte ikke å legge til stasjon" #: ../quodlibet/browsers/iradio.py:252 ../quodlibet/browsers/iradio.py:485 msgid "Internet Radio" msgstr "Nettradio" #: ../quodlibet/browsers/iradio.py:252 msgid "Downloading station list" msgstr "Laster ned stasjonsliste" #: ../quodlibet/browsers/iradio.py:353 msgid "New Station" msgstr "Ny stasjon" #: ../quodlibet/browsers/iradio.py:354 msgid "Enter the location of an Internet radio station:" msgstr "Skriv inn adressen til en nettradio-stasjon:" #: ../quodlibet/browsers/iradio.py:372 msgid "Electronic" msgstr "Elektronisk" #: ../quodlibet/browsers/iradio.py:375 msgid "Hip Hop / Rap" msgstr "Hip-Hop / Rap" #: ../quodlibet/browsers/iradio.py:376 msgid "Oldies" msgstr "Gamleviser" #: ../quodlibet/browsers/iradio.py:377 msgid "R&B" msgstr "R&B" #: ../quodlibet/browsers/iradio.py:378 msgid "Japanese" msgstr "Japansk" #: ../quodlibet/browsers/iradio.py:379 msgid "Indian" msgstr "Indisk" #: ../quodlibet/browsers/iradio.py:381 msgid "Religious" msgstr "Religiøst" #: ../quodlibet/browsers/iradio.py:383 msgid "Charts" msgstr "Lister" #: ../quodlibet/browsers/iradio.py:384 msgid "Turkish" msgstr "Tyrkisk" #: ../quodlibet/browsers/iradio.py:385 msgid "Reggae / Dancehall" msgstr "Reggae / Dancehall" #: ../quodlibet/browsers/iradio.py:386 msgid "Latin" msgstr "Latin" #: ../quodlibet/browsers/iradio.py:387 msgid "College Radio" msgstr "Studentradio" #: ../quodlibet/browsers/iradio.py:388 msgid "Talk / News" msgstr "Prat / Nyheter" #: ../quodlibet/browsers/iradio.py:389 msgid "Ambient" msgstr "Ambient" #: ../quodlibet/browsers/iradio.py:390 msgid "Jazz" msgstr "Jazz" #: ../quodlibet/browsers/iradio.py:391 ../quodlibet/ext/events/equalizer.py:46 msgid "Classical" msgstr "Klassisk" #: ../quodlibet/browsers/iradio.py:392 ../quodlibet/ext/events/equalizer.py:61 msgid "Pop" msgstr "Pop" #: ../quodlibet/browsers/iradio.py:393 msgid "Alternative" msgstr "Alternativt" #: ../quodlibet/browsers/iradio.py:394 msgid "Metal" msgstr "Metal" #: ../quodlibet/browsers/iradio.py:395 msgid "Country" msgstr "Country" #: ../quodlibet/browsers/iradio.py:396 msgid "News" msgstr "Nyheter" #: ../quodlibet/browsers/iradio.py:397 msgid "Schlager" msgstr "Schlager" #: ../quodlibet/browsers/iradio.py:398 msgid "Funk" msgstr "Funk" #: ../quodlibet/browsers/iradio.py:399 msgid "Indie" msgstr "Indie" #: ../quodlibet/browsers/iradio.py:400 msgid "Blues" msgstr "Blues" #: ../quodlibet/browsers/iradio.py:401 msgid "Soul" msgstr "Soul" #: ../quodlibet/browsers/iradio.py:402 msgid "Lounge" msgstr "Lounge" #: ../quodlibet/browsers/iradio.py:403 msgid "Punk" msgstr "Punk" #: ../quodlibet/browsers/iradio.py:404 msgid "Reggaeton" msgstr "Reggaeton" #: ../quodlibet/browsers/iradio.py:406 msgid "Slavic" msgstr "Slavisk" #: ../quodlibet/browsers/iradio.py:408 msgid "Greek" msgstr "Gresk" #: ../quodlibet/browsers/iradio.py:409 msgid "Gothic" msgstr "Gotisk" #: ../quodlibet/browsers/iradio.py:410 ../quodlibet/ext/events/equalizer.py:39 msgid "Rock" msgstr "Rock" #: ../quodlibet/browsers/iradio.py:463 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:469 msgid "_Load Stations" msgstr "Last inn stasjoner" #: ../quodlibet/browsers/iradio.py:486 msgid "_Internet Radio" msgstr "_Nettradio" #: ../quodlibet/browsers/iradio.py:552 msgid "_New Station…" msgstr "_Ny stasjon …" #: ../quodlibet/browsers/iradio.py:555 msgid "_Update Stations" msgstr "_Oppdater stasjoner" #: ../quodlibet/browsers/iradio.py:582 msgid "All Stations" msgstr "Alle stasjoner" #. TODO: support for ~#rating=!None etc (#1940) #: ../quodlibet/browsers/iradio.py:586 #: ../quodlibet/browsers/soundcloud/main.py:65 msgid "Favorites" msgstr "Favoritter" #: ../quodlibet/browsers/iradio.py:594 msgid "No Category" msgstr "Ingen kategori" #: ../quodlibet/browsers/iradio.py:816 msgid "No stations found" msgstr "Fant ingen stasjoner" #: ../quodlibet/browsers/iradio.py:817 #, python-format msgid "No Internet radio stations were found at %s." msgstr "Fant ingen nettradio-stasjoner på %s." #: ../quodlibet/browsers/iradio.py:825 msgid "All stations listed are already in your library." msgstr "Alle oppførte stasjoner ligger i biblioteket allerede." #: ../quodlibet/browsers/iradio.py:842 msgid "Add to Favorites" msgstr "Legg til i favoritter" #: ../quodlibet/browsers/iradio.py:846 msgid "Remove from Favorites" msgstr "Fjern fra favoritter" #: ../quodlibet/browsers/iradio.py:946 #, 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:42 ../quodlibet/qltk/shortcuts.py:45 msgid "Paned Browser" msgstr "Rutevisning" #: ../quodlibet/browsers/paned/main.py:43 msgid "_Paned Browser" msgstr "_Rutevisning" #: ../quodlibet/browsers/paned/main.py:93 msgid "Select _All" msgstr "Velg alle" #: ../quodlibet/browsers/paned/models.py:105 ../quodlibet/qltk/pluginwin.py:123 #: ../quodlibet/qltk/pluginwin.py:165 msgid "All" msgstr "Alle" #: ../quodlibet/browsers/paned/prefs.py:68 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "<tt>%s</tt>" msgstr "" "Taggmønster med valgfri markering som f.eks. <tt>komponist</tt> eller\n" "<tt>%s</tt>" #: ../quodlibet/browsers/paned/prefs.py:163 msgid "_Wide Mode" msgstr "_Bred modus" #: ../quodlibet/browsers/paned/prefs.py:198 msgid "Paned Browser Preferences" msgstr "Innstillinger for rutevisning" #: ../quodlibet/browsers/paned/prefs.py:205 msgid "Equal pane width" msgstr "Lik rutebredde" #: ../quodlibet/browsers/playlists/main.py:48 #: ../quodlibet/browsers/playlists/main.py:574 #: ../quodlibet/qltk/pluginwin.py:169 msgid "Playlists" msgstr "Spillelister" #: ../quodlibet/browsers/playlists/main.py:49 msgid "_Playlists" msgstr "_Spillelister" #: ../quodlibet/browsers/playlists/main.py:152 msgid "_Remove from Playlist" msgstr "_Fjern fra spilleliste" #: ../quodlibet/browsers/playlists/main.py:218 #: ../quodlibet/browsers/playlists/main.py:575 msgid "_Import" msgstr "_Importer" #: ../quodlibet/browsers/playlists/main.py:415 msgid "Unable to import playlist" msgstr "Klarte ikke å importere spilleliste" #: ../quodlibet/browsers/playlists/main.py:416 msgid "Quod Libet can only import playlists in the M3U and PLS formats." msgstr "Quod Libet kan bare importere spillelister i formatene M3U og PLS." #: ../quodlibet/browsers/playlists/main.py:466 msgid "_Rename" msgstr "_Gi nytt navn" #: ../quodlibet/browsers/playlists/main.py:564 msgid "Unable to rename playlist" msgstr "Klarte ikke å gi nytt navn til spilleliste" #: ../quodlibet/browsers/playlists/main.py:575 msgid "Import Playlist" msgstr "Importer spilleliste" #: ../quodlibet/browsers/playlists/menu.py:26 msgid "_New Playlist…" msgstr "_Ny spilleliste …" #: ../quodlibet/browsers/playlists/menu.py:87 #, 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:91 #, python-format msgid "Confirm action for playlist \"%s\"" msgstr "Bekreft handling for spilleliste «%s»" #: ../quodlibet/browsers/playlists/prefs.py:22 msgid "empty" msgstr "tom" #: ../quodlibet/browsers/playlists/prefs.py:40 msgid "Example Playlist" msgstr "Eksempelliste" #: ../quodlibet/browsers/playlists/prefs.py:48 msgid "Playlist Browser Preferences" msgstr "Innstillinger for spilleliste-utforsker" #: ../quodlibet/browsers/playlists/prefs.py:53 msgid "Playlist display" msgstr "Spillelistevisning" #: ../quodlibet/browsers/playlists/util.py:35 #, 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:37 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" "All informasjon om valgt spilleliste blir slettet, og kan ikke gjenopprettes." #: ../quodlibet/browsers/playlists/util.py:52 #: ../quodlibet/browsers/playlists/util.py:127 #: ../quodlibet/util/collection.py:575 msgid "New Playlist" msgstr "Ny spilleliste" #: ../quodlibet/browsers/playlists/util.py:53 msgid "Enter a name for the new playlist:" msgstr "Skriv inn navn på ny spilleliste:" #: ../quodlibet/browsers/playlists/util.py:91 #, 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/search.py:32 msgid "_Limit Results" msgstr "_Begrens resultater" #: ../quodlibet/browsers/search.py:47 msgid "Search Library" msgstr "Søk i bibliotek" #: ../quodlibet/browsers/search.py:48 msgid "_Search Library" msgstr "_Søk i bibliotek" #: ../quodlibet/browsers/soundcloud/main.py:39 msgid "Soundcloud Browser" msgstr "Soundcloud-utforsker" #: ../quodlibet/browsers/soundcloud/main.py:40 msgid "Sound_cloud" msgstr "Sound_cloud" #: ../quodlibet/browsers/soundcloud/main.py:60 #: ../quodlibet/qltk/searchbar.py:76 msgid "Search" msgstr "Søk" #: ../quodlibet/browsers/soundcloud/main.py:69 msgid "My tracks" msgstr "Spor" #: ../quodlibet/browsers/soundcloud/main.py:141 #, python-format msgid "Go to %s" msgstr "Gå til %s" #: ../quodlibet/browsers/soundcloud/main.py:393 msgid "Connected" msgstr "Tilkoblet" #: ../quodlibet/browsers/soundcloud/main.py:394 #, python-format msgid "Quod Libet is now connected, <b>%s</b>!" msgstr "Quod Libet er nå tilkoblet. <b>%s</b>!" #: ../quodlibet/browsers/soundcloud/main.py:406 #, python-format msgid "Log out of %s" msgstr "Logg ut av %s" #: ../quodlibet/browsers/soundcloud/main.py:408 msgid "Enter code…" msgstr "Skriv inn kode …" #: ../quodlibet/browsers/soundcloud/main.py:409 #, python-format msgid "Log in to %s" msgstr "Logg inn på %s" #: ../quodlibet/browsers/soundcloud/util.py:87 msgid "Soundcloud authorisation" msgstr "Soundcloud-autorisering" #: ../quodlibet/browsers/soundcloud/util.py:88 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 "Print player status" msgstr "Skriv ut spillerstatus" #: ../quodlibet/cli.py:106 msgid "Hide main window" msgstr "Skjul hovedvindu" #: ../quodlibet/cli.py:107 msgid "Show main window" msgstr "Vis hovedvindu" #: ../quodlibet/cli.py:108 msgid "Toggle main window visibility" msgstr "Vis/skjul hovedvindu" #: ../quodlibet/cli.py:109 msgid "Focus the running player" msgstr "Fokuser på kjørende spiller" #: ../quodlibet/cli.py:110 msgid "Remove active browser filters" msgstr "Fjern gjeldende visningsfiltre" #: ../quodlibet/cli.py:111 msgid "Refresh and rescan library" msgstr "Oppdater bibliotek og skann på nytt" #: ../quodlibet/cli.py:112 msgid "List available browsers" msgstr "Vis tilgjengelige utforskere" #: ../quodlibet/cli.py:113 msgid "Print the current playlist" msgstr "Skriv ut gjeldende spilleliste" #: ../quodlibet/cli.py:114 msgid "Print the contents of the queue" msgstr "Skriv ut innhold i kø" #: ../quodlibet/cli.py:115 msgid "Print the active text query" msgstr "Skriv ut gjeldende tekstspørring" #: ../quodlibet/cli.py:116 msgid "Start without plugins" msgstr "Start uten tillegg" #: ../quodlibet/cli.py:117 msgid "Start Quod Libet if it isn't running" msgstr "Start Quod Libet hvis det ikke kjører" #: ../quodlibet/cli.py:118 msgid "Exit Quod Libet" msgstr "Avslutt Quod Libet" #: ../quodlibet/cli.py:123 msgid "Seek within the playing song" msgstr "Søk i låta som spilles av" #: ../quodlibet/cli.py:123 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: ../quodlibet/cli.py:124 msgid "Set or toggle shuffle mode" msgstr "Slå av/på tilfeldig rekkefølge" #: ../quodlibet/cli.py:125 msgid "Set shuffle mode type" msgstr "Endre omstokkingsmodus" #: ../quodlibet/cli.py:126 msgid "Turn repeat off, on, or toggle it" msgstr "Bytt eller slå gjentakelsesmodus av/på" #: ../quodlibet/cli.py:127 msgid "Set repeat mode type" msgstr "Endre gjentakelsesmodus" #: ../quodlibet/cli.py:128 msgid "Set the volume" msgstr "Juster volum" #: ../quodlibet/cli.py:129 msgid "Search your audio library" msgstr "Søk i musikkbibliotek" #: ../quodlibet/cli.py:129 ../quodlibet/cli.py:141 ../quodlibet/cli.py:145 #: ../quodlibet/cli.py:147 msgid "query" msgstr "spørring" #: ../quodlibet/cli.py:130 msgid "Play a file" msgstr "Spill av en fil" #: ../quodlibet/cli.py:130 ../quodlibet/cli.py:141 ../quodlibet/cli.py:147 msgctxt "command" msgid "filename" msgstr "filnavn" #: ../quodlibet/cli.py:131 msgid "Rate the playing song" msgstr "Vurder låt som spilles av" #: ../quodlibet/cli.py:132 msgid "Set the current browser" msgstr "Velg visningsmodus for gjeldende vindu" #: ../quodlibet/cli.py:133 msgid "Stop after the playing song" msgstr "Stopp etter spillende låt" #: ../quodlibet/cli.py:134 msgid "Open a new browser" msgstr "Åpne nytt visningsvindu" #: ../quodlibet/cli.py:135 msgid "Show or hide the queue" msgstr "Vis eller skjul kø" #: ../quodlibet/cli.py:137 msgid "Show or hide the main song list (deprecated)" msgstr "Vis eller skjul hovedlåtliste (utgått)" #: ../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:159 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:207 #, python-format msgid "Invalid argument for '%s'." msgstr "Ugyldig argument for «%s»." #: ../quodlibet/cli.py:208 ../quodlibet/util/__init__.py:174 #, python-format msgid "Try %s --help." msgstr "Prøv %s --help." #: ../quodlibet/errorreport/ui.py:59 msgid "An Error Occurred" msgstr "Det oppstod en feil" #: ../quodlibet/errorreport/ui.py:61 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:70 ../quodlibet/errorreport/ui.py:86 msgid "Submit Error Report" msgstr "Send feilrapport" #: ../quodlibet/errorreport/ui.py:71 msgid "Quit Program" msgstr "Avslutt program" #: ../quodlibet/errorreport/ui.py:72 msgid "Ignore Error" msgstr "Ignorer feil" #: ../quodlibet/errorreport/ui.py:76 msgid "Error details:" msgstr "Feildetaljer:" #: ../quodlibet/errorreport/ui.py:88 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:96 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:105 msgid "_Send" msgstr "_Send" #: ../quodlibet/errorreport/ui.py:111 msgid "Short description…" msgstr "Kort beskrivelse …" #: ../quodlibet/errorreport/ui.py:114 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:160 msgid "directory" msgstr "mappe" #: ../quodlibet/exfalso.py:42 msgid "Audio metadata editor" msgstr "Metadata-behandler for lydfiler" #: ../quodlibet/ext/covers/artwork_url.py:20 msgid "Artwork URL Cover Source" msgstr "Nettadresse til omslagsbilde" #: ../quodlibet/ext/covers/artwork_url.py:21 msgid "" "Downloads covers linked to by the artwork_url tag. This works with the " "Soundcloud browser." msgstr "" "Laster ned omslagsbilder fra adressen i taggen «artwork_url». Dette fungerer " "med Soundcloud-utforskeren." #: ../quodlibet/ext/covers/discogs.py:29 msgid "Discogs Cover Source" msgstr "Discogs-omslagskilde" #: ../quodlibet/ext/covers/discogs.py:30 msgid "Downloads covers from Discogs." msgstr "Last ned omslagsbilder fra Discogs." #: ../quodlibet/ext/covers/lastfm.py:21 msgid "Last.fm Cover Source" msgstr "Last.fm-omslagskilde" #: ../quodlibet/ext/covers/lastfm.py:22 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:27 msgid "Convert Encodings" msgstr "Konverter kodinger" #: ../quodlibet/ext/editing/iconv.py:28 msgid "Fixes misinterpreted tag value encodings in the tag editor." msgstr "Retter opp feiltolkede kodinger av taggverdier i taggbehandleren." #: ../quodlibet/ext/editing/iconv.py:34 msgid "_Convert Encoding…" msgstr "_Konverter koding …" #: ../quodlibet/ext/editing/kakasi.py:27 msgid "Kana/Kanji Simple Inverter" msgstr "Enkel Kana/Kanji-omformer" #: ../quodlibet/ext/editing/kakasi.py:28 msgid "Converts kana/kanji to romaji before renaming." msgstr "Konverterer kana/kanji til romaji før navnebytte." #: ../quodlibet/ext/editing/kakasi.py:37 msgid "Romanize _Japanese text" msgstr "Romaniser _japansk tekst" #: ../quodlibet/ext/editing/kakasi.py:69 msgid "Couldn't find the 'Kanji Kana Simple Inverter' (kakasi)." msgstr "Fant ikke «Kanji Kana Simple Inverter» (kakasi)." #: ../quodlibet/ext/editing/resub.py:19 msgid "Regex Substitution" msgstr "Bruk reg.uttrykk" #: ../quodlibet/ext/editing/resub.py:20 msgid "" "Allows arbitrary regex substitutions (s///) when tagging or renaming files." msgstr "" "Tillater arbitrær bruk av regulære uttrykk («s///») ved tagging eller " "endring av filnavn." #: ../quodlibet/ext/editing/titlecase.py:21 msgid "Title Case" msgstr "Tittelversaler" #: ../quodlibet/ext/editing/titlecase.py:22 msgid "Title-cases tag values in the tag editor." msgstr "Tittelversaliser tagger i taggbehandler." #: ../quodlibet/ext/editing/titlecase.py:41 msgid "Title-_case Value" msgstr "Tittelversaliser verdi" #: ../quodlibet/ext/editing/titlecase.py:52 msgid "Allow _ALL-CAPS in tags" msgstr "Tillat tagger med _BARE STORE BOKSTAVER" #: ../quodlibet/ext/editing/titlecase.py:53 msgid "_Human title case" msgstr "_Tittelversalisering" #: ../quodlibet/ext/editing/titlecase.py:54 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:69 msgid "Advanced Preferences" msgstr "Avanserte innstillinger" #: ../quodlibet/ext/events/advanced_preferences.py:70 msgid "Allow editing of advanced config settings." msgstr "Tillat endring av avanserte oppsettsvalg." #: ../quodlibet/ext/events/advanced_preferences.py:176 msgid "I know what I'm doing" msgstr "Jeg vet hva jeg gjør" #: ../quodlibet/ext/events/animosd/main.py:28 msgid "Animated On-Screen Display" msgstr "Animert skjermvisning" #: ../quodlibet/ext/events/animosd/main.py:29 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:154 msgid "Top of screen" msgstr "Toppen av skjermen" #: ../quodlibet/ext/events/animosd/prefs.py:155 msgid "Middle of screen" msgstr "Midt på skjermen" #: ../quodlibet/ext/events/animosd/prefs.py:156 msgid "Bottom of screen" msgstr "Bunnen av skjermen" #: ../quodlibet/ext/events/animosd/prefs.py:159 msgid "_Position:" msgstr "_Posisjon:" #: ../quodlibet/ext/events/animosd/prefs.py:172 msgid "_Cover size:" msgstr "_Omslagsstørrelse:" #: ../quodlibet/ext/events/animosd/prefs.py:178 #: ../quodlibet/ext/events/weblyrics.py:318 ../quodlibet/qltk/prefs.py:267 msgid "Display" msgstr "Visning" #: ../quodlibet/ext/events/animosd/prefs.py:191 msgid "_Font:" msgstr "Skri_ft:" #: ../quodlibet/ext/events/animosd/prefs.py:196 msgid "Left" msgstr "Venstre" #: ../quodlibet/ext/events/animosd/prefs.py:197 msgid "Center" msgstr "Sentrum" #: ../quodlibet/ext/events/animosd/prefs.py:198 msgid "Right" msgstr "Høyre" #: ../quodlibet/ext/events/animosd/prefs.py:201 msgid "_Align text:" msgstr "_Juster tekst:" #: ../quodlibet/ext/events/animosd/prefs.py:207 msgid "Text" msgstr "Tekst" #: ../quodlibet/ext/events/animosd/prefs.py:218 msgid "_Text:" msgstr "_Tekst:" #: ../quodlibet/ext/events/animosd/prefs.py:228 msgid "_Fill:" msgstr "_Fyll:" #: ../quodlibet/ext/events/animosd/prefs.py:233 #: ../quodlibet/ext/events/synchronizedlyrics.py:67 msgid "Colors" msgstr "Farger" #: ../quodlibet/ext/events/animosd/prefs.py:241 msgid "_Shadows" msgstr "_Skygger" #: ../quodlibet/ext/events/animosd/prefs.py:242 msgid "_Outline" msgstr "K_ontur" #: ../quodlibet/ext/events/animosd/prefs.py:243 msgid "Rou_nded Corners" msgstr "Avru_ndede hjørner" #: ../quodlibet/ext/events/animosd/prefs.py:259 msgid "_Delay:" msgstr "_Forsinkelse:" #: ../quodlibet/ext/events/animosd/prefs.py:265 #: ../quodlibet/qltk/pluginwin.py:173 msgid "Effects" msgstr "Effekter" #: ../quodlibet/ext/events/animosd/prefs.py:271 msgid "Ed_it Display Pattern…" msgstr "Rediger visningsmønster …" #: ../quodlibet/ext/events/animosd/prefs.py:275 #: ../quodlibet/ext/events/trayicon/prefs.py:87 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 "Audio Backend" msgstr "Lyd-bakstykke" #: ../quodlibet/ext/events/auto_library_update.py:137 msgid "Automatic Library Update" msgstr "Automatisk bibliotek-oppdatering" #: ../quodlibet/ext/events/auto_library_update.py:138 #, python-format msgid "Keeps your library up to date with inotify. Requires %s." msgstr "Holder biblioteket oppdatert ved hjelp av inotify. Krever %s." #: ../quodlibet/ext/events/automask.py:23 msgid "Automatic Masking" msgstr "Automatisk maskering" #: ../quodlibet/ext/events/automask.py:24 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:16 msgid "Automatic Rating" msgstr "Automatisk vurdering" #: ../quodlibet/ext/events/autorating.py:17 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." #: ../quodlibet/ext/events/clock.py:25 msgid "Alarm Clock" msgstr "Vekkerklokke" #: ../quodlibet/ext/events/clock.py:26 msgid "Wakes you up with loud music." msgstr "Vekkefunksjon med høy musikk." #: ../quodlibet/ext/events/clock.py:120 msgid "Lullaby" msgstr "Nattasang" #: ../quodlibet/ext/events/clock.py:121 msgid "Fades out and pauses your music." msgstr "Toner ut og setter musikk på pause." #: ../quodlibet/ext/events/equalizer.py:27 msgid "Flat" msgstr "Flat" #: ../quodlibet/ext/events/equalizer.py:28 msgid "Live" msgstr "Levende" #: ../quodlibet/ext/events/equalizer.py:30 msgid "Full Bass & Treble" msgstr "Full bass og diskant" #: ../quodlibet/ext/events/equalizer.py:33 msgid "Club" msgstr "Klubb" #: ../quodlibet/ext/events/equalizer.py:35 msgid "Large Hall" msgstr "Stor hall" #: ../quodlibet/ext/events/equalizer.py:37 msgid "Party" msgstr "Fest" #: ../quodlibet/ext/events/equalizer.py:41 msgid "Soft" msgstr "Myk" #: ../quodlibet/ext/events/equalizer.py:43 msgid "Full Bass" msgstr "Full bass" #: ../quodlibet/ext/events/equalizer.py:49 msgid "Reggae" msgstr "Reggae" #: ../quodlibet/ext/events/equalizer.py:51 msgid "Headphones" msgstr "Hodetelefoner" #: ../quodlibet/ext/events/equalizer.py:54 msgid "Soft Rock" msgstr "Soft rock" #: ../quodlibet/ext/events/equalizer.py:56 msgid "Full Treble" msgstr "Full diskant" #: ../quodlibet/ext/events/equalizer.py:59 msgid "Dance" msgstr "Dance" #: ../quodlibet/ext/events/equalizer.py:63 msgid "Techno" msgstr "Techno" #: ../quodlibet/ext/events/equalizer.py:65 msgid "Ska" msgstr "Ska" #: ../quodlibet/ext/events/equalizer.py:67 msgid "Laptop" msgstr "Laptop" #: ../quodlibet/ext/events/equalizer.py:98 msgid "Equalizer" msgstr "Equalizer" #: ../quodlibet/ext/events/equalizer.py:99 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:133 msgid "The current backend does not support equalization." msgstr "Gjeldende bakstykke støtter ikke overtone-kontroll." #: ../quodlibet/ext/events/equalizer.py:139 #, python-format msgid "%.1f kHz" msgstr "%.1f kHz" #: ../quodlibet/ext/events/equalizer.py:140 #: ../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:174 #: ../quodlibet/ext/gstreamer/crossfeed.py:113 #, python-format msgid "%.1f dB" msgstr "%.1f dB" #: ../quodlibet/ext/events/equalizer.py:193 #: ../quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom" msgstr "Selvvalgt" #: ../quodlibet/ext/events/equalizer.py:200 msgid "_Clear" msgstr "_Tøm" #. 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:115 #: ../quodlibet/ext/events/mqtt.py:46 #: ../quodlibet/ext/events/telepathy_status.py:70 msgid "paused" msgstr "pauset" #: ../quodlibet/ext/events/gajim_status.py:146 msgid "Pattern:" msgstr "Mønster:" #: ../quodlibet/ext/events/gajim_status.py:155 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:158 msgid "Accounts:" msgstr "Kontoer:" #: ../quodlibet/ext/events/gajim_status.py:162 msgid "Add '[paused]'" msgstr "Legg til «[på pause]»" #: ../quodlibet/ext/events/gajim_status.py:165 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:189 msgid "Statuses for which message will be changed" msgstr "Statuser som statusmelding skal endres for" #: ../quodlibet/ext/events/headphonemon.py:158 msgid "Pause on Headphone Unplug" msgstr "Pause ved frakobling av hodetelefoner" #: ../quodlibet/ext/events/headphonemon.py:159 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:42 msgid "Inhibit Screensaver" msgstr "Hindre skjermsparer" #: ../quodlibet/ext/events/inhibit.py:43 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." #: ../quodlibet/ext/events/inhibit.py:52 msgid "Music is playing" msgstr "Musikk under avspilling" #: ../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:31 msgid "JEP-118" msgstr "JEP-118" #: ../quodlibet/ext/events/jep118.py:32 msgid "Outputs a Jabber User Tunes file to ~/.quodlibet/jabber." msgstr "Skriver ut Jabber User Tunes-fil til ~/.quodlibet/jabber." #: ../quodlibet/ext/events/language.py:22 msgid "Change Language" msgstr "Bytt språk" #: ../quodlibet/ext/events/language.py:23 msgid "Change the user interface language." msgstr "Endre grensesnitt-språk." #: ../quodlibet/ext/events/language.py:44 msgid "System Default" msgstr "Forvalgt av system" #: ../quodlibet/ext/events/language.py:71 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:38 msgid "UPnP AV Media Server" msgstr "UPnP AV-medietjener" #: ../quodlibet/ext/events/mediaserver.py:39 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/mpdserver/__init__.py:62 msgid "MPD Server" msgstr "MPD-tjener" #: ../quodlibet/ext/events/mpdserver/__init__.py:63 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:77 msgid "_Port:" msgstr "_Port:" #: ../quodlibet/ext/events/mpdserver/__init__.py:120 msgid "Local _IP:" msgstr "Lokal _IP:" #: ../quodlibet/ext/events/mpdserver/__init__.py:126 msgid "P_assword:" msgstr "P_assord:" #: ../quodlibet/ext/events/mpdserver/__init__.py:162 msgid "Connection" msgstr "Tilkobling" #: ../quodlibet/ext/events/mpdserver/__init__.py:164 msgid "Tested Clients" msgstr "Testede klienter" #: ../quodlibet/ext/events/mpris/__init__.py:39 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 MPRIS 1.0/2.0 D-Bus Interface " "Specification." msgstr "" "Tillater styring av Quod Libet ved bruk av D-Bus-grensesnitt-spesifikasjonen " "MPRIS 1.0/2.0." #: ../quodlibet/ext/events/mpris/__init__.py:46 #: ../quodlibet/ext/events/trayicon/prefs.py:37 msgid "Hide main window on close" msgstr "Skjul hovedvindu ved lukking" #: ../quodlibet/ext/events/mpris/__init__.py:49 #: ../quodlibet/ext/events/themeswitcher.py:85 #: ../quodlibet/ext/gstreamer/compressor.py:100 #: ../quodlibet/ext/gstreamer/crossfeed.py:137 #: ../quodlibet/ext/gstreamer/karaoke.py:100 #: ../quodlibet/ext/gstreamer/pitch.py:84 ../quodlibet/qltk/prefs.py:699 msgid "Preferences" msgstr "Innstillinger" #: ../quodlibet/ext/events/mqtt.py:51 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "Tillater QL-mønstre som f.eks. %s" #: ../quodlibet/ext/events/mqtt.py:57 msgid "MQTT Publisher" msgstr "MQTT-utgiver" #: ../quodlibet/ext/events/mqtt.py:58 msgid "Publishes status messages to an MQTT topic." msgstr "Sender statusmeldinger til et MQTT-emne." #: ../quodlibet/ext/events/mqtt.py:123 msgid "Broker hostname" msgstr "Mellomtjener-vertsnavn" #: ../quodlibet/ext/events/mqtt.py:123 msgid "broker hostname / IP" msgstr "mellomtjener-vertsnavn/-IP" #: ../quodlibet/ext/events/mqtt.py:125 msgid "Broker port" msgstr "Mellomtjener-port" #: ../quodlibet/ext/events/mqtt.py:125 msgid "broker port" msgstr "mellomtjener-port" #: ../quodlibet/ext/events/mqtt.py:127 msgid "Topic" msgstr "Emne" #: ../quodlibet/ext/events/mqtt.py:129 msgid "Playing Pattern" msgstr "Avspillingsmønster" #: ../quodlibet/ext/events/mqtt.py:131 msgid "Status text when a song is started." msgstr "Statustekst når du spiller av en låt." #: ../quodlibet/ext/events/mqtt.py:133 msgid "Paused Pattern" msgstr "Pausemønster" #: ../quodlibet/ext/events/mqtt.py:135 msgid "Text when a song is paused." msgstr "Tekst når du setter en låt på pause." #: ../quodlibet/ext/events/mqtt.py:137 msgid "No-song Text" msgstr "«Ingen låt»-tekst" #: ../quodlibet/ext/events/mqtt.py:139 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:150 msgid "MQTT Configuration" msgstr "MQTT-oppsett" #: ../quodlibet/ext/events/mqtt.py:154 msgid "Status Text" msgstr "Statustekst" #: ../quodlibet/ext/events/mqtt.py:186 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "Tilkoblet mellomtjener på %(host)s:%(port)d" #: ../quodlibet/ext/events/mqtt.py:190 #, 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:193 msgid "Connection error" msgstr "Tilkoblingsfeil" #: ../quodlibet/ext/events/notify.py:56 msgid "Notification text" msgstr "Varslingstekst" #: ../quodlibet/ext/events/notify.py:67 msgid "_Title:" msgstr "_Tittel:" #: ../quodlibet/ext/events/notify.py:78 ../quodlibet/ext/events/notify.py:114 msgid "Revert to default pattern" msgstr "Tilbakestill til standardmønster" #: ../quodlibet/ext/events/notify.py:104 msgid "_Body:" msgstr "_Brødtekst:" #: ../quodlibet/ext/events/notify.py:124 msgid "_Show notification" msgstr "Vi_s varsling" #: ../quodlibet/ext/events/notify.py:142 msgid "Show notifications" msgstr "Vis varslinger" #: ../quodlibet/ext/events/notify.py:148 msgid "Only on <i>_manual</i> song changes" msgstr "Bare ved <i>_manuelt</i> låtbytte" #: ../quodlibet/ext/events/notify.py:156 msgid "Only on <i>_automatic</i> song changes" msgstr "Bare ved <i>_automatisk</i> låtbytte" #: ../quodlibet/ext/events/notify.py:164 msgid "On <i>a_ll</i> song changes" msgstr "Ved <i>a_lle</i> typer låtbytte" #: ../quodlibet/ext/events/notify.py:179 msgid "Only when the main window is not _focused" msgstr "Bare når hovedvindu ikke er i _fokus" #: ../quodlibet/ext/events/notify.py:187 msgid "Show \"_Next\" button" msgstr "Vis «_Neste»-knapp" #: ../quodlibet/ext/events/notify.py:209 msgid "Connection Error" msgstr "Tilkoblingsfeil" #: ../quodlibet/ext/events/notify.py:210 ../quodlibet/ext/events/notify.py:364 #: ../quodlibet/ext/events/notify.py:406 msgid "Couldn't connect to notification daemon." msgstr "Klarte ikke å koble til bakgrunnsprosess for varslinger." #: ../quodlibet/ext/events/notify.py:224 msgid "Song Notifications" msgstr "Låtvarslinger" #: ../quodlibet/ext/events/notify.py:225 msgid "Displays a notification when the song changes." msgstr "Viser et varsel ved låtbytte." #: ../quodlibet/ext/events/notify.py:388 ../quodlibet/qltk/unity.py:63 msgid "Next" msgstr "Neste" #: ../quodlibet/ext/events/qlscrobbler.py:175 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:252 #, python-format msgid "Could not contact service '%s'." msgstr "Klarte ikke å koble til tjenesten «%s»." #: ../quodlibet/ext/events/qlscrobbler.py:258 msgid "Authentication failed: invalid URL." msgstr "Autentisering mislyktes. Ugyldig nettadresse." #: ../quodlibet/ext/events/qlscrobbler.py:275 #, 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:280 msgid "Client is banned. Contact the author." msgstr "Klienten er utestengt. Kontakt forfatteren." #: ../quodlibet/ext/events/qlscrobbler.py:284 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:349 msgid "AudioScrobbler Submission" msgstr "AudioScrobbler-innsending" #: ../quodlibet/ext/events/qlscrobbler.py:350 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:448 msgid "Authentication successful." msgstr "Du er nå autentisert." #: ../quodlibet/ext/events/qlscrobbler.py:460 msgid "_Service:" msgstr "_Tjeneste:" #: ../quodlibet/ext/events/qlscrobbler.py:460 msgid "_URL:" msgstr "_Adresse:" #: ../quodlibet/ext/events/qlscrobbler.py:460 msgid "User_name:" msgstr "Bruker_navn:" #: ../quodlibet/ext/events/qlscrobbler.py:461 msgid "_Password:" msgstr "_Passord:" #. Translators: Other service #: ../quodlibet/ext/events/qlscrobbler.py:477 msgid "Other…" msgstr "Annet …" #. verify data #: ../quodlibet/ext/events/qlscrobbler.py:515 msgid "_Verify account data" msgstr "_Bekreft kontoinformasjon" #: ../quodlibet/ext/events/qlscrobbler.py:520 #: ../quodlibet/ext/songsmenu/lastfmsync.py:313 msgid "Account" msgstr "Konto" #: ../quodlibet/ext/events/qlscrobbler.py:528 msgid "_Artist pattern:" msgstr "_Artistmønster:" #: ../quodlibet/ext/events/qlscrobbler.py:528 msgid "_Title pattern:" msgstr "_Tittelmønster:" #: ../quodlibet/ext/events/qlscrobbler.py:529 msgid "Exclude _filter:" msgstr "Utelat _filter:" #: ../quodlibet/ext/events/qlscrobbler.py:547 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:557 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:566 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:574 msgid "_Offline mode (don't submit anything)" msgstr "_Frakoblet modus (ikke send inn noe)" #: ../quodlibet/ext/events/qlscrobbler.py:578 msgid "Submission" msgstr "Innsending" #: ../quodlibet/ext/events/radioadmute.py:21 msgid "Mute Radio Ads" msgstr "Demp reklamelyd" #: ../quodlibet/ext/events/radioadmute.py:22 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:28 msgid "Random Album Playback" msgstr "Tilfeldig albumavspilling" #: ../quodlibet/ext/events/randomalbum.py:29 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:39 msgid "Rated higher" msgstr "Høyere vurdering" #: ../quodlibet/ext/events/randomalbum.py:40 msgid "Played more often" msgstr "Oftere spilt" #: ../quodlibet/ext/events/randomalbum.py:41 msgid "Skipped more often" msgstr "Oftere hoppet over" #: ../quodlibet/ext/events/randomalbum.py:42 msgid "Played more recently" msgstr "Nyligere spilt" #: ../quodlibet/ext/events/randomalbum.py:43 msgid "Started more recently" msgstr "Nyligere startet" #: ../quodlibet/ext/events/randomalbum.py:44 msgid "Added more recently" msgstr "Nyligere lagt til" #: ../quodlibet/ext/events/randomalbum.py:45 msgid "Longer albums" msgstr "Lengre album" #: ../quodlibet/ext/events/randomalbum.py:84 msgid "seconds before starting next album" msgstr "sekunder før neste album spilles av" #: ../quodlibet/ext/events/randomalbum.py:88 msgid "Weights" msgstr "Vektinger" #: ../quodlibet/ext/events/randomalbum.py:90 msgid "Play some albums more than others" msgstr "Spill noen album oftere enn andre" #: ../quodlibet/ext/events/randomalbum.py:104 msgid "avoid" msgstr "unngå" #: ../quodlibet/ext/events/randomalbum.py:115 msgid "prefer" msgstr "foretrekk" #: ../quodlibet/ext/events/randomalbum.py:208 msgid "Random Album" msgstr "Tilfeldig album" #: ../quodlibet/ext/events/randomalbum.py:209 #, python-format msgid "Waiting to start %s" msgstr "Venter på å starte %s" #: ../quodlibet/ext/events/rbimport.py:115 msgid "Import Failed" msgstr "Importering mislyktes" #: ../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/rbimport.py:133 msgid "Start Import" msgstr "Start importering" #: ../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 slår seg på" #: ../quodlibet/ext/events/searchprovider.py:74 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:80 msgid "GNOME Search Provider" msgstr "GNOME-søketilbyder" #: ../quodlibet/ext/events/searchprovider.py:81 msgid "Allows GNOME Shell to search the library." msgstr "Lar GNOME Shell søke i biblioteket." #: ../quodlibet/ext/events/seekbar.py:123 msgid "Alternative Seek Bar" msgstr "Alternativ søkelinje" #: ../quodlibet/ext/events/seekbar.py:124 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:21 msgid "Seekpoint Bookmarks" msgstr "Punkt-bokmerker" #: ../quodlibet/ext/events/seekpoints.py:25 msgid "" "Store Seekpoints A and/or B for tracks. Skip to time A and stop after time B " "when track is played.\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 sporet spilles av.\n" "Ved å endre navn på punktene nedenfor endrer du bare hvilke bokmerkenavn " "programtillegget søker etter. Faktiske bokmerkenavn blir ikke endret av " "dette." #: ../quodlibet/ext/events/seekpoints.py:109 msgid "Bookmark name for point A" msgstr "Bokmerkenavn på punkt A" #: ../quodlibet/ext/events/seekpoints.py:110 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:125 msgid "Bookmark name for point B" msgstr "Bokmerkenavn på punkt B" #: ../quodlibet/ext/events/seekpoints.py:126 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:29 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:58 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "Fant ikke Squeezebox-tjener" #: ../quodlibet/ext/events/squeezebox_sync.py:59 #: ../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/synchronizedlyrics.py:35 msgid "Synchronized Lyrics" msgstr "Synkronisert sangtekst" #: ../quodlibet/ext/events/synchronizedlyrics.py:36 msgid "Shows synchronized lyrics from .lrc file with same name as the track." msgstr "" "Viser synkronisert sangtekst når en «.lrc»-fil som har samme navn som en låt" #: ../quodlibet/ext/events/synchronizedlyrics.py:70 msgid "Text:" msgstr "Tekst:" #: ../quodlibet/ext/events/synchronizedlyrics.py:80 msgid "Background:" msgstr "Bakgrunn:" #: ../quodlibet/ext/events/synchronizedlyrics.py:91 msgid "Font" msgstr "Skrifttype" #: ../quodlibet/ext/events/synchronizedlyrics.py:94 msgid "Size (px):" msgstr "Størrelse (px):" #: ../quodlibet/ext/events/telepathy_status.py:63 msgid "Telepathy Status Messages" msgstr "Telepathy-statusmeldinger" #: ../quodlibet/ext/events/telepathy_status.py:64 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:123 msgid "Playing:" msgstr "Spiller:" #: ../quodlibet/ext/events/telepathy_status.py:124 #, 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:140 msgid "Paused:" msgstr "Pauset:" #: ../quodlibet/ext/events/telepathy_status.py:141 #, 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:157 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:158 msgid "No song:" msgstr "Ingen låt:" #. Frame #: ../quodlibet/ext/events/telepathy_status.py:165 msgid "Status Patterns" msgstr "Statusmønstre" #: ../quodlibet/ext/events/themeswitcher.py:26 msgid "Theme Switcher" msgstr "Temaveksler" #: ../quodlibet/ext/events/themeswitcher.py:27 msgid "Changes the active GTK+ theme." msgstr "Endrer gjeldende GTK+-tema." #: ../quodlibet/ext/events/themeswitcher.py:50 msgid "_Theme:" msgstr "_Tema:" #: ../quodlibet/ext/events/themeswitcher.py:55 msgid "Default Theme" msgstr "Forvalgt tema" #: ../quodlibet/ext/events/themeswitcher.py:67 msgid "Prefer dark theme version" msgstr "Foretrekk mørk temaversjon" #: ../quodlibet/ext/events/toggle_menu.py:19 msgid "Toggle Menu Bar" msgstr "Slå på/av menylinje" #: ../quodlibet/ext/events/toggle_menu.py:20 msgid "Toggle the menu bar by pressing the Alt key." msgstr "Slå på/av menylinja ved å trykke Alt." #: ../quodlibet/ext/events/trayicon/appindicator.py:78 #: ../quodlibet/ext/events/trayicon/prefs.py:107 #: ../quodlibet/ext/events/trayicon/systemtray.py:178 #: ../quodlibet/qltk/info.py:48 msgid "Not playing" msgstr "Ingenting spilles av" #: ../quodlibet/ext/events/trayicon/__init__.py:54 msgid "Tray Icon" msgstr "Systemkurv-ikon" #: ../quodlibet/ext/events/trayicon/__init__.py:55 msgid "Controls Quod Libet from the system tray." msgstr "Kontrollerer Quod Libet fra systemkurven." #: ../quodlibet/ext/events/trayicon/menu.py:42 #, python-format msgid "_Show %(application-name)s" msgstr "_Vis %(application-name)s" #: ../quodlibet/ext/events/trayicon/menu.py:61 #: ../quodlibet/qltk/quodlibetwindow.py:185 #: ../quodlibet/qltk/quodlibetwindow.py:1083 #: ../quodlibet/qltk/quodlibetwindow.py:1275 msgid "_Play" msgstr "S_pill av" #: ../quodlibet/ext/events/trayicon/menu.py:64 #: ../quodlibet/qltk/quodlibetwindow.py:187 #: ../quodlibet/qltk/quodlibetwindow.py:1277 ../quodlibet/qltk/wlw.py:52 msgid "P_ause" msgstr "P_ause" #: ../quodlibet/ext/events/trayicon/menu.py:69 #: ../quodlibet/qltk/quodlibetwindow.py:192 #: ../quodlibet/qltk/quodlibetwindow.py:1078 msgid "Pre_vious" msgstr "_Forrige" #: ../quodlibet/ext/events/trayicon/menu.py:72 #: ../quodlibet/qltk/quodlibetwindow.py:196 #: ../quodlibet/qltk/quodlibetwindow.py:1088 msgid "_Next" msgstr "_Neste" #: ../quodlibet/ext/events/trayicon/menu.py:77 msgid "_Shuffle" msgstr "_Stokk om" #: ../quodlibet/ext/events/trayicon/menu.py:82 msgid "_Repeat" msgstr "_Gjenta" #: ../quodlibet/ext/events/trayicon/menu.py:87 msgid "Stop _After This Song" msgstr "Stopp _etter denne låta" #: ../quodlibet/ext/events/trayicon/menu.py:93 #: ../quodlibet/qltk/quodlibetwindow.py:1049 msgid "Open _Browser" msgstr "Åpne _utforsker" #: ../quodlibet/ext/events/trayicon/menu.py:104 #: ../quodlibet/qltk/quodlibetwindow.py:1068 ../quodlibet/qltk/songsmenu.py:382 msgid "Edit _Tags" msgstr "Rediger _tagger" #: ../quodlibet/ext/events/trayicon/menu.py:113 #: ../quodlibet/qltk/quodlibetwindow.py:1012 ../quodlibet/qltk/songsmenu.py:395 msgid "_Information" msgstr "_Informasjon" #: ../quodlibet/ext/events/trayicon/menu.py:115 #: ../quodlibet/qltk/songsmenu.py:323 msgid "Play_lists" msgstr "Spille_lister" #: ../quodlibet/ext/events/trayicon/menu.py:133 #: ../quodlibet/qltk/quodlibetwindow.py:1063 msgid "_Quit" msgstr "_Avslutt" #: ../quodlibet/ext/events/trayicon/prefs.py:39 ../quodlibet/qltk/prefs.py:70 msgid "Behavior" msgstr "Oppførsel" #: ../quodlibet/ext/events/trayicon/prefs.py:49 msgid "Scroll wheel adjusts volume" msgstr "Rullehjul stiller inn volum" #: ../quodlibet/ext/events/trayicon/prefs.py:55 msgid "Scroll wheel changes song" msgstr "Rullehjul bytter låt" #: ../quodlibet/ext/events/trayicon/prefs.py:63 msgid "Scroll _Wheel" msgstr "Rulle_hjul" #: ../quodlibet/ext/events/trayicon/prefs.py:93 msgid "Tooltip Display" msgstr "Vis hjelpebobler" #: ../quodlibet/ext/events/viewlyrics.py:26 msgid "View Lyrics" msgstr "Vis sangtekst" #: ../quodlibet/ext/events/viewlyrics.py:27 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:88 #, python-format msgid "" "No lyrics found for\n" " %s" msgstr "" "Fant ingen sangtekst for\n" "%s" #: ../quodlibet/ext/events/viewlyrics.py:118 #: ../quodlibet/ext/events/weblyrics.py:193 msgid "No active song" msgstr "Ingen låt spilles av" #: ../quodlibet/ext/events/visualisations.py:37 msgid "Launch Visualisations" msgstr "Start visualisering" #: ../quodlibet/ext/events/visualisations.py:39 msgid "Launch external visualisations." msgstr "Start ekstern visualisering." #: ../quodlibet/ext/events/visualisations.py:56 #, python-format msgid "Couldn't run visualisations using '%s'" msgstr "Klarte ikke å kjøre visualisering med «%s»" #: ../quodlibet/ext/events/visualisations.py:58 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:45 msgid "Error" msgstr "Feil" #: ../quodlibet/ext/events/visualisations.py:77 msgid "Visualiser executable:" msgstr "Kjørbart visualiseringsprogram:" #: ../quodlibet/ext/events/visualisations.py:92 msgid "Reload" msgstr "Last inn på nytt" #: ../quodlibet/ext/events/waveformseekbar.py:558 msgid "Waveform Seek Bar" msgstr "Lydbølge-søkelinje" #: ../quodlibet/ext/events/waveformseekbar.py:562 msgid "A seekbar in the shape of the waveform of the current song." msgstr "Søkelinje som former seg etter lydbølge av gjeldende låt." #: ../quodlibet/ext/events/waveformseekbar.py:619 msgid "Override foreground color:" msgstr "Overstyr forgrunnsfarge:" #: ../quodlibet/ext/events/waveformseekbar.py:623 msgid "Override hover color:" msgstr "Overstyr farge ved peking:" #: ../quodlibet/ext/events/waveformseekbar.py:627 msgid "Override remaining color:" msgstr "Overstyr farge for gjenværende tid:" #: ../quodlibet/ext/events/waveformseekbar.py:631 msgid "Show current position" msgstr "Vis gjeldende posisjon" #: ../quodlibet/ext/events/weblyrics.py:208 msgid "No lyrics found" msgstr "Fant ingen sangtekst" #: ../quodlibet/ext/events/weblyrics.py:268 msgid "_Zoom level:" msgstr "_Zoomnivå:" #: ../quodlibet/ext/events/weblyrics.py:286 msgid "URL:" msgstr "Adresse:" #: ../quodlibet/ext/events/weblyrics.py:291 msgid "Revert to default" msgstr "Tilbakestill til standardverdi" #: ../quodlibet/ext/events/weblyrics.py:306 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." #: ../quodlibet/ext/events/weblyrics.py:323 msgid "Alternate search" msgstr "Alternativt søk" #: ../quodlibet/ext/events/weblyrics.py:332 msgid "Web Lyrics" msgstr "Sangtekst fra nett" #: ../quodlibet/ext/events/weblyrics.py:333 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." #: ../quodlibet/ext/events/write_cover.py:34 msgid "Picture Saver" msgstr "Bildelagring" #: ../quodlibet/ext/events/write_cover.py:35 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:68 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 #, 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 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:17 msgid "Mono Downmix" msgstr "Mono-nedmiks" #: ../quodlibet/ext/gstreamer/mono.py:18 msgid "Downmixes audio channels to mono." msgstr "Mikser ned flere lydkanaler til mono." #: ../quodlibet/ext/gstreamer/pitch.py:21 msgid "R_ate:" msgstr "Fr_ekvens:" #: ../quodlibet/ext/gstreamer/pitch.py:22 msgid "_Tempo:" msgstr "_Tempo:" #: ../quodlibet/ext/gstreamer/pitch.py:23 msgid "_Pitch:" msgstr "_Tonehøyde:" #: ../quodlibet/ext/gstreamer/pitch.py:90 msgid "Audio Pitch / Speed" msgstr "Tonehøyde / hastighet" #: ../quodlibet/ext/gstreamer/pitch.py:91 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:139 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:100 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:157 msgid "Default filename pattern:" msgstr "_Forvalgt filnavn-mønster:" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:23 msgid "Export to Squeezebox" msgstr "Eksporter til Squeezebox" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:25 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." #: ../quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Export playlist to Squeezebox" msgstr "Eksporter spilleliste til Squeezebox" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:80 msgid "Playlist name (will overwrite existing)" msgstr "Spillelistenavn (overskriver gjeldende navn)" #. Save button #: ../quodlibet/ext/playlist/export_to_squeezebox.py:81 #: ../quodlibet/ext/songsmenu/albumart.py:324 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:357 #: ../quodlibet/ext/songsmenu/cover_download.py:309 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:279 #: ../quodlibet/ext/songsmenu/html.py:77 #: ../quodlibet/ext/songsmenu/lastfmsync.py:220 #: ../quodlibet/ext/songsmenu/playlist.py:52 #: ../quodlibet/ext/songsmenu/replaygain.py:365 #: ../quodlibet/ext/songsmenu/tapbpm.py:183 ../quodlibet/qltk/_editutils.py:41 #: ../quodlibet/qltk/lyrics.py:35 ../quodlibet/qltk/msg.py:53 #: ../quodlibet/qltk/renamefiles.py:218 ../quodlibet/qltk/tagsfrompath.py:154 #: ../quodlibet/qltk/tracknumbers.py:114 msgid "_Save" msgstr "La_gre" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:97 msgid "Export to Squeezebox playlist" msgstr "Eksporter til Squeezebox-spilleliste" #: ../quodlibet/ext/playlist/remove_duplicates.py:21 msgid "Remove Playlist Duplicates" msgstr "Fjern duplikater fra spilleliste" #: ../quodlibet/ext/playlist/remove_duplicates.py:22 msgid "Removes duplicate entries in a playlist." msgstr "Fjerner duplikater fra spillelister." #: ../quodlibet/ext/playlist/remove_duplicates.py:50 #, 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:53 #, 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:16 msgid "Shuffle Playlist" msgstr "Stokk om spilleliste" #: ../quodlibet/ext/playlist/shuffle.py:17 msgid "Randomly shuffles a playlist." msgstr "Stokker om låter i en spilleliste." #: ../quodlibet/ext/playorder/follow.py:19 msgid "Follow Cursor" msgstr "Følg peker" #: ../quodlibet/ext/playorder/follow.py:21 msgid "" "Playback follows your selection, or the next song in the list once exhausted." msgstr "" "Avspilling følger utvalg, eller neste låt i lista når utvalg er oppbrukt." #: ../quodlibet/ext/playorder/playcounteq.py:23 msgid "Playcount Equalizer" msgstr "Avspillingsutjevner" #: ../quodlibet/ext/playorder/playcounteq.py:24 msgid "Shuffle, preferring songs with fewer total plays." msgstr "" "Spill av i omstokket rekkefølge, med vekt på låter som har blitt spilt " "færrest antall ganger." #: ../quodlibet/ext/playorder/playcounteq.py:26 msgid "Prefer less played" msgstr "Foretrekk låter med færre avspillinger" #: ../quodlibet/ext/playorder/queue.py:20 msgid "Queue Only" msgstr "Bare kø" #: ../quodlibet/ext/playorder/queue.py:22 msgid "" "Limits playing of songs to the queue. 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å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/reverse.py:15 msgid "Reverse" msgstr "Omvendt" #: ../quodlibet/ext/playorder/reverse.py:17 msgid "Reverses the play order of songs." msgstr "Spiller av låter i omvendt rekkefølge" #: ../quodlibet/ext/playorder/shufflebygrouping.py:32 #: ../quodlibet/ext/playorder/shufflebygrouping.py:94 msgid "Shuffle by Grouping" msgstr "Stokk om per gruppering" #: ../quodlibet/ext/playorder/shufflebygrouping.py:33 msgid "" "Shuffles by a grouping of songs defined by a common tag instead of by track, " "similar to album shuffle. This is useful for shuffling multi-movement " "classical works while 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, og kan være nyttig når du vil " "stokke om f.eks. klassiske stykker og samtidig være sikker på at alle " "partiene spilles av 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:95 msgid "Waiting to start new group…" msgstr "Venter på å starte ny gruppe …" #: ../quodlibet/ext/playorder/shufflebygrouping.py:145 msgid "Grouping tag:" msgstr "Grupperingstagg:" #: ../quodlibet/ext/playorder/shufflebygrouping.py:149 msgid "Tag to group songs by" msgstr "Tagg som låter skal grupperes på" #: ../quodlibet/ext/playorder/shufflebygrouping.py:151 msgid "Filter tag:" msgstr "Filtertagg:" #: ../quodlibet/ext/playorder/shufflebygrouping.py:156 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:161 msgid "Delay:" msgstr "Forsinkelse:" #: ../quodlibet/ext/playorder/shufflebygrouping.py:167 msgid "Time delay in seconds before starting next group" msgstr "Forsinkelse (i sekunder) før neste gruppe skal startes" #: ../quodlibet/ext/playorder/shufflebygrouping.py:183 msgid "Reset to defaults" msgstr "Tilbakestill til forvalg" #: ../quodlibet/ext/playorder/skip_songs.py:26 msgid "Skip Songs" msgstr "Hopp over låter" #: ../quodlibet/ext/playorder/skip_songs.py:28 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." #: ../quodlibet/ext/playorder/track_repeat.py:31 msgid "Repeat Each Track" msgstr "Gjenta hvert spor" #: ../quodlibet/ext/playorder/track_repeat.py:33 msgid "Shuffle songs, but repeat every track a set number of times." msgstr "Stokk om låtrekkefølge og spill av hvert spor valgt antall ganger." #: ../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:16 msgid "Conditional Query" msgstr "Betinget spørring" #: ../quodlibet/ext/query/conditional.py:17 msgid "" "Chooses the query to match based on a condition query. Syntax is '@(if: " "condition, then, else)'." msgstr "" "Velger spørring å samsvare med basert på en betingelsesspørring. Syntaks: " "«@(if: tilstand, så, ellers)»." #: ../quodlibet/ext/query/pythonexpression.py:19 msgid "Python Query" msgstr "Python-spørring" #: ../quodlibet/ext/query/pythonexpression.py:20 msgid "" "Use Python expressions in queries. Syntax is '@(python: expression)'. The " "variable 's' (or 'a') is the song / album being matched. '_ts' is a (real " "number) timestamp at start of query. Modules 'time' and 'random' are also " "available, and the class 'Random' (==random.Random) too." msgstr "" "Bruk Python-uttrykk i spørringer. Syntaks er «@(python: uttrykk)». " "Variabelen «s» eller «a» er låt / album som skal samsvare. «_ts» er et (ekte " "numerisk) tidsstempel i begynnelsen av en spørring. Modulene «time» (tid) og " "«random» (vilkårlig) er også tilgjengelig, i tillegg til klassen " "«Random» (==random.Random)." #: ../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. Syntax is " "'@(saved: search name)'." msgstr "" "Ta med søketreff fra lagret søk som del av en annen spørring. Syntaks: " "«@(saved: søkenavn)»." #: ../quodlibet/ext/_shared/squeezebox/base.py:78 #, python-format msgid "Squeezebox OK. Using the only player (%s)." msgstr "Squeezebox OK. Bruker eneste spiller (%s)." #: ../quodlibet/ext/_shared/squeezebox/base.py:87 #, python-format msgid "Couldn't connect to %s" msgstr "Klarte ikke å koble til %s" #: ../quodlibet/ext/_shared/squeezebox/base.py:111 msgid "Hostname:" msgstr "Vertsnavn:" #: ../quodlibet/ext/_shared/squeezebox/base.py:117 msgid "Port:" msgstr "Port:" #: ../quodlibet/ext/_shared/squeezebox/base.py:122 msgid "Username:" msgstr "Brukernavn:" #: ../quodlibet/ext/_shared/squeezebox/base.py:127 msgid "Password:" msgstr "Passord:" #: ../quodlibet/ext/_shared/squeezebox/base.py:131 msgid "Library directory the server connects to" msgstr "Bibliotekmappe som tjener kobler til" #: ../quodlibet/ext/_shared/squeezebox/base.py:133 msgid "Library path:" msgstr "Bibliotek-sti:" #. Add verify button #: ../quodlibet/ext/_shared/squeezebox/base.py:142 msgid "_Verify settings" msgstr "_Kontroller oppsett" #. Server settings Frame #: ../quodlibet/ext/_shared/squeezebox/base.py:148 msgid "Squeezebox Server" msgstr "Squeezebox-tjener" #: ../quodlibet/ext/_shared/squeezebox/base.py:151 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:16 msgid "Choose Squeezebox player" msgstr "Velg Squeezebox-spiller" #: ../quodlibet/ext/_shared/squeezebox/util.py:21 #: ../quodlibet/ext/songsmenu/importexport.py:39 #: ../quodlibet/qltk/getstring.py:22 msgid "_OK" msgstr "_OK" #: ../quodlibet/ext/_shared/squeezebox/util.py:27 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" "Fant Squeezebox-tjener.\n" "Velg spiller" #: ../quodlibet/ext/songsmenu/albumart.py:331 msgid "Fit image to _window" msgstr "Tilpass bilde til _vindu" #: ../quodlibet/ext/songsmenu/albumart.py:337 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:343 msgid "_Program:" msgstr "_Program:" #: ../quodlibet/ext/songsmenu/albumart.py:348 msgid "_Edit image after saving" msgstr "_Rediger bilde etter lagring" #: ../quodlibet/ext/songsmenu/albumart.py:350 msgid "File_name:" msgstr "Fil_navn:" #: ../quodlibet/ext/songsmenu/albumart.py:466 msgid "Saving failed" msgstr "Lagring mislyktes" #: ../quodlibet/ext/songsmenu/albumart.py:467 #, python-format msgid "Unable to save \"%s\"." msgstr "Klarte ikke å lagre «%s»." #: ../quodlibet/ext/songsmenu/albumart.py:565 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "[albumart] HTTP-feil: %s" #: ../quodlibet/ext/songsmenu/albumart.py:622 msgid "Album Art Downloader" msgstr "Nedlastingsverktøy for omslag" #: ../quodlibet/ext/songsmenu/albumart.py:675 #, python-format msgid "from %(source)s" msgstr "fra %(source)s" #: ../quodlibet/ext/songsmenu/albumart.py:678 #, python-format msgid "Resolution: %s" msgstr "Oppløsning: %s" #: ../quodlibet/ext/songsmenu/albumart.py:681 #, python-format msgid "Size: %s" msgstr "Størrelse: %s" #: ../quodlibet/ext/songsmenu/albumart.py:727 msgid "Per engine 'at best' results limit" msgstr "Grense for antall «at best» (i beste fall)-resultater" #: ../quodlibet/ext/songsmenu/albumart.py:737 msgid "_Search" msgstr "_Søk" #: ../quodlibet/ext/songsmenu/albumart.py:819 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:453 msgid "Searching…" msgstr "Søker …" #: ../quodlibet/ext/songsmenu/albumart.py:884 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:43 msgid "Done" msgstr "Ferdig" #: ../quodlibet/ext/songsmenu/albumart.py:1006 msgid "Download Album Art" msgstr "Last ned album-omslag" #: ../quodlibet/ext/songsmenu/albumart.py:1007 msgid "Downloads album covers from various websites." msgstr "Last ned omslagsbilder fra diverse nettsteder." #: ../quodlibet/ext/songsmenu/albumart.py:1020 msgid "Sources" msgstr "Kilder" #: ../quodlibet/ext/songsmenu/ape2id3.py:27 msgid "APEv2 to ID3v2" msgstr "APEv2 til ID3v2" #: ../quodlibet/ext/songsmenu/ape2id3.py:28 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:24 msgid "Go to Bookmark" msgstr "Gå til bokmerke" #: ../quodlibet/ext/songsmenu/bookmarks.py:25 msgid "Manages bookmarks in the selected files." msgstr "Håndterer bokmerker i valgte filer." #: ../quodlibet/ext/songsmenu/bookmarks.py:64 #: ../quodlibet/qltk/seekbutton.py:245 msgid "_Edit Bookmarks…" msgstr "R_ediger bokmerker …" #: ../quodlibet/ext/songsmenu/bookmarks.py:74 msgid "No Bookmarks" msgstr "Ingen bokmerker" #: ../quodlibet/ext/songsmenu/brainz/__init__.py:25 msgid "MusicBrainz Lookup" msgstr "MusicBrainz-oppslag" #: ../quodlibet/ext/songsmenu/brainz/__init__.py:27 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:51 msgid "Only use year for \"date\" tag" msgstr "Bare bruk år i «date»-tagg" #: ../quodlibet/ext/songsmenu/brainz/__init__.py:52 msgid "Write \"_albumartist\" when needed" msgstr "Skriv «_albumartist» hvis nødvendig" #: ../quodlibet/ext/songsmenu/brainz/__init__.py:53 msgid "Write sort tags for artist names" msgstr "Skriv sorteringstagger for artistnavn" #: ../quodlibet/ext/songsmenu/brainz/__init__.py:54 msgid "Write _standard MusicBrainz tags" msgstr "Skriv _standard MusicBrainz-tagger" #: ../quodlibet/ext/songsmenu/brainz/__init__.py:55 msgid "Write \"labelid\" tag" msgstr "Skriv «labelid»-tagg" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:131 msgid "Filename" msgstr "Filnavn" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:132 msgid "Disc" msgstr "Plate" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:133 #: ../quodlibet/ext/songsmenu/replaygain.py:404 #: ../quodlibet/qltk/tracknumbers.py:93 msgid "Track" msgstr "Spor" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:134 msgid "Title" msgstr "Tittel" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:135 msgid "Artist" msgstr "Artist" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:354 msgid "MusicBrainz lookup" msgstr "MusicBrainz-oppslag" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:377 msgid "_Query:" msgstr "_Spørring:" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:380 msgid "S_earch" msgstr "S_øk" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:393 msgid "Results <i>(drag to reorder)</i>" msgstr "Treff <i>(dra for å endre rekkefølge)</i>" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:449 msgid "Please enter a query." msgstr "Skriv inn en spørring." #: ../quodlibet/ext/songsmenu/brainz/widgets.py:467 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:498 msgid "Error encountered. Please retry." msgstr "Det oppstod en feil. Prøv på nytt." #: ../quodlibet/ext/songsmenu/brainz/widgets.py:474 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:490 msgid "Loading result…" msgstr "Laster inn treff …" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:477 msgid "No results found." msgstr "Søket ga ingen treff." #: ../quodlibet/ext/songsmenu/browsefolders.py:41 msgid "Browse Folders" msgstr "Utforsk mapper" #: ../quodlibet/ext/songsmenu/browsefolders.py:42 msgid "Opens the songs' folders in a file manager." msgstr "Åpner låtmapper i filutforsker." #: ../quodlibet/ext/songsmenu/browsefolders.py:50 msgid "Unable to open folders" msgstr "Klarte ikke å åpne mapper" #: ../quodlibet/ext/songsmenu/browsefolders.py:51 msgid "No program available to open folders." msgstr "Ingen filutforsker tilgjengelig." #: ../quodlibet/ext/songsmenu/console.py:42 msgid "Python Console" msgstr "Python-konsoll" #: ../quodlibet/ext/songsmenu/console.py:43 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:87 msgid "Your current working directory is:" msgstr "Gjeldende arbeidsmappe er:" #: ../quodlibet/ext/songsmenu/cover_download.py:119 msgid "Small" msgstr "Liten" #: ../quodlibet/ext/songsmenu/cover_download.py:120 msgid "Classic" msgstr "Klassisk" #: ../quodlibet/ext/songsmenu/cover_download.py:121 msgid "Large" msgstr "Stor" #: ../quodlibet/ext/songsmenu/cover_download.py:122 msgid "HD" msgstr "HD" #: ../quodlibet/ext/songsmenu/cover_download.py:123 msgid "Full HD" msgstr "Full HD" #: ../quodlibet/ext/songsmenu/cover_download.py:124 msgid "WQXGA" msgstr "WQXGA" #: ../quodlibet/ext/songsmenu/cover_download.py:125 msgid "4K UHD" msgstr "4K UHD" #: ../quodlibet/ext/songsmenu/cover_download.py:130 msgid "Cover Art Download" msgstr "Last ned omslagsbilde" #: ../quodlibet/ext/songsmenu/cover_download.py:180 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "Laster inn %(source)s - %(dimensions)s …" #: ../quodlibet/ext/songsmenu/cover_download.py:231 #, python-format msgid "" "Nothing found for albums:\n" "<i>%(albums)s</i>.\n" "\n" "Providers used:\n" "<tt>%(providers)s</tt>" msgstr "" "Fant ingenting om:\n" "<i>%(albums)s</i>.\n" "\n" "Søket ble utført på:\n" "<tt>%(providers)s</tt>" #: ../quodlibet/ext/songsmenu/cover_download.py:234 msgid "No covers found" msgstr "Fant ingen omslag" #: ../quodlibet/ext/songsmenu/cover_download.py:254 #, python-format msgid "%(size)d ✕ %(size)d px" msgstr "%(size)d ✕ %(size)d px" #: ../quodlibet/ext/songsmenu/cover_download.py:267 msgid "Preview size" msgstr "Forhåndsvis størrelse" #: ../quodlibet/ext/songsmenu/cover_download.py:276 msgid "Save destination" msgstr "Lagre mål" #: ../quodlibet/ext/songsmenu/cover_download.py:336 msgid "Download Cover Art" msgstr "Last ned omslag" #: ../quodlibet/ext/songsmenu/cover_download.py:337 msgid "Downloads high-quality album covers using cover plugins." msgstr "Laster ned album-omslag i høy kvalitet ved bruk av programtillegg." #: ../quodlibet/ext/songsmenu/custom_commands.py:42 msgid "Command" msgstr "Kommando" #: ../quodlibet/ext/songsmenu/custom_commands.py:45 msgid "name" msgstr "navn" #: ../quodlibet/ext/songsmenu/custom_commands.py:45 msgid "The name of this command" msgstr "Navn på denne kommandoen" #: ../quodlibet/ext/songsmenu/custom_commands.py:47 msgid "command" msgstr "kommando" #: ../quodlibet/ext/songsmenu/custom_commands.py:47 msgid "The shell command syntax to run" msgstr "Skallkommando-syntaks som skal kjøres" #: ../quodlibet/ext/songsmenu/custom_commands.py:49 msgid "parameter" msgstr "parameter" #: ../quodlibet/ext/songsmenu/custom_commands.py:50 #, 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 "pattern" msgstr "mønster" #: ../quodlibet/ext/songsmenu/custom_commands.py:57 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:62 msgid "unique" msgstr "unik" #: ../quodlibet/ext/songsmenu/custom_commands.py:63 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:66 msgid "max args" msgstr "maks argumenter" #: ../quodlibet/ext/songsmenu/custom_commands.py:67 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:92 msgid "Input value" msgstr "Inndataverdi" #: ../quodlibet/ext/songsmenu/custom_commands.py:93 #, python-format msgid "Value for %s?" msgstr "Verdi for %s?" #: ../quodlibet/ext/songsmenu/custom_commands.py:137 msgid "Custom Commands" msgstr "Selvvalgte kommandoer" #: ../quodlibet/ext/songsmenu/custom_commands.py:138 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:189 #: ../quodlibet/ext/songsmenu/custom_commands.py:199 #: ../quodlibet/ext/songsmenu/custom_commands.py:253 msgid "Edit Custom Commands" msgstr "Rediger selvvalgte kommandoer" #: ../quodlibet/ext/songsmenu/custom_commands.py:200 msgid "" "Supports QL patterns\n" "eg <tt><~artist~title></tt>" msgstr "" "Støtter QL-mønstre\n" "f.eks. <tt><~artist~title></tt>" #: ../quodlibet/ext/songsmenu/custom_commands.py:284 #, python-format msgid "Unable to run custom command %s" msgstr "Klarte ikke å kjøre selvvalgt kommando %s" #: ../quodlibet/ext/songsmenu/duplicates.py:289 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "%d duplikatgruppe" msgstr[1] "%d duplikatgrupper" #: ../quodlibet/ext/songsmenu/duplicates.py:342 msgid "Collapse / Expand all" msgstr "Fold sammen / Utvid alle" #: ../quodlibet/ext/songsmenu/duplicates.py:346 #, python-format msgid "Duplicate key expression is '%s'" msgstr "Uttrykk for duplikatnøkkel er «%s»" #: ../quodlibet/ext/songsmenu/duplicates.py:371 msgid "Duplicates Browser" msgstr "Dupliserer utforsker" #: ../quodlibet/ext/songsmenu/duplicates.py:372 msgid "Finds and displays similarly tagged versions of songs." msgstr "FInner og viser låtversjoner med liknende tagger." #: ../quodlibet/ext/songsmenu/duplicates.py:410 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:412 msgid "_Group duplicates by:" msgstr "_Grupper duplikater etter:" #: ../quodlibet/ext/songsmenu/duplicates.py:417 msgid "Duplicate Key" msgstr "Duplikatnøkkel" #: ../quodlibet/ext/songsmenu/duplicates.py:422 msgid "Remove _Whitespace" msgstr "Fjern _blanktegn" #: ../quodlibet/ext/songsmenu/duplicates.py:423 msgid "Remove _Diacritics" msgstr "Fjern _diakritikk" #: ../quodlibet/ext/songsmenu/duplicates.py:424 msgid "Remove _Punctuation" msgstr "Fjern _tegnsetting" #: ../quodlibet/ext/songsmenu/duplicates.py:425 msgid "Case _Insensitive" msgstr "Ignorer små/store bokstaver" #: ../quodlibet/ext/songsmenu/duplicates.py:433 msgid "Matching options" msgstr "Søkevalg" #. Create a dialog. #: ../quodlibet/ext/songsmenu/editplaycount.py:20 #: ../quodlibet/ext/songsmenu/editplaycount.py:42 msgid "Edit Playcount" msgstr "Rediger antall avspillinger" #: ../quodlibet/ext/songsmenu/editplaycount.py:21 msgid "" "Edit a song's ~#playcount and ~#skipcount.\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's ~#playcount to 0, the ~#lastplayed and ~#laststarted " "entries will be cleared. However, when setting a 0-play song to a positive " "play count, no play times will be created." msgstr "" "Rediger ~#playcount og ~#skipcount for en låt.\n" "\n" "Antall blir økt - ikke endret - hvis flere låter er valgt.\n" "\n" "Hvis du endrer ~#playcount til 0, blir ~#lastplayed og ~#laststarted tømt. " "Hvis du endrer en låt uten avspillinger til positivt antall avspillinger, " "får ingen av disse noen verdi." #: ../quodlibet/ext/songsmenu/editplaycount.py:69 msgid "Play Count" msgstr "Antall avspillinger" #: ../quodlibet/ext/songsmenu/editplaycount.py:70 msgid "Skip Count" msgstr "Antall ganger hoppet over" #: ../quodlibet/ext/songsmenu/embedded.py:25 msgid "Edit Embedded Images" msgstr "Rediger innebygde bilder" #: ../quodlibet/ext/songsmenu/embedded.py:26 msgid "Removes or replaces embedded images." msgstr "Sletter eller erstatter innebygde bilder." #: ../quodlibet/ext/songsmenu/embedded.py:79 msgid "_Remove all Images" msgstr "_Fjern alle bilder" #: ../quodlibet/ext/songsmenu/embedded.py:83 msgid "_Embed Current Image" msgstr "_Bygg inn gjeldende bilde" #: ../quodlibet/ext/songsmenu/exact_rating.py:24 msgid "Set Exact Rating" msgstr "Endre nøyaktig vurdering" #: ../quodlibet/ext/songsmenu/exact_rating.py:25 msgid "Allows setting the rating of songs with a number." msgstr "Tillater endring av låtvurderinger med tallverdier." #: ../quodlibet/ext/songsmenu/exact_rating.py:37 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:81 msgid "Filter on Any Tag" msgstr "Filtrer etter hvilken som helst tagg" #: ../quodlibet/ext/songsmenu/filterall.py:82 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:20 msgid "Filter on Directory" msgstr "Filtrer etter mappe" #: ../quodlibet/ext/songsmenu/filterbrowser.py:21 msgid "Filters on directory in a new browser window." msgstr "Filtrerer på mappe i nytt utforskervindu." #: ../quodlibet/ext/songsmenu/fingerprint/__init__.py:31 msgid "Acoustic Fingerprint Lookup" msgstr "Akustisk fingeravtrykk-søk" #: ../quodlibet/ext/songsmenu/fingerprint/__init__.py:32 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:52 #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:42 msgid "Submit Acoustic Fingerprints" msgstr "Send inn akustiske fingeravtrykk" #: ../quodlibet/ext/songsmenu/fingerprint/__init__.py:53 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:61 msgid "API Key Missing" msgstr "API-nøkkel mangler" #: ../quodlibet/ext/songsmenu/fingerprint/__init__.py:62 msgid "" "You have to specify an acoustid.org API key in the plugin preferences before " "you can submit fingerprints." msgstr "" "Du må sette opp en API-nøkkel for acoustid.org i tilleggsoppsettet for å " "sende inn fingeravtrykk." #: ../quodlibet/ext/songsmenu/fingerprint/__init__.py:76 msgid "Request API key" msgstr "Be om API-nøkkel" #: ../quodlibet/ext/songsmenu/fingerprint/__init__.py:83 msgid "API _key:" msgstr "API-_nøkkel:" #: ../quodlibet/ext/songsmenu/fingerprint/__init__.py:90 msgid "AcoustID Web Service" msgstr "AcoustID-nettjeneste" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:37 msgid "Queued" msgstr "I kø" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:39 msgid "Analyzing" msgstr "Analyserer" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:41 msgid "Lookup" msgstr "Oppslag" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:117 msgid "Write" msgstr "Skriv" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:145 msgid "Status" msgstr "Status" #. Translators: album release ID #: ../quodlibet/ext/songsmenu/fingerprint/search.py:159 msgid "Release" msgstr "Utgivelse" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:291 msgid "Write MusicBrainz tags" msgstr "Skriv MusicBrainz-tagger" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:297 msgid "Group by directory" msgstr "Grupper etter mappe" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:306 msgid "Album Mode" msgstr "Albummodus" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:308 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:50 msgid "Generating fingerprints:" msgstr "Lager fingeravtrykk:" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:66 msgid "_Details" msgstr "_Detaljer" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:89 msgid "_Submit" msgstr "_Send inn" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:119 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:122 msgid "Fingerprints:" msgstr "Fingeravtrykk:" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs with MBIDs:" msgstr "Låter med MBID:" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:126 msgid "Songs with sufficient tags:" msgstr "Låter med tilstrekkelig taggdata:" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:128 msgid "Songs to submit:" msgstr "Låter å sende inn:" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:166 #, 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:182 msgid "Submitting fingerprints:" msgstr "Sender inn fingeravtrykk:" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:190 msgid "Submitting…" msgstr "Sender inn …" #: ../quodlibet/ext/songsmenu/forcewrite.py:18 msgid "Update Tags in Files" msgstr "Oppdater tagger i filer" #: ../quodlibet/ext/songsmenu/forcewrite.py:19 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:67 ../quodlibet/ext/songsmenu/html.py:77 msgid "Export to HTML" msgstr "Eksporter til HTML" #: ../quodlibet/ext/songsmenu/html.py:68 msgid "Exports the selected song list to HTML." msgstr "Eksporterer valgt låtliste i HTML-format." #: ../quodlibet/ext/songsmenu/ifp.py:22 msgid "Send to iFP" msgstr "Send til iFP" #: ../quodlibet/ext/songsmenu/ifp.py:23 msgid "Uploads songs to an iRiver iFP device." msgstr "Last opp låter til iRiver iFP-enhet." #: ../quodlibet/ext/songsmenu/ifp.py:31 msgid "No iFP device found" msgstr "Fant ingen iFP-enhet" #: ../quodlibet/ext/songsmenu/ifp.py:32 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:40 #, python-format msgid "Uploading %(current)d/%(total)d" msgstr "Laster opp %(current)d/%(total)d" #: ../quodlibet/ext/songsmenu/ifp.py:63 msgid "Error uploading" msgstr "Feil under opplasting" #: ../quodlibet/ext/songsmenu/ifp.py:64 #, python-format msgid "" "Unable to upload <b>%s</b>. The device may be out of space, or turned off." msgstr "" "Klarte ikke å laste opp <b>%s</b>. Enheten kan være full eller slått av." #: ../quodlibet/ext/songsmenu/importexport.py:60 msgid "Export Metadata" msgstr "Eksporter metadata" #: ../quodlibet/ext/songsmenu/importexport.py:61 msgid "Exports metadata of selected songs as a .tags file." msgstr "Eksporterer metadata for valgte låter til en «.tags»-fil." #: ../quodlibet/ext/songsmenu/importexport.py:105 msgid "Import Metadata" msgstr "Importer metadata" #: ../quodlibet/ext/songsmenu/importexport.py:106 msgid "Imports metadata for selected songs from a .tags file." msgstr "Importerer metadata for valgte låter fra en «.tags»-fil." #: ../quodlibet/ext/songsmenu/k3b.py:24 msgid "Burn CD" msgstr "Skriv CD" #: ../quodlibet/ext/songsmenu/k3b.py:25 msgid "Burns CDs with K3b, Brasero or xfburn." msgstr "Skriver CD-er med K3b, Brasero eller xfburn." #: ../quodlibet/ext/songsmenu/lastfmsync.py:98 msgid "Updating chart list." msgstr "Oppdaterer liste." #. No charts to fetch, no update scheduled. #: ../quodlibet/ext/songsmenu/lastfmsync.py:117 msgid "Already up-to-date." msgstr "Allerede oppdatert." #: ../quodlibet/ext/songsmenu/lastfmsync.py:125 #, python-format msgid "Fetching chart for week of %s." msgstr "Henter ukeliste for %s." #: ../quodlibet/ext/songsmenu/lastfmsync.py:147 msgid "Sync complete." msgstr "Synk utført." #: ../quodlibet/ext/songsmenu/lastfmsync.py:153 msgid "Error during sync" msgstr "Feil under synk" #: ../quodlibet/ext/songsmenu/lastfmsync.py:218 #: ../quodlibet/ext/songsmenu/lastfmsync.py:248 msgid "Last.fm Sync" msgstr "Last.fm-synk" #: ../quodlibet/ext/songsmenu/lastfmsync.py:249 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:302 msgid "_Username:" msgstr "Br_ukernavn:" #: ../quodlibet/ext/songsmenu/makesorttags.py:37 msgid "Create Sort Tags" msgstr "Lag sorteringstagger" #: ../quodlibet/ext/songsmenu/makesorttags.py:38 msgid "Converts album and artist names to sort names, poorly." msgstr "Konverterer album- og artistnavn til sorteringsnavn, på enkelt vis." #. Create a dialog. #: ../quodlibet/ext/songsmenu/migratemetadata.py:37 #: ../quodlibet/ext/songsmenu/migratemetadata.py:46 msgid "Migrate Metadata" msgstr "Flytt over metadata" #: ../quodlibet/ext/songsmenu/migratemetadata.py:40 msgid "Copies the quodlibet-specific metadata between songs." msgstr "Kopierer quodlibet-bestemte metadata mellom låter." #: ../quodlibet/ext/songsmenu/migratemetadata.py:53 msgid "_Copy" msgstr "_Kopier" #: ../quodlibet/ext/songsmenu/migratemetadata.py:55 msgid "_Paste" msgstr "_Lim inn" #. Create the tag table. #: ../quodlibet/ext/songsmenu/migratemetadata.py:65 msgid "Information to copy/paste" msgstr "Informasjon å kopiere/lime inn" #. Create the indexing box. #: ../quodlibet/ext/songsmenu/migratemetadata.py:87 msgid "Map tracks by disc and track number" msgstr "Tilordne spor etter plate- og spornummer" #: ../quodlibet/ext/songsmenu/migratemetadata.py:88 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" "<b>Merk:</b> dette må være slått på når metadata blir kopiert for at " "sporinformasjon skal bli lagret." #: ../quodlibet/ext/songsmenu/migratemetadata.py:104 #, python-format 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." #: ../quodlibet/ext/songsmenu/playlist.py:32 msgid "Export as Playlist" msgstr "Eksporter som spilleliste" #: ../quodlibet/ext/songsmenu/playlist.py:33 msgid "Exports songs to an M3U or PLS playlist." msgstr "Eksporterer låter til M3U- eller PLS-spilleliste." #: ../quodlibet/ext/songsmenu/playlist.py:78 msgid "Use relative paths" msgstr "Bruk relative filstier" #: ../quodlibet/ext/songsmenu/playlist.py:78 msgid "Use absolute paths" msgstr "Bruk fullstendige filstier" #: ../quodlibet/ext/songsmenu/playlist.py:133 msgid "Unable to export playlist" msgstr "Klarte ikke å eksportere spilleliste" #: ../quodlibet/ext/songsmenu/playlist.py:134 #, python-format msgid "Writing to <b>%s</b> failed." msgstr "Skriving til <b>%s</b> mislyktes." #. Translators: Plugin name #: ../quodlibet/ext/songsmenu/refresh.py:23 msgid "Rescan Songs" msgstr "Søk gjennom låter på nytt" #: ../quodlibet/ext/songsmenu/refresh.py:24 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:32 msgid "Rescan songs" msgstr "Søk gjennom låter på nytt" #: ../quodlibet/ext/songsmenu/replaygain.py:362 msgid "ReplayGain Analyzer" msgstr "ReplayGain-analyseringsverktøy" #: ../quodlibet/ext/songsmenu/replaygain.py:418 msgid "Progress" msgstr "Framdrift" #: ../quodlibet/ext/songsmenu/replaygain.py:433 msgid "Gain" msgstr "Forsterkning" #: ../quodlibet/ext/songsmenu/replaygain.py:448 msgid "Peak" msgstr "Maksverdi" #: ../quodlibet/ext/songsmenu/replaygain.py:463 #, python-format msgid "There is <b>%(to-process)s</b> album to update (of %(all)s)" msgid_plural "There are <b>%(to-process)s</b> albums to update (of %(all)s)" msgstr[0] "<b>%(to-process)s</b> album skal oppdateres (av %(all)s)" msgstr[1] "<b>%(to-process)s</b> album skal oppdateres (av %(all)s)" #: ../quodlibet/ext/songsmenu/replaygain.py:579 msgid "Replay Gain" msgstr "ReplayGain" #: ../quodlibet/ext/songsmenu/replaygain.py:580 msgid "" "Analyzes and updates ReplayGain information, using GStreamer. Results are " "grouped by album." msgstr "" "Analyserer og oppdaterer ReplayGain-informasjon ved hjelp av GStreamer. " "Resultater blir gruppert per album." #: ../quodlibet/ext/songsmenu/replaygain.py:618 msgid "always" msgstr "alltid" #: ../quodlibet/ext/songsmenu/replaygain.py:619 msgid "if <b>any</b> RG tags are missing" msgstr "hvis <b>hvilken som helst</b> RG-tagg mangler" #: ../quodlibet/ext/songsmenu/replaygain.py:621 msgid "if <b>album</b> RG tags are missing" msgstr "hvis <b>album</b>-RG-tagg mangler" #: ../quodlibet/ext/songsmenu/replaygain.py:638 msgid "_Process albums:" msgstr "_Behandle album:" #. Server settings Frame #: ../quodlibet/ext/songsmenu/replaygain.py:650 msgid "Existing Tags" msgstr "Gjeldende tagger" #: ../quodlibet/ext/songsmenu/splitting.py:32 msgid "Split Tags" msgstr "Splitt tagger" #: ../quodlibet/ext/songsmenu/splitting.py:33 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:57 msgid "Split Album" msgstr "Del opp album" #: ../quodlibet/ext/songsmenu/splitting.py:58 msgid "Split out disc number." msgstr "Trekk ut platenummer." #. TRANSLATORS: BPM mean "beats per minute" #: ../quodlibet/ext/songsmenu/tapbpm.py:32 msgid "BPM:" msgstr "BPM:" #: ../quodlibet/ext/songsmenu/tapbpm.py:33 #: ../quodlibet/ext/songsmenu/tapbpm.py:62 msgid "n/a" msgstr "i/t" #: ../quodlibet/ext/songsmenu/tapbpm.py:37 msgid "Reset" msgstr "Tilbakestill" #: ../quodlibet/ext/songsmenu/tapbpm.py:43 msgid "Tap" msgstr "Trykk" #: ../quodlibet/ext/songsmenu/tapbpm.py:173 #: ../quodlibet/ext/songsmenu/tapbpm.py:180 msgid "Tap BPM" msgstr "Beregn BPM" #: ../quodlibet/ext/songsmenu/tapbpm.py:174 msgid "Tap BPM for the selected song." msgstr "Beregn BPM for valgt låt ved å trykke i takt." #: ../quodlibet/ext/songsmenu/website_search.py:38 msgid "Website Search" msgstr "Nettsted-søk" #: ../quodlibet/ext/songsmenu/website_search.py:39 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern-example)s." msgstr "" "Søker på valgt nettside med tagger.\n" "Støtter mønstre som f.eks. %(pattern-example)s." #: ../quodlibet/ext/songsmenu/website_search.py:81 msgid "Search URL patterns" msgstr "Søk i adressemønstre" #: ../quodlibet/ext/songsmenu/website_search.py:91 msgid "Edit search URLs" msgstr "Rediger søkeadresser …" #. Add link to editor #: ../quodlibet/ext/songsmenu/website_search.py:117 msgid "Configure Searches…" msgstr "Sett opp søk …" #: ../quodlibet/ext/songsmenu/wikipedia.py:47 #, python-format msgid "Search at %(website)s" msgstr "Søk på %(website)s" #: ../quodlibet/ext/songsmenu/wikipedia.py:64 msgid "Search Artist in Wikipedia" msgstr "Søk etter artist på Wikipedia" #: ../quodlibet/ext/songsmenu/wikipedia.py:65 msgid "" "Opens a browser window with Wikipedia article on the playing song artist." msgstr "" "Åpner nettleservindu med Wikipedia-artikkel om artisten for spillende artist." #: ../quodlibet/ext/songsmenu/wikipedia.py:72 msgid "Search Album in Wikipedia" msgstr "Søk etter album på Wikipedia" #: ../quodlibet/ext/songsmenu/wikipedia.py:73 msgid "" "Opens a browser window with Wikipedia article on the playing song album." msgstr "" "Åpner nettleservindu med Wikipedia-artikkel om artisten for spillende album." #. then (try to) load all new files #: ../quodlibet/library/libraries.py:654 ../quodlibet/library/libraries.py:664 #: ../quodlibet/library/libraries.py:730 ../quodlibet/library/libraries.py:749 #: ../quodlibet/qltk/information.py:273 ../quodlibet/qltk/prefs.py:650 #: ../quodlibet/util/library.py:124 msgid "Library" msgstr "Bibliotek" #: ../quodlibet/library/libraries.py:654 msgid "Checking mount points" msgstr "Kontrollerer monteringspunkter" #: ../quodlibet/library/libraries.py:664 msgid "Scanning library" msgstr "Søker gjennom bibliotek" #: ../quodlibet/library/libraries.py:729 #, python-format msgid "Scanning %s" msgstr "Søker gjennom %s" #: ../quodlibet/library/libraries.py:749 msgid "Loading files" msgstr "Laster inn filer" #: ../quodlibet/main.py:51 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:38 msgid "List tags" msgstr "Vis tagger" #: ../quodlibet/operon/commands.py:43 ../quodlibet/operon/commands.py:82 #: ../quodlibet/operon/commands.py:462 msgid "Print terse output" msgstr "Skriv ut kortfattet info" #: ../quodlibet/operon/commands.py:45 ../quodlibet/operon/commands.py:84 #: ../quodlibet/operon/commands.py:464 #, 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:48 ../quodlibet/operon/commands.py:87 msgid "Also list programmatic tags" msgstr "Vis programmatiske tagger" #: ../quodlibet/operon/commands.py:52 ../quodlibet/operon/commands.py:130 #: ../quodlibet/operon/commands.py:221 ../quodlibet/operon/commands.py:294 #: ../quodlibet/operon/commands.py:337 ../quodlibet/operon/commands.py:341 #: ../quodlibet/operon/commands.py:392 ../quodlibet/operon/commands.py:395 #: ../quodlibet/operon/commands.py:434 ../quodlibet/operon/commands.py:469 #: ../quodlibet/operon/commands.py:509 ../quodlibet/operon/commands.py:544 #: ../quodlibet/operon/commands.py:586 msgid "Not enough arguments" msgstr "Argument(er) mangler" #: ../quodlibet/operon/commands.py:54 ../quodlibet/operon/commands.py:91 #: ../quodlibet/operon/commands.py:132 ../quodlibet/operon/commands.py:223 #: ../quodlibet/operon/commands.py:471 msgid "Too many arguments" msgstr "For mange argumenter" #: ../quodlibet/operon/commands.py:57 ../quodlibet/operon/commands.py:93 #: ../quodlibet/operon/commands.py:476 ../quodlibet/qltk/data_editors.py:354 msgid "Description" msgstr "Beskrivelse" #: ../quodlibet/operon/commands.py:57 ../quodlibet/operon/commands.py:476 #: ../quodlibet/qltk/edittags.py:455 msgid "Value" msgstr "Verdi" #: ../quodlibet/operon/commands.py:77 msgid "List all common tags" msgstr "Vis alle fellestagger" #: ../quodlibet/operon/commands.py:119 msgid "Copy tags from one file to another" msgstr "Kopier tagger fra en fil til en annen" #: ../quodlibet/operon/commands.py:124 ../quodlibet/operon/commands.py:165 #: ../quodlibet/operon/commands.py:290 ../quodlibet/operon/commands.py:325 #: ../quodlibet/operon/commands.py:385 msgid "Show changes, don't apply them" msgstr "Vis endringer, men ikke lagre dem" #: ../quodlibet/operon/commands.py:126 msgid "Skip tags that can't be written" msgstr "Hopp over tagger som ikke kan skrives" #: ../quodlibet/operon/commands.py:146 #, python-format msgid "Can't copy tag %r to file: %r" msgstr "Klarte ikke å kopiere tagg %r til fil: %r" #: ../quodlibet/operon/commands.py:158 msgid "Edit tags in a text editor" msgstr "Rediger tagger med tekstbehandler" #: ../quodlibet/operon/commands.py:252 msgid "Editing aborted" msgstr "Redigering avbrutt" #: ../quodlibet/operon/commands.py:256 #, python-format msgid "Starting text editor '%(editor-name)s' failed." msgstr "Oppstart av tekstbehadnler «%(editor-name)s» mislyktes." #: ../quodlibet/operon/commands.py:261 msgid "No changes detected" msgstr "Fant ingen endringer" #: ../quodlibet/operon/commands.py:285 msgid "Set a tag and remove existing values" msgstr "Endre tagg og fjern gjeldende verdier" #: ../quodlibet/operon/commands.py:305 ../quodlibet/operon/commands.py:445 #: ../quodlibet/operon/commands.py:677 #, python-format msgid "Can not set %r" msgstr "Klarte ikke å endre %r" #: ../quodlibet/operon/commands.py:320 msgid "Remove tags" msgstr "Fjern tagger" #: ../quodlibet/operon/commands.py:327 ../quodlibet/operon/commands.py:387 msgid "Value is a regular expression" msgstr "Verdien er et regulært uttrykk" #: ../quodlibet/operon/commands.py:329 msgid "Remove all tags" msgstr "Fjern alle tagger" #: ../quodlibet/operon/commands.py:333 msgid "Can't combine '--all' with '--regexp'" msgstr "Du kan ikke bruke «--all» og «--regexp» samtidig" #: ../quodlibet/operon/commands.py:367 #, python-format msgid "Can't remove %r from %r" msgstr "Klarte ikke å fjerne %r fra %r" #: ../quodlibet/operon/commands.py:380 msgid "Remove a tag value" msgstr "Fjern taggverdi" #: ../quodlibet/operon/commands.py:429 msgid "Add a tag value" msgstr "Legg til taggverdi" #: ../quodlibet/operon/commands.py:457 msgid "List file information" msgstr "Vis filinformasjon" #: ../quodlibet/operon/commands.py:503 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:516 #, python-format msgid "Failed to load image file: %r" msgstr "Klarte ikke å laste inn bildefil: %r" #: ../quodlibet/operon/commands.py:523 ../quodlibet/operon/commands.py:552 #, 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:539 msgid "Remove all embedded images" msgstr "Fjern alle innebygde bilder" #: ../quodlibet/operon/commands.py:569 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "Pakk ut innebygde bilder i %(filepath)s" #: ../quodlibet/operon/commands.py:581 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:640 msgid "Rename files based on tags" msgstr "Gi filer nytt navn basert på tagger" #: ../quodlibet/operon/commands.py:655 msgid "Fill tags based on the file path" msgstr "Fyll ut tagger basert på filsti" #: ../quodlibet/operon/commands.py:705 ../quodlibet/qltk/information.py:310 #: ../quodlibet/qltk/properties.py:85 ../quodlibet/qltk/renamefiles.py:226 #: ../quodlibet/qltk/tagsfrompath.py:230 ../quodlibet/qltk/tracknumbers.py:80 msgid "File" msgstr "Fil" #: ../quodlibet/operon/commands.py:713 msgid "Fill tracknumbers for all files" msgstr "Fyll ut spornummer for alle filer" #: ../quodlibet/operon/commands.py:732 msgid "Print tags based on the given pattern" msgstr "Skriv tagger basert på valgt mønster" #: ../quodlibet/operon/commands.py:769 msgid "Display help information" msgstr "Vis hjelpetekst" #: ../quodlibet/operon/util.py:43 #, 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:31 msgid "_Unknown" msgstr "_Ukjent" #: ../quodlibet/order/__init__.py:143 msgid "In Order" msgstr "I rekkefølge" #: ../quodlibet/order/__init__.py:144 msgid "_In Order" msgstr "_I rekkefølge" #: ../quodlibet/order/reorder.py:24 msgid "Random" msgstr "Tilfeldig" #: ../quodlibet/order/reorder.py:25 ../quodlibet/qltk/queue.py:121 msgid "_Random" msgstr "_Tilfeldig" #: ../quodlibet/order/reorder.py:40 ../quodlibet/order/reorder.py:41 msgid "Prefer higher rated" msgstr "Foretrekk låter med høy vurderingskarakter" #: ../quodlibet/order/repeat.py:44 ../quodlibet/order/repeat.py:45 msgid "Repeat this track" msgstr "Gjenta gjeldende spor" #: ../quodlibet/order/repeat.py:58 ../quodlibet/order/repeat.py:59 msgid "Repeat all" msgstr "Gjenta alle" #: ../quodlibet/order/repeat.py:74 ../quodlibet/order/repeat.py:75 msgid "One Song" msgstr "Én låt" #: ../quodlibet/player/gstbe/player.py:99 msgid "Stream" msgstr "Strøm" #: ../quodlibet/player/gstbe/player.py:99 msgid "Buffering" msgstr "Bygger mellomlager" #: ../quodlibet/player/gstbe/player.py:447 msgid "Could not create GStreamer pipeline" msgstr "Klarte ikke å lage GStreamer-datarør" #: ../quodlibet/player/gstbe/player.py:669 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:670 #, python-format msgid "Media format: %(format-description)s" msgstr "Medieformat: %(format-description)s" #: ../quodlibet/player/gstbe/plugins.py:36 #, 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. In case 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:37 msgid "_Output pipeline:" msgstr "_Utdatarør:" #: ../quodlibet/player/gstbe/prefs.py:44 #, python-format msgid "%.1f seconds" msgstr "%.1f sekunder" #: ../quodlibet/player/gstbe/prefs.py:58 msgid "_Buffer duration:" msgstr "_Mellomlagringstid:" #: ../quodlibet/player/gstbe/prefs.py:67 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/util.py:104 msgid "No GStreamer audio sink found" msgstr "Fant ingen GStreamer-lydutgang" #: ../quodlibet/player/gstbe/util.py:123 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:63 #, 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:72 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "Fant ikke GStreamer-element «{element}»" #: ../quodlibet/plugins/playlist.py:24 #, 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:28 ../quodlibet/qltk/songsmenu.py:54 #: ../quodlibet/qltk/songsmenu.py:65 msgid "_Run Plugin" msgstr "_Kjør programtillegg" #. Translators: Refers to the beginning of the playing song. #: ../quodlibet/qltk/bookmarks.py:28 msgid "Beginning" msgstr "Begynnelse" #: ../quodlibet/qltk/bookmarks.py:39 ../quodlibet/qltk/bookmarks.py:79 msgid "N/A" msgstr "I.T." #: ../quodlibet/qltk/bookmarks.py:84 msgid "Time" msgstr "Tid" #: ../quodlibet/qltk/bookmarks.py:90 ../quodlibet/qltk/bookmarks.py:125 msgid "Bookmark Name" msgstr "Bokmerkenavn" #: ../quodlibet/qltk/bookmarks.py:123 msgid "MM:SS" msgstr "MM:SS" #: ../quodlibet/qltk/bookmarks.py:211 ../quodlibet/qltk/information.py:133 msgid "Bookmarks" msgstr "Bokmerker" #: ../quodlibet/qltk/browser.py:57 msgid "_Filters" msgstr "_Filtre" #: ../quodlibet/qltk/browser.py:58 msgid "Recently _Played" msgstr "Sist s_pilt" #: ../quodlibet/qltk/browser.py:60 msgid "Recently _Added" msgstr "Sist lagt til" #: ../quodlibet/qltk/browser.py:62 msgid "_Top 40" msgstr "40 på _topp" #: ../quodlibet/qltk/browser.py:64 msgid "All _Songs" msgstr "Alle _låter" #: ../quodlibet/qltk/browser.py:72 msgid "On Current _Genre(s)" msgstr "På gjeldende _sjanger(e)" #: ../quodlibet/qltk/browser.py:73 msgid "On Current _Artist(s)" msgstr "På gjeldende _artist(er)" #: ../quodlibet/qltk/browser.py:74 msgid "On Current Al_bum" msgstr "På gjeldende al_bum" #: ../quodlibet/qltk/browser.py:82 msgid "Random _Genre" msgstr "Tilfeldig _sjanger" #: ../quodlibet/qltk/browser.py:83 msgid "Random _Artist" msgstr "Tilfeldig _artist" #: ../quodlibet/qltk/browser.py:84 msgid "Random Al_bum" msgstr "Tilfeldig al_bum" #: ../quodlibet/qltk/browser.py:97 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 har blitt spilt av like mange ganger)" #: ../quodlibet/qltk/cbes.py:41 msgid "_Name:" msgstr "_Navn:" #: ../quodlibet/qltk/cbes.py:49 ../quodlibet/qltk/edittags.py:312 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:118 #, python-format msgid "New %s" msgstr "Ny %s" #: ../quodlibet/qltk/data_editors.py:217 msgid "(unknown)" msgstr "(ukjent)" #: ../quodlibet/qltk/data_editors.py:346 msgid "Tag expression" msgstr "Tagguttrykk" #: ../quodlibet/qltk/data_editors.py:373 msgid "Tag expression e.g. people:real or ~album~year" msgstr "Tagguttrykk, som f.eks. «people:real» «~album~year»" #: ../quodlibet/qltk/data_editors.py:374 msgid "Enter new tag" msgstr "Skriv inn ny tagg" #: ../quodlibet/qltk/delete.py:38 msgid "Files:" msgstr "Filer:" #: ../quodlibet/qltk/delete.py:64 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:73 msgid "The selected files will be deleted from disk." msgstr "Valgte filer blir slettet for godt." #: ../quodlibet/qltk/delete.py:77 #, 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:92 msgid "_Delete Files" msgstr "Sle_tt filer" #: ../quodlibet/qltk/delete.py:107 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:116 msgid "The selected files will be moved to the trash." msgstr "Valgte filer blir flyttet til papirkurv." #: ../quodlibet/qltk/delete.py:121 #, 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:135 ../quodlibet/qltk/delete.py:142 msgid "_Move to Trash" msgstr "_Flytt til papirkurv" #: ../quodlibet/qltk/delete.py:153 ../quodlibet/qltk/delete.py:188 #, python-format msgid "Moving %(current)d/%(total)d." msgstr "Flytter %(current)d/%(total)d." #: ../quodlibet/qltk/delete.py:174 ../quodlibet/qltk/delete.py:206 msgid "Unable to move to trash" msgstr "Klarte ikke å flytte til papirkurv" #: ../quodlibet/qltk/delete.py:175 ../quodlibet/qltk/delete.py:207 msgid "Moving one or more files to the trash failed." msgstr "Flytting av én eller flere filer til papirkurv mislyktes." #: ../quodlibet/qltk/delete.py:217 ../quodlibet/qltk/delete.py:251 #, python-format msgid "Deleting %(current)d/%(total)d." msgstr "Sletter %(current)d/%(total)d." #: ../quodlibet/qltk/delete.py:237 ../quodlibet/qltk/delete.py:270 msgid "Unable to delete files" msgstr "Klarte ikke å slette filer" #: ../quodlibet/qltk/delete.py:238 ../quodlibet/qltk/delete.py:271 msgid "Deleting one or more files failed." msgstr "Sletting av én eller flere filer mislyktes." #: ../quodlibet/qltk/edittags.py:64 ../quodlibet/qltk/edittags.py:75 #, 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:68 ../quodlibet/qltk/edittags.py:72 #, 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:194 msgid "Split into _Multiple Values" msgstr "Del opp i _flere verdier" #: ../quodlibet/qltk/edittags.py:212 msgid "Split Disc out of _Album" msgstr "Trekk platenummer ut av _album" #: ../quodlibet/qltk/edittags.py:229 msgid "Split _Version out of Title" msgstr "Trekk _versjon ut av tittel" #: ../quodlibet/qltk/edittags.py:260 msgid "Split Arranger out of Ar_tist" msgstr "Trekk arrangør ut av ar_tist" #: ../quodlibet/qltk/edittags.py:265 msgid "Split _Performer out of Artist" msgstr "Trekk _utøver ut av artist" #: ../quodlibet/qltk/edittags.py:271 msgid "Split _Performer out of Title" msgstr "Trekk _utøver ut av tittel" #: ../quodlibet/qltk/edittags.py:277 msgid "Split _Originalartist out of Title" msgstr "Trekk _originalartist ut av tittel" #: ../quodlibet/qltk/edittags.py:284 msgid "Add a Tag" msgstr "Legg til tagg" #: ../quodlibet/qltk/edittags.py:303 msgid "_Tag:" msgstr "_Tagg:" #: ../quodlibet/qltk/edittags.py:405 msgid "Edit Tags" msgstr "Rediger tagger" #: ../quodlibet/qltk/edittags.py:478 msgid "Show _programmatic tags" msgstr "Vis programmatiske tagger" #: ../quodlibet/qltk/edittags.py:479 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" #. Translators: Revert button in the tag editor #: ../quodlibet/qltk/edittags.py:509 msgctxt "edittags" msgid "_Revert" msgstr "_Tilbakestill" #. Translators: Save button in the tag editor #: ../quodlibet/qltk/edittags.py:514 msgctxt "edittags" msgid "_Save" msgstr "_Lagre" #: ../quodlibet/qltk/edittags.py:660 msgid "Unable to add tag" msgstr "Klarte ikke å legge til tagg" #: ../quodlibet/qltk/edittags.py:661 #, python-format msgid "Unable to add <b>%s</b>" msgstr "Klarte ikke å legge til <b>%s</b>" #: ../quodlibet/qltk/edittags.py:663 #, python-format msgid "" "The files currently selected do not support multiple values for <b>%s</b>." msgstr "Valgte filer støtter ikke at <b>%s</b> har flere enn én verdi." #. Can't add the new tag. #: ../quodlibet/qltk/edittags.py:690 ../quodlibet/qltk/edittags.py:857 #: ../quodlibet/qltk/tagsfrompath.py:213 ../quodlibet/util/__init__.py:506 #: ../quodlibet/util/tags.py:243 msgid "Invalid tag" msgstr "Ugyldig tagg" #: ../quodlibet/qltk/edittags.py:691 ../quodlibet/qltk/edittags.py:858 #: ../quodlibet/qltk/tagsfrompath.py:214 #, python-format msgid "" "Invalid tag <b>%s</b>\n" "\n" "The files currently selected do not support editing this tag." msgstr "" "<b>%s</b> er en ugyldig tagg\n" "\n" "Valgte filer støtter ikke redigering av denne taggen." #: ../quodlibet/qltk/edittags.py:829 ../quodlibet/qltk/edittags.py:869 msgid "Invalid value" msgstr "Ugyldig verdi" #: ../quodlibet/qltk/edittags.py:830 ../quodlibet/qltk/edittags.py:870 #, python-format msgid "" "Invalid value: <b>%(value)s</b>\n" "\n" "%(error)s" msgstr "" "Ugyldig verdi: <b>%(value)s</b>\n" "\n" "%(error)s" #: ../quodlibet/qltk/_editutils.py:30 msgid "Tag may not be accurate" msgstr "Taggen er kanskje ikke nøyaktig" #: ../quodlibet/qltk/_editutils.py:33 #, 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:49 msgid "Unable to save song" msgstr "Klarte ikke å lagre låt" #: ../quodlibet/qltk/_editutils.py:52 #, 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 er skrivebeskyttet, ødelagt, eller " "du mangler tillatelser til å redigere 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:96 #: ../quodlibet/qltk/quodlibetwindow.py:1103 msgid "_About" msgstr "O_m" #: ../quodlibet/qltk/exfalsowindow.py:100 #: ../quodlibet/qltk/quodlibetwindow.py:1125 msgid "_Check for Updates…" msgstr "_Se etter oppdateringer …" #: ../quodlibet/qltk/exfalsowindow.py:106 #: ../quodlibet/qltk/quodlibetwindow.py:1058 ../quodlibet/qltk/songsmenu.py:288 msgid "_Plugins" msgstr "_Programtillegg" #: ../quodlibet/qltk/exfalsowindow.py:268 #, 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/exfalsowindow.py:290 ../quodlibet/qltk/prefs.py:609 msgid "Split _on:" msgstr "Splitt _på:" #: ../quodlibet/qltk/exfalsowindow.py:296 ../quodlibet/qltk/prefs.py:624 msgid "Tag Editing" msgstr "Taggredigering" #: ../quodlibet/qltk/filesel.py:211 msgid "Folders" msgstr "Mapper" #: ../quodlibet/qltk/filesel.py:266 msgid "_New Folder…" msgstr "_Ny mappe …" #: ../quodlibet/qltk/filesel.py:275 msgid "_Select all Sub-Folders" msgstr "_Velg alle undermapper" #: ../quodlibet/qltk/filesel.py:381 msgid "New Folder" msgstr "Ny mappe" #: ../quodlibet/qltk/filesel.py:381 msgid "Enter a name for the new folder:" msgstr "Skriv inn navn på ny mappe:" #: ../quodlibet/qltk/filesel.py:394 msgid "Unable to create folder" msgstr "Klarte ikke å lage mappe" #: ../quodlibet/qltk/filesel.py:411 msgid "Unable to delete folder" msgstr "Klarte ikke å slette mappe" #: ../quodlibet/qltk/filesel.py:526 ../quodlibet/qltk/pluginwin.py:168 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:172 #: ../quodlibet/qltk/information.py:453 #, python-format msgid "Disc %s" msgstr "Plate %s" #: ../quodlibet/qltk/info.py:45 ../quodlibet/qltk/information.py:177 #, python-format msgid "Track %s" msgstr "Spor %s" #: ../quodlibet/qltk/info.py:109 msgid "_Edit Display…" msgstr "R_ediger visning …" #: ../quodlibet/qltk/information.py:107 msgid "No songs are selected." msgstr "Ingen låter er valgt." #: ../quodlibet/qltk/information.py:108 msgid "No Songs" msgstr "Ingen låter" #: ../quodlibet/qltk/information.py:123 ../quodlibet/qltk/information.py:343 #: ../quodlibet/qltk/information.py:476 ../quodlibet/qltk/information.py:544 msgid "Information" msgstr "Informasjon" #: ../quodlibet/qltk/information.py:128 msgid "Lyrics" msgstr "Sangtekst" #: ../quodlibet/qltk/information.py:189 ../quodlibet/qltk/information.py:401 #, python-format msgid "Produced by %s" msgstr "Produsert av %s" #: ../quodlibet/qltk/information.py:204 ../quodlibet/util/tags.py:87 msgid "artist" msgstr "artist" #: ../quodlibet/qltk/information.py:205 ../quodlibet/qltk/information.py:574 #: ../quodlibet/util/tags.py:87 msgid "artists" msgstr "artister" #. for backwards compat #: ../quodlibet/qltk/information.py:226 ../quodlibet/util/tags.py:98 #: ../quodlibet/util/tags.py:126 msgid "performers" msgstr "utøvere" #: ../quodlibet/qltk/information.py:240 ../quodlibet/qltk/information.py:253 #: ../quodlibet/qltk/songlistcolumns.py:276 msgid "Never" msgstr "Aldri" #: ../quodlibet/qltk/information.py:241 #, 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:259 ../quodlibet/util/tags.py:151 msgid "added" msgstr "lagt til" #: ../quodlibet/qltk/information.py:260 ../quodlibet/util/tags.py:152 msgid "last played" msgstr "sist spilt" #: ../quodlibet/qltk/information.py:261 ../quodlibet/util/tags.py:162 msgid "plays" msgstr "avspillinger" #: ../quodlibet/qltk/information.py:262 ../quodlibet/util/tags.py:163 msgid "skips" msgstr "hoppet over" #: ../quodlibet/qltk/information.py:263 ../quodlibet/util/tags.py:168 msgid "rating" msgstr "vurdering" #: ../quodlibet/qltk/information.py:292 msgid "path" msgstr "sti" #: ../quodlibet/qltk/information.py:293 ../quodlibet/util/tags.py:166 msgid "length" msgstr "varighet" #: ../quodlibet/qltk/information.py:294 msgid "format" msgstr "format" #: ../quodlibet/qltk/information.py:295 ../quodlibet/util/tags.py:175 msgid "codec" msgstr "codec" #: ../quodlibet/qltk/information.py:296 ../quodlibet/util/tags.py:176 msgid "encoding" msgstr "koding" #: ../quodlibet/qltk/information.py:297 ../quodlibet/util/tags.py:172 msgid "bitrate" msgstr "bitfrekvens" #: ../quodlibet/qltk/information.py:298 ../quodlibet/util/tags.py:173 msgid "file size" msgstr "filstørrelse" #: ../quodlibet/qltk/information.py:299 ../quodlibet/util/tags.py:161 msgid "modified" msgstr "endret" #: ../quodlibet/qltk/information.py:336 msgid "Additional" msgstr "Tillegg" #: ../quodlibet/qltk/information.py:388 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d valgt" msgstr[1] "%d valgte" #: ../quodlibet/qltk/information.py:463 msgid "Track unavailable" msgstr "Spor utilgjengelig" #: ../quodlibet/qltk/information.py:469 msgid "Track List" msgstr "Sporliste" #: ../quodlibet/qltk/information.py:501 ../quodlibet/qltk/information.py:591 #, 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:504 msgid "Selected Discography" msgstr "Valgt diskografi" #: ../quodlibet/qltk/information.py:571 #, 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:599 ../quodlibet/util/tags.py:85 msgid "albums" msgstr "album" #: ../quodlibet/qltk/information.py:612 msgid "Total length:" msgstr "Total varighet:" #: ../quodlibet/qltk/information.py:616 msgid "Total size:" msgstr "Total størrelse:" #: ../quodlibet/qltk/information.py:619 msgid "Files" msgstr "Filer" #: ../quodlibet/qltk/lyrics.py:37 msgid "_View online" msgstr "_Vis på nett" #: ../quodlibet/qltk/lyrics.py:65 msgid "No lyrics found for this song." msgstr "Fant ingen sangtekst for denne låta." #: ../quodlibet/qltk/lyrics.py:76 msgid "Searching for lyrics…" msgstr "Søker etter sangtekst …" #: ../quodlibet/qltk/maskedbox.py:21 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:22 msgid "The selected songs will be removed from the library." msgstr "Valgte låter blir fjernet fra biblioteket." #: ../quodlibet/qltk/maskedbox.py:45 msgid "Unhide" msgstr "Vis" #: ../quodlibet/qltk/maskedbox.py:87 msgid "_Unhide" msgstr "_Vis" #: ../quodlibet/qltk/msg.py:42 msgid "Discard tag changes?" msgstr "Vil du forkaste taggendringer?" #: ../quodlibet/qltk/msg.py:43 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:56 ../quodlibet/qltk/prefs.py:606 #: ../quodlibet/qltk/textedit.py:65 ../quodlibet/qltk/tracknumbers.py:118 msgid "_Revert" msgstr "_Tilbakestill" #: ../quodlibet/qltk/msg.py:105 msgid "File exists" msgstr "Fila finnes" #: ../quodlibet/qltk/msg.py:107 #, python-format msgid "Replace %(file-name)s?" msgstr "Vil du erstatte %(file-name)s?" #: ../quodlibet/qltk/msg.py:113 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:257 msgid "Toggle shuffle mode" msgstr "Slå av/på tilfeldig rekkefølge" #: ../quodlibet/qltk/playorder.py:273 msgid "Toggle repeat mode" msgstr "Slå av/på gjentakelse" #: ../quodlibet/qltk/pluginwin.py:45 msgid "Plugin Errors" msgstr "Programtillegg-feil" #: ../quodlibet/qltk/pluginwin.py:125 msgid "Enabled" msgstr "Slått på" #: ../quodlibet/qltk/pluginwin.py:126 msgid "Disabled" msgstr "Slått av" #: ../quodlibet/qltk/pluginwin.py:132 msgid "No category" msgstr "Ingen kategori" #: ../quodlibet/qltk/pluginwin.py:170 msgid "Events" msgstr "Hendelser" #: ../quodlibet/qltk/pluginwin.py:171 msgid "Play Order" msgstr "Avspillingsrekkefølge" #: ../quodlibet/qltk/pluginwin.py:172 msgid "Editing" msgstr "Redigering" #: ../quodlibet/qltk/pluginwin.py:174 msgid "Covers" msgstr "Omslag" #: ../quodlibet/qltk/pluginwin.py:310 msgid "No plugins found." msgstr "Fant ingen programtillegg." #: ../quodlibet/qltk/pluginwin.py:359 msgid "Plugins" msgstr "Programtillegg" #: ../quodlibet/qltk/pluginwin.py:383 msgid "Filter by plugin state / tag" msgstr "Filtrer etter tilstand / tagg" #: ../quodlibet/qltk/pluginwin.py:389 msgid "Filter by plugin type" msgstr "Filtrer etter type" #: ../quodlibet/qltk/pluginwin.py:395 msgid "Filter by plugin name or description" msgstr "Filtrer etter navn eller beskrivelse" #: ../quodlibet/qltk/pluginwin.py:404 msgid "Show _Errors" msgstr "Vis _feil" #: ../quodlibet/qltk/prefs.py:46 msgid "_Disc" msgstr "_Plate" #: ../quodlibet/qltk/prefs.py:47 msgid "_Track" msgstr "_Spor" #: ../quodlibet/qltk/prefs.py:48 msgid "Grou_ping" msgstr "Gru_ppering" #: ../quodlibet/qltk/prefs.py:51 msgid "Al_bum" msgstr "Al_bum" #: ../quodlibet/qltk/prefs.py:56 msgid "_Filename" msgstr "_Filnavn" #: ../quodlibet/qltk/prefs.py:58 msgid "_Length" msgstr "_Varighet" #: ../quodlibet/qltk/prefs.py:65 msgid "_Jump to playing song automatically" msgstr "_Hopp til spillende låt automatisk" #: ../quodlibet/qltk/prefs.py:67 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:83 msgid "_Others:" msgstr "_Annet:" #: ../quodlibet/qltk/prefs.py:89 msgid "_Edit…" msgstr "R_ediger …" #: ../quodlibet/qltk/prefs.py:92 msgid "Add or remove additional column headers" msgstr "Legg til eller fjern tilleggskolonner" #: ../quodlibet/qltk/prefs.py:102 msgid "Visible Columns" msgstr "Synlige kolonner" #: ../quodlibet/qltk/prefs.py:105 msgid "Title includes _version" msgstr "Tittel inkluderer _versjon" #: ../quodlibet/qltk/prefs.py:107 msgid "Artist includes all _people" msgstr "Artist inneholder alle _personer" #: ../quodlibet/qltk/prefs.py:109 msgid "Album includes _disc subtitle" msgstr "Album inneholder _plate-undertittel" #: ../quodlibet/qltk/prefs.py:111 msgid "Filename includes _folder" msgstr "Filnavn inneholder _mappe" #: ../quodlibet/qltk/prefs.py:124 msgid "Column Preferences" msgstr "Kolonneoppsett" #: ../quodlibet/qltk/prefs.py:130 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:143 ../quodlibet/qltk/shortcuts.py:25 msgid "Song List" msgstr "Låtliste" #: ../quodlibet/qltk/prefs.py:223 msgid "Edit Columns" msgstr "Rediger kolonner" #: ../quodlibet/qltk/prefs.py:260 msgid "Duration totals" msgstr "Total varighet" #: ../quodlibet/qltk/prefs.py:272 msgid "_Global filter:" msgstr "_Globalt filter:" #: ../quodlibet/qltk/prefs.py:278 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:284 msgctxt "heading" msgid "Search" msgstr "Søk" #: ../quodlibet/qltk/prefs.py:288 ../quodlibet/qltk/shortcuts.py:22 msgid "Browsers" msgstr "Utforskere" #: ../quodlibet/qltk/prefs.py:294 msgid "Confirm _multiple ratings" msgstr "Bekreft _multi-vurdering" #: ../quodlibet/qltk/prefs.py:296 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:299 msgid "Enable _one-click ratings" msgstr "Slå på _énklikksvurdering" #: ../quodlibet/qltk/prefs.py:301 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:307 ../quodlibet/qltk/prefs.py:627 msgid "Ratings" msgstr "Vurderinger" #. Filename choice algorithm config #: ../quodlibet/qltk/prefs.py:313 msgid "Prefer _embedded art" msgstr "Foretrekk _innebygd omslag" #: ../quodlibet/qltk/prefs.py:315 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:320 msgid "_Fixed image filename:" msgstr "_Fast bildefilnavn:" #: ../quodlibet/qltk/prefs.py:322 msgid "The single image filename to use if selected" msgstr "Bildefilnavn som skal brukes hvis dette er valgt" #: ../quodlibet/qltk/prefs.py:328 msgid "The album art image file to use when forced (supports wildcards)" msgstr "Omslagsbildefil som skal brukes ved tvang (støtter jokertegn)" #: ../quodlibet/qltk/prefs.py:338 msgid "Album Art" msgstr "Albumomslag" #: ../quodlibet/qltk/prefs.py:359 msgid "Playback" msgstr "Avspilling" #: ../quodlibet/qltk/prefs.py:364 msgid "Output Configuration" msgstr "Utdata-oppsett" #: ../quodlibet/qltk/prefs.py:375 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:378 msgid "_Fall-back gain (dB):" msgstr "_Tilbakefalls-forsterkning (dB):" #: ../quodlibet/qltk/prefs.py:389 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:392 msgid "_Pre-amp gain (dB):" msgstr "_For-forsterkning (dB):" #: ../quodlibet/qltk/prefs.py:397 msgid "_Enable Replay Gain volume adjustment" msgstr "_Slå på Replay Gain-volumjustering" #: ../quodlibet/qltk/prefs.py:422 msgid "Replay Gain Volume Adjustment" msgstr "Replay Gain-volumjustering" #: ../quodlibet/qltk/prefs.py:452 msgid "_Default rating:" msgstr "_Forvalgt vurdering:" #: ../quodlibet/qltk/prefs.py:495 msgid "Rating _scale:" msgstr "Vurderings_skala:" #: ../quodlibet/qltk/prefs.py:544 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 aggregerte 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:549 msgid "_Bayesian averaging amount:" msgstr "_Bayesisk gjennomsnittsmengde:" #: ../quodlibet/qltk/prefs.py:558 msgid "Save ratings and play _counts in tags" msgstr "Lagre vurderinger og avspillings_antall i tagger" #: ../quodlibet/qltk/prefs.py:566 msgid "_Email:" msgstr "_E-post:" #: ../quodlibet/qltk/prefs.py:568 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:588 msgid "Auto-save tag changes" msgstr "Lagre taggendringer automatisk" #: ../quodlibet/qltk/prefs.py:590 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:598 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:621 msgid "Tags" msgstr "Tagger" #: ../quodlibet/qltk/prefs.py:642 msgid "Updating for new ratings" msgstr "Ser etter nye vurderinger" #: ../quodlibet/qltk/prefs.py:652 msgid "Scan library _on start" msgstr "Søk gjennom bibliotek ved _oppstart" #: ../quodlibet/qltk/prefs.py:662 ../quodlibet/qltk/quodlibetwindow.py:1137 msgid "_Scan Library" msgstr "_Søk gjennom bibliotek" #: ../quodlibet/qltk/prefs.py:664 ../quodlibet/qltk/quodlibetwindow.py:1199 msgid "Check for changes in your library" msgstr "Se etter endringer i biblioteket" #: ../quodlibet/qltk/prefs.py:669 msgid "Re_build Library" msgstr "_Bygg bibliotek på nytt" #: ../quodlibet/qltk/prefs.py:672 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:682 msgid "Scan Directories" msgstr "Søk gjennom mapper" #: ../quodlibet/qltk/prefs.py:688 msgid "Hidden Songs" msgstr "Skjulte låter" #: ../quodlibet/qltk/properties.py:159 ../quodlibet/util/collection.py:403 #, 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:163 ../quodlibet/qltk/properties.py:165 msgid "Properties" msgstr "Egenskaper" #: ../quodlibet/qltk/queue.py:103 msgid "_Queue" msgstr "_Kø" #: ../quodlibet/qltk/queue.py:127 msgid "Stop Once Empty" msgstr "Stopp når tomt" #: ../quodlibet/qltk/queue.py:131 msgid "_Clear Queue" msgstr "_Tøm kø" #: ../quodlibet/qltk/queue.py:242 #, 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:200 msgid "_Browse Library" msgstr "_Utforsk bibliotek" #: ../quodlibet/qltk/quodlibetwindow.py:397 msgid "Toggle queue visibility" msgstr "Vis/skjul kø" #: ../quodlibet/qltk/quodlibetwindow.py:518 msgid "Playback Error" msgstr "Avspillingsfeil" #: ../quodlibet/qltk/quodlibetwindow.py:526 msgid "Set up library directories?" msgstr "Vil du sette opp bibliotekmapper?" #: ../quodlibet/qltk/quodlibetwindow.py:527 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:533 msgid "_Not Now" msgstr "_Ikke nå" #: ../quodlibet/qltk/quodlibetwindow.py:534 msgid "_Set Up" msgstr "_Sett opp" #: ../quodlibet/qltk/quodlibetwindow.py:993 msgid "Unable to add songs" msgstr "Klarte ikke å legge til låter" #: ../quodlibet/qltk/quodlibetwindow.py:994 #: ../quodlibet/qltk/quodlibetwindow.py:1398 #, python-format msgid "%s uses an unsupported protocol." msgstr "%s bruker en ustøttet protokoll." #: ../quodlibet/qltk/quodlibetwindow.py:1017 msgid "_Jump to Playing Song" msgstr "_Hopp til spillende låt" #: ../quodlibet/qltk/quodlibetwindow.py:1023 msgid "_File" msgstr "_Fil" #: ../quodlibet/qltk/quodlibetwindow.py:1024 msgid "_Song" msgstr "_Låter" #: ../quodlibet/qltk/quodlibetwindow.py:1025 msgid "_View" msgstr "_Visning" #: ../quodlibet/qltk/quodlibetwindow.py:1026 msgid "_Browse" msgstr "_Bla gjennom" #: ../quodlibet/qltk/quodlibetwindow.py:1027 msgid "_Control" msgstr "_Kontroll" #: ../quodlibet/qltk/quodlibetwindow.py:1028 msgid "_Help" msgstr "_Hjelp" #: ../quodlibet/qltk/quodlibetwindow.py:1034 msgid "_Add a Folder…" msgstr "_Legg til mappe …" #: ../quodlibet/qltk/quodlibetwindow.py:1039 msgid "_Add a File…" msgstr "_Legg til fil …" #: ../quodlibet/qltk/quodlibetwindow.py:1044 msgid "_Add a Location…" msgstr "_Legg til plassering …" #: ../quodlibet/qltk/quodlibetwindow.py:1073 msgid "Edit Bookmarks…" msgstr "Rediger bokmerker …" #: ../quodlibet/qltk/quodlibetwindow.py:1093 msgid "Stop After This Song" msgstr "Stopp etter denne låta" #: ../quodlibet/qltk/quodlibetwindow.py:1099 msgid "_Keyboard Shortcuts" msgstr "_Tastatursnarveier" #: ../quodlibet/qltk/quodlibetwindow.py:1108 msgid "Online Help" msgstr "Hjelp på nett" #: ../quodlibet/qltk/quodlibetwindow.py:1117 msgid "Search Help" msgstr "Søk etter hjelp" #: ../quodlibet/qltk/quodlibetwindow.py:1386 msgid "Add a Location" msgstr "Legg til plassering" #: ../quodlibet/qltk/quodlibetwindow.py:1387 msgid "Enter the location of an audio file:" msgstr "Skriv inn plassering til en lydfil:" #: ../quodlibet/qltk/quodlibetwindow.py:1392 #: ../quodlibet/qltk/quodlibetwindow.py:1397 msgid "Unable to add location" msgstr "Klarte ikke å legge til plassering" #: ../quodlibet/qltk/quodlibetwindow.py:1393 #, python-format msgid "%s is not a valid location." msgstr "%s er en ugyldig plassering." #: ../quodlibet/qltk/quodlibetwindow.py:1406 #: ../quodlibet/qltk/quodlibetwindow.py:1415 msgid "Add Music" msgstr "Legg til musikk" #: ../quodlibet/qltk/quodlibetwindow.py:1406 ../quodlibet/qltk/scanbox.py:100 msgid "_Add Folders" msgstr "_Legg til mapper" #: ../quodlibet/qltk/quodlibetwindow.py:1413 msgid "Music Files" msgstr "Musikkfiler" #: ../quodlibet/qltk/quodlibetwindow.py:1415 msgid "_Add Files" msgstr "_Legg til filer" #: ../quodlibet/qltk/ratingsmenu.py:25 #, 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:27 msgid "The saved ratings will be removed" msgstr "Gjeldende vurderinger blir fjernet" #: ../quodlibet/qltk/ratingsmenu.py:28 #, 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:58 ../quodlibet/qltk/ratingsmenu.py:112 msgid "_Remove Rating" msgstr "_Fjern vurdering" #: ../quodlibet/qltk/ratingsmenu.py:99 msgid "Change _Rating" msgstr "Fjern _vurdering" #: ../quodlibet/qltk/renamefiles.py:53 msgid "Replace spaces with _underscores" msgstr "Erstatt mellomrom med _understrek" #: ../quodlibet/qltk/renamefiles.py:63 msgid "Strip _Windows-incompatible characters" msgstr "Fjern tegn som ikke søttes av _Windows" #: ../quodlibet/qltk/renamefiles.py:81 msgid "Strip _diacritical marks" msgstr "Fjern diakritiske merker" #: ../quodlibet/qltk/renamefiles.py:92 msgid "Strip non-_ASCII characters" msgstr "Fjern tegn som ikke er en del av _ASCII" #: ../quodlibet/qltk/renamefiles.py:102 msgid "Use only _lowercase characters" msgstr "Bare bruk _små bokstaver" #: ../quodlibet/qltk/renamefiles.py:130 msgid "Rename Files" msgstr "Endre filnavn" #: ../quodlibet/qltk/renamefiles.py:148 ../quodlibet/qltk/tagsfrompath.py:117 msgid "Path Patterns" msgstr "Sti-mønstre" #: ../quodlibet/qltk/renamefiles.py:149 ../quodlibet/qltk/tagsfrompath.py:118 msgid "Edit saved patterns…" msgstr "Rediger lagrede mønstre …" #: ../quodlibet/qltk/renamefiles.py:152 ../quodlibet/qltk/tagsfrompath.py:121 #: ../quodlibet/qltk/tracknumbers.py:59 msgid "_Preview" msgstr "_Forhåndsvisning" #: ../quodlibet/qltk/renamefiles.py:179 msgid "File names" msgstr "Filnavn" #: ../quodlibet/qltk/renamefiles.py:189 msgid "_Move album art" msgstr "_Flytt albumomslag" #: ../quodlibet/qltk/renamefiles.py:192 msgid "See '[albumart] filenames' config entry for image search strings" msgstr "Se oppsettsvalg «[albumart] filenames» for bilde-søkestrenger" #: ../quodlibet/qltk/renamefiles.py:197 msgid "_Overwrite album art at target" msgstr "_Overskriv albumomslag ved mål" #: ../quodlibet/qltk/renamefiles.py:205 msgid "_Remove empty directories" msgstr "_Fjern tomme mapper" #: ../quodlibet/qltk/renamefiles.py:211 msgid "Album art" msgstr "Albumomslag" #: ../quodlibet/qltk/renamefiles.py:240 msgid "New Name" msgstr "Nytt navn" #: ../quodlibet/qltk/renamefiles.py:317 msgid "Unable to rename file" msgstr "Klarte ikke å endre filnavn" #: ../quodlibet/qltk/renamefiles.py:318 #, python-format msgid "" "Renaming <b>%(old-name)s</b> to <b>%(new-name)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." msgstr "" "Endring av navn fra <b>%(old-name)s</b> til <b>%(new-name)s</b> mislyktes. " "Målfila finnes allerede, eller du mangler tillatelser til enten å lage den " "nye fila eller fjerne den gamle." #: ../quodlibet/qltk/renamefiles.py:326 msgid "Ignore _All Errors" msgstr "Ignorer _alle feil" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: ../quodlibet/qltk/renamefiles.py:327 ../quodlibet/qltk/wlw.py:51 msgid "_Stop" msgstr "_Stopp" #: ../quodlibet/qltk/renamefiles.py:329 msgid "_Continue" msgstr "_Fortsett" #: ../quodlibet/qltk/renamefiles.py:442 msgid "Path is not absolute" msgstr "Stien er ikke absolutt" #: ../quodlibet/qltk/renamefiles.py:443 #, python-format msgid "" "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 ~/." msgstr "" "Mønsteret\n" "\t<b>%s</b>\n" "inneholder «/», men starter ikke fra rotmappe. For å unngå feilutformede " "mappenavn må du begynne mønsteret med «/» eller «~/»." #: ../quodlibet/qltk/scanbox.py:48 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:100 msgid "Select Directories" msgstr "Velg mapper" #: ../quodlibet/qltk/searchbar.py:54 msgid "Saved Searches" msgstr "Lagrede søk" #: ../quodlibet/qltk/searchbar.py:55 msgid "Edit saved searches…" msgstr "Rediger lagrede søk …" #: ../quodlibet/qltk/searchbar.py:77 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:139 msgid "Search after _typing" msgstr "Søk e_tter skriving" #: ../quodlibet/qltk/searchbar.py:142 msgid "Show search results after the user stops typing" msgstr "Vil søketreff når bruker slutter å skrive" #: ../quodlibet/qltk/searchbar.py:201 msgid "_Limit:" msgstr "_Grense:" #: ../quodlibet/qltk/searchbar.py:214 msgid "_Weight" msgstr "_Vekting" #: ../quodlibet/qltk/seekbutton.py:239 msgid "Display remaining time" msgstr "Vis gjenstående tid" #: ../quodlibet/qltk/shortcuts.py:17 msgid "Main Window" msgstr "Hovedvindu" #: ../quodlibet/qltk/shortcuts.py:18 msgid "Seek backwards by 10 seconds" msgstr "Hopp 10 sekunder bakover" #: ../quodlibet/qltk/shortcuts.py:19 msgid "Seek forward by 10 seconds" msgstr "Hopp 10 sekunder framover" #: ../quodlibet/qltk/shortcuts.py:20 msgid "Focus the search entry" msgstr "Fokuser på søkefelt" #: ../quodlibet/qltk/shortcuts.py:23 msgid "Reset filters and jump to the playing song" msgstr "Tilbakestill filtre og hopp til spillende låt" #: ../quodlibet/qltk/shortcuts.py:27 msgid "Open the information window for the selected songs" msgstr "Åpne informasjonsvindu for valgte låter" #: ../quodlibet/qltk/shortcuts.py:28 msgid "Open the tag editor for the selected songs" msgstr "Åpne taggbehandler for valgte låter" #: ../quodlibet/qltk/shortcuts.py:29 msgid "Queue the selected songs" msgstr "Legg valgte låter i kø" #: ../quodlibet/qltk/shortcuts.py:30 msgid "Delete the selected songs" msgstr "Slett valgte låter" #: ../quodlibet/qltk/shortcuts.py:31 msgid "Show the inline search entry" msgstr "Vis søketekst" #: ../quodlibet/qltk/shortcuts.py:32 msgid "Left click on a column header" msgstr "Venstreklikk på kolonneoverskrift" #: ../quodlibet/qltk/shortcuts.py:33 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:35 msgid "Tree View" msgstr "Trevisning" #: ../quodlibet/qltk/shortcuts.py:37 msgid "Collapses the element or select the parent element" msgstr "Folder sammen element eller velger forelder-element" #: ../quodlibet/qltk/shortcuts.py:38 msgid "Expands the element" msgstr "Utvider element" #: ../quodlibet/qltk/shortcuts.py:40 msgid "Text Entries" msgstr "Tekstskriving" #: ../quodlibet/qltk/shortcuts.py:42 msgid "Undo the last change" msgstr "Angre siste endring" #: ../quodlibet/qltk/shortcuts.py:43 msgid "Redo the last undone change" msgstr "Gjør om siste angrede endring" #: ../quodlibet/qltk/shortcuts.py:46 msgid "Select all songs in all panes" msgstr "Velg alle låter i faner" #: ../quodlibet/qltk/songlist.py:366 #, python-format msgid "_Filter on %s" msgstr "_Filtrer på %s" #: ../quodlibet/qltk/songlist.py:1083 msgid "All _Headers" msgstr "Alle _hoder" #: ../quodlibet/qltk/songlist.py:1084 msgid "_Track Headers" msgstr "_Sporkolonner" #: ../quodlibet/qltk/songlist.py:1085 msgid "_Album Headers" msgstr "_Albumkolonner" #: ../quodlibet/qltk/songlist.py:1086 msgid "_People Headers" msgstr "_Personkolonner" #: ../quodlibet/qltk/songlist.py:1087 msgid "_Date Headers" msgstr "_Datokolonner" #: ../quodlibet/qltk/songlist.py:1088 msgid "_File Headers" msgstr "_Filkolonner" #: ../quodlibet/qltk/songlist.py:1089 msgid "_Production Headers" msgstr "_Produksjonskolonner" #: ../quodlibet/qltk/songlist.py:1104 msgid "_Customize Headers…" msgstr "_Tilpass hoder …" #: ../quodlibet/qltk/songlist.py:1109 msgid "_Expand Column" msgstr "_Utvid kolonne" #: ../quodlibet/qltk/songsmenu.py:39 #, python-format msgid "Remove track: \"%(title)s\" from library?" msgid_plural "Remove %(count)d tracks from library?" msgstr[0] "Vil du fjerne dette sporet fra biblioteket?" msgstr[1] "Vil du fjerne %(count)d spor fra biblioteket?" #: ../quodlibet/qltk/songsmenu.py:45 msgid "Remove from Library" msgstr "Fjern fra bibliotek" #: ../quodlibet/qltk/songsmenu.py:50 #, 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:61 #, 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:133 msgid "Configure Plugins…" msgstr "Sett opp tillegg …" #: ../quodlibet/qltk/songsmenu.py:328 msgid "Add to _Queue" msgstr "Legg i _kø" #: ../quodlibet/qltk/songsmenu.py:348 msgid "_Remove from Library…" msgstr "_Fjern fra bibliotek …" #: ../quodlibet/qltk/tagsfrompath.py:48 msgid "Replace _underscores with spaces" msgstr "Erstatt _understrek med mellomrom" #: ../quodlibet/qltk/tagsfrompath.py:58 msgid "_Title-case tags" msgstr "Tittelversaliser tagger" #: ../quodlibet/qltk/tagsfrompath.py:68 msgid "Split into multiple _values" msgstr "Del opp i flere _verdier" #: ../quodlibet/qltk/tagsfrompath.py:102 msgid "Tags From Path" msgstr "Tagger fra sti" #: ../quodlibet/qltk/tagsfrompath.py:139 msgid "Tags replace existing ones" msgstr "Tagger erstatter gjeldende tagger" #: ../quodlibet/qltk/tagsfrompath.py:140 msgid "Tags are added to existing ones" msgstr "Tagger legges til gjeldende tagger" #: ../quodlibet/qltk/tagsfrompath.py:196 #, python-format msgid "" "The pattern\n" "\t<b>%s</b>\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 ugyldig. Det inneholder enten samme tagg flere ganger, eller har " "ubalanserte parenteser (< / >)." #: ../quodlibet/qltk/tagsfrompath.py:217 msgid "Invalid tags" msgstr "Ugyldige tagger" #: ../quodlibet/qltk/tagsfrompath.py:218 #, 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." #: ../quodlibet/qltk/textedit.py:143 #, 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:159 msgid "Edit Display" msgstr "Rediger visning" #: ../quodlibet/qltk/tracknumbers.py:40 msgid "Track Numbers" msgstr "Spornummer" #: ../quodlibet/qltk/tracknumbers.py:43 msgid "Start fro_m:" msgstr "Start fr_a:" #: ../quodlibet/qltk/tracknumbers.py:52 msgid "_Total tracks:" msgstr "_Totalt antall:" #: ../quodlibet/qltk/unity.py:53 msgid "Play/Pause" msgstr "Spill av/pause" #: ../quodlibet/qltk/unity.py:73 msgid "Previous" msgstr "Forrige" #: ../quodlibet/qltk/views.py:924 #, python-format msgid "and %d more…" msgstr "og %d andre …" #: ../quodlibet/qltk/wlw.py:201 msgid "Saving the songs you changed." msgstr "Lagrer endrede låter." #: ../quodlibet/qltk/wlw.py:202 #, 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:235 #, 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>\n" "for å laste ned ny versjon" #: ../quodlibet/util/collection.py:425 msgid "Playlists must have a name" msgstr "Spillelister må ha navn" #: ../quodlibet/util/collection.py:608 #, python-format msgid "A playlist named %s already exists." msgstr "Det finnes allerede en spilleliste med navnet %s." #: ../quodlibet/util/cover/built_in.py:32 msgid "Embedded album covers" msgstr "Innebygde album-omslag" #: ../quodlibet/util/cover/built_in.py:33 msgid "Uses covers embedded into audio files." msgstr "Bruker innebygde omslagsbilder." #: ../quodlibet/util/cover/built_in.py:55 msgid "Filesystem cover" msgstr "Filsystem-omslag" #: ../quodlibet/util/cover/built_in.py:56 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:231 msgid "Cover Art" msgstr "Omslagsbilde" #: ../quodlibet/util/cover/manager.py:231 msgid "Querying album art providers" msgstr "Søker etter album-omslag hos tilbydere" #: ../quodlibet/util/__init__.py:77 msgid "Display brief usage information" msgstr "Vis kortfattet bruksinformasjon" #: ../quodlibet/util/__init__.py:79 msgid "Display version and copyright" msgstr "Vis versjon og opphavsrett" #: ../quodlibet/util/__init__.py:119 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "Bruk: %(program)s %(usage)s" #: ../quodlibet/util/__init__.py:121 msgid "[options]" msgstr "[valg]" #: ../quodlibet/util/__init__.py:166 #, python-format msgid "Option %r not recognized." msgstr "Valget %r er ukjent." #: ../quodlibet/util/__init__.py:169 #, python-format msgid "Option %r requires an argument." msgstr "Valget %r krever argument." #: ../quodlibet/util/__init__.py:172 #, python-format msgid "%r is not a unique prefix." msgstr "%r er ikke et unikt prefiks." #: ../quodlibet/util/__init__.py:348 #, python-format msgid "%d kbps" msgstr "%d kbps" #: ../quodlibet/util/__init__.py:403 #, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%s sekund" msgstr[1] "%s sekunder" #: ../quodlibet/util/__init__.py:416 msgid "No time information" msgstr "Ingen tidsinformasjon" #: ../quodlibet/util/__init__.py:419 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d sekund" msgstr[1] "%d sekunder" #: ../quodlibet/util/__init__.py:420 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d minutt" msgstr[1] "%d minutter" #: ../quodlibet/util/__init__.py:421 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d time" msgstr[1] "%d timer" #: ../quodlibet/util/__init__.py:422 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d dag" msgstr[1] "%d dager" #: ../quodlibet/util/__init__.py:423 #, 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:515 msgctxt "check" msgid "titlecase?" msgstr "kontroller|tittelversaler" #: ../quodlibet/util/massagers.py:116 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:131 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:152 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:174 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:196 msgid "" "MusicBrainz release status must be 'official', 'promotional', or 'bootleg'." msgstr "" "MusicBrainz-utgivelsesstatus må være «official», «promotional» eller " "«bootleg»." #: ../quodlibet/util/massagers.py:209 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:117 msgid "Unable to edit song" msgstr "Klarte ikke å redigere låt" #: ../quodlibet/util/songwrapper.py:118 #, python-format msgid "" "Saving <b>%s</b> failed. The file may be read-only, corrupted, or you do not " "have permission to edit it." msgstr "" "Lagring av <b>%s</b> mislyktes. Fila kan være skrivebeskyttet, ødelagt, " "eller du mangler tillatelser til å redigere den." #: ../quodlibet/util/string/__init__.py:35 #: ../quodlibet/util/string/__init__.py:45 msgid "[Invalid Encoding]" msgstr "[Ugyldig tegnkoding]" #: ../quodlibet/util/tags.py:85 msgid "album" msgstr "album" #: ../quodlibet/util/tags.py:86 msgid "arranger" msgstr "arrangør" #: ../quodlibet/util/tags.py:86 msgid "arrangers" msgstr "arrangører" #: ../quodlibet/util/tags.py:86 msgid "arrangement" msgstr "arrangement" #: ../quodlibet/util/tags.py:88 msgid "author" msgstr "opphavsrettseier" #: ../quodlibet/util/tags.py:88 msgid "authors" msgstr "opphavsrettseiere" #: ../quodlibet/util/tags.py:89 msgid "comment" msgstr "kommentar" #: ../quodlibet/util/tags.py:90 msgid "composer" msgstr "komponist" #: ../quodlibet/util/tags.py:90 msgid "composers" msgstr "komponister" #: ../quodlibet/util/tags.py:90 msgid "composition" msgstr "komposisjon" #. Translators: conducting as in conducting a musical performance #: ../quodlibet/util/tags.py:92 msgid "conductor" msgstr "dirigent" #: ../quodlibet/util/tags.py:92 msgid "conductors" msgstr "dirigenter" #: ../quodlibet/util/tags.py:92 msgid "conducting" msgstr "dirigering" #: ../quodlibet/util/tags.py:93 msgid "contact" msgstr "kontakt" #: ../quodlibet/util/tags.py:94 msgid "copyright" msgstr "opphavsrett" #: ../quodlibet/util/tags.py:95 msgid "date" msgstr "dato" #: ../quodlibet/util/tags.py:96 msgid "description" msgstr "beskrivelse" #: ../quodlibet/util/tags.py:97 msgid "genre" msgstr "sjanger" #: ../quodlibet/util/tags.py:97 msgid "genres" msgstr "sjangrer" #: ../quodlibet/util/tags.py:98 msgid "performer" msgstr "utøver" #: ../quodlibet/util/tags.py:98 msgid "performance" msgstr "fremføring" #: ../quodlibet/util/tags.py:99 msgid "grouping" msgstr "gruppering" #: ../quodlibet/util/tags.py:100 msgid "language" msgstr "språk" #: ../quodlibet/util/tags.py:101 msgid "license" msgstr "lisens" #: ../quodlibet/util/tags.py:102 msgid "location" msgstr "sted" #: ../quodlibet/util/tags.py:103 msgid "lyricist" msgstr "sangtekstforfatter" #: ../quodlibet/util/tags.py:103 msgid "lyricists" msgstr "sangtekstforfattere" #: ../quodlibet/util/tags.py:103 msgid "lyrics" msgstr "sangtekst" #. Translators: Also e.g. "record label", "publisher" #: ../quodlibet/util/tags.py:105 msgid "organization" msgstr "organisasjon" #: ../quodlibet/util/tags.py:106 msgid "title" msgstr "tittel" #: ../quodlibet/util/tags.py:107 msgid "version" msgstr "versjon" #: ../quodlibet/util/tags.py:108 msgid "website" msgstr "nettsted" #: ../quodlibet/util/tags.py:110 msgid "album artist" msgstr "albumartist" #: ../quodlibet/util/tags.py:111 msgid "BPM" msgstr "BPM" #. Translators: This used to be called "part". #: ../quodlibet/util/tags.py:114 ../quodlibet/util/tags.py:115 msgid "disc subtitle" msgstr "plate-undertittel" #: ../quodlibet/util/tags.py:116 ../quodlibet/util/tags.py:153 msgid "disc" msgstr "plate" #: ../quodlibet/util/tags.py:117 ../quodlibet/util/tags.py:155 msgid "track" msgstr "spor" #: ../quodlibet/util/tags.py:118 msgid "label ID" msgstr "platemerke-ID" #: ../quodlibet/util/tags.py:119 msgid "original release date" msgstr "opprinnelig utgivelsesdato" #: ../quodlibet/util/tags.py:120 msgid "original album" msgstr "opprinnelig album" #: ../quodlibet/util/tags.py:121 msgid "original artist" msgstr "opprinnelig artist" #: ../quodlibet/util/tags.py:122 msgid "recording date" msgstr "innspillingsdato" #: ../quodlibet/util/tags.py:123 msgid "release country" msgstr "utgivelsesland" #. 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:132 msgid "MusicBrainz recording ID" msgstr "MusicBrainz-innspillings-ID" #: ../quodlibet/util/tags.py:133 msgid "MusicBrainz release track ID" msgstr "MusicBrainz-utgivelsesspor-ID" #: ../quodlibet/util/tags.py:134 msgid "MusicBrainz release ID" msgstr "MusicBrainz-utgivelses-ID" #: ../quodlibet/util/tags.py:135 msgid "MusicBrainz artist ID" msgstr "MusicBrainz-artist-ID" #: ../quodlibet/util/tags.py:136 msgid "MusicBrainz release artist ID" msgstr "MusicBrainz-utgivelsesartist-ID" #: ../quodlibet/util/tags.py:137 msgid "MusicBrainz TRM ID" msgstr "MusicBrainz-TRM-ID" #: ../quodlibet/util/tags.py:138 msgid "MusicIP PUID" msgstr "MusicIP-PUID" #: ../quodlibet/util/tags.py:139 msgid "MusicBrainz album status" msgstr "MusicBrainz-albumstatus" #: ../quodlibet/util/tags.py:140 msgid "MusicBrainz album type" msgstr "MusicBrainz-albumtype" #: ../quodlibet/util/tags.py:141 msgid "MusicBrainz release group ID" msgstr "MusicBrainz-utgivelsesgruppe-ID" #. Translators: "gain" means a volume adjustment, not "to acquire". #: ../quodlibet/util/tags.py:144 msgid "track gain" msgstr "sporforsterkning" #: ../quodlibet/util/tags.py:145 msgid "track peak" msgstr "spor-maksverdi" #. Translators: "gain" means a volume adjustment, not "to acquire". #: ../quodlibet/util/tags.py:147 msgid "album gain" msgstr "albumforsterkning" #: ../quodlibet/util/tags.py:148 msgid "album peak" msgstr "album-maksverdi" #: ../quodlibet/util/tags.py:149 msgid "reference loudness" msgstr "referansenivå" #: ../quodlibet/util/tags.py:154 msgid "discs" msgstr "plater" #: ../quodlibet/util/tags.py:156 msgid "tracks" msgstr "spor" #: ../quodlibet/util/tags.py:157 msgid "last started" msgstr "sist startet" #: ../quodlibet/util/tags.py:158 msgid "full name" msgstr "fullt navn" #: ../quodlibet/util/tags.py:165 msgid "mount point" msgstr "monteringspunkt" #: ../quodlibet/util/tags.py:167 msgid "people" msgstr "personer" #: ../quodlibet/util/tags.py:169 msgid "year" msgstr "år" #: ../quodlibet/util/tags.py:170 msgid "original release year" msgstr "opprinnelig utgivelsesår" #: ../quodlibet/util/tags.py:171 msgid "bookmark" msgstr "bokmerke" #: ../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 "channel count" msgstr "antall kanaler" #. Translators: e.g. "artist (sort)" #: ../quodlibet/util/tags.py:268 msgid "sort" msgstr "sortering" #. Translators: e.g. "performer (roles)" #: ../quodlibet/util/tags.py:276 msgid "roles" msgstr "roller" #~ 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 "_Download…" #~ msgstr "Last ne_d …" #~ msgid "Download Files" #~ msgstr "Last ned filer" #~ msgid "Download File" #~ msgstr "Last ned fil" #~ 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 "_Edit" #~ msgstr "R_ediger" #~ 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 "Could not find '%s'." #~ msgstr "Fant ikke «%s»." #~ 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 _album covers" #~ msgstr "Kopier _albumomslag" #~ msgid "_Copy to Device" #~ msgstr "_Kopier til enhet" #~ msgid "Save" #~ msgstr "Lagre" #~ msgid "Remove all songs from the queue" #~ msgstr "Fjern alle låter fra kø" #~ 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 "Watch this folder for new songs" #~ msgstr "Se etter nye låter i denne mappa" #~ 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 "_Create Database" #~ msgstr "_Lag database" #~ msgid "_Volume Gain (dB):" #~ msgstr "_Volumforsterkning (dB):" #~ msgid "Combine tags with _multiple values" #~ msgstr "Kombiner tagger med _flere verdier" #~ msgid "Model:" #~ msgstr "Modell:" #~ msgid "Capacity:" #~ msgstr "Kapasitet:" #~ msgid "Firmware:" #~ msgstr "Fastvare:" #~ msgid "Removing orphaned iPod track" #~ msgstr "Fjerner foreldreløst iPod-spor" #~ 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 "Slett denne filen permanent?" #~ msgid "Permanently delete these files?" #~ msgstr "Slett 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 "" #~ "Klarte ikke å finne en nettleser. Angi $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 biblioteket ditt" #, 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 "_Select" #~ msgstr "_Velg" #~ 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..." #, fuzzy #~ msgid "Quod Libet" #~ msgstr "Avslutt Quod Libet" #~ 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 din GStreamer-kommandokø ved å endre " #~ "linjen 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 klarte ikke å finne GStreamer-elementet «filesrc». Kontroller " #~ "GStreamer-installasjonen din." �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9711857 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/po/nl.po����������������������������������������������������������������������������0000644�0001750�0001750�00000654757�00000000000�014115� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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: 2020-09-17 20:02+0200\n" "PO-Revision-Date: 2020-09-17 20:09+0200\n" "Last-Translator: Heimen Stoffels <vistausss@outlook.com>\n" "Language-Team: Nederlands <en@li.org>\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 2.4.1\n" #: quodlibet/browsers/albums/main.py:222 #: quodlibet/browsers/covergrid/main.py:54 msgid "_Title" msgstr "_Titel" #: quodlibet/browsers/albums/main.py:223 #: quodlibet/browsers/covergrid/main.py:55 quodlibet/qltk/prefs.py:49 msgid "_Artist" msgstr "_Artiest" #: quodlibet/browsers/albums/main.py:224 #: quodlibet/browsers/covergrid/main.py:56 quodlibet/qltk/prefs.py:54 msgid "_Date" msgstr "_Datum" #: quodlibet/browsers/albums/main.py:225 msgid "_Date Added" msgstr "Toevoegings_datum" #: quodlibet/browsers/albums/main.py:226 msgid "_Original Date" msgstr "_Oorspronkelijke datum" #: quodlibet/browsers/albums/main.py:227 #: quodlibet/browsers/covergrid/main.py:57 quodlibet/qltk/prefs.py:53 msgid "_Genre" msgstr "_Genre" #: quodlibet/browsers/albums/main.py:228 #: quodlibet/browsers/covergrid/main.py:58 quodlibet/qltk/prefs.py:58 #: quodlibet/qltk/ratingsmenu.py:39 msgid "_Rating" msgstr "Waa_rdering" #: quodlibet/browsers/albums/main.py:229 msgid "_Playcount" msgstr "Aantal keer afges_peeld" #: quodlibet/browsers/albums/main.py:235 #: quodlibet/browsers/covergrid/main.py:64 msgid "Sort _by…" msgstr "Sorteren o_p…" #: quodlibet/browsers/albums/main.py:256 #: quodlibet/browsers/covergrid/main.py:85 #: quodlibet/browsers/paned/prefs.py:203 #: quodlibet/browsers/playlists/main.py:674 quodlibet/qltk/exfalsowindow.py:108 #: quodlibet/qltk/pluginwin.py:341 quodlibet/qltk/quodlibetwindow.py:906 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:545 #: quodlibet/browsers/covergrid/main.py:285 #: quodlibet/browsers/covergrid/main.py:501 msgid "All Albums" msgstr "Alle albums" #: quodlibet/browsers/albums/main.py:546 #: quodlibet/browsers/covergrid/main.py:286 #: quodlibet/browsers/covergrid/main.py:502 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d album" msgstr[1] "%d albums" #: quodlibet/browsers/albums/main.py:727 #: quodlibet/browsers/covergrid/main.py:480 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:16 #: 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:385 quodlibet/util/collection.py:259 #, 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:383 quodlibet/util/collection.py:263 #, 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:124 #: quodlibet/ext/songsmenu/cover_download.py:243 msgid "Options" msgstr "Opties" #: quodlibet/browsers/albums/prefs.py:74 #: quodlibet/browsers/covergrid/prefs.py:127 msgid "Album Display" msgstr "Albumweergave" #: quodlibet/browsers/albums/prefs.py:78 #: quodlibet/browsers/covergrid/prefs.py:131 #: quodlibet/browsers/playlists/prefs.py:56 #: quodlibet/ext/songsmenu/albumart.py:330 #: quodlibet/ext/songsmenu/duplicates.py:345 #: quodlibet/ext/songsmenu/filterall.py:48 quodlibet/qltk/bookmarks.py:101 #: quodlibet/qltk/cbes.py:95 quodlibet/qltk/data_editors.py:96 #: quodlibet/qltk/data_editors.py:321 quodlibet/qltk/exfalsowindow.py:286 #: quodlibet/qltk/pluginwin.py:79 quodlibet/qltk/pluginwin.py:428 #: quodlibet/qltk/prefs.py:767 quodlibet/qltk/textedit.py:163 #: quodlibet/update.py:149 msgid "_Close" msgstr "_Sluiten" #: quodlibet/browsers/audiofeeds.py:52 quodlibet/browsers/audiofeeds.py:64 #: quodlibet/browsers/audiofeeds.py:66 quodlibet/browsers/audiofeeds.py:156 #: quodlibet/browsers/paned/models.py:88 #: quodlibet/ext/songsmenu/fingerprint/search.py:46 #: quodlibet/formats/_audio.py:501 quodlibet/order/__init__.py:29 #: quodlibet/qltk/information.py:244 quodlibet/qltk/information.py:251 #: quodlibet/qltk/information.py:277 quodlibet/qltk/wlw.py:69 msgid "Unknown" msgstr "Onbekend" #: quodlibet/browsers/audiofeeds.py:251 msgid "New Feed" msgstr "Nieuwe feed" #: quodlibet/browsers/audiofeeds.py:252 msgid "Enter the location of an audio feed:" msgstr "Voer de locatie van een audiofeed in:" #: quodlibet/browsers/audiofeeds.py:253 #: quodlibet/browsers/collection/prefs.py:89 quodlibet/browsers/iradio.py:360 #: quodlibet/browsers/paned/prefs.py:120 #: quodlibet/browsers/playlists/menu.py:96 #: quodlibet/browsers/playlists/util.py:52 quodlibet/qltk/bookmarks.py:62 #: quodlibet/qltk/cbes.py:57 quodlibet/qltk/data_editors.py:308 #: quodlibet/qltk/edittags.py:328 quodlibet/qltk/edittags.py:528 #: quodlibet/qltk/quodlibetwindow.py:1276 quodlibet/qltk/scanbox.py:61 msgid "_Add" msgstr "_Toevoegen" #: quodlibet/browsers/audiofeeds.py:307 msgid "Audio Feeds" msgstr "Audiofeeds" #: quodlibet/browsers/audiofeeds.py:308 msgid "_Audio Feeds" msgstr "_Audiofeeds" #: quodlibet/browsers/audiofeeds.py:411 quodlibet/qltk/data_editors.py:93 msgid "_New" msgstr "_Nieuw" #: quodlibet/browsers/audiofeeds.py:471 quodlibet/browsers/audiofeeds.py:530 msgid "Unable to add feed" msgstr "Kan feed niet toevoegen" #: quodlibet/browsers/audiofeeds.py:472 quodlibet/browsers/audiofeeds.py:531 #, python-format msgid "" "%s could not be added. The server may be down, or the location may not be an " "audio feed." msgstr "" "%s kan niet worden toegevoegd. Wellicht is de server tijdelijk niet " "beschikbaar of de locatie geen audiofeed." #: quodlibet/browsers/audiofeeds.py:479 quodlibet/qltk/filesel.py:260 #: quodlibet/qltk/pluginwin.py:414 msgid "_Refresh" msgstr "Ve_rversen" #: quodlibet/browsers/audiofeeds.py:480 #: quodlibet/browsers/playlists/main.py:494 #: quodlibet/browsers/playlists/util.py:43 quodlibet/qltk/delete.py:143 #: quodlibet/qltk/filesel.py:257 quodlibet/qltk/lyrics.py:35 #: quodlibet/qltk/maskedbox.py:28 quodlibet/qltk/songsmenu.py:364 msgid "_Delete" msgstr "Verwij_deren" #: quodlibet/browsers/audiofeeds.py:547 msgid "" "The current audio backend does not support URLs, Audio Feeds browser " "disabled." msgstr "" "Het huidige audiobackend ondersteunt geen url's - de audiofeedverkenner is " "uitgeschakeld." #: quodlibet/browsers/_base.py:147 quodlibet/browsers/_base.py:150 msgid "Library Browser" msgstr "Verzameling verkennen" #: quodlibet/browsers/_base.py:274 quodlibet/ext/songsmenu/console.py:45 #: quodlibet/ext/songsmenu/refresh.py:30 quodlibet/qltk/exfalsowindow.py:240 #: quodlibet/qltk/information.py:554 quodlibet/qltk/maskedbox.py:68 #: quodlibet/util/collection.py:542 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d nummer" msgstr[1] "%d nummers" #: quodlibet/browsers/_base.py:402 quodlibet/browsers/_base.py:407 #: quodlibet/qltk/tagsfrompath.py:193 quodlibet/qltk/textedit.py:140 #: quodlibet/util/__init__.py:575 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:23 #, python-format msgid "Unknown %s" msgstr "Onbekende %s" #: quodlibet/browsers/collection/models.py:24 #, 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" #. Remove button #: quodlibet/browsers/collection/prefs.py:93 #: quodlibet/browsers/paned/prefs.py:124 #: quodlibet/browsers/playlists/menu.py:97 #: quodlibet/ext/playlist/remove_duplicates.py:60 #: quodlibet/qltk/bookmarks.py:97 quodlibet/qltk/bookmarks.py:127 #: quodlibet/qltk/cbes.py:84 quodlibet/qltk/cbes.py:91 #: quodlibet/qltk/data_editors.py:78 quodlibet/qltk/data_editors.py:91 #: quodlibet/qltk/data_editors.py:298 quodlibet/qltk/data_editors.py:311 #: quodlibet/qltk/data_editors.py:319 quodlibet/qltk/edittags.py:534 #: quodlibet/qltk/edittags.py:711 quodlibet/qltk/maskedbox.py:48 #: quodlibet/qltk/maskedbox.py:88 quodlibet/qltk/queue.py:427 #: quodlibet/qltk/scanbox.py:36 quodlibet/qltk/scanbox.py:63 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:471 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:247 #: quodlibet/ext/songsmenu/editplaycount.py:45 #: quodlibet/ext/songsmenu/exact_rating.py:38 #: quodlibet/player/gstbe/prefs.py:40 quodlibet/qltk/prefs.py:127 #: quodlibet/qltk/textedit.py:64 msgid "_Apply" msgstr "Toep_assen" #: quodlibet/browsers/collection/prefs.py:197 #: quodlibet/browsers/paned/prefs.py:251 #: quodlibet/browsers/playlists/menu.py:95 #: quodlibet/browsers/playlists/util.py:42 quodlibet/errorreport/ui.py:103 #: quodlibet/ext/playlist/export_to_folder.py:38 #: 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:44 #: quodlibet/ext/songsmenu/fingerprint/search.py:281 #: quodlibet/ext/songsmenu/fingerprint/submit.py:90 #: quodlibet/ext/songsmenu/importexport.py:39 #: quodlibet/ext/songsmenu/lastfmsync.py:215 #: quodlibet/ext/songsmenu/playlist.py:50 #: quodlibet/ext/songsmenu/replaygain.py:354 #: 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:327 #: quodlibet/qltk/_editutils.py:41 quodlibet/qltk/getstring.py:28 #: quodlibet/qltk/maskedbox.py:27 quodlibet/qltk/msg.py:54 #: quodlibet/qltk/msg.py:93 quodlibet/qltk/msg.py:111 #: quodlibet/qltk/ratingsmenu.py:33 quodlibet/update.py:95 msgid "_Cancel" msgstr "Ann_uleren" #: quodlibet/browsers/covergrid/main.py:126 msgid "Cover Grid" msgstr "Hoesrooster" #: quodlibet/browsers/covergrid/main.py:127 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:71 msgid "Show \"All Albums\" Item" msgstr "Item 'Alle albums' tonen" #: quodlibet/browsers/covergrid/prefs.py:82 msgid "Wide Mode" msgstr "Brede modus" #: quodlibet/browsers/covergrid/prefs.py:114 #: quodlibet/browsers/covergrid/prefs.py:115 msgid "Cover Magnification" msgstr "Hoesvergroting" #: quodlibet/browsers/filesystem.py:39 msgid "File System" msgstr "Bestandssysteem" #: quodlibet/browsers/filesystem.py:40 msgid "_File System" msgstr "_Bestandssysteem" #: quodlibet/browsers/filesystem.py:124 quodlibet/qltk/songlist.py:258 msgid "Unable to copy songs" msgstr "Kan nummers niet kopiëren" #: quodlibet/browsers/filesystem.py:125 quodlibet/qltk/songlist.py:259 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:197 msgid "_Add to Library" msgstr "Toevoegen _aan verzameling" #: quodlibet/browsers/iradio.py:184 msgid "Unsupported file type" msgstr "Niet-ondersteund bestandstype" #: quodlibet/browsers/iradio.py:185 #, 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:246 quodlibet/browsers/iradio.py:831 #: quodlibet/browsers/iradio.py:843 msgid "Unable to add station" msgstr "Kan zender niet toevoegen" #: quodlibet/browsers/iradio.py:257 quodlibet/browsers/iradio.py:490 msgid "Internet Radio" msgstr "Online-radiostation" #: quodlibet/browsers/iradio.py:257 msgid "Downloading station list" msgstr "Bezig met ophalen van zenderlijst" #: quodlibet/browsers/iradio.py:358 msgid "New Station" msgstr "Nieuwe zender" #: quodlibet/browsers/iradio.py:359 msgid "Enter the location of an Internet radio station:" msgstr "Voer de locatie van een online-radiozender in:" #: quodlibet/browsers/iradio.py:377 msgid "Electronic" msgstr "Elektronisch" #: quodlibet/browsers/iradio.py:380 msgid "Hip Hop / Rap" msgstr "Hiphop/Rap" #: quodlibet/browsers/iradio.py:381 msgid "Oldies" msgstr "Gouwe ouwen" #: quodlibet/browsers/iradio.py:382 msgid "R&B" msgstr "R&B" #: quodlibet/browsers/iradio.py:383 msgid "Japanese" msgstr "Japans" #: quodlibet/browsers/iradio.py:384 msgid "Indian" msgstr "Indisch" #: quodlibet/browsers/iradio.py:386 msgid "Religious" msgstr "Religieus" #: quodlibet/browsers/iradio.py:388 msgid "Charts" msgstr "Hitlijsten" #: quodlibet/browsers/iradio.py:389 msgid "Turkish" msgstr "Turks" #: quodlibet/browsers/iradio.py:390 msgid "Reggae / Dancehall" msgstr "Reggae/Dancehall" #: quodlibet/browsers/iradio.py:391 msgid "Latin" msgstr "Latin" #: quodlibet/browsers/iradio.py:392 msgid "College Radio" msgstr "Studentenradio" #: quodlibet/browsers/iradio.py:393 msgid "Talk / News" msgstr "Praatprogramma's/Nieuws" #: quodlibet/browsers/iradio.py:394 msgid "Ambient" msgstr "Sfeervol" #: quodlibet/browsers/iradio.py:395 msgid "Jazz" msgstr "Jazz" #: quodlibet/browsers/iradio.py:396 quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "Klassiek" #: quodlibet/browsers/iradio.py:397 quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "Pop" #: quodlibet/browsers/iradio.py:398 msgid "Alternative" msgstr "Alternatief" #: quodlibet/browsers/iradio.py:399 msgid "Metal" msgstr "Metal" #: quodlibet/browsers/iradio.py:400 msgid "Country" msgstr "Country" #: quodlibet/browsers/iradio.py:401 msgid "News" msgstr "Nieuws" #: quodlibet/browsers/iradio.py:402 msgid "Schlager" msgstr "Schlager" #: quodlibet/browsers/iradio.py:403 msgid "Funk" msgstr "Funk" #: quodlibet/browsers/iradio.py:404 msgid "Indie" msgstr "Indie" #: quodlibet/browsers/iradio.py:405 msgid "Blues" msgstr "Blues" #: quodlibet/browsers/iradio.py:406 msgid "Soul" msgstr "Soul" #: quodlibet/browsers/iradio.py:407 msgid "Lounge" msgstr "Lounge" #: quodlibet/browsers/iradio.py:408 msgid "Punk" msgstr "Punk" #: quodlibet/browsers/iradio.py:409 msgid "Reggaeton" msgstr "Reggaeton" #: quodlibet/browsers/iradio.py:411 msgid "Slavic" msgstr "Slavisch" #: quodlibet/browsers/iradio.py:413 msgid "Greek" msgstr "Grieks" #: quodlibet/browsers/iradio.py:414 msgid "Gothic" msgstr "Gothic" #: quodlibet/browsers/iradio.py:415 quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "Rock" #: quodlibet/browsers/iradio.py:468 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:474 msgid "_Load Stations" msgstr "Zenders _bekijken" #: quodlibet/browsers/iradio.py:491 msgid "_Internet Radio" msgstr "Onl_ine-radiostation" #: quodlibet/browsers/iradio.py:564 msgid "_New Station…" msgstr "_Nieuwe zender…" #: quodlibet/browsers/iradio.py:567 msgid "_Update Stations" msgstr "_Zenders bijwerken" #: quodlibet/browsers/iradio.py:594 msgid "All Stations" msgstr "Alle zenders" #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:598 quodlibet/browsers/soundcloud/main.py:65 msgid "Favorites" msgstr "Favorieten" #: quodlibet/browsers/iradio.py:606 msgid "No Category" msgstr "Geen categorie" #: quodlibet/browsers/iradio.py:835 msgid "No stations found" msgstr "Geen zenders gevonden" #: quodlibet/browsers/iradio.py:836 #, python-format msgid "No Internet radio stations were found at %s." msgstr "Er zijn geen online-radiozenders gevonden op %s." #: quodlibet/browsers/iradio.py:844 msgid "All stations listed are already in your library." msgstr "Alle vermelde zenders staan al in je verzameling." #: quodlibet/browsers/iradio.py:861 msgid "Add to Favorites" msgstr "Toevoegen aan favorieten" #: quodlibet/browsers/iradio.py:865 msgid "Remove from Favorites" msgstr "Verwijderen uit favorieten" #: quodlibet/browsers/iradio.py:965 #, 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:106 quodlibet/qltk/pluginwin.py:122 #: quodlibet/qltk/pluginwin.py:164 msgid "All" msgstr "Alles" #: quodlibet/browsers/paned/prefs.py:41 #: quodlibet/ext/songsmenu/cover_download.py:118 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 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "<tt>%s</tt>" msgstr "" "Een tagpatroon met optionele opmaak, bijv. <tt>componist</tt> of\n" "<tt>%s</tt>" #: quodlibet/browsers/paned/prefs.py:231 msgid "Paned Browser Preferences" msgstr "Paneelverkennervoorkeuren" #: quodlibet/browsers/paned/prefs.py:236 msgid "Column layout" msgstr "Kolomindeling" #: quodlibet/browsers/paned/prefs.py:240 msgid "Column content" msgstr "Kolominhoud" #: quodlibet/browsers/paned/prefs.py:242 msgid "Equal pane width" msgstr "Vaste paneelbreedte" #: quodlibet/browsers/playlists/main.py:48 #: quodlibet/browsers/playlists/main.py:610 quodlibet/qltk/pluginwin.py:168 msgid "Playlists" msgstr "Afspeellijsten" #: quodlibet/browsers/playlists/main.py:49 msgid "_Playlists" msgstr "Afs_peellijsten" #: quodlibet/browsers/playlists/main.py:159 msgid "_Remove from Playlist" msgstr "Ve_rwijderen van afspeellijst" #: quodlibet/browsers/playlists/main.py:224 msgid "New" msgstr "Nieuw" #: quodlibet/browsers/playlists/main.py:228 msgid "Import" msgstr "Importeren" #: quodlibet/browsers/playlists/main.py:450 msgid "Unable to import playlist" msgstr "Kan afspeellijst niet importeren" #: quodlibet/browsers/playlists/main.py:451 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:501 msgid "_Rename" msgstr "_Naam wijzigen" #: quodlibet/browsers/playlists/main.py:599 msgid "Unable to rename playlist" msgstr "Kan afspeellijstnaam niet wijzigen" #: quodlibet/browsers/playlists/main.py:611 msgid "Import Playlist" msgstr "Afspeellijst importeren" #: quodlibet/browsers/playlists/main.py:611 msgid "_Import" msgstr "_Importeren" #: quodlibet/browsers/playlists/menu.py:25 msgid "_New Playlist…" msgstr "_Nieuwe afspeellijst…" #: quodlibet/browsers/playlists/menu.py:86 #, 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:90 #, 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:33 #, 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:35 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:50 #: quodlibet/browsers/playlists/util.py:125 quodlibet/util/collection.py:592 msgid "New Playlist" msgstr "Nieuwe afspeellijst" #: quodlibet/browsers/playlists/util.py:51 msgid "Enter a name for the new playlist:" msgstr "Geef de nieuwe afspeellijst een naam:" #: quodlibet/browsers/playlists/util.py:89 #, 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/tracks.py:32 msgid "_Limit Results" msgstr "Resu_ltaten beperken" #: quodlibet/browsers/tracks.py:37 msgid "_Allow multiple queries" msgstr "Meerdere w_aarden toestaan" #: quodlibet/browsers/tracks.py:51 quodlibet/qltk/information.py:468 msgid "Track List" msgstr "Nummerlijst" #: quodlibet/browsers/tracks.py:52 msgid "_Track List" msgstr "Nummerlijs_t" #: quodlibet/browsers/soundcloud/main.py:39 msgid "Soundcloud Browser" msgstr "Soundcloud-verkenner" #: quodlibet/browsers/soundcloud/main.py:40 msgid "Sound_cloud" msgstr "Sound_cloud" #: quodlibet/browsers/soundcloud/main.py:60 quodlibet/qltk/searchbar.py:81 msgid "Search" msgstr "Zoeken" #: quodlibet/browsers/soundcloud/main.py:69 msgid "My tracks" msgstr "Mijn nummers" #: quodlibet/browsers/soundcloud/main.py:141 #, python-format msgid "Go to %s" msgstr "Ga naar %s" #: quodlibet/browsers/soundcloud/main.py:443 msgid "Connected" msgstr "Verbonden" #: quodlibet/browsers/soundcloud/main.py:444 #, python-format msgid "Quod Libet is now connected, <b>%s</b>!" msgstr "Quod Libet is nu verbonden met <b>%s</b>!" #: quodlibet/browsers/soundcloud/main.py:456 #, python-format msgid "Log out of %s" msgstr "%s ontkoppelen" #: quodlibet/browsers/soundcloud/main.py:458 msgid "Enter code…" msgstr "Voer de code in…" #: quodlibet/browsers/soundcloud/main.py:459 #, python-format msgid "Log in to %s" msgstr "%s koppelen" #: quodlibet/browsers/soundcloud/util.py:86 msgid "Soundcloud authorisation" msgstr "Soundcloud-autorisatie" #: quodlibet/browsers/soundcloud/util.py:87 msgid "Enter Soundcloud auth code:" msgstr "Voer de Soundcloud-autorisatiecode in:" #: quodlibet/cli.py:50 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:86 msgid "a music library and player" msgstr "een muziekverzameling en -speler" #: quodlibet/cli.py:87 msgid "[option]" msgstr "[optie]" #: quodlibet/cli.py:89 msgid "Print the playing song and exit" msgstr "Toon het spelende nummer en sluit af" #: quodlibet/cli.py:90 msgid "Begin playing immediately" msgstr "Onmiddelijk beginnen met afspelen" #: quodlibet/cli.py:91 msgid "Don't show any windows on start" msgstr "Geminimaliseerd opstarten" #: quodlibet/cli.py:94 msgid "Jump to next song" msgstr "Ga naar volgend nummer" #: quodlibet/cli.py:96 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:97 msgid "Jump to previous song" msgstr "Ga naar vorig nummer" #: quodlibet/cli.py:98 msgid "Start playback" msgstr "Afspelen" #: quodlibet/cli.py:99 msgid "Pause playback" msgstr "Afspelen onderbreken" #: quodlibet/cli.py:100 msgid "Toggle play/pause mode" msgstr "Afspelen/Pauzeren aan/uit" #: quodlibet/cli.py:101 msgid "Stop playback" msgstr "Afspelen stoppen" #: quodlibet/cli.py:102 msgid "Turn up volume" msgstr "Volume verhogen" #: quodlibet/cli.py:103 msgid "Turn down volume" msgstr "Volume verlagen" #: quodlibet/cli.py:104 msgid "Increase rating of playing song by one star" msgstr "Waardering van spelend nummer verhogen met één ster" #: quodlibet/cli.py:105 msgid "Decrease rating of playing song by one star" msgstr "Waardering van spelend nummer verlagen met één ster" #: quodlibet/cli.py:106 msgid "Print player status" msgstr "Toon de spelerstatus" #: quodlibet/cli.py:107 msgid "Hide main window" msgstr "Hoofdvenster verbergen" #: quodlibet/cli.py:108 msgid "Show main window" msgstr "Hoofdvenster tonen" #: quodlibet/cli.py:109 msgid "Toggle main window visibility" msgstr "Hoofdvenster tonen/verbergen" #: quodlibet/cli.py:110 msgid "Focus the running player" msgstr "Actieve speler focussen" #: quodlibet/cli.py:111 msgid "Remove active browser filters" msgstr "Actieve verkennerfilters wissen" #: quodlibet/cli.py:112 msgid "Refresh and rescan library" msgstr "Verversen en verzameling opnieuw doorzoeken" #: quodlibet/cli.py:113 msgid "List available browsers" msgstr "Beschikbare verkenners tonen" #: quodlibet/cli.py:114 msgid "Print the current playlist" msgstr "Toon de huidige afspeellijst" #: quodlibet/cli.py:115 msgid "Print the contents of the queue" msgstr "Toon de inhoud van de wachtrij" #: quodlibet/cli.py:116 msgid "Print the active text query" msgstr "Toon de actieve tekstzoekopdracht" #: quodlibet/cli.py:117 msgid "Start without plugins" msgstr "Starten zonder plug-ins" #: quodlibet/cli.py:118 msgid "Start Quod Libet if it isn't running" msgstr "Start Quod Libet indien inactief" #: quodlibet/cli.py:119 msgid "Exit Quod Libet" msgstr "Sluit Quod Libet af" #: quodlibet/cli.py:124 msgid "Seek within the playing song" msgstr "Spelend nummer verderspoelen" #: quodlibet/cli.py:124 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][UU:]MM:SS" #: quodlibet/cli.py:125 msgid "Set or toggle shuffle mode" msgstr "Willekeurig aan/uit" #: quodlibet/cli.py:126 msgid "Set shuffle mode type" msgstr "Willekeurige modus instellen" #: quodlibet/cli.py:127 msgid "Turn repeat off, on, or toggle it" msgstr "Herhalen aan/uit" #: quodlibet/cli.py:128 msgid "Set repeat mode type" msgstr "Herhaalmodus instellen" #: quodlibet/cli.py:129 msgid "Set the volume" msgstr "Volume instellen" #: quodlibet/cli.py:130 msgid "Search your audio library" msgstr "Verzameling doorzoeken" #: quodlibet/cli.py:130 quodlibet/cli.py:140 quodlibet/cli.py:144 #: quodlibet/cli.py:146 msgid "query" msgstr "zoekopdracht" #: quodlibet/cli.py:131 msgid "Play a file" msgstr "Bestand afspelen" #: quodlibet/cli.py:131 quodlibet/cli.py:140 quodlibet/cli.py:146 msgctxt "command" msgid "filename" msgstr "bestandsnaam" #: quodlibet/cli.py:132 msgid "Set rating of playing song" msgstr "Spelende nummer waarderen" #: quodlibet/cli.py:133 msgid "Set the current browser" msgstr "Huidige verkenner instellen" #: quodlibet/cli.py:134 msgid "Stop after the playing song" msgstr "Stoppen na spelende nummer" #: quodlibet/cli.py:135 msgid "Open a new browser" msgstr "Nieuwe verkenner openen" #: quodlibet/cli.py:136 msgid "Show or hide the queue" msgstr "Wachtrij tonen/verbergen" #: quodlibet/cli.py:137 msgid "Filter on a random value" msgstr "Filteren op willekeurige waarde" #: quodlibet/cli.py:137 msgctxt "command" msgid "tag" msgstr "tag" #: quodlibet/cli.py:138 msgid "Filter on a tag value" msgstr "Filteren op tagwaarde" #: quodlibet/cli.py:138 msgid "tag=value" msgstr "tag=waarde" #: quodlibet/cli.py:139 msgid "Enqueue a file or query" msgstr "Bestand of zoekopdracht in wachtrij zetten" #: quodlibet/cli.py:141 msgid "Enqueue comma-separated files" msgstr "Plaats door komma's gescheiden bestanden in wachtrij" #: quodlibet/cli.py:142 quodlibet/util/tags.py:158 msgid "filename" msgstr "bestandsnaam" #: quodlibet/cli.py:143 msgid "Print filenames of results of query to stdout" msgstr "Stuur bestandsnamen van zoekresultaten naar stdout" #: quodlibet/cli.py:145 msgid "Unqueue a file or query" msgstr "Bestand of zoekopdracht uit wachtrij halen" #: quodlibet/cli.py:147 msgid "Add a file or directory to the library" msgstr "Bestand of map toevoegen aan verzameling" #: quodlibet/cli.py:148 quodlibet/util/tags.py:100 msgid "location" msgstr "locatie" #: quodlibet/cli.py:213 #, python-format msgid "Invalid argument for '%s'." msgstr "Ongeldig argument voor '%s'." #: quodlibet/cli.py:214 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:34 msgid "an audio tag editor" msgstr "een audiotagbewerker" #: quodlibet/exfalso.py:34 quodlibet/util/tags.py:159 msgid "directory" msgstr "map" #: quodlibet/exfalso.py:41 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:20 msgid "" "Downloads covers linked to by the artwork_url tag. This works with the " "Soundcloud browser." msgstr "" "Haalt albumhoezen op van de bij artwork_url-tag 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:20 msgid "MusicBrainz Cover Source" msgstr "MusicBrainz-albumhoesbron" #: quodlibet/ext/covers/musicbrainz.py:21 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:19 msgid "" "Allows arbitrary regex substitutions (s///) when tagging or renaming files." msgstr "" "Laat arbitraire regex-vervangingen toe (s///) 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:71 msgid "Advanced Preferences" msgstr "Geavanceerde voorkeuren" #: quodlibet/ext/events/advanced_preferences.py:72 msgid "Allow editing of advanced config settings." msgstr "Pas de geavanceerde configuratie-instellingen aan." #: quodlibet/ext/events/advanced_preferences.py:190 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/ext/events/weblyrics.py:318 quodlibet/qltk/prefs.py:266 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:66 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:172 msgid "Effects" msgstr "Effecten" #: quodlibet/ext/events/animosd/prefs.py:288 msgid "Ed_it Display Pattern…" msgstr "Weergavepa_troon aanpassen…" #: quodlibet/ext/events/animosd/prefs.py:292 #: 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_library_update.py:139 msgid "Automatic Library Update" msgstr "Verzameling automatisch bijwerken" #: quodlibet/ext/events/auto_library_update.py:140 #, python-format msgid "Keeps your library up to date with inotify. Requires %s." msgstr "Gebruik inotify om je verzameling actueel te houden. Vereist %s." #: 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 dan " "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 #, 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:570 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:123 #, python-format msgid "Error in %s" msgstr "Fout in %s" #: quodlibet/ext/events/auto_update_tags_in_files.py:188 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:222 msgid "_Update strategy:" msgstr "_Bijwerkmethode:" #: quodlibet/ext/events/auto_update_tags_in_files.py:236 #: quodlibet/ext/events/mpris/__init__.py:47 #: 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/qltk/prefs.py:744 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 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." #: quodlibet/ext/events/bansheeimport.py:106 msgid "Specified Banshee database is malformed or missing" msgstr "De opgegeven Banshee-databank is beschadigd of ontbreekt" #: quodlibet/ext/events/bansheeimport.py:111 #: quodlibet/ext/events/rbimport.py:114 msgid "Import Failed" msgstr "Importeren mislukt" #: quodlibet/ext/events/bansheeimport.py:117 #, 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:126 msgid "Banshee Import" msgstr "Importeren uit Banshee" #: quodlibet/ext/events/bansheeimport.py:127 msgid "Imports ratings and song statistics from Banshee." msgstr "Importeer waarderingen en nummerstatistieken uit Banshee." #: quodlibet/ext/events/bansheeimport.py:136 msgid "_Database path:" msgstr "_Databankpad:" #: quodlibet/ext/events/bansheeimport.py:164 #: quodlibet/ext/events/rbimport.py:132 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/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/playlist/export_to_squeezebox.py:80 #: quodlibet/ext/songsmenu/albumart.py:326 #: quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/cover_download.py:309 #: quodlibet/ext/songsmenu/fingerprint/search.py:278 #: quodlibet/ext/songsmenu/html.py:75 quodlibet/ext/songsmenu/lastfmsync.py:216 #: quodlibet/ext/songsmenu/playlist.py:51 #: quodlibet/ext/songsmenu/replaygain.py:355 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/_editutils.py:42 #: quodlibet/qltk/lyrics.py:34 quodlibet/qltk/msg.py:52 #: quodlibet/qltk/renamefiles.py:216 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:16 msgid "Internet Radio Log" msgstr "Online-radiologboek" #: quodlibet/ext/events/iradiolog.py:17 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:31 msgid "Outputs a Jabber User Tunes file to ~/.quodlibet/jabber." msgstr "Legt een Jabber User Tunes-bestand vast in ~/.quodlibet/jabber." #: 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 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:37 msgid "MPRIS D-Bus Support" msgstr "MPRIS D-Bus-ondersteuning" #: quodlibet/ext/events/mpris/__init__.py:38 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." #: quodlibet/ext/events/mpris/__init__.py:44 #: 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" msgstr "Broker-hostnaam" #: quodlibet/ext/events/mqtt.py:138 msgid "broker hostname / IP (defaults to localhost)" msgstr "broker-hostnaam/ip-adres (standaard: localhost)" #: quodlibet/ext/events/mqtt.py:140 msgid "Broker port" msgstr "Broker-poort" #: quodlibet/ext/events/mqtt.py:140 msgid "broker port (defaults to 1883)" msgstr "broker-poort (standaard: 1883)" #: quodlibet/ext/events/mqtt.py:142 msgid "Broker username" msgstr "Broker-gebruikersnaam" #: 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: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 statustekst 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:205 #, 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:209 #, 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:212 msgid "Connection error" msgstr "Verbindingsfout" #: 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/qlscrobbler.py:176 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" "Stel QLScrobbler in in het plug-insvenster. Tot dan worden nummers niet " "ingediend." #: quodlibet/ext/events/qlscrobbler.py:253 #, python-format msgid "Could not contact service '%s'." msgstr "Kan niet verbinden met de dienst '%s'." #: quodlibet/ext/events/qlscrobbler.py:259 msgid "Authentication failed: invalid URL." msgstr "Authenticatie mislukt: ongeldige url." #: quodlibet/ext/events/qlscrobbler.py:276 #, 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:281 msgid "Client is banned. Contact the author." msgstr "De client is verbannen. Neem contact op met de maker." #: quodlibet/ext/events/qlscrobbler.py:285 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:350 msgid "AudioScrobbler Submission" msgstr "AudioScrobbler-indiening" #: quodlibet/ext/events/qlscrobbler.py:351 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:456 msgid "Authentication successful." msgstr "Authenticatie gelukt." #: quodlibet/ext/events/qlscrobbler.py:468 msgid "_Service:" msgstr "Dien_st:" #: quodlibet/ext/events/qlscrobbler.py:468 msgid "_URL:" msgstr "_URL:" #: quodlibet/ext/events/qlscrobbler.py:468 msgid "User_name:" msgstr "Gebruikers_naam:" #: quodlibet/ext/events/qlscrobbler.py:469 msgid "_Password:" msgstr "_Wachtwoord:" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:485 msgid "Other…" msgstr "Overige…" #. verify data #: quodlibet/ext/events/qlscrobbler.py:523 msgid "_Verify account data" msgstr "Accountgegevens _verifiëren" #: quodlibet/ext/events/qlscrobbler.py:528 #: quodlibet/ext/songsmenu/lastfmsync.py:309 msgid "Account" msgstr "Account" #: quodlibet/ext/events/qlscrobbler.py:536 msgid "_Artist pattern:" msgstr "_Artiestpatroon:" #: quodlibet/ext/events/qlscrobbler.py:536 msgid "_Title pattern:" msgstr "_Titelpatroon:" #: quodlibet/ext/events/qlscrobbler.py:537 msgid "Exclude _filter:" msgstr "Uitsluit_filter:" #: quodlibet/ext/events/qlscrobbler.py:555 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:565 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:574 msgid "Songs matching this filter will not be submitted" msgstr "Nummers die overeenkomen met dit filter worden niet ingediend" #: quodlibet/ext/events/qlscrobbler.py:582 msgid "_Offline mode (don't submit anything)" msgstr "_Offline-modus (niets indienen)" #: quodlibet/ext/events/qlscrobbler.py:586 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:119 #, 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:127 msgid "Rhythmbox Import" msgstr "Rhythmbox-import" #: quodlibet/ext/events/rbimport.py:128 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:73 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:79 msgid "GNOME Search Provider" msgstr "GNOME-zoekmachine" #: quodlibet/ext/events/searchprovider.py:80 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" "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" "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:29 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:57 #: quodlibet/ext/playlist/export_to_squeezebox.py:89 msgid "Error finding Squeezebox server" msgstr "Fout bij zoeken naar Squeezebox-server" #: quodlibet/ext/events/squeezebox_sync.py:58 #: quodlibet/ext/playlist/export_to_squeezebox.py:90 #, python-format msgid "Error finding %s. Please check settings" msgstr "Fout bij zoeken naar %s. Controleer de instellingen." #: quodlibet/ext/events/synchronizedlyrics.py:34 msgid "Synchronized Lyrics" msgstr "Gesynchroniseerde songteksten" #: quodlibet/ext/events/synchronizedlyrics.py:35 msgid "Shows synchronized lyrics from .lrc file with same name as the track." msgstr "" "Toont gesynchroniseerde songteksten uit .lrc-bestanden met dezelfde naam als " "de nummers." #: quodlibet/ext/events/synchronizedlyrics.py:69 msgid "Text:" msgstr "Tekst:" #: quodlibet/ext/events/synchronizedlyrics.py:79 msgid "Background:" msgstr "Achtergrond:" #: quodlibet/ext/events/synchronizedlyrics.py:90 msgid "Font" msgstr "Lettertype" #: quodlibet/ext/events/synchronizedlyrics.py:93 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:145 msgid "Paused:" msgstr "Gepauzeerd:" #: quodlibet/ext/events/telepathy_status.py:146 #, 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:162 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:163 msgid "No song:" msgstr "Geen nummer:" #. Frame #: quodlibet/ext/events/telepathy_status.py:170 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:91 msgid "Thumb Rating" msgstr "Waarderen met duimpjes" #: quodlibet/ext/events/thumbrating.py:92 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 '~#score'." msgstr "" "Biedt een waardeersysteem met duimpjes toe (duimpje omhoog/omlaag), wat " "wordt omgezet naar een waardeerwaarde. Dit is handig voor totalen en " "sorteren op '~#score'." #: 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:47 msgid "Not playing" msgstr "Speelt niet" #: quodlibet/ext/events/trayicon/__init__.py:53 msgid "Tray Icon" msgstr "Systeemvakpictogram" #: quodlibet/ext/events/trayicon/__init__.py:54 msgid "Controls Quod Libet from the system tray." msgstr "Bedien Quod Libet vanuit het systeemvak." #: quodlibet/ext/events/trayicon/menu.py:42 #, python-format msgid "_Show %(application-name)s" msgstr "%(application-name)s _tonen" #: quodlibet/ext/events/trayicon/menu.py:61 #: quodlibet/qltk/quodlibetwindow.py:183 quodlibet/qltk/quodlibetwindow.py:936 #: quodlibet/qltk/quodlibetwindow.py:1142 msgid "_Play" msgstr "Afs_pelen" #: quodlibet/ext/events/trayicon/menu.py:64 #: quodlibet/qltk/quodlibetwindow.py:185 quodlibet/qltk/quodlibetwindow.py:1144 #: quodlibet/qltk/wlw.py:50 msgid "P_ause" msgstr "P_auzeren" #: quodlibet/ext/events/trayicon/menu.py:69 #: quodlibet/qltk/quodlibetwindow.py:190 quodlibet/qltk/quodlibetwindow.py:931 msgid "Pre_vious" msgstr "_Vorige" #: quodlibet/ext/events/trayicon/menu.py:72 #: quodlibet/qltk/quodlibetwindow.py:194 quodlibet/qltk/quodlibetwindow.py:941 msgid "_Next" msgstr "Volge_nde" #: quodlibet/ext/events/trayicon/menu.py:77 msgid "_Shuffle" msgstr "_Willekeurig" #: quodlibet/ext/events/trayicon/menu.py:82 msgid "_Repeat" msgstr "He_rhalen" #: quodlibet/ext/events/trayicon/menu.py:87 msgid "Stop _After This Song" msgstr "Stoppen n_a dit nummer" #: quodlibet/ext/events/trayicon/menu.py:93 #: quodlibet/qltk/quodlibetwindow.py:902 msgid "Open _Browser" msgstr "_Verkenner openen" #: quodlibet/ext/events/trayicon/menu.py:104 #: quodlibet/qltk/quodlibetwindow.py:921 quodlibet/qltk/songsmenu.py:383 msgid "Edit _Tags" msgstr "_Tags bewerken" #: quodlibet/ext/events/trayicon/menu.py:113 #: quodlibet/qltk/quodlibetwindow.py:864 quodlibet/qltk/songsmenu.py:396 msgid "_Information" msgstr "_Informatie" #: quodlibet/ext/events/trayicon/menu.py:115 quodlibet/qltk/songsmenu.py:324 msgid "Play_lists" msgstr "Afspeel_lijsten" #: quodlibet/ext/events/trayicon/menu.py:133 #: quodlibet/qltk/quodlibetwindow.py:916 msgid "_Quit" msgstr "_Afsluiten" #: quodlibet/ext/events/trayicon/prefs.py:38 quodlibet/qltk/prefs.py:69 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 quodlibet/ext/events/weblyrics.py:193 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:606 msgid "Waveform Seek Bar" msgstr "Golvende spoelbalk" #: quodlibet/ext/events/waveformseekbar.py:610 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:679 msgid "Override foreground color:" msgstr "Andere voorgrondkleur:" #: quodlibet/ext/events/waveformseekbar.py:683 msgid "Override hover color:" msgstr "Andere zweefkleur:" #: quodlibet/ext/events/waveformseekbar.py:687 msgid "Override remaining color:" msgstr "Andere resterende kleur:" #: quodlibet/ext/events/waveformseekbar.py:691 msgid "Show current position" msgstr "Huidige positie tonen" #: quodlibet/ext/events/waveformseekbar.py:696 msgid "Show time labels" msgstr "Tijdstempels tonen" #: quodlibet/ext/events/waveformseekbar.py:704 msgid "Seek amount when scrolling (milliseconds):" msgstr "Spoellengte bij scrollen (in milliseconden):" #: quodlibet/ext/events/weblyrics.py:208 msgid "No lyrics found" msgstr "Geen songteksten gevonden" #: quodlibet/ext/events/weblyrics.py:268 msgid "_Zoom level:" msgstr "_Zoomniveau:" #: quodlibet/ext/events/weblyrics.py:286 msgid "URL:" msgstr "URL:" #: quodlibet/ext/events/weblyrics.py:291 msgid "Revert to default" msgstr "Standaardwaarden" #: quodlibet/ext/events/weblyrics.py:306 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." #: quodlibet/ext/events/weblyrics.py:323 msgid "Alternate search" msgstr "Alternatieve zoekopdracht" #: quodlibet/ext/events/weblyrics.py:332 msgid "Web Lyrics" msgstr "Online-songteksten" #: quodlibet/ext/events/weblyrics.py:333 msgid "Shows a sidebar containing online lyrics of the playing song." msgstr "Toont een zijbalk met de songtekst van het huidige nummer." #: 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 #, 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:147 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:100 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:121 #: quodlibet/ext/songsmenu/playlist.py:132 msgid "Unable to export playlist" msgstr "Kan afspeellijst niet exporteren" #: quodlibet/ext/playlist/export_to_folder.py:122 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:165 msgid "Default filename pattern:" msgstr "Standaard bestandsnaampatroon:" #: 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. 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>." #: 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:96 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 "" "Playback 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/playcounteq.py:21 msgid "Playcount Equalizer" msgstr "Afspeeltelling-equalizer" #: quodlibet/ext/playorder/playcounteq.py:22 msgid "Shuffle, preferring songs with fewer total plays." msgstr "" "Speel willekeurig af met voorkeur voor minder vaak afgespeelde nummers." #: quodlibet/ext/playorder/playcounteq.py:24 msgid "Prefer less played" msgstr "Voorkeur voor minder vaak" #: quodlibet/ext/playorder/queue.py:19 msgid "Queue Only" msgstr "Alleen wachtrij" #: quodlibet/ext/playorder/queue.py:21 msgid "" "Limits playing of songs to the queue. 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. Selecteer de afspeelvolgorde in " "het hoofdvenster en dubbelklik op een nummer om het in de wachtrij te " "plaatsen." #: quodlibet/ext/playorder/reverse.py:14 msgid "Reverse" msgstr "Omkeren" #: quodlibet/ext/playorder/reverse.py:16 msgid "Reverses the play order of songs." msgstr "Keert de afspeelvolgorde van de nummers om." #: quodlibet/ext/playorder/shufflebygrouping.py:31 #: quodlibet/ext/playorder/shufflebygrouping.py:93 msgid "Shuffle by Grouping" msgstr "Willekeurige groepen afspelen" #: quodlibet/ext/playorder/shufflebygrouping.py:32 msgid "" "Shuffles by a grouping of songs defined by a common tag instead of by track, " "similar to album shuffle. This is useful for shuffling multi-movement " "classical works while 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. Hiermee " "kun je bijv. heel handig klassieke werken in de juiste volgorde afspelen." #: quodlibet/ext/playorder/shufflebygrouping.py:38 msgid "Shuffle by grouping" msgstr "Willekeurige groepen afspelen" #: quodlibet/ext/playorder/shufflebygrouping.py:94 msgid "Waiting to start new group…" msgstr "Bezig met wachten op nieuwe groep…" #: quodlibet/ext/playorder/shufflebygrouping.py:144 msgid "Grouping tag:" msgstr "Groepstag:" #: quodlibet/ext/playorder/shufflebygrouping.py:148 msgid "Tag to group songs by" msgstr "Tag om nummers op te groeperen" #: quodlibet/ext/playorder/shufflebygrouping.py:150 msgid "Filter tag:" msgstr "Filtertag:" #: quodlibet/ext/playorder/shufflebygrouping.py:155 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:160 msgid "Delay:" msgstr "Vertraging:" #: quodlibet/ext/playorder/shufflebygrouping.py:166 msgid "Time delay in seconds before starting next group" msgstr "Het aantal seconden voor de volgende groep wordt afgespeeld" #: quodlibet/ext/playorder/shufflebygrouping.py:182 msgid "Reset to defaults" msgstr "Standaardwaarden herstellen" #: quodlibet/ext/playorder/skip_songs.py:25 msgid "Skip Songs" msgstr "Nummers overslaan" #: quodlibet/ext/playorder/skip_songs.py:27 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." #: quodlibet/ext/playorder/track_repeat.py:30 msgid "Repeat Each Track" msgstr "Elk nummer herhalen" #: quodlibet/ext/playorder/track_repeat.py:32 msgid "Shuffle songs, but repeat 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:51 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. Syntax is '@(if: " "condition, then, else)'." msgstr "" "Bepaal de voorwaarden waarop een overeenkomst dient plaats te vinden. De " "syntaxis is '@(if: condition, then, else)'." #: quodlibet/ext/query/missing.py:15 msgid "Missing Query" msgstr "Ontbrekende opdracht" #: quodlibet/ext/query/missing.py:16 msgid "Matches songs without the given tag." msgstr "Laat nummers met de opgegeven tag overeenkomen." #: quodlibet/ext/query/missing.py:27 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. Syntax is '@(python: expression)'. The " "variable 's' (or 'a') is the song / album being matched. '_ts' is a (real " "number) timestamp at start of query. Modules 'time' and 'random' are also " "available, and the class 'Random' (==random.Random) too." msgstr "" "Gebruik Python-uitdrukkingen in zoekopdrachten. De syntaxis is '@(python: " "uitdrukking)'. De variabel 's' (of 'a') is het nummer/album dat overeen " "dient te komen. '_ts' is het tijdstempel (bestaand getal) aan het begin van " "een zoekopdracht. Verder zijn de modules 'time' en 'random' beschikbaar, " "evenals de klasse 'Random' (==random.Random)." #: quodlibet/ext/query/savedsearch.py:19 msgid "Include Saved Search" msgstr "Opgeslagen zoekopdracht opnemen" #: quodlibet/ext/query/savedsearch.py:20 msgid "" "Include the results of a saved search as part of another query. Syntax is " "'@(saved: search name)'." msgstr "" "Toon ook de resultaten van een opgeslagen zoekopdracht als onderdeel van de " "zoekopdracht. De syntaxis is '@(saved: search name)'." #: 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 "Verzamelingspad:" #. 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:20 #: quodlibet/ext/songsmenu/importexport.py:38 quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "_Oké" #: 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:333 msgid "Fit image to _window" msgstr "Afbeelding inpassen in _venster" #: quodlibet/ext/songsmenu/albumart.py:339 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:345 msgid "_Program:" msgstr "_Programma:" #: quodlibet/ext/songsmenu/albumart.py:350 msgid "_Edit image after saving" msgstr "Afbeelding b_ewerken na opslaan" #: quodlibet/ext/songsmenu/albumart.py:352 msgid "File_name:" msgstr "Bestands_naam:" #: quodlibet/ext/songsmenu/albumart.py:468 msgid "Saving failed" msgstr "Opslaan mislukt" #: quodlibet/ext/songsmenu/albumart.py:469 #, python-format msgid "Unable to save \"%s\"." msgstr "Kan \"%s\" niet opslaan." #: quodlibet/ext/songsmenu/albumart.py:567 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "[albumart] HTTP-fout: %s" #: quodlibet/ext/songsmenu/albumart.py:624 msgid "Album Art Downloader" msgstr "Albumhoezen ophalen" #: quodlibet/ext/songsmenu/albumart.py:677 #, python-format msgid "from %(source)s" msgstr "van %(source)s" #: quodlibet/ext/songsmenu/albumart.py:680 #, python-format msgid "Resolution: %s" msgstr "Resolutie: %s" #: quodlibet/ext/songsmenu/albumart.py:683 #, python-format msgid "Size: %s" msgstr "Grootte: %s" #: quodlibet/ext/songsmenu/albumart.py:729 msgid "Per engine 'at best' results limit" msgstr "Resultaatlimiet van maximale afmetingen" #: quodlibet/ext/songsmenu/albumart.py:739 msgid "_Search" msgstr "_Zoeken" #: quodlibet/ext/songsmenu/albumart.py:821 #: quodlibet/ext/songsmenu/brainz/widgets.py:451 msgid "Searching…" msgstr "Bezig met zoeken…" #: quodlibet/ext/songsmenu/albumart.py:886 #: quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "Klaar" #: quodlibet/ext/songsmenu/albumart.py:1008 msgid "Download Album Art" msgstr "Albumhoes ophalen" #: quodlibet/ext/songsmenu/albumart.py:1009 msgid "Downloads album covers from various websites." msgstr "Haalt albumhoezen op van verscheidene websites." #: quodlibet/ext/songsmenu/albumart.py:1022 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 msgid "Disc" msgstr "Schijf" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 #: quodlibet/ext/songsmenu/replaygain.py:394 quodlibet/qltk/tracknumbers.py:91 msgid "Track" msgstr "Nummer" #: quodlibet/ext/songsmenu/brainz/widgets.py:132 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:447 msgid "Please enter a query." msgstr "Voer een zoekopdracht in." #: quodlibet/ext/songsmenu/brainz/widgets.py:465 #: quodlibet/ext/songsmenu/brainz/widgets.py:496 msgid "Error encountered. Please retry." msgstr "Er is een fout opgetreden. Probeer het opnieuw." #: quodlibet/ext/songsmenu/brainz/widgets.py:472 #: quodlibet/ext/songsmenu/brainz/widgets.py:488 msgid "Loading result…" msgstr "Bezig met laden van resultaten…" #: quodlibet/ext/songsmenu/brainz/widgets.py:475 msgid "No results found." msgstr "Geen resultaten gevonden." #: quodlibet/ext/songsmenu/console.py:40 msgid "Python Console" msgstr "Python-opdrachtregel" #: quodlibet/ext/songsmenu/console.py:41 msgid "Interactive Python console. Opens a new window." msgstr "Opent de interactieve Python-opdrachtregel in een nieuw venster." #: quodlibet/ext/songsmenu/console.py:48 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "{plugin_name} voor {songs} ({app})" #: quodlibet/ext/songsmenu/console.py:55 msgid "Python Console Sidebar" msgstr "Python-opdrachtregel in zijbalk" #: quodlibet/ext/songsmenu/console.py:56 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:75 msgid "You can access the following objects by default:" msgstr "Je hebt standaard toegang tot de volgende objecten:" #: quodlibet/ext/songsmenu/console.py:85 msgid "Your current working directory is:" msgstr "Je huidige werkmap is:" #: quodlibet/ext/songsmenu/cover_download.py:119 msgid "Classic" msgstr "Traditioneel" #: quodlibet/ext/songsmenu/cover_download.py:120 msgid "Large" msgstr "Groot" #: quodlibet/ext/songsmenu/cover_download.py:121 msgid "HD" msgstr "HD" #: quodlibet/ext/songsmenu/cover_download.py:122 msgid "Full HD" msgstr "Full HD" #: quodlibet/ext/songsmenu/cover_download.py:123 msgid "WQXGA" msgstr "WQXGA" #: quodlibet/ext/songsmenu/cover_download.py:124 msgid "4K UHD" msgstr "4K UHD" #: quodlibet/ext/songsmenu/cover_download.py:129 msgid "Cover Art Download" msgstr "Albumhoezen ophalen" #: quodlibet/ext/songsmenu/cover_download.py:180 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "Bezig met laden van %(source)s - %(dimensions)s…" #: quodlibet/ext/songsmenu/cover_download.py:231 #, python-format msgid "" "Nothing found for albums:\n" "<i>%(albums)s</i>.\n" "\n" "Providers used:\n" "<tt>%(providers)s</tt>" msgstr "" "Niks gevonden voor:\n" "<i>%(albums)s</i>.\n" "\n" "Gebruikte diensten:\n" "<tt>%(providers)s</tt>" #: quodlibet/ext/songsmenu/cover_download.py:234 msgid "No covers found" msgstr "Geen hoezen gevonden" #: quodlibet/ext/songsmenu/cover_download.py:254 #, python-format msgid "%(size)d ✕ %(size)d px" msgstr "%(size)d ✕ %(size)d px" #: quodlibet/ext/songsmenu/cover_download.py:267 msgid "Preview size" msgstr "Voorvertoningsgrootte" #: quodlibet/ext/songsmenu/cover_download.py:276 msgid "Save destination" msgstr "Opslagmap" #: quodlibet/ext/songsmenu/cover_download.py:336 msgid "Download Cover Art" msgstr "Albumhoezen ophalen" #: quodlibet/ext/songsmenu/cover_download.py:337 msgid "Downloads high-quality album covers using cover plugins." msgstr "Haalt hoogwaardige albumhoezen op middels hoesplug-ins." #: 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, bijv. " "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:55 msgid "pattern" msgstr "patroon" #: 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:91 msgid "Input value" msgstr "Invoerwaarde" #: quodlibet/ext/songsmenu/custom_commands.py:92 #, python-format msgid "Value for %s?" msgstr "Waarde van %s?" #: quodlibet/ext/songsmenu/custom_commands.py:137 msgid "Custom Commands" msgstr "Aangepaste opdrachten" #: quodlibet/ext/songsmenu/custom_commands.py:138 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:197 #: quodlibet/ext/songsmenu/custom_commands.py:207 #: quodlibet/ext/songsmenu/custom_commands.py:259 msgid "Edit Custom Commands" msgstr "Aangepaste opdrachten bewerken" #: quodlibet/ext/songsmenu/custom_commands.py:290 #, 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:41 msgid "Edit Playcount" msgstr "Afspeeltelling bewerken" #: quodlibet/ext/songsmenu/editplaycount.py:20 msgid "" "Edit a song's ~#playcount and ~#skipcount.\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's ~#playcount to 0, the ~#lastplayed and ~#laststarted " "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 ~#playcount en ~#skipcount van een nummer.\n" "\n" "Indien meerdere nummers geselecteerd zijn, zullen de tellers verhoogd worden " "i.p.v. ingesteld.\n" "\n" "Indien de ~#playcount van een nummer op 0 wordt gezet, zullen de " "~#lastplayed- ~#laststarted-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:68 msgid "Play Count" msgstr "Aantal keer afgespeeld" #: quodlibet/ext/songsmenu/editplaycount.py:69 msgid "Skip Count" msgstr "Aantal keer overgeslagen" #: quodlibet/ext/songsmenu/embedded.py:25 msgid "Edit Embedded Images" msgstr "Bijgevoegde afbeeldingen bewerken" #: quodlibet/ext/songsmenu/embedded.py:26 msgid "Removes or replaces embedded images." msgstr "Verwijdert of vervangt bijgevoegde afbeeldingen." #: quodlibet/ext/songsmenu/embedded.py:80 msgid "_Remove all Images" msgstr "Alle afbeeldingen ve_rwijderen" #: quodlibet/ext/songsmenu/embedded.py:85 msgid "_Embed Current Image" msgstr "Huidige afbeeldingen bijvo_egen" #: 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/exact_rating.py:54 quodlibet/qltk/ratingsmenu.py:98 msgid "Change _Rating" msgstr "Waa_rdering veranderen" #: 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 "" "Je dient een acoustid.org api-sleutel op te geven in de plug-invoorkeuren " "voordat je vingerafdrukken kunt indienen." #: 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" #: quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" msgstr "Status" #. 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:65 quodlibet/ext/songsmenu/html.py:75 msgid "Export to HTML" msgstr "Exporteren naar html" #: quodlibet/ext/songsmenu/html.py:66 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:62 msgid "Error uploading" msgstr "Fout tijdens uploaden" #: quodlibet/ext/songsmenu/ifp.py:63 #, python-format msgid "" "Unable to upload <b>%s</b>. 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/importexport.py:59 msgid "Export Metadata" msgstr "Metagegevens exporteren" #: quodlibet/ext/songsmenu/importexport.py:60 msgid "Exports metadata of selected songs as a .tags file." msgstr "" "Exporteer metagegevens van geselecteerde nummers naar een .tags-bestand." #: quodlibet/ext/songsmenu/importexport.py:104 msgid "Import Metadata" msgstr "Metagegevens importeren" #: quodlibet/ext/songsmenu/importexport.py:105 msgid "Imports metadata for selected songs from a .tags file." msgstr "" "Importeer metagegevens van geselecteerde nummers uit een .tags-bestand." #: quodlibet/ext/songsmenu/k3b.py:23 msgid "Burn CD" msgstr "CD branden" #: quodlibet/ext/songsmenu/k3b.py:24 msgid "Burns CDs with K3b, Brasero or xfburn." msgstr "Brand cd's met K3b, Brasero of xfburn." #: quodlibet/ext/songsmenu/lastfmsync.py:94 msgid "Updating chart list." msgstr "De hitlijsten worden bijgewerkt." #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:113 msgid "Already up-to-date." msgstr "Reeds actueel." #: quodlibet/ext/songsmenu/lastfmsync.py:121 #, python-format msgid "Fetching chart for week of %s." msgstr "De hitlijst van week van %s wordt opgehaald." #: quodlibet/ext/songsmenu/lastfmsync.py:143 msgid "Sync complete." msgstr "Synchronisatie voltooid." #: quodlibet/ext/songsmenu/lastfmsync.py:149 msgid "Error during sync" msgstr "Fout tijdens synchronisatie" #: quodlibet/ext/songsmenu/lastfmsync.py:214 #: quodlibet/ext/songsmenu/lastfmsync.py:244 msgid "Last.fm Sync" msgstr "Last.fm-synchronisatie" #: quodlibet/ext/songsmenu/lastfmsync.py:245 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:298 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." #. Create a dialog. #: quodlibet/ext/songsmenu/migratemetadata.py:37 #: quodlibet/ext/songsmenu/migratemetadata.py:46 msgid "Migrate Metadata" msgstr "Metagegevens exporteren" #: quodlibet/ext/songsmenu/migratemetadata.py:40 msgid "Copies the quodlibet-specific metadata between songs." msgstr "Synchroniseert de Quod Libet-specifieke metagegevens tussen nummers." #: quodlibet/ext/songsmenu/migratemetadata.py:53 msgid "_Copy" msgstr "_Kopiëren" #: quodlibet/ext/songsmenu/migratemetadata.py:55 msgid "_Paste" msgstr "_Plakken" #. Create the tag table. #: quodlibet/ext/songsmenu/migratemetadata.py:65 msgid "Information to copy/paste" msgstr "De te kopiëren/plakken informatie" #. Create the indexing box. #: quodlibet/ext/songsmenu/migratemetadata.py:87 msgid "Map tracks by disc and track number" msgstr "Schijf- en volgnummer toekennen aan nummers" #: quodlibet/ext/songsmenu/migratemetadata.py:88 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." #: quodlibet/ext/songsmenu/migratemetadata.py:104 #, python-format 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." #: quodlibet/ext/songsmenu/playlist.py:31 msgid "Export as Playlist" msgstr "Exporteren als afspeellijst" #: quodlibet/ext/songsmenu/playlist.py:32 msgid "Exports songs to an M3U or PLS playlist." msgstr "Exporteer nummers naar een m3u- of pls-afspeellijst." #: quodlibet/ext/songsmenu/playlist.py:77 msgid "Use relative paths" msgstr "Relatieve paden gebruiken" #: quodlibet/ext/songsmenu/playlist.py:77 msgid "Use absolute paths" msgstr "Absolute paden gebruiken" #: quodlibet/ext/songsmenu/playlist.py:133 #, python-format msgid "Writing to <b>%s</b> 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:352 msgid "ReplayGain Analyzer" msgstr "ReplayGain-analyse" #: 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 #, python-format msgid "There is <b>%(to-process)s</b> album to update (of %(all)s)" msgid_plural "There are <b>%(to-process)s</b> 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:570 msgid "" "Analyzes and updates ReplayGain information, using GStreamer. Results are " "grouped by album." msgstr "" "Analyseert en werkt ReplayGain-informatie bij met GStreamer. De resultaten " "worden gegroepeerd per album." #: quodlibet/ext/songsmenu/replaygain.py:608 msgid "always" msgstr "altijd" #: quodlibet/ext/songsmenu/replaygain.py:609 msgid "if <b>any</b> RG tags are missing" msgstr "indien er RG-tags ontbreken" #: quodlibet/ext/songsmenu/replaygain.py:611 msgid "if <b>album</b> RG tags are missing" msgstr "indien album-RG-tags ontbreken" #: quodlibet/ext/songsmenu/replaygain.py:628 msgid "_Process albums:" msgstr "Te verwerken al_bums:" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:640 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:37 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern-example)s." msgstr "" "Doorzoekt de door jou opgegeven website aan de hand van eender welke " "nummertags.\n" "Ondersteunt patronen als %(pattern-example)s." #: quodlibet/ext/songsmenu/website_search.py:81 msgid "Search URL patterns" msgstr "Zoek-urlpatronen" #: quodlibet/ext/songsmenu/website_search.py:91 msgid "Edit search URLs" msgstr "Zoek-url's wijzigen" #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:117 msgid "Configure Searches…" msgstr "Zoekopdrachten instellen…" #: quodlibet/ext/songsmenu/wikipedia.py:35 msgid "Search Tag in Wikipedia" msgstr "Tag zoeken op Wikipedia" #: quodlibet/ext/songsmenu/wikipedia.py:36 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:56 #, python-format msgid "Search at %(website)s" msgstr "Zoeken op %(website)s" #: quodlibet/ext/songsmenu/wikipedia.py:70 #: quodlibet/ext/songsmenu/wikipedia.py:76 quodlibet/qltk/edittags.py:444 msgid "Edit Tags" msgstr "Tags bewerken" #: quodlibet/ext/songsmenu/wikipedia.py:111 msgid "Search failed" msgstr "Zoeken mislukt" #: quodlibet/ext/songsmenu/wikipedia.py:112 #, python-format msgid "Tag \"%s\" not found." msgstr "De tag \"%s\" kan niet worden gevonden." #. then (try to) load all new files #: quodlibet/library/libraries.py:651 quodlibet/library/libraries.py:661 #: quodlibet/library/libraries.py:727 quodlibet/library/libraries.py:746 #: quodlibet/qltk/information.py:272 quodlibet/qltk/prefs.py:695 #: quodlibet/util/library.py:123 msgid "Library" msgstr "Verzameling" #: quodlibet/library/libraries.py:651 msgid "Checking mount points" msgstr "Bezig met controleren van aankoppelpunten" #: quodlibet/library/libraries.py:661 msgid "Scanning library" msgstr "Bezig met doorzoeken van verzameling" #: quodlibet/library/libraries.py:726 #, python-format msgid "Scanning %s" msgstr "Bezig met scannen van %s" #: quodlibet/library/libraries.py:746 msgid "Loading files" msgstr "Bezig met laden van bestanden" #: quodlibet/main.py:50 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:462 msgid "Print terse output" msgstr "Toon beknopte uitvoer" #: quodlibet/operon/commands.py:43 quodlibet/operon/commands.py:82 #: quodlibet/operon/commands.py:464 #, 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:336 quodlibet/operon/commands.py:340 #: quodlibet/operon/commands.py:392 quodlibet/operon/commands.py:395 #: quodlibet/operon/commands.py:434 quodlibet/operon/commands.py:469 #: quodlibet/operon/commands.py:509 quodlibet/operon/commands.py:544 #: quodlibet/operon/commands.py:586 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:471 msgid "Too many arguments" msgstr "Te veel opdrachtregelopties" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:91 #: quodlibet/operon/commands.py:476 quodlibet/qltk/data_editors.py:352 msgid "Description" msgstr "Omschrijving" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:476 #: quodlibet/qltk/edittags.py:494 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:324 #: quodlibet/operon/commands.py:385 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 "Openen van tekstverwerker '%(editor-name)s' mislukt." #: 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:304 quodlibet/operon/commands.py:445 #: quodlibet/operon/commands.py:677 #, python-format msgid "Can not set %r" msgstr "Kan %r niet instellen" #: quodlibet/operon/commands.py:319 msgid "Remove tags" msgstr "Tags verwijderen" #: quodlibet/operon/commands.py:326 quodlibet/operon/commands.py:387 msgid "Value is a regular expression" msgstr "De waarde is een reguliere uitdrukking" #: quodlibet/operon/commands.py:328 msgid "Remove all tags" msgstr "Alle tags verwijderen" #: quodlibet/operon/commands.py:332 msgid "Can't combine '--all' with '--regexp'" msgstr "Kan '--all' niet combineren met '--regexp'" #: quodlibet/operon/commands.py:366 #, python-brace-format msgid "Can't remove {tagname} from {filename}" msgstr "Kan \"{tagname}\" niet wissen uit {filename}" #: quodlibet/operon/commands.py:380 msgid "Remove a tag value" msgstr "Tagwaarde verwijderen" #: quodlibet/operon/commands.py:429 msgid "Add a tag value" msgstr "Tagwaarde toevoegen" #: quodlibet/operon/commands.py:457 msgid "List file information" msgstr "Bestandsinformatie tonen" #: quodlibet/operon/commands.py:503 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:516 #, python-format msgid "Failed to load image file: %r" msgstr "Laden van afbeeldingsbestand mislukt: %r" #: quodlibet/operon/commands.py:523 quodlibet/operon/commands.py:552 #, 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:539 msgid "Remove all embedded images" msgstr "Alle bijgevoegde afbeeldingen verwijderen" #: quodlibet/operon/commands.py:569 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "Extraheer bijgevoegde afbeeldingen naar %(filepath)s" #: quodlibet/operon/commands.py:581 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" "Pad waar de afbeeldingen zullen worden opgeslagen (standaard is dit de " "werkmap)" #: quodlibet/operon/commands.py:640 msgid "Rename files based on tags" msgstr "Bestandsnamen wijzigen op basis van tags" #: quodlibet/operon/commands.py:655 msgid "Fill tags based on the file path" msgstr "Tags invullen op basis van bestandspad" #: quodlibet/operon/commands.py:705 quodlibet/qltk/information.py:309 #: quodlibet/qltk/properties.py:83 quodlibet/qltk/renamefiles.py:224 #: quodlibet/qltk/tagsfrompath.py:228 quodlibet/qltk/tracknumbers.py:78 msgid "File" msgstr "Bestand" #: quodlibet/operon/commands.py:713 msgid "Fill tracknumbers for all files" msgstr "Volgnummers toekennen aan alle bestanden" #: quodlibet/operon/commands.py:732 msgid "Print tags based on the given pattern" msgstr "Tags tonen op basis van opgegeven patroon" #: quodlibet/operon/commands.py:769 msgid "Display help information" msgstr "Hulpinformatie tonen" #: quodlibet/operon/util.py:43 #, 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:32 msgid "_Unknown" msgstr "_Onbekend" #: quodlibet/order/__init__.py:144 msgid "In Order" msgstr "Op volgorde" #: quodlibet/order/__init__.py:145 msgid "_In Order" msgstr "_Op volgorde" #: quodlibet/order/reorder.py:22 msgid "Random" msgstr "Willekeurig" #: quodlibet/order/reorder.py:23 quodlibet/qltk/queue.py:147 msgid "_Random" msgstr "Willekeu_rig" #: quodlibet/order/reorder.py:40 quodlibet/order/reorder.py:41 msgid "Prefer higher rated" msgstr "Voorkeur voor hoger gewaardeerd" #: quodlibet/order/repeat.py:43 quodlibet/order/repeat.py:44 msgid "Repeat this track" msgstr "Nummer herhalen" #: quodlibet/order/repeat.py:57 quodlibet/order/repeat.py:58 msgid "Repeat all" msgstr "Alles herhalen" #: quodlibet/order/repeat.py:73 quodlibet/order/repeat.py:74 msgid "One Song" msgstr "Één nummer" #: quodlibet/player/gstbe/player.py:99 msgid "Stream" msgstr "Stream" #: quodlibet/player/gstbe/player.py:99 msgid "Buffering" msgstr "Bufferen" #: quodlibet/player/gstbe/player.py:453 msgid "Could not create GStreamer pipeline" msgstr "Kan geen GStreamer-pijplijn aanmaken" #: quodlibet/player/gstbe/player.py:652 msgid "No GStreamer element found to handle media format" msgstr "Geen GStreamer-element gevonden om mediaformaat te verwerken" #: quodlibet/player/gstbe/player.py:653 #, 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:25 msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. In case 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:36 msgid "_Output pipeline:" msgstr "Uitv_oerpijplijn:" #: quodlibet/player/gstbe/prefs.py:43 #, python-format msgid "%.1f seconds" msgstr "%.1f seconden" #: quodlibet/player/gstbe/prefs.py:57 msgid "_Buffer duration:" msgstr "_Bufferduur:" #: quodlibet/player/gstbe/prefs.py:66 msgid "Disable _gapless playback" msgstr "_Naadloos afspelen uitschakelen" #: quodlibet/player/gstbe/prefs.py:70 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/util.py:101 msgid "No GStreamer audio sink found" msgstr "Geen GStreamer-audiosink aangetroffen" #: quodlibet/player/gstbe/util.py:120 msgid "Invalid GStreamer output pipeline" msgstr "Ongeldige GStreamer-uitvoerpijplijn" #: quodlibet/player/xinebe/player.py:90 msgid "Unable to create audio output" msgstr "Kan audio-uitvoer niet aanmaken" #: quodlibet/player/xinebe/player.py:91 #, 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:61 #, 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:70 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "Het GStreamer-element '{element}' is niet aangetroffen." #: 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:55 #: quodlibet/qltk/songsmenu.py:66 msgid "_Run Plugin" msgstr "Plugin uitvoe_ren" #. 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:351 msgid "_Value:" msgstr "_Waarde:" #: quodlibet/qltk/cbes.py:265 msgid "Saved Values" msgstr "Opgeslagen waarden" #: quodlibet/qltk/cbes.py:266 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:116 #, python-format msgid "New %s" msgstr "Nieuw(e) %s" #: quodlibet/qltk/data_editors.py:215 msgid "(unknown)" msgstr "(onbekend)" #: quodlibet/qltk/data_editors.py:344 msgid "Tag expression" msgstr "Tag-uitdrukking" #: quodlibet/qltk/data_editors.py:371 msgid "Tag expression e.g. people:real or ~album~year" msgstr "Tag-uitdrukking, bijv. personen:echt of ~album~jaar" #: quodlibet/qltk/data_editors.py:372 msgid "Enter new tag" msgstr "Voer een nieuwe tag in" #: 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 één 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 één of meerdere bestanden mislukt." #: quodlibet/qltk/edittags.py:63 quodlibet/qltk/edittags.py:74 #, 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:67 quodlibet/qltk/edittags.py:71 #, 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:299 msgid "Split Arranger out of Ar_tist" msgstr "Componist losmaken van ar_tiest" #: quodlibet/qltk/edittags.py:304 msgid "Split _Performer out of Artist" msgstr "_Uitvoerend artiest scheiden van artiest" #: quodlibet/qltk/edittags.py:310 msgid "Split _Performer out of Title" msgstr "_Uitvoerend artiest weghalen uit titel" #: quodlibet/qltk/edittags.py:316 msgid "Split _Originalartist out of Title" msgstr "_Oorspronkelijke artiest weghalen uit titel" #: quodlibet/qltk/edittags.py:323 msgid "Add a Tag" msgstr "Tag toevoegen" #: quodlibet/qltk/edittags.py:342 msgid "_Tag:" msgstr "_Tag:" #: quodlibet/qltk/edittags.py:517 msgid "Show _programmatic tags" msgstr "_Programmatische tags tonen" #: quodlibet/qltk/edittags.py:518 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" #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:548 msgctxt "edittags" msgid "_Revert" msgstr "Onge_daan maken" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:553 msgctxt "edittags" msgid "_Save" msgstr "Op_slaan" #: quodlibet/qltk/edittags.py:682 msgid "_Configure" msgstr "_Instellen" #: quodlibet/qltk/edittags.py:697 msgid "_Split Tag" msgstr "Tag _splitsen" #: quodlibet/qltk/edittags.py:706 msgid "_Copy Value(s)" msgstr "Waarde(n) _kopiëren" #: quodlibet/qltk/edittags.py:737 msgid "Unable to add tag" msgstr "Kan tag niet toevoegen" #: quodlibet/qltk/edittags.py:738 #, python-format msgid "Unable to add <b>%s</b>" msgstr "Kan <b>%s</b> niet toevoegen" #: quodlibet/qltk/edittags.py:740 #, python-format msgid "" "The files currently selected do not support multiple values for <b>%s</b>." msgstr "" "De geselecteerde bestanden ondersteunen meerdere waarden van <b>%s</b> niet." #. Can't add the new tag. #: quodlibet/qltk/edittags.py:767 quodlibet/qltk/edittags.py:948 #: quodlibet/qltk/tagsfrompath.py:211 quodlibet/util/__init__.py:507 #: quodlibet/util/tags.py:244 msgid "Invalid tag" msgstr "Ongeldige tag" #: quodlibet/qltk/edittags.py:768 quodlibet/qltk/edittags.py:949 #: quodlibet/qltk/tagsfrompath.py:212 #, python-format msgid "" "Invalid tag <b>%s</b>\n" "\n" "The files currently selected do not support editing this tag." msgstr "" "Ongeldige tag <b>%s</b>\n" "\n" "De geselecteerde bestanden ondersteunen het bewerken van deze tag niet." #: quodlibet/qltk/edittags.py:919 quodlibet/qltk/edittags.py:960 msgid "Invalid value" msgstr "Ongeldige waarde" #: quodlibet/qltk/edittags.py:920 quodlibet/qltk/edittags.py:961 #, python-format msgid "" "Invalid value: <b>%(value)s</b>\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 #, 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:145 msgid "_More options…" msgstr "_Meer opties…" #: quodlibet/qltk/entry.py:78 msgid "_Undo" msgstr "O_ngedaan maken" #: quodlibet/qltk/entry.py:80 msgid "_Redo" msgstr "_Opnieuw" #: quodlibet/qltk/exfalsowindow.py:94 quodlibet/qltk/quodlibetwindow.py:956 msgid "_About" msgstr "Ov_er" #: quodlibet/qltk/exfalsowindow.py:98 quodlibet/qltk/quodlibetwindow.py:978 msgid "_Check for Updates…" msgstr "_Controleren op updates…" #: quodlibet/qltk/exfalsowindow.py:104 quodlibet/qltk/quodlibetwindow.py:911 #: quodlibet/qltk/songsmenu.py:289 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:278 msgid "Ex Falso Preferences" msgstr "Ex Falso-voorkeuren" #: quodlibet/qltk/exfalsowindow.py:284 quodlibet/qltk/prefs.py:669 msgid "Tag Editing" msgstr "Tag bewerken" #: 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:386 msgid "Unable to create folder" msgstr "Kan map niet aanmaken" #: quodlibet/qltk/filesel.py:403 msgid "Unable to delete folder" msgstr "Kan map niet verwijderen" #: quodlibet/qltk/filesel.py:519 quodlibet/qltk/pluginwin.py:167 msgid "Songs" msgstr "Nummers" #. Translators: As in "by Artist Name" #: quodlibet/qltk/info.py:42 #, python-format msgid "by %s" msgstr "door %s" #: quodlibet/qltk/info.py:43 quodlibet/qltk/information.py:171 #: quodlibet/qltk/information.py:452 #, python-format msgid "Disc %s" msgstr "Disc %s" #: quodlibet/qltk/info.py:44 quodlibet/qltk/information.py:176 #, python-format msgid "Track %s" msgstr "Nummer %s" #: quodlibet/qltk/info.py:98 msgid "Current _Song" msgstr "Huidige _nummer" #: quodlibet/qltk/info.py:108 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:342 #: quodlibet/qltk/information.py:475 quodlibet/qltk/information.py:543 msgid "Information" msgstr "Informatie" #: quodlibet/qltk/information.py:127 msgid "Lyrics" msgstr "Songtekst" #: quodlibet/qltk/information.py:188 quodlibet/qltk/information.py:400 #, python-format msgid "Produced by %s" msgstr "Geproduceerd door %s" #: quodlibet/qltk/information.py:203 quodlibet/util/tags.py:85 msgid "artist" msgstr "artiest" #: quodlibet/qltk/information.py:204 quodlibet/qltk/information.py:573 #: quodlibet/util/tags.py:85 msgid "artists" msgstr "artiesten" #. for backwards compat #: quodlibet/qltk/information.py:225 quodlibet/util/tags.py:96 #: quodlibet/util/tags.py:125 msgid "performers" msgstr "uitvoerend artiesten" #: quodlibet/qltk/information.py:239 quodlibet/qltk/information.py:252 #: quodlibet/qltk/songlistcolumns.py:273 msgid "Never" msgstr "Nooit" #: quodlibet/qltk/information.py:240 #, 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:258 quodlibet/util/tags.py:150 msgid "added" msgstr "toegevoegd" #: quodlibet/qltk/information.py:259 quodlibet/util/tags.py:151 msgid "last played" msgstr "laatst afgespeeld" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:161 msgid "plays" msgstr "speelt" #: quodlibet/qltk/information.py:261 quodlibet/util/tags.py:162 msgid "skips" msgstr "slaat over" #: quodlibet/qltk/information.py:262 quodlibet/util/tags.py:167 msgid "rating" msgstr "waardering" #: quodlibet/qltk/information.py:291 msgid "path" msgstr "pad" #: quodlibet/qltk/information.py:292 quodlibet/util/tags.py:165 msgid "length" msgstr "duur" #: quodlibet/qltk/information.py:293 msgid "format" msgstr "formaat" #: quodlibet/qltk/information.py:294 quodlibet/util/tags.py:175 msgid "codec" msgstr "codec" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:176 msgid "encoding" msgstr "codering" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:172 msgid "bitrate" msgstr "bitsnelheid" #: quodlibet/qltk/information.py:297 quodlibet/util/tags.py:173 msgid "file size" msgstr "bestandsgrootte" #: quodlibet/qltk/information.py:298 quodlibet/util/tags.py:160 msgid "modified" msgstr "gewijzigd" #: quodlibet/qltk/information.py:335 msgid "Additional" msgstr "Aanvullend" #: quodlibet/qltk/information.py:387 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d geselecteerd" msgstr[1] "%d geselecteerd" #: quodlibet/qltk/information.py:462 msgid "Track unavailable" msgstr "Het nummer is niet beschikbaar" #: quodlibet/qltk/information.py:500 quodlibet/qltk/information.py:590 #, 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:503 msgid "Selected Discography" msgstr "Bepaalde discografie" #: quodlibet/qltk/information.py:570 #, 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:598 quodlibet/util/tags.py:83 msgid "albums" msgstr "albums" #: quodlibet/qltk/information.py:611 msgid "Total length:" msgstr "Totaalduur:" #: quodlibet/qltk/information.py:615 msgid "Total size:" msgstr "Totaalgrootte:" #: quodlibet/qltk/information.py:618 msgid "Files" msgstr "Bestanden" #: quodlibet/qltk/lyrics.py:36 msgid "_View online" msgstr "Online _bekijken" #: quodlibet/qltk/lyrics.py:64 msgid "No lyrics found for this song." msgstr "Geen songtekst gevonden bij dit nummer." #: quodlibet/qltk/lyrics.py:75 msgid "Searching for lyrics…" msgstr "Bezig met zoeken naar songtekst…" #: 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/msg.py:41 msgid "Discard tag changes?" msgstr "Tagwijzigingen verwerpen?" #: quodlibet/qltk/msg.py:42 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:55 quodlibet/qltk/prefs.py:631 #: quodlibet/qltk/prefs.py:638 quodlibet/qltk/textedit.py:63 #: quodlibet/qltk/tracknumbers.py:116 msgid "_Revert" msgstr "Onge_daan maken" #: quodlibet/qltk/msg.py:104 msgid "File exists" msgstr "Bestand bestaat" #: quodlibet/qltk/msg.py:106 #, python-format msgid "Replace %(file-name)s?" msgstr "%(file-name)s vervangen?" #: quodlibet/qltk/msg.py:112 msgid "_Replace File" msgstr "Bestand ve_rvangen" #: quodlibet/qltk/notif.py:182 msgid "Active tasks" msgstr "Actieve taken" #: quodlibet/qltk/notif.py:188 #, python-format msgid "%d tasks running" msgstr "Er worden %d taken uitgevoerd" #: quodlibet/qltk/playorder.py:256 msgid "Toggle shuffle mode" msgstr "Willekeurige modus aan/uit" #: quodlibet/qltk/playorder.py:272 msgid "Toggle repeat mode" msgstr "Herhaalmodus aan/uit" #: quodlibet/qltk/pluginwin.py:44 msgid "Plugin Errors" msgstr "Plug-infouten" #: quodlibet/qltk/pluginwin.py:124 msgid "Enabled" msgstr "Ingeschakeld" #: quodlibet/qltk/pluginwin.py:125 msgid "Disabled" msgstr "Uitgeschakeld" #: quodlibet/qltk/pluginwin.py:131 msgid "No category" msgstr "Geen categorie" #: quodlibet/qltk/pluginwin.py:169 msgid "Events" msgstr "Evenementen" #: quodlibet/qltk/pluginwin.py:170 msgid "Play Order" msgstr "Afspeelvolgorde" #: quodlibet/qltk/pluginwin.py:171 msgid "Editing" msgstr "Bewerken" #: quodlibet/qltk/pluginwin.py:173 msgid "Covers" msgstr "Hoezen" #: quodlibet/qltk/pluginwin.py:309 msgid "No plugins found." msgstr "Geen plug-ins aangetroffen." #: quodlibet/qltk/pluginwin.py:358 msgid "Plugins" msgstr "Plug-ins" #: quodlibet/qltk/pluginwin.py:382 msgid "Filter by plugin state / tag" msgstr "Filteren op plug-instatus/tag" #: quodlibet/qltk/pluginwin.py:388 msgid "Filter by plugin type" msgstr "Filteren op soort plug-in" #: quodlibet/qltk/pluginwin.py:394 msgid "Filter by plugin name or description" msgstr "Filteren op plug-innaam of -omschrijving" #: quodlibet/qltk/pluginwin.py:403 msgid "Show _Errors" msgstr "Fout_en tonen" #: quodlibet/qltk/prefs.py:45 msgid "_Disc" msgstr "_Schijf" #: quodlibet/qltk/prefs.py:46 msgid "_Track" msgstr "_Nummer" #: quodlibet/qltk/prefs.py:47 msgid "Grou_ping" msgstr "Groe_peren" #: quodlibet/qltk/prefs.py:50 msgid "Al_bum" msgstr "Al_bum" #: quodlibet/qltk/prefs.py:55 msgid "_Filename" msgstr "_Bestandsnaam" #: quodlibet/qltk/prefs.py:57 msgid "_Length" msgstr "_Duur" #: quodlibet/qltk/prefs.py:64 msgid "_Jump to playing song automatically" msgstr "_Automatisch schakelen naar huidige nummer" #: quodlibet/qltk/prefs.py:66 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:82 msgid "_Others:" msgstr "_Overige:" #: quodlibet/qltk/prefs.py:88 msgid "_Edit…" msgstr "B_ewerken…" #: quodlibet/qltk/prefs.py:91 msgid "Add or remove additional column headers" msgstr "Kolomkoppen toevoegen of verwijderen" #: quodlibet/qltk/prefs.py:101 msgid "Visible Columns" msgstr "Zichtbare kolommen" #: quodlibet/qltk/prefs.py:104 msgid "Title includes _version" msgstr "Titel bevat _versie" #: quodlibet/qltk/prefs.py:106 msgid "Artist includes all _people" msgstr "Artiest bevat alle _personen" #: quodlibet/qltk/prefs.py:108 msgid "Album includes _disc subtitle" msgstr "Album bevat schijfon_dertitels" #: quodlibet/qltk/prefs.py:110 msgid "Filename includes _folder" msgstr "Bestandsnaam bevat _map" #: quodlibet/qltk/prefs.py:123 msgid "Column Preferences" msgstr "Kolomvoorkeuren" #: quodlibet/qltk/prefs.py:129 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:142 quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Nummerlijst" #: quodlibet/qltk/prefs.py:222 msgid "Edit Columns" msgstr "Kolommen aanpassen" #: quodlibet/qltk/prefs.py:259 msgid "Duration totals" msgstr "Totaalduur" #: quodlibet/qltk/prefs.py:271 msgid "_Global filter:" msgstr "_Globaal filter:" #: quodlibet/qltk/prefs.py:277 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:283 msgctxt "heading" msgid "Search" msgstr "Zoeken" #: quodlibet/qltk/prefs.py:287 quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Verkenners" #: quodlibet/qltk/prefs.py:293 msgid "Confirm _multiple ratings" msgstr "_Meerdere waarderingen bevestigen" #: quodlibet/qltk/prefs.py:295 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:298 msgid "Enable _one-click ratings" msgstr "Eé_nklikwaarderingen inschakelen" #: quodlibet/qltk/prefs.py:300 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:306 quodlibet/qltk/prefs.py:672 msgid "Ratings" msgstr "Waarderingen" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:312 msgid "Prefer _embedded art" msgstr "Voorkeur voor bijg_evoegde hoes" #: quodlibet/qltk/prefs.py:314 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:321 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:325 msgid "_Preferred image filename(s):" msgstr "Bestandsnamen van _voorkeursafbeeldingen:" #: quodlibet/qltk/prefs.py:340 msgid "Album Art" msgstr "Albumhoes" #: quodlibet/qltk/prefs.py:361 msgid "Playback" msgstr "Afspelen" #: quodlibet/qltk/prefs.py:366 msgid "Output Configuration" msgstr "Uitvoerinstellingen" #: quodlibet/qltk/prefs.py:377 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:380 msgid "_Fall-back gain (dB):" msgstr "Terug_valversterking (dB):" #: quodlibet/qltk/prefs.py:391 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:394 msgid "_Pre-amp gain (dB):" msgstr "Voorvers_terking (dB):" #: quodlibet/qltk/prefs.py:399 msgid "_Enable Replay Gain volume adjustment" msgstr "ReplayGain volume-aanpassing inschak_elen" #: quodlibet/qltk/prefs.py:424 msgid "Replay Gain Volume Adjustment" msgstr "ReplayGain volume-aanpassing" #: quodlibet/qltk/prefs.py:431 msgid "_Continue playback on startup" msgstr "Afspelen her_vatten bij opstarten" #: quodlibet/qltk/prefs.py:433 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:437 msgid "Startup" msgstr "Opstarten" #: quodlibet/qltk/prefs.py:464 msgid "_Default rating:" msgstr "Stan_daardwaardering:" #: quodlibet/qltk/prefs.py:507 msgid "Rating _scale:" msgstr "Waardeer_schaal:" #: quodlibet/qltk/prefs.py:556 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:561 msgid "_Bayesian averaging amount:" msgstr "_Bayesiaans gemiddelde-waarde:" #: quodlibet/qltk/prefs.py:578 msgid "_Email:" msgstr "_E-mailadres:" #: quodlibet/qltk/prefs.py:580 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:600 msgid "Auto-save tag changes" msgstr "Tagwijzigingen automatisch opslaan" #: quodlibet/qltk/prefs.py:602 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:611 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:621 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:634 msgid "Split _tag on:" msgstr "Tag _splitsen op:" #: quodlibet/qltk/prefs.py:641 msgid "Split _subtag on:" msgstr "_Subtag splitsen op:" #: quodlibet/qltk/prefs.py:666 msgid "Tags" msgstr "Tags" #: quodlibet/qltk/prefs.py:687 msgid "Updating for new ratings" msgstr "Bijwerken voor nieuwe waarderingen" #: quodlibet/qltk/prefs.py:697 msgid "Scan library _on start" msgstr "Verzameling d_oorzoeken bij opstarten" #: quodlibet/qltk/prefs.py:707 quodlibet/qltk/quodlibetwindow.py:990 msgid "_Scan Library" msgstr "Verzameling _doorzoeken" #: quodlibet/qltk/prefs.py:709 quodlibet/qltk/quodlibetwindow.py:1052 msgid "Check for changes in your library" msgstr "Controleren op aanpassingen aan je verzameling" #: quodlibet/qltk/prefs.py:714 msgid "Re_build Library" msgstr "Verzameling o_pnieuw samenstellen" #: quodlibet/qltk/prefs.py:717 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:727 msgid "Scan Directories" msgstr "Mappen doorzoeken" #: quodlibet/qltk/prefs.py:733 msgid "Hidden Songs" msgstr "Verborgen nummers" #: quodlibet/qltk/properties.py:157 quodlibet/util/collection.py:415 #, 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:104 msgid "_Queue" msgstr "_Wachtrij" #: quodlibet/qltk/queue.py:124 msgid "Ephemeral" msgstr "Eenmalig" #: quodlibet/qltk/queue.py:125 msgid "Remove songs from the queue after playing them" msgstr "Verwijder alle nummers uit de wachtrij nadat ze zijn afgespeeld" #: quodlibet/qltk/queue.py:133 msgid "Persistent" msgstr "Permanent" #: quodlibet/qltk/queue.py:134 msgid "Keep songs in the queue after playing them" msgstr "Behoud alle nummers in de wachtrij nadat ze zijn afgespeeld" #: quodlibet/qltk/queue.py:142 msgid "Mode" msgstr "Modus" #: quodlibet/qltk/queue.py:153 msgid "Stop at End" msgstr "Stoppen na einde" #: quodlibet/qltk/queue.py:157 msgid "_Clear Queue" msgstr "Wa_chrij wissen" #: quodlibet/qltk/queue.py:178 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:290 #, 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:198 msgid "_Browse Library" msgstr "Verzameling _verkennen" #: quodlibet/qltk/quodlibetwindow.py:348 msgid "Toggle queue visibility" msgstr "Wachtrij tonen/verbergen" #: quodlibet/qltk/quodlibetwindow.py:376 msgid "Playback Error" msgstr "Afspeelfout" #: quodlibet/qltk/quodlibetwindow.py:384 msgid "Set up library directories?" msgstr "Verzamelingsmappen instellen?" #: quodlibet/qltk/quodlibetwindow.py:385 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:391 msgid "_Not Now" msgstr "_Niet nu" #: quodlibet/qltk/quodlibetwindow.py:392 msgid "_Set Up" msgstr "Samen_stellen" #: quodlibet/qltk/quodlibetwindow.py:845 msgid "Unable to add songs" msgstr "Kan nummers niet toevoegen" #: quodlibet/qltk/quodlibetwindow.py:846 quodlibet/qltk/quodlibetwindow.py:1286 #, python-format msgid "%s uses an unsupported protocol." msgstr "%s gebruikt een niet-ondersteund protocol." #: quodlibet/qltk/quodlibetwindow.py:869 msgid "_Jump to Playing Song" msgstr "_Ga naar spelend nummer" #: quodlibet/qltk/quodlibetwindow.py:876 msgid "_File" msgstr "_Bestand" #: quodlibet/qltk/quodlibetwindow.py:877 msgid "_Song" msgstr "_Nummer" #: quodlibet/qltk/quodlibetwindow.py:878 msgid "_View" msgstr "Weerga_ve" #: quodlibet/qltk/quodlibetwindow.py:879 msgid "_Browse" msgstr "_Verkennen" #: quodlibet/qltk/quodlibetwindow.py:880 msgid "_Control" msgstr "_Bediening" #: quodlibet/qltk/quodlibetwindow.py:881 msgid "_Help" msgstr "_Hulp" #: quodlibet/qltk/quodlibetwindow.py:887 msgid "_Add a Folder…" msgstr "M_ap toevoegen…" #: quodlibet/qltk/quodlibetwindow.py:892 msgid "_Add a File…" msgstr "Best_and toevoegen…" #: quodlibet/qltk/quodlibetwindow.py:897 msgid "_Add a Location…" msgstr "Loc_atie toevoegen…" #: quodlibet/qltk/quodlibetwindow.py:926 msgid "Edit Bookmarks…" msgstr "Bladwijzers bewerken…" #: quodlibet/qltk/quodlibetwindow.py:946 msgid "Stop After This Song" msgstr "Stoppen na dit nummer" #: quodlibet/qltk/quodlibetwindow.py:952 msgid "_Keyboard Shortcuts" msgstr "_Sneltoetsen" #: quodlibet/qltk/quodlibetwindow.py:961 msgid "Online Help" msgstr "Online-hulp" #: quodlibet/qltk/quodlibetwindow.py:970 msgid "Search Help" msgstr "Zoekhulp" #: quodlibet/qltk/quodlibetwindow.py:1274 msgid "Add a Location" msgstr "Locatie toevoegen" #: quodlibet/qltk/quodlibetwindow.py:1275 msgid "Enter the location of an audio file:" msgstr "Voer de locatie van een audiobestand in:" #: quodlibet/qltk/quodlibetwindow.py:1280 #: quodlibet/qltk/quodlibetwindow.py:1285 msgid "Unable to add location" msgstr "Kan locatie niet toevoegen" #: quodlibet/qltk/quodlibetwindow.py:1281 #, python-format msgid "%s is not a valid location." msgstr "%s is geen geldige locatie." #: quodlibet/qltk/quodlibetwindow.py:1294 #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "Add Music" msgstr "Muziek toevoegen" #: quodlibet/qltk/quodlibetwindow.py:1294 quodlibet/qltk/scanbox.py:99 msgid "_Add Folders" msgstr "M_appen toevoegen" #: quodlibet/qltk/quodlibetwindow.py:1301 msgid "Music Files" msgstr "Muziekbestanden" #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "_Add Files" msgstr "Best_anden toevoegen" #: quodlibet/qltk/ratingsmenu.py:24 #, 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:26 msgid "The saved ratings will be removed" msgstr "De opgeslagen waarderingen worden verwijderd" #: quodlibet/qltk/ratingsmenu.py:27 #, 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:57 quodlibet/qltk/ratingsmenu.py:111 msgid "_Remove Rating" msgstr "Waardering ve_rwijderen" #: quodlibet/qltk/renamefiles.py:51 msgid "Replace spaces with _underscores" msgstr "Spaties vervangen door _onderliggende streepjes" #: quodlibet/qltk/renamefiles.py:61 msgid "Strip _Windows-incompatible characters" msgstr "_Windows-incompatibele tekens wissen" #: quodlibet/qltk/renamefiles.py:79 msgid "Strip _diacritical marks" msgstr "_Diakritische tekens wissen" #: quodlibet/qltk/renamefiles.py:90 msgid "Strip non-_ASCII characters" msgstr "Niet-_ascii-tekens wissen" #: quodlibet/qltk/renamefiles.py:100 msgid "Use only _lowercase characters" msgstr "Alleen k_leine letters gebruiken" #: quodlibet/qltk/renamefiles.py:128 msgid "Rename Files" msgstr "Bestandsnamen wijzigen" #: quodlibet/qltk/renamefiles.py:146 quodlibet/qltk/tagsfrompath.py:115 msgid "Path Patterns" msgstr "Padpatronen" #: quodlibet/qltk/renamefiles.py:147 quodlibet/qltk/tagsfrompath.py:116 msgid "Edit saved patterns…" msgstr "Opgeslagen patronen bewerken…" #: quodlibet/qltk/renamefiles.py:150 quodlibet/qltk/tagsfrompath.py:119 #: quodlibet/qltk/tracknumbers.py:57 msgid "_Preview" msgstr "_Voorvertoning" #: quodlibet/qltk/renamefiles.py:177 msgid "File names" msgstr "Bestandsnamen" #: quodlibet/qltk/renamefiles.py:187 msgid "_Move album art" msgstr "Albu_mhoezen verplaatsen" #: quodlibet/qltk/renamefiles.py:190 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:195 msgid "_Overwrite album art at target" msgstr "Albumhoezen _overschrijven" #: quodlibet/qltk/renamefiles.py:203 msgid "_Remove empty directories" msgstr "Lege mappen ve_rwijderen" #: quodlibet/qltk/renamefiles.py:209 msgid "Album art" msgstr "Albumhoezen" #: quodlibet/qltk/renamefiles.py:238 msgid "New Name" msgstr "Nieuwe naam" #: quodlibet/qltk/renamefiles.py:315 msgid "Unable to rename file" msgstr "Kan bestandsnaam niet wijzigen" #: quodlibet/qltk/renamefiles.py:316 #, python-format msgid "" "Renaming <b>%(old-name)s</b> to <b>%(new-name)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." 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:324 msgid "Ignore _All Errors" msgstr "_Alle fouten negeren" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: quodlibet/qltk/renamefiles.py:325 quodlibet/qltk/wlw.py:49 msgid "_Stop" msgstr "_Stoppen" #: quodlibet/qltk/renamefiles.py:327 msgid "_Continue" msgstr "_Doorgaan" #: quodlibet/qltk/renamefiles.py:440 msgid "Path is not absolute" msgstr "Het pad is niet absoluut" #: quodlibet/qltk/renamefiles.py:441 #, python-format msgid "" "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 ~/." 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:47 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:99 msgid "Select Directories" msgstr "Mappen kiezen" #: quodlibet/qltk/searchbar.py:57 msgid "Saved Searches" msgstr "Opgeslagen zoekopdrachten" #: quodlibet/qltk/searchbar.py:58 msgid "Edit saved searches…" msgstr "Opgeslagen zoekopdrachten bewerken…" #: quodlibet/qltk/searchbar.py:82 msgid "Search your library, using free text or QL queries" msgstr "Doorzoek je verzameling met vrije tekst of QL-zoekopdrachten" #: quodlibet/qltk/searchbar.py:144 msgid "Search after _typing" msgstr "Zoeken na _typen" #: quodlibet/qltk/searchbar.py:147 msgid "Show search results after the user stops typing" msgstr "Zoekresultaten tonen nadat stoppen met typen" #: quodlibet/qltk/searchbar.py:215 msgid "_Limit:" msgstr "_Limiet:" #: quodlibet/qltk/searchbar.py:228 msgid "_Weight" msgstr "Z_waarte" #: quodlibet/qltk/searchbar.py:355 msgid "Add query" msgstr "Zoekopdracht toevoegen" #: quodlibet/qltk/searchbar.py:356 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:379 #, python-format msgid "_Filter on %s" msgstr "_Filteren op %s" #: quodlibet/qltk/songlist.py:1098 msgid "All _Headers" msgstr "Alle _koppen" #: quodlibet/qltk/songlist.py:1099 msgid "_Track Headers" msgstr "_Nummerkoppen" #: quodlibet/qltk/songlist.py:1100 msgid "_Album Headers" msgstr "_Albumkoppen" #: quodlibet/qltk/songlist.py:1101 msgid "_People Headers" msgstr "_Persoonkoppen" #: quodlibet/qltk/songlist.py:1102 msgid "_Date Headers" msgstr "_Datumkoppen" #: quodlibet/qltk/songlist.py:1103 msgid "_File Headers" msgstr "_Bestandskoppen" #: quodlibet/qltk/songlist.py:1104 msgid "_Production Headers" msgstr "_Productiekoppen" #: quodlibet/qltk/songlist.py:1119 msgid "_Customize Headers…" msgstr "Kop_pen aanpassen…" #: quodlibet/qltk/songlist.py:1124 msgid "_Expand Column" msgstr "Kolom uitvouw_en" #: quodlibet/qltk/songsmenu.py:40 #, python-format msgid "Remove track: \"%%(title)s\" from library?" msgid_plural "Remove %(count)d tracks from library?" msgstr[0] "Wil je \"%%(title)s\" ve_rwijderen uit je verzameling?" msgstr[1] "Wil je %(count)d nummers verwijderen uit je verzameling?" #: quodlibet/qltk/songsmenu.py:46 msgid "Remove from Library" msgstr "Ve_rwijderen uit verzameling" #: quodlibet/qltk/songsmenu.py:51 #, 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:62 #, 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:134 msgid "Configure Plugins…" msgstr "Plug-ins instellen…" #: quodlibet/qltk/songsmenu.py:329 msgid "Add to _Queue" msgstr "Toevoegen aan _wachtrij" #: quodlibet/qltk/songsmenu.py:349 msgid "_Remove from Library…" msgstr "Ve_rwijderen uit verzameling…" #: quodlibet/qltk/songsmenu.py:414 msgid "Unable to show files" msgstr "Kan bestanden niet tonen" #: quodlibet/qltk/songsmenu.py:415 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:422 #, 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/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 pad" #: 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 #, python-format msgid "" "The pattern\n" "\t<b>%s</b>\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/tagsfrompath.py:215 msgid "Invalid tags" msgstr "Ongeldige tags" #: quodlibet/qltk/tagsfrompath.py:216 #, 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." #: 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:925 #, python-format msgid "and %d more…" msgstr "en nog %d…" #: quodlibet/qltk/wlw.py:199 msgid "Saving the songs you changed." msgstr "Slaat de aangepaste nummers op." #: quodlibet/qltk/wlw.py:200 #, 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:233 #, 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:437 msgid "Playlists must have a name" msgstr "Afspeellijsten moeten een naam hebben" #: quodlibet/util/collection.py:626 #, 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:33 msgid "Embedded album covers" msgstr "Bijgevoegde albumhoezen" #: quodlibet/util/cover/built_in.py:34 msgid "Uses covers embedded into audio files." msgstr "Gebruik albumhoezen bijgevoegd bij audiobestanden." #: quodlibet/util/cover/built_in.py:56 msgid "Filesystem cover" msgstr "Bestandssysteemhoes" #: quodlibet/util/cover/built_in.py:57 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:349 #, python-format msgid "%d kbps" msgstr "%d kbps" #: quodlibet/util/__init__.py:404 #, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%s seconde" msgstr[1] "%s seconden" #: quodlibet/util/__init__.py:417 msgid "No time information" msgstr "Geen tijdsinformatie" #: quodlibet/util/__init__.py:420 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d seconde" msgstr[1] "%d seconden" #: quodlibet/util/__init__.py:421 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d minuut" msgstr[1] "%d minuten" #: quodlibet/util/__init__.py:422 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d uur" msgstr[1] "%d uur" #: quodlibet/util/__init__.py:423 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d dag" msgstr[1] "%d dagen" #: quodlibet/util/__init__.py:424 #, 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:516 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 zijn: 'official', 'promotional' of " "'bootleg'." #: 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:116 msgid "Unable to edit song" msgstr "Kan nummer niet aanpassen" #: quodlibet/util/songwrapper.py:117 #, python-format msgid "" "Saving <b>%s</b> 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 "_Download…" #~ msgstr "_Download…" #~ msgid "Download Files" #~ msgstr "Download bestanden" #~ msgid "Download File" #~ msgstr "Download bestand" #~ 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 "_Edit" #~ msgstr "B_ewerken" #~ 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 "Watch this folder for new songs" #~ msgstr "Controleer deze map op nieuwe nummers" #~ 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 "_Create Database" #~ msgstr "Database aanma_ken" #~ 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 "Removing orphaned iPod track" #~ msgstr "Verweesd iPodnummer wordt verwijderd" #~ 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9711857 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/po/pl.po����������������������������������������������������������������������������0000644�0001750�0001750�00000604122�00000000000�014074� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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: 2020-03-15 13:45+0100\n" "PO-Revision-Date: 2020-03-15 14:05+0100\n" "Last-Translator: Piotr Drąg <piotrdrag@gmail.com>\n" "Language-Team: Polish <community-poland@mozilla.org>\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" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:5 #: data/io.github.quodlibet.ExFalso.desktop.in:3 msgid "Ex Falso" msgstr "Ex Falso" #: data/io.github.quodlibet.ExFalso.appdata.xml.in:6 #: data/io.github.quodlibet.ExFalso.desktop.in:5 msgid "Edit tags in your audio files" msgstr "Modyfikowanie etykiet w plikach dźwiękowych" #: 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.ExFalso.desktop.in:4 msgid "Audio tag editor" msgstr "Edytor etykiet plików dźwiękowych" #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:5 #: data/io.github.quodlibet.QuodLibet.desktop.in:3 msgid "Quod Libet" msgstr "Quod Libet" #: data/io.github.quodlibet.QuodLibet.appdata.xml.in:6 #: data/io.github.quodlibet.QuodLibet.desktop.in:5 msgid "Listen to, browse, or edit your audio collection" msgstr "Słuchanie, przeglądanie i modyfikowanie kolekcji muzycznej" #: 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." #: data/io.github.quodlibet.QuodLibet.desktop.in:4 msgid "Music Player" msgstr "Odtwarzacz muzyki" #: quodlibet/browsers/albums/main.py:206 #: quodlibet/browsers/covergrid/main.py:54 msgid "_Title" msgstr "_Tytuł" #: quodlibet/browsers/albums/main.py:207 #: quodlibet/browsers/covergrid/main.py:55 quodlibet/qltk/prefs.py:49 msgid "_Artist" msgstr "_Wykonawca" #: quodlibet/browsers/albums/main.py:208 #: quodlibet/browsers/covergrid/main.py:56 quodlibet/qltk/prefs.py:54 msgid "_Date" msgstr "Da_ta" #: quodlibet/browsers/albums/main.py:209 msgid "_Original Date" msgstr "_Oryginalna data" #: quodlibet/browsers/albums/main.py:210 #: quodlibet/browsers/covergrid/main.py:57 quodlibet/qltk/prefs.py:53 msgid "_Genre" msgstr "_Gatunek" #: quodlibet/browsers/albums/main.py:211 #: quodlibet/browsers/covergrid/main.py:58 quodlibet/qltk/prefs.py:58 #: quodlibet/qltk/ratingsmenu.py:39 msgid "_Rating" msgstr "_Ocena" #: quodlibet/browsers/albums/main.py:212 msgid "_Playcount" msgstr "_Liczba odtworzeń" #: quodlibet/browsers/albums/main.py:218 #: quodlibet/browsers/covergrid/main.py:64 msgid "Sort _by…" msgstr "Porządkowanie _według…" #: quodlibet/browsers/albums/main.py:239 #: quodlibet/browsers/covergrid/main.py:85 #: quodlibet/browsers/paned/prefs.py:203 #: quodlibet/browsers/playlists/main.py:667 quodlibet/qltk/exfalsowindow.py:108 #: quodlibet/qltk/pluginwin.py:341 quodlibet/qltk/quodlibetwindow.py:906 msgid "_Preferences" msgstr "_Preferencje" #: quodlibet/browsers/albums/main.py:409 msgid "Album List" msgstr "Lista albumów" #: quodlibet/browsers/albums/main.py:410 msgid "_Album List" msgstr "Lista _albumów" #: quodlibet/browsers/albums/main.py:524 #: quodlibet/browsers/covergrid/main.py:285 #: quodlibet/browsers/covergrid/main.py:501 msgid "All Albums" msgstr "Wszystkie albumy" #: quodlibet/browsers/albums/main.py:706 #: quodlibet/browsers/covergrid/main.py:480 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/main.py:819 quodlibet/browsers/albums/main.py:827 #: quodlibet/browsers/covergrid/main.py:634 #: quodlibet/browsers/covergrid/main.py:642 quodlibet/browsers/iradio.py:876 #: quodlibet/browsers/paned/main.py:311 quodlibet/browsers/paned/main.py:317 #: quodlibet/browsers/search.py:127 quodlibet/browsers/soundcloud/main.py:344 #: quodlibet/util/library.py:36 msgid "browsers" msgstr "przeglądarki" #: quodlibet/browsers/albums/prefs.py:28 #: quodlibet/browsers/collection/models.py:16 #: quodlibet/browsers/covergrid/prefs.py:30 msgid "Songs not in an album" msgstr "Utwory nieprzypisane do albumów" #: 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:124 #: quodlibet/ext/songsmenu/cover_download.py:243 msgid "Options" msgstr "Opcje" #: quodlibet/browsers/albums/prefs.py:74 #: quodlibet/browsers/covergrid/prefs.py:127 msgid "Album Display" msgstr "Lista albumów" #: quodlibet/browsers/albums/prefs.py:78 #: quodlibet/browsers/covergrid/prefs.py:131 #: quodlibet/browsers/playlists/prefs.py:56 #: quodlibet/ext/songsmenu/albumart.py:328 #: quodlibet/ext/songsmenu/duplicates.py:345 #: quodlibet/ext/songsmenu/filterall.py:48 quodlibet/qltk/bookmarks.py:101 #: quodlibet/qltk/cbes.py:93 quodlibet/qltk/data_editors.py:96 #: quodlibet/qltk/data_editors.py:321 quodlibet/qltk/exfalsowindow.py:286 #: quodlibet/qltk/pluginwin.py:79 quodlibet/qltk/pluginwin.py:428 #: quodlibet/qltk/prefs.py:764 quodlibet/qltk/textedit.py:163 #: quodlibet/update.py:149 msgid "_Close" msgstr "Za_mknij" #: quodlibet/browsers/audiofeeds.py:52 quodlibet/browsers/audiofeeds.py:64 #: quodlibet/browsers/audiofeeds.py:66 quodlibet/browsers/audiofeeds.py:156 #: quodlibet/browsers/paned/models.py:85 #: quodlibet/ext/songsmenu/fingerprint/search.py:46 #: quodlibet/formats/_audio.py:488 quodlibet/order/__init__.py:27 #: quodlibet/qltk/information.py:244 quodlibet/qltk/information.py:251 #: quodlibet/qltk/information.py:277 quodlibet/qltk/wlw.py:69 msgid "Unknown" msgstr "Nieznany" #: quodlibet/browsers/audiofeeds.py:247 msgid "New Feed" msgstr "Nowy kanał" #: quodlibet/browsers/audiofeeds.py:248 msgid "Enter the location of an audio feed:" msgstr "Położenie kanału dźwiękowego:" #: quodlibet/browsers/audiofeeds.py:249 #: quodlibet/browsers/collection/prefs.py:89 quodlibet/browsers/iradio.py:360 #: quodlibet/browsers/paned/prefs.py:120 #: quodlibet/browsers/playlists/menu.py:96 #: quodlibet/browsers/playlists/util.py:52 quodlibet/qltk/bookmarks.py:62 #: quodlibet/qltk/cbes.py:55 quodlibet/qltk/data_editors.py:308 #: quodlibet/qltk/edittags.py:327 quodlibet/qltk/edittags.py:527 #: quodlibet/qltk/quodlibetwindow.py:1276 quodlibet/qltk/scanbox.py:61 msgid "_Add" msgstr "_Dodaj" #: quodlibet/browsers/audiofeeds.py:303 msgid "Audio Feeds" msgstr "Kanały dźwiękowe" #: quodlibet/browsers/audiofeeds.py:304 msgid "_Audio Feeds" msgstr "_Kanały dźwiękowe" #: quodlibet/browsers/audiofeeds.py:407 quodlibet/qltk/data_editors.py:93 msgid "_New" msgstr "_Nowe" #: quodlibet/browsers/audiofeeds.py:467 quodlibet/browsers/audiofeeds.py:526 msgid "Unable to add feed" msgstr "Nie można dodać kanału" #: quodlibet/browsers/audiofeeds.py:468 quodlibet/browsers/audiofeeds.py:527 #, python-format msgid "" "%s could not be added. The server may be down, or the location may not be an " "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/audiofeeds.py:475 quodlibet/qltk/filesel.py:260 #: quodlibet/qltk/pluginwin.py:414 msgid "_Refresh" msgstr "_Odśwież" #: quodlibet/browsers/audiofeeds.py:476 #: quodlibet/browsers/playlists/main.py:487 #: quodlibet/browsers/playlists/util.py:43 quodlibet/qltk/delete.py:143 #: quodlibet/qltk/filesel.py:257 quodlibet/qltk/lyrics.py:35 #: quodlibet/qltk/maskedbox.py:28 quodlibet/qltk/songsmenu.py:364 msgid "_Delete" msgstr "_Usuń" #: quodlibet/browsers/audiofeeds.py:543 msgid "" "The current audio backend does not support URLs, Audio Feeds 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/_base.py:146 quodlibet/browsers/_base.py:149 msgid "Library Browser" msgstr "Przeglądarka kolekcji" #: quodlibet/browsers/_base.py:401 quodlibet/browsers/_base.py:406 #: quodlibet/qltk/tagsfrompath.py:193 quodlibet/qltk/textedit.py:140 #: quodlibet/util/__init__.py:573 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:23 #, python-format msgid "Unknown %s" msgstr "Nieznane %s" #: quodlibet/browsers/collection/models.py:24 #, 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" #. Remove button #: quodlibet/browsers/collection/prefs.py:93 #: quodlibet/browsers/paned/prefs.py:124 #: quodlibet/browsers/playlists/menu.py:97 #: quodlibet/ext/playlist/remove_duplicates.py:60 #: quodlibet/qltk/bookmarks.py:97 quodlibet/qltk/bookmarks.py:127 #: quodlibet/qltk/cbes.py:82 quodlibet/qltk/cbes.py:89 #: quodlibet/qltk/data_editors.py:78 quodlibet/qltk/data_editors.py:91 #: quodlibet/qltk/data_editors.py:298 quodlibet/qltk/data_editors.py:311 #: quodlibet/qltk/data_editors.py:319 quodlibet/qltk/edittags.py:533 #: quodlibet/qltk/edittags.py:710 quodlibet/qltk/maskedbox.py:48 #: quodlibet/qltk/maskedbox.py:88 quodlibet/qltk/queue.py:427 #: quodlibet/qltk/scanbox.py:36 quodlibet/qltk/scanbox.py:63 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:470 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:247 #: quodlibet/ext/songsmenu/editplaycount.py:45 #: quodlibet/ext/songsmenu/exact_rating.py:38 #: quodlibet/player/gstbe/prefs.py:40 quodlibet/qltk/prefs.py:127 #: quodlibet/qltk/textedit.py:64 msgid "_Apply" msgstr "_Zastosuj" #: quodlibet/browsers/collection/prefs.py:197 #: quodlibet/browsers/paned/prefs.py:251 #: quodlibet/browsers/playlists/menu.py:95 #: quodlibet/browsers/playlists/util.py:42 quodlibet/errorreport/ui.py:103 #: quodlibet/ext/playlist/export_to_folder.py:38 #: 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:44 #: quodlibet/ext/songsmenu/fingerprint/search.py:281 #: quodlibet/ext/songsmenu/fingerprint/submit.py:90 #: quodlibet/ext/songsmenu/importexport.py:40 #: quodlibet/ext/songsmenu/lastfmsync.py:218 #: quodlibet/ext/songsmenu/playlist.py:50 #: 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:326 #: quodlibet/qltk/_editutils.py:39 quodlibet/qltk/getstring.py:28 #: quodlibet/qltk/maskedbox.py:27 quodlibet/qltk/msg.py:54 #: quodlibet/qltk/msg.py:93 quodlibet/qltk/msg.py:111 #: quodlibet/qltk/ratingsmenu.py:33 quodlibet/update.py:95 msgid "_Cancel" msgstr "_Anuluj" #: quodlibet/browsers/covergrid/main.py:126 msgid "Cover Grid" msgstr "Siatka okładek" #: quodlibet/browsers/covergrid/main.py:127 msgid "_Cover Grid" msgstr "_Siatka okładek" #: quodlibet/browsers/covergrid/main.py:286 #: quodlibet/browsers/covergrid/main.py:502 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d album" msgstr[1] "%d albumy" msgstr[2] "%d albumów" #: 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:71 msgid "Show \"All Albums\" Item" msgstr "Wyświetlanie elementu „Wszystkie albumy”" #: quodlibet/browsers/covergrid/prefs.py:82 msgid "Wide Mode" msgstr "Tryb szeroki" #: quodlibet/browsers/covergrid/prefs.py:114 #: quodlibet/browsers/covergrid/prefs.py:115 msgid "Cover Magnification" msgstr "Powiększanie okładek" #: quodlibet/browsers/filesystem.py:39 msgid "File System" msgstr "System plików" #: quodlibet/browsers/filesystem.py:40 msgid "_File System" msgstr "_System plików" #: quodlibet/browsers/filesystem.py:124 quodlibet/qltk/songlist.py:255 msgid "Unable to copy songs" msgstr "Nie można skopiować utworów" #: quodlibet/browsers/filesystem.py:125 quodlibet/qltk/songlist.py:256 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:197 msgid "_Add to Library" msgstr "_Dodaj do kolekcji" #: quodlibet/browsers/iradio.py:184 msgid "Unsupported file type" msgstr "Nieobsługiwany typ pliku" #: quodlibet/browsers/iradio.py:185 #, 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:246 quodlibet/browsers/iradio.py:831 #: quodlibet/browsers/iradio.py:843 msgid "Unable to add station" msgstr "Nie można dodać stacji" #: quodlibet/browsers/iradio.py:257 quodlibet/browsers/iradio.py:490 msgid "Internet Radio" msgstr "Radio internetowe" #: quodlibet/browsers/iradio.py:257 msgid "Downloading station list" msgstr "Pobieranie listy stacji" #: quodlibet/browsers/iradio.py:358 msgid "New Station" msgstr "Nowa stacja" #: quodlibet/browsers/iradio.py:359 msgid "Enter the location of an Internet radio station:" msgstr "Położenie internetowej stacji radiowej:" #: quodlibet/browsers/iradio.py:377 msgid "Electronic" msgstr "Elektroniczne" #: quodlibet/browsers/iradio.py:380 msgid "Hip Hop / Rap" msgstr "Hip-hop/rap" #: quodlibet/browsers/iradio.py:381 msgid "Oldies" msgstr "Oldies" #: quodlibet/browsers/iradio.py:382 msgid "R&B" msgstr "R&B" #: quodlibet/browsers/iradio.py:383 msgid "Japanese" msgstr "Japońskie" #: quodlibet/browsers/iradio.py:384 msgid "Indian" msgstr "Indyjskie" #: quodlibet/browsers/iradio.py:386 msgid "Religious" msgstr "Religijne" #: quodlibet/browsers/iradio.py:388 msgid "Charts" msgstr "Listy przebojów" #: quodlibet/browsers/iradio.py:389 msgid "Turkish" msgstr "Tureckie" #: quodlibet/browsers/iradio.py:390 msgid "Reggae / Dancehall" msgstr "Reggae/dancehall" #: quodlibet/browsers/iradio.py:391 msgid "Latin" msgstr "Latynoskie" #: quodlibet/browsers/iradio.py:392 msgid "College Radio" msgstr "Radia uniwersyteckie" #: quodlibet/browsers/iradio.py:393 msgid "Talk / News" msgstr "Talk-show/wiadomości" #: quodlibet/browsers/iradio.py:394 msgid "Ambient" msgstr "Ambient" #: quodlibet/browsers/iradio.py:395 msgid "Jazz" msgstr "Jazz" #: quodlibet/browsers/iradio.py:396 quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "Klasyczna" #: quodlibet/browsers/iradio.py:397 quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "Pop" #: quodlibet/browsers/iradio.py:398 msgid "Alternative" msgstr "Alternative" #: quodlibet/browsers/iradio.py:399 msgid "Metal" msgstr "Metal" #: quodlibet/browsers/iradio.py:400 msgid "Country" msgstr "Country" #: quodlibet/browsers/iradio.py:401 msgid "News" msgstr "Wiadomości" #: quodlibet/browsers/iradio.py:402 msgid "Schlager" msgstr "Schlager" #: quodlibet/browsers/iradio.py:403 msgid "Funk" msgstr "Funk" #: quodlibet/browsers/iradio.py:404 msgid "Indie" msgstr "Indie" #: quodlibet/browsers/iradio.py:405 msgid "Blues" msgstr "Blues" #: quodlibet/browsers/iradio.py:406 msgid "Soul" msgstr "Soul" #: quodlibet/browsers/iradio.py:407 msgid "Lounge" msgstr "Lounge" #: quodlibet/browsers/iradio.py:408 msgid "Punk" msgstr "Punk" #: quodlibet/browsers/iradio.py:409 msgid "Reggaeton" msgstr "Reggaeton" #: quodlibet/browsers/iradio.py:411 msgid "Slavic" msgstr "Słowiańskie" #: quodlibet/browsers/iradio.py:413 msgid "Greek" msgstr "Greckie" #: quodlibet/browsers/iradio.py:414 msgid "Gothic" msgstr "Gothic" #: quodlibet/browsers/iradio.py:415 quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "Rock" #: quodlibet/browsers/iradio.py:468 msgid "Would you like to load a list of popular radio stations?" msgstr "Wczytać listę popularnych stacji radiowych?" #: quodlibet/browsers/iradio.py:474 msgid "_Load Stations" msgstr "_Wczytaj stacje" #: quodlibet/browsers/iradio.py:491 msgid "_Internet Radio" msgstr "Radio _internetowe" #: quodlibet/browsers/iradio.py:564 msgid "_New Station…" msgstr "_Nowa stacja…" #: quodlibet/browsers/iradio.py:567 msgid "_Update Stations" msgstr "Zakt_ualizuj stacje" #: quodlibet/browsers/iradio.py:594 msgid "All Stations" msgstr "Wszystkie stacje" #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:598 quodlibet/browsers/soundcloud/main.py:65 msgid "Favorites" msgstr "Ulubione" #: quodlibet/browsers/iradio.py:606 msgid "No Category" msgstr "Bez kategorii" #: quodlibet/browsers/iradio.py:835 msgid "No stations found" msgstr "Nie odnaleziono żadnych stacji" #: quodlibet/browsers/iradio.py:836 #, python-format msgid "No Internet radio stations were found at %s." msgstr "Nie odnaleziono internetowych stacji radiowych w %s." #: quodlibet/browsers/iradio.py:844 msgid "All stations listed are already in your library." msgstr "Wszystkie podane stacje już znajdują się w kolekcji." #: quodlibet/browsers/iradio.py:861 msgid "Add to Favorites" msgstr "Dodaj do ulubionych" #: quodlibet/browsers/iradio.py:865 msgid "Remove from Favorites" msgstr "Usuń z ulubionych" #: 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:103 quodlibet/qltk/pluginwin.py:122 #: quodlibet/qltk/pluginwin.py:164 msgid "All" msgstr "Wszystkie" #: quodlibet/browsers/paned/prefs.py:41 #: quodlibet/ext/songsmenu/cover_download.py:118 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 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "<tt>%s</tt>" msgstr "" "Wzorzec etykiety z opcjonalnymi znacznikami, np. <tt>composer</tt> lub\n" "<tt>%s</tt>" #: quodlibet/browsers/paned/prefs.py:231 msgid "Paned Browser Preferences" msgstr "Preferencje przeglądarki panelowej" #: quodlibet/browsers/paned/prefs.py:236 msgid "Column layout" msgstr "Układ kolumn" #: quodlibet/browsers/paned/prefs.py:240 msgid "Column content" msgstr "Treść kolumn" #: quodlibet/browsers/paned/prefs.py:242 msgid "Equal pane width" msgstr "Równa szerokość paneli" #: quodlibet/browsers/playlists/main.py:48 #: quodlibet/browsers/playlists/main.py:603 quodlibet/qltk/pluginwin.py:168 msgid "Playlists" msgstr "Listy odtwarzania" #: quodlibet/browsers/playlists/main.py:49 msgid "_Playlists" msgstr "_Listy odtwarzania" #: quodlibet/browsers/playlists/main.py:152 msgid "_Remove from Playlist" msgstr "_Usuń z listy odtwarzania" #: quodlibet/browsers/playlists/main.py:217 msgid "New" msgstr "Nowa" #: quodlibet/browsers/playlists/main.py:221 msgid "Import" msgstr "Zaimportuj" #: quodlibet/browsers/playlists/main.py:443 msgid "Unable to import playlist" msgstr "Nie można zaimportować listy odtwarzania" #: quodlibet/browsers/playlists/main.py:444 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:494 msgid "_Rename" msgstr "_Zmień nazwę" #: quodlibet/browsers/playlists/main.py:592 msgid "Unable to rename playlist" msgstr "Nie można zmienić nazwy listy odtwarzania" #: quodlibet/browsers/playlists/main.py:604 msgid "Import Playlist" msgstr "Zaimportuj listę odtwarzania" #: quodlibet/browsers/playlists/main.py:604 msgid "_Import" msgstr "Za_importuj" #: quodlibet/browsers/playlists/menu.py:25 msgid "_New Playlist…" msgstr "_Nowa lista odtwarzania…" #: quodlibet/browsers/playlists/menu.py:86 #, 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:90 #, 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:33 #, 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:35 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:50 #: quodlibet/browsers/playlists/util.py:125 quodlibet/util/collection.py:575 msgid "New Playlist" msgstr "Nowa lista odtwarzania" #: quodlibet/browsers/playlists/util.py:51 msgid "Enter a name for the new playlist:" msgstr "Nazwa nowej listy odtwarzania:" #: quodlibet/browsers/playlists/util.py:89 #, 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/search.py:32 msgid "_Limit Results" msgstr "_Ograniczenie liczby wyników" #: quodlibet/browsers/search.py:37 msgid "_Allow multiple queries" msgstr "_Wiele zapytań" #: quodlibet/browsers/search.py:53 msgid "Search Library" msgstr "Wyszukiwanie w kolekcji" #: quodlibet/browsers/search.py:54 msgid "_Search Library" msgstr "_Wyszukiwanie w kolekcji" #: quodlibet/browsers/soundcloud/main.py:39 msgid "Soundcloud Browser" msgstr "Przeglądarka SoundCloud" #: quodlibet/browsers/soundcloud/main.py:40 msgid "Sound_cloud" msgstr "Sound_Cloud" #: quodlibet/browsers/soundcloud/main.py:60 quodlibet/qltk/searchbar.py:81 msgid "Search" msgstr "Wyszukaj" #: quodlibet/browsers/soundcloud/main.py:69 msgid "My tracks" msgstr "Moje ścieżki" #: quodlibet/browsers/soundcloud/main.py:141 #, python-format msgid "Go to %s" msgstr "Przechodzi do serwisu %s" #: quodlibet/browsers/soundcloud/main.py:443 msgid "Connected" msgstr "Połączono" #: quodlibet/browsers/soundcloud/main.py:444 #, python-format msgid "Quod Libet is now connected, <b>%s</b>!" msgstr "Program Quod Libet jest teraz połączony, <b>%s</b>!" #: quodlibet/browsers/soundcloud/main.py:456 #, python-format msgid "Log out of %s" msgstr "Wyloguj z serwisu %s" #: quodlibet/browsers/soundcloud/main.py:458 msgid "Enter code…" msgstr "Kod…" #: quodlibet/browsers/soundcloud/main.py:459 #, python-format msgid "Log in to %s" msgstr "Zaloguj w serwisie %s" #: quodlibet/browsers/soundcloud/util.py:86 msgid "Soundcloud authorisation" msgstr "Upoważnienie serwisu SoundCloud" #: quodlibet/browsers/soundcloud/util.py:87 msgid "Enter Soundcloud auth code:" msgstr "Kod upoważnienia serwisu SoundCloud:" #: quodlibet/cli.py:50 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:86 msgid "a music library and player" msgstr "kolekcja muzyki i odtwarzacz" #: quodlibet/cli.py:87 msgid "[option]" msgstr "[opcja]" #: quodlibet/cli.py:89 msgid "Print the playing song and exit" msgstr "Wyświetla odtwarzany utwór i kończy działanie" #: quodlibet/cli.py:90 msgid "Begin playing immediately" msgstr "Natychmiast rozpoczyna odtwarzanie" #: quodlibet/cli.py:91 msgid "Don't show any windows on start" msgstr "Bez wyświetlania okien po uruchomieniu" #: quodlibet/cli.py:94 msgid "Jump to next song" msgstr "Przechodzi do następnego utworu" #: quodlibet/cli.py:96 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:97 msgid "Jump to previous song" msgstr "Przechodzi do poprzedniego utworu" #: quodlibet/cli.py:98 msgid "Start playback" msgstr "Rozpoczyna odtwarzanie" #: quodlibet/cli.py:99 msgid "Pause playback" msgstr "Wstrzymuje odtwarzanie" #: quodlibet/cli.py:100 msgid "Toggle play/pause mode" msgstr "Przełącza tryb odtwarzania/wstrzymania" #: quodlibet/cli.py:101 msgid "Stop playback" msgstr "Zatrzymuje odtwarzanie" #: quodlibet/cli.py:102 msgid "Turn up volume" msgstr "Zwiększa głośność" #: quodlibet/cli.py:103 msgid "Turn down volume" msgstr "Zmniejsza głośność" #: quodlibet/cli.py:104 msgid "Increase rating of playing song by one star" msgstr "Zwiększa ocenę odtwarzanego utworu o jedną gwiazdkę" #: quodlibet/cli.py:105 msgid "Decrease rating of playing song by one star" msgstr "Zmniejsza ocenę odtwarzanego utworu o jedną gwiazdkę" #: quodlibet/cli.py:106 msgid "Print player status" msgstr "Wyświetla stan odtwarzacza" #: quodlibet/cli.py:107 msgid "Hide main window" msgstr "Ukrywa główne okno" #: quodlibet/cli.py:108 msgid "Show main window" msgstr "Wyświetla główne okno" #: quodlibet/cli.py:109 msgid "Toggle main window visibility" msgstr "Przełącza widoczność głównego okna" #: quodlibet/cli.py:110 msgid "Focus the running player" msgstr "Przenosi działający odtwarzacz na pierwszy plan" #: quodlibet/cli.py:111 msgid "Remove active browser filters" msgstr "Usuwa aktywne filtry przeglądarki" #: quodlibet/cli.py:112 msgid "Refresh and rescan library" msgstr "Odświeża i ponownie skanuje kolekcję" #: quodlibet/cli.py:113 msgid "List available browsers" msgstr "Wyświetla listę dostępnych przeglądarek" #: quodlibet/cli.py:114 msgid "Print the current playlist" msgstr "Wyświetla obecną listę odtwarzania" #: quodlibet/cli.py:115 msgid "Print the contents of the queue" msgstr "Wyświetla zawartość kolejki" #: quodlibet/cli.py:116 msgid "Print the active text query" msgstr "Wyświetla aktywne zapytanie tekstowe" #: quodlibet/cli.py:117 msgid "Start without plugins" msgstr "Uruchamia bez wtyczek" #: quodlibet/cli.py:118 msgid "Start Quod Libet if it isn't running" msgstr "Uruchamia program Quod Libet, jeśli nie jest uruchomiony" #: quodlibet/cli.py:119 msgid "Exit Quod Libet" msgstr "Kończy działanie programu Quod Libet" #: quodlibet/cli.py:124 msgid "Seek within the playing song" msgstr "Przewija odtwarzany utwór" #: quodlibet/cli.py:124 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][GG∶]MM∶SS" #: quodlibet/cli.py:125 msgid "Set or toggle shuffle mode" msgstr "Ustawia lub przełącza tryb losowy" #: quodlibet/cli.py:126 msgid "Set shuffle mode type" msgstr "Ustawia typ trybu losowego" #: quodlibet/cli.py:127 msgid "Turn repeat off, on, or toggle it" msgstr "Włącza, wyłącza lub przełącza stan powtarzania" #: quodlibet/cli.py:128 msgid "Set repeat mode type" msgstr "Ustawia typ trybu powtarzania" #: quodlibet/cli.py:129 msgid "Set the volume" msgstr "Ustawia głośność" #: quodlibet/cli.py:130 msgid "Search your audio library" msgstr "Przeszukuje kolekcję" #: quodlibet/cli.py:130 quodlibet/cli.py:140 quodlibet/cli.py:144 #: quodlibet/cli.py:146 msgid "query" msgstr "zapytanie" #: quodlibet/cli.py:131 msgid "Play a file" msgstr "Odtwarza plik" #: quodlibet/cli.py:131 quodlibet/cli.py:140 quodlibet/cli.py:146 msgctxt "command" msgid "filename" msgstr "nazwa pliku" #: quodlibet/cli.py:132 msgid "Set rating of playing song" msgstr "Ustawia ocenę odtwarzanego utworu" #: quodlibet/cli.py:133 msgid "Set the current browser" msgstr "Ustawia obecną przeglądarkę" #: quodlibet/cli.py:134 msgid "Stop after the playing song" msgstr "Zatrzymuje po odtwarzanym utworze" #: quodlibet/cli.py:135 msgid "Open a new browser" msgstr "Otwiera nową przeglądarkę" #: quodlibet/cli.py:136 msgid "Show or hide the queue" msgstr "Wyświetla lub ukrywa kolejkę" #: quodlibet/cli.py:137 msgid "Filter on a random value" msgstr "Filtruje losowo" #: quodlibet/cli.py:137 msgctxt "command" msgid "tag" msgstr "etykieta" #: quodlibet/cli.py:138 msgid "Filter on a tag value" msgstr "Filtruje według wartości etykiety" #: quodlibet/cli.py:138 msgid "tag=value" msgstr "etykieta=wartość" #: quodlibet/cli.py:139 msgid "Enqueue a file or query" msgstr "Dodaje do kolejki plik lub zapytanie" #: quodlibet/cli.py:141 msgid "Enqueue comma-separated files" msgstr "Dodaje do kolejki pliki oddzielone przecinkami" #: quodlibet/cli.py:142 quodlibet/util/tags.py:157 msgid "filename" msgstr "nazwa pliku" #: quodlibet/cli.py:143 msgid "Print filenames of results of query to stdout" msgstr "Wyświetla nazwy plików wyniku zapytania na standardowym wyjściu" #: quodlibet/cli.py:145 msgid "Unqueue a file or query" msgstr "Usuwa z kolejki plik lub zapytanie" #: quodlibet/cli.py:147 msgid "Add a file or directory to the library" msgstr "Dodaje plik lub katalog do kolekcji" #: quodlibet/cli.py:148 quodlibet/util/tags.py:100 msgid "location" msgstr "położenie" #: quodlibet/cli.py:213 #, python-format msgid "Invalid argument for '%s'." msgstr "Nieprawidłowy parametr dla „%s”." #: quodlibet/cli.py:214 quodlibet/util/__init__.py:173 #, 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 "Quit Program" msgstr "Zakończ program" #: 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:34 msgid "an audio tag editor" msgstr "edytor etykiet plików dźwiękowych" #: quodlibet/exfalso.py:34 quodlibet/util/tags.py:158 msgid "directory" msgstr "katalog" #: quodlibet/exfalso.py:41 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:20 msgid "" "Downloads covers linked to by the artwork_url tag. This works with the " "Soundcloud browser." 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:20 msgid "MusicBrainz Cover Source" msgstr "Źródło okładek serwisu MusicBrainz" #: quodlibet/ext/covers/musicbrainz.py:21 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:19 msgid "" "Allows arbitrary regex substitutions (s///) 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:68 msgid "Advanced Preferences" msgstr "Zaawansowane preferencje" #: quodlibet/ext/events/advanced_preferences.py:69 msgid "Allow editing of advanced config settings." msgstr "Umożliwia modyfikowanie zaawansowanych ustawień konfiguracji." #: quodlibet/ext/events/advanced_preferences.py:187 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/ext/events/weblyrics.py:318 quodlibet/qltk/prefs.py:266 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:66 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:172 msgid "Effects" msgstr "Efekty" #: quodlibet/ext/events/animosd/prefs.py:288 msgid "Ed_it Display Pattern…" msgstr "_Modyfikuj wzorzec wyświetlania…" #: quodlibet/ext/events/animosd/prefs.py:292 #: 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_library_update.py:138 msgid "Automatic Library Update" msgstr "Automatyczna aktualizacja kolekcji" #: quodlibet/ext/events/auto_library_update.py:139 #, python-format msgid "Keeps your library up to date with inotify. Requires %s." msgstr "Aktualizuje kolekcję za pomocą mechanizmu inotify. Wymaga %s." #: 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 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." #: quodlibet/ext/events/bansheeimport.py:106 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:111 #: quodlibet/ext/events/rbimport.py:114 msgid "Import Failed" msgstr "Importowanie się nie powiodło" #: quodlibet/ext/events/bansheeimport.py:117 #, 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:126 msgid "Banshee Import" msgstr "Importowanie z programu Banshee" #: quodlibet/ext/events/bansheeimport.py:127 msgid "Imports ratings and song statistics from Banshee." msgstr "Importuje oceny i statystyki utworów z programu Banshee." #: quodlibet/ext/events/bansheeimport.py:136 msgid "_Database path:" msgstr "Ś_cieżka do bazy danych:" #: quodlibet/ext/events/bansheeimport.py:164 #: quodlibet/ext/events/rbimport.py:132 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/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:93 #: quodlibet/ext/gstreamer/karaoke.py:95 #, python-format msgid "%d Hz" msgstr "%d Hz" #: quodlibet/ext/events/equalizer.py:198 #: quodlibet/ext/gstreamer/crossfeed.py:112 #, 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/playlist/export_to_squeezebox.py:80 #: quodlibet/ext/songsmenu/albumart.py:324 #: quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/cover_download.py:309 #: quodlibet/ext/songsmenu/fingerprint/search.py:278 #: quodlibet/ext/songsmenu/html.py:75 quodlibet/ext/songsmenu/lastfmsync.py:219 #: quodlibet/ext/songsmenu/playlist.py:51 #: quodlibet/ext/songsmenu/replaygain.py:354 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/_editutils.py:40 #: quodlibet/qltk/lyrics.py:34 quodlibet/qltk/msg.py:52 #: quodlibet/qltk/renamefiles.py:216 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:42 msgid "Inhibit Screensaver" msgstr "Wstrzymanie wygaszacza ekranu" #: quodlibet/ext/events/inhibit.py:43 msgid "Prevents the GNOME screensaver from activating while a song is playing." msgstr "" "Uniemożliwia działanie wygaszacza ekranu środowiska GNOME podczas " "odtwarzania muzyki." #: quodlibet/ext/events/inhibit.py:52 msgid "Music is playing" msgstr "Odtwarzanie muzyki" #: quodlibet/ext/events/iradiolog.py:16 msgid "Internet Radio Log" msgstr "Dziennik radia internetowego" #: quodlibet/ext/events/iradiolog.py:17 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:31 msgid "Outputs a Jabber User Tunes file to ~/.quodlibet/jabber." 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:28 quodlibet/qltk/quodlibetwindow.py:1170 #: quodlibet/qltk/songlistcolumns.py:283 msgid "settings" msgstr "ustawienia" #: quodlibet/ext/events/language.py:43 msgid "System Default" msgstr "Domyślny systemu" #: quodlibet/ext/events/language.py:70 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:37 msgid "MPRIS D-Bus Support" msgstr "Obsługa MPRIS przez D-Bus" #: quodlibet/ext/events/mpris/__init__.py:38 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." #: quodlibet/ext/events/mpris/__init__.py:44 #: quodlibet/ext/events/trayicon/prefs.py:36 msgid "Hide main window on close" msgstr "Ukrywanie głównego okna podczas zamykania" #: quodlibet/ext/events/mpris/__init__.py:47 #: quodlibet/ext/events/themeswitcher.py:84 #: quodlibet/ext/gstreamer/compressor.py:99 #: quodlibet/ext/gstreamer/crossfeed.py:136 #: quodlibet/ext/gstreamer/karaoke.py:99 quodlibet/ext/gstreamer/pitch.py:89 #: quodlibet/qltk/prefs.py:741 msgid "Preferences" msgstr "Preferencje" #: quodlibet/ext/events/mqtt.py:54 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "Przyjmuje wzorce QL, np. %s" #: quodlibet/ext/events/mqtt.py:60 msgid "MQTT Publisher" msgstr "Publikowanie MQTT" #: quodlibet/ext/events/mqtt.py:61 msgid "Publishes status messages to an MQTT topic." msgstr "Publikuje wiadomości stanu do tematu MQTT." #: quodlibet/ext/events/mqtt.py:128 msgid "Broker hostname" msgstr "Nazwa komputera brokera" #: quodlibet/ext/events/mqtt.py:129 msgid "broker hostname / IP (defaults to localhost)" msgstr "nazwa komputera/adres IP brokera (domyślnie „localhost”)" #: quodlibet/ext/events/mqtt.py:131 msgid "Broker port" msgstr "Port brokera" #: quodlibet/ext/events/mqtt.py:131 msgid "broker port (defaults to 1883)" msgstr "port brokera (domyślnie 1883)" #: quodlibet/ext/events/mqtt.py:133 msgid "Topic" msgstr "Temat" #: quodlibet/ext/events/mqtt.py:135 msgid "Playing Pattern" msgstr "Wzorzec odtwarzania" #: quodlibet/ext/events/mqtt.py:137 msgid "Status text when a song is started." msgstr "Tekst stanu, kiedy utwór jest rozpoczynany." #: quodlibet/ext/events/mqtt.py:139 msgid "Paused Pattern" msgstr "Wzorzec wstrzymania" #: quodlibet/ext/events/mqtt.py:141 msgid "Text when a song is paused." msgstr "Tekst, kiedy utwór jest wstrzymany." #: quodlibet/ext/events/mqtt.py:143 msgid "No-song Text" msgstr "Tekst braku utworu" #: quodlibet/ext/events/mqtt.py:145 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:156 msgid "MQTT Configuration" msgstr "Konfiguracja MQTT" #: quodlibet/ext/events/mqtt.py:160 msgid "Status Text" msgstr "Tekst stanu" #: quodlibet/ext/events/mqtt.py:192 #, 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:196 #, 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:199 msgid "Connection error" msgstr "Błąd połączenia" #: quodlibet/ext/events/notify.py:54 msgid "Notification text" msgstr "Tekst powiadomienia" #: quodlibet/ext/events/notify.py:57 quodlibet/ext/events/notify.py:79 #: quodlibet/ext/events/notify.py:376 msgid "titlepattern" msgstr "wzorzec tytułu" #: 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:86 quodlibet/ext/events/notify.py:114 #: quodlibet/ext/events/notify.py:381 msgid "bodypattern" msgstr "wzorzec treści" #: 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:173 quodlibet/ext/events/notify.py:435 msgid "show_notifications" msgstr "wyświetlanie_powiadomień" #: 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/qlscrobbler.py:175 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:252 #, python-format msgid "Could not contact service '%s'." msgstr "Nie można połączyć z serwisem „%s”." #: quodlibet/ext/events/qlscrobbler.py:258 msgid "Authentication failed: invalid URL." msgstr "Uwierzytelnienie się nie powiodło: nieprawidłowy adres URL." #: quodlibet/ext/events/qlscrobbler.py:275 #, 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:280 msgid "Client is banned. Contact the author." msgstr "Klient został zabroniony. Proszę skontaktować się z autorem." #: quodlibet/ext/events/qlscrobbler.py:284 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:349 msgid "AudioScrobbler Submission" msgstr "Wysyłanie do serwisów AudioScrobbler" #: quodlibet/ext/events/qlscrobbler.py:350 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:455 msgid "Authentication successful." msgstr "Pomyślnie uwierzytelniono." #: quodlibet/ext/events/qlscrobbler.py:467 msgid "_Service:" msgstr "_Serwis:" #: quodlibet/ext/events/qlscrobbler.py:467 msgid "_URL:" msgstr "Adres _URL:" #: quodlibet/ext/events/qlscrobbler.py:467 msgid "User_name:" msgstr "_Nazwa użytkownika:" #: quodlibet/ext/events/qlscrobbler.py:468 msgid "_Password:" msgstr "_Hasło:" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:484 msgid "Other…" msgstr "Inny…" #. verify data #: quodlibet/ext/events/qlscrobbler.py:522 msgid "_Verify account data" msgstr "_Sprawdź poprawność danych konta" #: quodlibet/ext/events/qlscrobbler.py:527 #: quodlibet/ext/songsmenu/lastfmsync.py:312 msgid "Account" msgstr "Konto" #: quodlibet/ext/events/qlscrobbler.py:535 msgid "_Artist pattern:" msgstr "_Wzorzec wykonawcy:" #: quodlibet/ext/events/qlscrobbler.py:535 msgid "_Title pattern:" msgstr "Wzorzec _tytułu:" #: quodlibet/ext/events/qlscrobbler.py:536 msgid "Exclude _filter:" msgstr "_Filtr wykluczenia:" #: quodlibet/ext/events/qlscrobbler.py:554 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:564 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:573 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:581 msgid "_Offline mode (don't submit anything)" msgstr "Tryb _offline (bez wysyłania)" #: quodlibet/ext/events/qlscrobbler.py:585 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:28 msgid "Random Album Playback" msgstr "Odtwarzanie losowego albumu" #: quodlibet/ext/events/randomalbum.py:29 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:39 msgid "Rated higher" msgstr "Wyżej oceniane" #: quodlibet/ext/events/randomalbum.py:40 msgid "Played more often" msgstr "Częściej odtwarzane" #: quodlibet/ext/events/randomalbum.py:41 msgid "Skipped more often" msgstr "Częściej pomijane" #: quodlibet/ext/events/randomalbum.py:42 msgid "Played more recently" msgstr "Ostatnio odtwarzane" #: quodlibet/ext/events/randomalbum.py:43 msgid "Started more recently" msgstr "Ostatnio rozpoczęte" #: quodlibet/ext/events/randomalbum.py:44 msgid "Added more recently" msgstr "Ostatnio dodane" #: quodlibet/ext/events/randomalbum.py:45 msgid "Longer albums" msgstr "Dłuższe albumy" #: quodlibet/ext/events/randomalbum.py:84 msgid "seconds before starting next album" msgstr "sekundy przed rozpoczęciem następnego albumu" #: quodlibet/ext/events/randomalbum.py:88 msgid "Weights" msgstr "Waga" #: quodlibet/ext/events/randomalbum.py:90 msgid "Play some albums more than others" msgstr "Odtwarzanie niektórych albumów częściej, niż innych" #: quodlibet/ext/events/randomalbum.py:104 msgid "avoid" msgstr "unikanie" #: quodlibet/ext/events/randomalbum.py:115 msgid "prefer" msgstr "preferowanie" #: quodlibet/ext/events/randomalbum.py:219 msgid "Random Album" msgstr "Losowy album" #: quodlibet/ext/events/randomalbum.py:220 #, python-format msgid "Waiting to start %s" msgstr "Oczekiwanie na rozpoczęcie %s" #: quodlibet/ext/events/rbimport.py:119 #, 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:127 msgid "Rhythmbox Import" msgstr "Importowanie z programu Rhythmbox" #: quodlibet/ext/events/rbimport.py:128 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:73 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:79 msgid "GNOME Search Provider" msgstr "Dostawca wyszukiwania GNOME" #: quodlibet/ext/events/searchprovider.py:80 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 msgid "" "Store Seekpoints A and/or B for tracks. Skip to time A and stop after time B " "when track is played.\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:29 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:57 #: quodlibet/ext/playlist/export_to_squeezebox.py:89 msgid "Error finding Squeezebox server" msgstr "Błąd podczas wyszukiwania serwera Squeezebox" #: quodlibet/ext/events/squeezebox_sync.py:58 #: quodlibet/ext/playlist/export_to_squeezebox.py:90 #, python-format msgid "Error finding %s. Please check settings" msgstr "Błąd podczas wyszukiwania %s. Proszę sprawdzić poprawność ustawień" #: quodlibet/ext/events/synchronizedlyrics.py:34 msgid "Synchronized Lyrics" msgstr "Synchronizowany tekst utworu" #: quodlibet/ext/events/synchronizedlyrics.py:35 msgid "Shows synchronized lyrics from .lrc file with same name as the track." msgstr "" "Wyświetla synchronizowany tekst utworu z pliku .lrc o tej samej nazwie co " "ścieżka." #: quodlibet/ext/events/synchronizedlyrics.py:69 msgid "Text:" msgstr "Tekst:" #: quodlibet/ext/events/synchronizedlyrics.py:79 msgid "Background:" msgstr "Tło:" #: quodlibet/ext/events/synchronizedlyrics.py:90 msgid "Font" msgstr "Czcionka" #: quodlibet/ext/events/synchronizedlyrics.py:93 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:145 msgid "Paused:" msgstr "Wstrzymano:" #: quodlibet/ext/events/telepathy_status.py:146 #, 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:162 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:163 msgid "No song:" msgstr "Brak utworu:" #. Frame #: quodlibet/ext/events/telepathy_status.py:170 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:91 msgid "Thumb Rating" msgstr "Oceny „kciuk w górę/kciuk w dół”" #: quodlibet/ext/events/thumbrating.py:92 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 '~#score'." 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:47 msgid "Not playing" msgstr "Bezczynny" #: quodlibet/ext/events/trayicon/__init__.py:53 msgid "Tray Icon" msgstr "Ikona obszaru powiadamiania" #: quodlibet/ext/events/trayicon/__init__.py:54 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:183 quodlibet/qltk/quodlibetwindow.py:936 #: quodlibet/qltk/quodlibetwindow.py:1142 msgid "_Play" msgstr "_Odtwórz" #: quodlibet/ext/events/trayicon/menu.py:63 #: quodlibet/qltk/quodlibetwindow.py:185 quodlibet/qltk/quodlibetwindow.py:1144 #: quodlibet/qltk/wlw.py:50 msgid "P_ause" msgstr "_Wstrzymaj" #: quodlibet/ext/events/trayicon/menu.py:68 #: quodlibet/qltk/quodlibetwindow.py:190 quodlibet/qltk/quodlibetwindow.py:931 msgid "Pre_vious" msgstr "_Poprzedni" #: quodlibet/ext/events/trayicon/menu.py:71 #: quodlibet/qltk/quodlibetwindow.py:194 quodlibet/qltk/quodlibetwindow.py:941 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:902 msgid "Open _Browser" msgstr "Otwórz p_rzeglądarkę" #: quodlibet/ext/events/trayicon/menu.py:103 #: quodlibet/qltk/quodlibetwindow.py:921 quodlibet/qltk/songsmenu.py:383 msgid "Edit _Tags" msgstr "Modyfikuj _etykiety" #: quodlibet/ext/events/trayicon/menu.py:112 #: quodlibet/qltk/quodlibetwindow.py:864 quodlibet/qltk/songsmenu.py:396 msgid "_Information" msgstr "_Informacje" #: quodlibet/ext/events/trayicon/menu.py:114 quodlibet/qltk/songsmenu.py:324 msgid "Play_lists" msgstr "_Listy odtwarzania" #: quodlibet/ext/events/trayicon/menu.py:132 #: quodlibet/qltk/quodlibetwindow.py:916 msgid "_Quit" msgstr "Za_kończ" #: quodlibet/ext/events/trayicon/prefs.py:38 quodlibet/qltk/prefs.py:69 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:74 #: quodlibet/ext/events/trayicon/prefs.py:97 msgid "tooltip" msgstr "podpowiedź" #: 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 quodlibet/ext/events/weblyrics.py:193 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:603 msgid "Waveform Seek Bar" msgstr "Pasek przewijania w kształcie fali" #: quodlibet/ext/events/waveformseekbar.py:607 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:676 msgid "Override foreground color:" msgstr "Zastąpienie koloru czcionki:" #: quodlibet/ext/events/waveformseekbar.py:680 msgid "Override hover color:" msgstr "Zastąpienie koloru najechania:" #: quodlibet/ext/events/waveformseekbar.py:684 msgid "Override remaining color:" msgstr "Zastąpienie koloru pozostałych:" #: quodlibet/ext/events/waveformseekbar.py:688 msgid "Show current position" msgstr "Obecne położenie" #: quodlibet/ext/events/waveformseekbar.py:693 msgid "Show time labels" msgstr "Etykiety czasu" #: quodlibet/ext/events/waveformseekbar.py:701 msgid "Seek amount when scrolling (milliseconds):" msgstr "O ile przewijać podczas przewijania myszą (w milisekundach):" #: quodlibet/ext/events/weblyrics.py:208 msgid "No lyrics found" msgstr "Nie odnaleziono tekstu utworu" #: quodlibet/ext/events/weblyrics.py:268 msgid "_Zoom level:" msgstr "_Poziom powiększenia:" #: quodlibet/ext/events/weblyrics.py:286 msgid "URL:" msgstr "Adres URL:" #: quodlibet/ext/events/weblyrics.py:291 msgid "Revert to default" msgstr "Przywróć domyślne" #: quodlibet/ext/events/weblyrics.py:306 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." #: quodlibet/ext/events/weblyrics.py:323 msgid "Alternate search" msgstr "Alternatywne wyszukiwanie" #: quodlibet/ext/events/weblyrics.py:332 msgid "Web Lyrics" msgstr "Teksty utworów z Internetu" #: quodlibet/ext/events/weblyrics.py:333 msgid "Shows a sidebar containing online lyrics of the playing song." msgstr "" "Wyświetla panel boczny zawierający tekst odtwarzanego utworu z Internetu." #: 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:20 msgid "_Threshold:" msgstr "_Próg:" #: quodlibet/ext/gstreamer/compressor.py:21 msgid "Threshold until the filter is activated" msgstr "Próg, po którym filtr jest aktywny" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "R_atio:" msgstr "_Współczynnik:" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "Compression ratio" msgstr "Współczynnik kompresji" #: quodlibet/ext/gstreamer/compressor.py:74 #: quodlibet/ext/gstreamer/karaoke.py:91 #, python-format msgid "%d %%" msgstr "%d%%" #: quodlibet/ext/gstreamer/compressor.py:105 msgid "Audio Compressor" msgstr "Kompresja dźwięku" #: quodlibet/ext/gstreamer/compressor.py:106 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:19 msgid "_Preset:" msgstr "_Ustawienie:" #: quodlibet/ext/gstreamer/crossfeed.py:19 msgid "Filter preset" msgstr "Filtruj ustawienia" #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Frequency cut:" msgstr "Wycięcie _częstotliwości:" #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Low-pass filter cut frequency" msgstr "Częstotliwość niskiego filtru wycięcia" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed _level:" msgstr "Poziom _kanału:" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed level" msgstr "Poziom kanału" #: quodlibet/ext/gstreamer/crossfeed.py:25 msgid "Default" msgstr "Domyślne" #: quodlibet/ext/gstreamer/crossfeed.py:26 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:27 msgid "Chu Moy" msgstr "Chu Moy" #: quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "Najbliżej do przenikania Chu Moy (popularne)" #: quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Jan Meier" msgstr "Jan Meier" #: quodlibet/ext/gstreamer/crossfeed.py:30 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:31 msgid "Custom" msgstr "Niestandardowe" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Custom settings" msgstr "Niestandardowe ustawienia" #: quodlibet/ext/gstreamer/crossfeed.py:152 msgid "Crossfeed" msgstr "Przenikanie" #: quodlibet/ext/gstreamer/crossfeed.py:153 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:20 msgid "Filter _band:" msgstr "_Filtrowanie pasma:" #: quodlibet/ext/gstreamer/karaoke.py:21 msgid "The Frequency band of the filter" msgstr "Pasmo częstotliwości filtru" #: quodlibet/ext/gstreamer/karaoke.py:22 msgid "Filter _width:" msgstr "Filtrowanie _szerokości:" #: quodlibet/ext/gstreamer/karaoke.py:23 msgid "The Frequency width of the filter" msgstr "Szerokość częstotliwości filtru" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "_Level:" msgstr "_Poziom:" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "Level of the effect" msgstr "Poziom efektu" #: quodlibet/ext/gstreamer/karaoke.py:105 msgid "Karaoke" msgstr "Karaoke" #: quodlibet/ext/gstreamer/karaoke.py:106 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:21 msgid "R_ate:" msgstr "_Prędkość:" #: quodlibet/ext/gstreamer/pitch.py:22 msgid "_Tempo:" msgstr "_Tempo:" #: quodlibet/ext/gstreamer/pitch.py:23 msgid "_Pitch:" msgstr "T_onacja:" #: quodlibet/ext/gstreamer/pitch.py:95 msgid "Audio Pitch / Speed" msgstr "Tonacja/prędkość dźwięku" #: quodlibet/ext/gstreamer/pitch.py:96 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:147 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:100 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:121 #: quodlibet/ext/songsmenu/playlist.py:132 msgid "Unable to export playlist" msgstr "Nie można wyeksportować listy odtwarzania" #: quodlibet/ext/playlist/export_to_folder.py:122 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:165 msgid "Default filename pattern:" msgstr "Domyślny wzorzec nazw plików:" #: quodlibet/ext/playlist/export_to_squeezebox.py:22 msgid "Export to Squeezebox" msgstr "Wyeksportuj do Squeezebox" #: quodlibet/ext/playlist/export_to_squeezebox.py:24 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 "" "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: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:96 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 msgid "" "Playback 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/playcounteq.py:21 msgid "Playcount Equalizer" msgstr "Wyrównywanie liczby odtworzeń" #: quodlibet/ext/playorder/playcounteq.py:22 msgid "Shuffle, preferring songs with fewer total plays." msgstr "Losuje kolejność, preferując utwory z mniejszą liczbą odtworzeń." #: quodlibet/ext/playorder/playcounteq.py:24 msgid "Prefer less played" msgstr "Preferowanie rzadziej odtwarzanych" #: quodlibet/ext/playorder/queue.py:19 msgid "Queue Only" msgstr "Tylko kolejka" #: quodlibet/ext/playorder/queue.py:21 msgid "" "Limits playing of songs to the queue. 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/reverse.py:14 msgid "Reverse" msgstr "Odwrotnie" #: quodlibet/ext/playorder/reverse.py:16 msgid "Reverses the play order of songs." msgstr "Odwraca kolejność odtwarzania utworów." #: quodlibet/ext/playorder/shufflebygrouping.py:31 #: quodlibet/ext/playorder/shufflebygrouping.py:93 msgid "Shuffle by Grouping" msgstr "Losowa kolejność według grupowania" #: quodlibet/ext/playorder/shufflebygrouping.py:32 msgid "" "Shuffles by a grouping of songs defined by a common tag instead of by track, " "similar to album shuffle. This is useful for shuffling multi-movement " "classical works while 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:38 msgid "Shuffle by grouping" msgstr "Losowa kolejność według grupowania" #: quodlibet/ext/playorder/shufflebygrouping.py:45 #: quodlibet/ext/playorder/shufflebygrouping.py:132 #: quodlibet/ext/playorder/shufflebygrouping.py:147 quodlibet/util/tags.py:97 msgid "grouping" msgstr "grupowanie" #: quodlibet/ext/playorder/shufflebygrouping.py:46 #: quodlibet/ext/playorder/shufflebygrouping.py:133 #: quodlibet/ext/playorder/shufflebygrouping.py:153 msgid "grouping_filter" msgstr "filtr_grupowania" #: quodlibet/ext/playorder/shufflebygrouping.py:94 msgid "Waiting to start new group…" msgstr "Oczekiwanie na rozpoczęcie nowej grupy…" #: quodlibet/ext/playorder/shufflebygrouping.py:144 msgid "Grouping tag:" msgstr "Etykieta grupowania:" #: quodlibet/ext/playorder/shufflebygrouping.py:148 msgid "Tag to group songs by" msgstr "Etykieta, według której grupować utwory" #: quodlibet/ext/playorder/shufflebygrouping.py:150 msgid "Filter tag:" msgstr "Etykieta filtrowania:" #: quodlibet/ext/playorder/shufflebygrouping.py:155 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:160 msgid "Delay:" msgstr "Opóźnienie:" #: quodlibet/ext/playorder/shufflebygrouping.py:166 msgid "Time delay in seconds before starting next group" msgstr "Sekundy przed rozpoczęciem następnej grupy" #: quodlibet/ext/playorder/shufflebygrouping.py:182 msgid "Reset to defaults" msgstr "Przywróć domyślne" #: quodlibet/ext/playorder/skip_songs.py:25 msgid "Skip Songs" msgstr "Pomijanie utworów" #: quodlibet/ext/playorder/skip_songs.py:27 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." #: quodlibet/ext/playorder/track_repeat.py:30 msgid "Repeat Each Track" msgstr "Powtarzanie każdej ścieżki" #: quodlibet/ext/playorder/track_repeat.py:32 msgid "Shuffle songs, but repeat 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:51 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 msgid "" "Chooses the query to match based on a condition query. Syntax is '@(if: " "condition, then, else)'." msgstr "" "Wybiera zapytanie do dopasowania na podstawie zapytania warunkowego. " "Składnia: „@(if: condition, then, else)”." #: quodlibet/ext/query/missing.py:15 msgid "Missing Query" msgstr "Zapytanie brakujących" #: quodlibet/ext/query/missing.py:16 msgid "Matches songs without the given tag." msgstr "Dopasowuje utwory bez podanej etykiety." #: quodlibet/ext/query/missing.py:27 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. Syntax is '@(python: expression)'. The " "variable 's' (or 'a') is the song / album being matched. '_ts' is a (real " "number) timestamp at start of query. Modules 'time' and 'random' are also " "available, and the class 'Random' (==random.Random) 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:19 msgid "Include Saved Search" msgstr "Dołączenie zapisanego wyszukiwania" #: quodlibet/ext/query/savedsearch.py:20 msgid "" "Include the results of a saved search as part of another query. Syntax is " "'@(saved: search name)'." msgstr "" "Dołączenie wyników zapisanego wyszukiwania jako część innego zapytania. " "Składnia: „@(saved: search name)”." #: 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:116 msgid "Port:" msgstr "Port:" #: quodlibet/ext/_shared/squeezebox/base.py:121 msgid "Username:" msgstr "Nazwa użytkownika:" #: quodlibet/ext/_shared/squeezebox/base.py:126 msgid "Password:" msgstr "Hasło:" #: quodlibet/ext/_shared/squeezebox/base.py:130 msgid "Library directory the server connects to" msgstr "Katalog kolekcji, z którym serwer ma się łączyć" #: quodlibet/ext/_shared/squeezebox/base.py:132 msgid "Library path:" msgstr "Ścieżka do kolekcji:" #. Add verify button #: quodlibet/ext/_shared/squeezebox/base.py:141 msgid "_Verify settings" msgstr "_Sprawdź ustawienia" #. Server settings Frame #: quodlibet/ext/_shared/squeezebox/base.py:147 msgid "Squeezebox Server" msgstr "Serwer Squeezebox" #: quodlibet/ext/_shared/squeezebox/base.py:150 msgid "Debug" msgstr "Debugowanie" #: quodlibet/ext/_shared/squeezebox/server.py:26 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "Serwer Squeezebox pod adresem {hostname}:{port}" #: quodlibet/ext/_shared/squeezebox/server.py:28 msgid "unidentified Squeezebox server" msgstr "niezidentyfikowany serwer Squeezebox" #: quodlibet/ext/_shared/squeezebox/server.py:37 #, 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:20 #: quodlibet/ext/songsmenu/importexport.py:39 quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "_OK" #: 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:331 msgid "Fit image to _window" msgstr "Dopasowanie _obrazu do okna" #: quodlibet/ext/songsmenu/albumart.py:337 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:343 msgid "_Program:" msgstr "_Program:" #: quodlibet/ext/songsmenu/albumart.py:348 msgid "_Edit image after saving" msgstr "_Modyfikowanie obrazu po zapisaniu" #: quodlibet/ext/songsmenu/albumart.py:350 msgid "File_name:" msgstr "_Nazwa pliku:" #: quodlibet/ext/songsmenu/albumart.py:466 msgid "Saving failed" msgstr "Zapisanie się nie powiodło" #: quodlibet/ext/songsmenu/albumart.py:467 #, python-format msgid "Unable to save \"%s\"." msgstr "Nie można zapisać „%s”." #: quodlibet/ext/songsmenu/albumart.py:565 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "[albumart] Błąd HTTP: %s" #: quodlibet/ext/songsmenu/albumart.py:622 msgid "Album Art Downloader" msgstr "Pobieranie okładek" #: quodlibet/ext/songsmenu/albumart.py:675 #, python-format msgid "from %(source)s" msgstr "z %(source)s" #: quodlibet/ext/songsmenu/albumart.py:678 #, python-format msgid "Resolution: %s" msgstr "Rozdzielczość: %s" #: quodlibet/ext/songsmenu/albumart.py:681 #, python-format msgid "Size: %s" msgstr "Rozmiar: %s" #: quodlibet/ext/songsmenu/albumart.py:727 msgid "Per engine 'at best' results limit" msgstr "Ograniczenie wyników „co najwyżej” na mechanizm" #: quodlibet/ext/songsmenu/albumart.py:737 msgid "_Search" msgstr "Wy_szukaj" #: quodlibet/ext/songsmenu/albumart.py:819 #: quodlibet/ext/songsmenu/brainz/widgets.py:451 msgid "Searching…" msgstr "Wyszukiwanie…" #: quodlibet/ext/songsmenu/albumart.py:884 #: quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "Gotowe" #: quodlibet/ext/songsmenu/albumart.py:1006 msgid "Download Album Art" msgstr "Pobieranie okładek" #: quodlibet/ext/songsmenu/albumart.py:1007 msgid "Downloads album covers from various websites." msgstr "Pobiera okładki z różnych stron WWW." #: quodlibet/ext/songsmenu/albumart.py:1020 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 msgid "Disc" msgstr "Płyta" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 #: quodlibet/ext/songsmenu/replaygain.py:393 quodlibet/qltk/tracknumbers.py:91 msgid "Track" msgstr "Ścieżka" #: quodlibet/ext/songsmenu/brainz/widgets.py:132 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:447 msgid "Please enter a query." msgstr "Proszę wprowadzić zapytanie." #: quodlibet/ext/songsmenu/brainz/widgets.py:465 #: quodlibet/ext/songsmenu/brainz/widgets.py:496 msgid "Error encountered. Please retry." msgstr "Wystąpił błąd. Proszę ponowić." #: quodlibet/ext/songsmenu/brainz/widgets.py:472 #: quodlibet/ext/songsmenu/brainz/widgets.py:488 msgid "Loading result…" msgstr "Wczytywanie wyników…" #: quodlibet/ext/songsmenu/brainz/widgets.py:475 msgid "No results found." msgstr "Nie odnaleziono wyników." #: quodlibet/ext/songsmenu/console.py:40 msgid "Python Console" msgstr "Konsola języka Python" #: quodlibet/ext/songsmenu/console.py:41 msgid "Interactive Python console. Opens a new window." msgstr "Interaktywna konsola języka Python. Otwiera nowe okno." #: quodlibet/ext/songsmenu/console.py:45 quodlibet/qltk/information.py:554 #: quodlibet/qltk/maskedbox.py:68 quodlibet/util/collection.py:532 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d utwór" msgstr[1] "%d utwory" msgstr[2] "%d utworów" #: quodlibet/ext/songsmenu/console.py:48 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "{plugin_name} dla: {songs} ({app})" #: quodlibet/ext/songsmenu/console.py:55 msgid "Python Console Sidebar" msgstr "Panel boczny konsoli języka Python" #: quodlibet/ext/songsmenu/console.py:56 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:75 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:85 msgid "Your current working directory is:" msgstr "Bieżący katalog roboczy:" #: quodlibet/ext/songsmenu/cover_download.py:119 msgid "Classic" msgstr "Klasyczny" #: quodlibet/ext/songsmenu/cover_download.py:120 msgid "Large" msgstr "Duży" #: quodlibet/ext/songsmenu/cover_download.py:121 msgid "HD" msgstr "HD" #: quodlibet/ext/songsmenu/cover_download.py:122 msgid "Full HD" msgstr "Full HD" #: quodlibet/ext/songsmenu/cover_download.py:123 msgid "WQXGA" msgstr "WQXGA" #: quodlibet/ext/songsmenu/cover_download.py:124 msgid "4K UHD" msgstr "4K UHD" #: quodlibet/ext/songsmenu/cover_download.py:129 msgid "Cover Art Download" msgstr "Pobieranie okładek" #: quodlibet/ext/songsmenu/cover_download.py:180 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "Wczytywanie %(source)s — %(dimensions)s…" #: quodlibet/ext/songsmenu/cover_download.py:231 #, python-format msgid "" "Nothing found for albums:\n" "<i>%(albums)s</i>.\n" "\n" "Providers used:\n" "<tt>%(providers)s</tt>" 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:234 msgid "No covers found" msgstr "Nie odnaleziono okładek" #: quodlibet/ext/songsmenu/cover_download.py:254 #, python-format msgid "%(size)d ✕ %(size)d px" msgstr "%(size)d×%(size)d px" #: quodlibet/ext/songsmenu/cover_download.py:267 msgid "Preview size" msgstr "Rozmiar podglądu" #: quodlibet/ext/songsmenu/cover_download.py:276 msgid "Save destination" msgstr "Miejsce docelowe zapisywania" #: quodlibet/ext/songsmenu/cover_download.py:336 msgid "Download Cover Art" msgstr "Pobieranie okładek" #: quodlibet/ext/songsmenu/cover_download.py:337 msgid "Downloads high-quality album covers using cover plugins." msgstr "Pobiera wysokiej jakości okładki albumów za pomocą wtyczek." #: 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:55 msgid "pattern" msgstr "wzorzec" #: 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:91 msgid "Input value" msgstr "Wprowadzenie wartości" #: quodlibet/ext/songsmenu/custom_commands.py:92 #, python-format msgid "Value for %s?" msgstr "Wartość dla %s?" #: quodlibet/ext/songsmenu/custom_commands.py:137 msgid "Custom Commands" msgstr "Niestandardowe polecenia" #: quodlibet/ext/songsmenu/custom_commands.py:138 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:197 #: quodlibet/ext/songsmenu/custom_commands.py:207 #: quodlibet/ext/songsmenu/custom_commands.py:259 msgid "Edit Custom Commands" msgstr "Modyfikuj niestandardowe polecenia" #: quodlibet/ext/songsmenu/custom_commands.py:290 #, python-format msgid "Unable to run custom command %s" msgstr "Nie można wykonać niestandardowego polecenia %s" #: 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:397 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:399 msgid "_Group duplicates by:" msgstr "_Grupowanie duplikatów według:" #: quodlibet/ext/songsmenu/duplicates.py:404 msgid "Duplicate Key" msgstr "Klucz duplikatu" #: quodlibet/ext/songsmenu/duplicates.py:409 msgid "Remove _Whitespace" msgstr "Usuwanie _spacji" #: quodlibet/ext/songsmenu/duplicates.py:410 msgid "Remove _Diacritics" msgstr "Usuwanie znaków _diakrytycznych" #: quodlibet/ext/songsmenu/duplicates.py:411 msgid "Remove _Punctuation" msgstr "Usuwanie _interpunkcji" #: quodlibet/ext/songsmenu/duplicates.py:412 msgid "Case _Insensitive" msgstr "Rozróżnianie wielkości _liter" #: quodlibet/ext/songsmenu/duplicates.py:420 msgid "Matching options" msgstr "Opcje dopasowywania" #. Create a dialog. #: quodlibet/ext/songsmenu/editplaycount.py:19 #: quodlibet/ext/songsmenu/editplaycount.py:41 msgid "Edit Playcount" msgstr "Modyfikuj liczbę odtworzeń" #: quodlibet/ext/songsmenu/editplaycount.py:20 msgid "" "Edit a song's ~#playcount and ~#skipcount.\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's ~#playcount to 0, the ~#lastplayed and ~#laststarted " "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:68 msgid "Play Count" msgstr "Liczba odtworzeń" #: quodlibet/ext/songsmenu/editplaycount.py:69 msgid "Skip Count" msgstr "Liczba pominięć" #: quodlibet/ext/songsmenu/embedded.py:25 msgid "Edit Embedded Images" msgstr "Modyfikowanie osadzonych obrazów" #: quodlibet/ext/songsmenu/embedded.py:26 msgid "Removes or replaces embedded images." msgstr "Usuwa lub zastępuje osadzone obrazy." #: quodlibet/ext/songsmenu/embedded.py:80 msgid "_Remove all Images" msgstr "_Usuń wszystkie obrazy" #: quodlibet/ext/songsmenu/embedded.py:85 msgid "_Embed Current Image" msgstr "_Osadź obecny obraz" #: 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/exact_rating.py:54 quodlibet/qltk/ratingsmenu.py:98 msgid "Change _Rating" msgstr "Zmień _oceny" #: 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" #: quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" msgstr "Stan" #. 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:65 quodlibet/ext/songsmenu/html.py:75 msgid "Export to HTML" msgstr "Eksport do pliku HTML" #: quodlibet/ext/songsmenu/html.py:66 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:62 msgid "Error uploading" msgstr "Błąd podczas wysyłania" #: quodlibet/ext/songsmenu/ifp.py:63 #, python-format msgid "" "Unable to upload <b>%s</b>. 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/importexport.py:60 msgid "Export Metadata" msgstr "Eksport metadanych" #: quodlibet/ext/songsmenu/importexport.py:61 msgid "Exports metadata of selected songs as a .tags file." msgstr "Eksportuje metadane zaznaczonych utworów jako plik .tags." #: quodlibet/ext/songsmenu/importexport.py:105 msgid "Import Metadata" msgstr "Import metadanych" #: quodlibet/ext/songsmenu/importexport.py:106 msgid "Imports metadata for selected songs from a .tags file." msgstr "Importuje metadane zaznaczonych utworów z pliku .tags." #: quodlibet/ext/songsmenu/k3b.py:23 msgid "Burn CD" msgstr "Nagrywanie płyt CD" #: quodlibet/ext/songsmenu/k3b.py:24 msgid "Burns CDs with K3b, Brasero or xfburn." msgstr "Nagrywa płyty CD za pomocą programu K3b, Brasero lub xfburn." #: quodlibet/ext/songsmenu/lastfmsync.py:97 msgid "Updating chart list." msgstr "Aktualizowanie listy wykresów." #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:116 msgid "Already up-to-date." msgstr "Jest już aktualne." #: quodlibet/ext/songsmenu/lastfmsync.py:124 #, python-format msgid "Fetching chart for week of %s." msgstr "Pobieranie wykresu dla tygodnia: %s." #: quodlibet/ext/songsmenu/lastfmsync.py:146 msgid "Sync complete." msgstr "Synchronizacja ukończona." #: quodlibet/ext/songsmenu/lastfmsync.py:152 msgid "Error during sync" msgstr "Błąd podczas synchronizacji" #: quodlibet/ext/songsmenu/lastfmsync.py:217 #: quodlibet/ext/songsmenu/lastfmsync.py:247 msgid "Last.fm Sync" msgstr "Synchronizacja z serwisem Last.fm" #: quodlibet/ext/songsmenu/lastfmsync.py:248 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:301 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)." #. Create a dialog. #: quodlibet/ext/songsmenu/migratemetadata.py:36 #: quodlibet/ext/songsmenu/migratemetadata.py:45 msgid "Migrate Metadata" msgstr "Migracja metadanych" #: quodlibet/ext/songsmenu/migratemetadata.py:39 msgid "Copies the quodlibet-specific metadata between songs." msgstr "Kopiuje metadane programu Quod Libet między utworami." #: quodlibet/ext/songsmenu/migratemetadata.py:52 msgid "_Copy" msgstr "S_kopiuj" #: quodlibet/ext/songsmenu/migratemetadata.py:54 msgid "_Paste" msgstr "Wk_lej" #. Create the tag table. #: quodlibet/ext/songsmenu/migratemetadata.py:64 msgid "Information to copy/paste" msgstr "Informacje do skopiowania/wklejenia" #. Create the indexing box. #: quodlibet/ext/songsmenu/migratemetadata.py:86 msgid "Map tracks by disc and track number" msgstr "Mapowanie ścieżek według numerów płyty i ścieżki" #: quodlibet/ext/songsmenu/migratemetadata.py:87 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." #: quodlibet/ext/songsmenu/migratemetadata.py:103 #, python-format 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." #: quodlibet/ext/songsmenu/playlist.py:31 msgid "Export as Playlist" msgstr "Wyeksportuj jako listę odtwarzania" #: quodlibet/ext/songsmenu/playlist.py:32 msgid "Exports songs to an M3U or PLS playlist." msgstr "Eksportuje utwory do listy odtwarzania M3U lub PLS." #: quodlibet/ext/songsmenu/playlist.py:77 msgid "Use relative paths" msgstr "Ścieżki względne" #: quodlibet/ext/songsmenu/playlist.py:77 msgid "Use absolute paths" msgstr "Ścieżki bezwzględne" #: quodlibet/ext/songsmenu/playlist.py:133 #, python-format msgid "Writing to <b>%s</b> 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" #: quodlibet/ext/songsmenu/replaygain.py:407 msgid "Progress" msgstr "Postęp" #: quodlibet/ext/songsmenu/replaygain.py:422 msgid "Gain" msgstr "Wzmocnienie" #: quodlibet/ext/songsmenu/replaygain.py:437 msgid "Peak" msgstr "Szczyt" #: quodlibet/ext/songsmenu/replaygain.py:452 #, python-format msgid "There is <b>%(to-process)s</b> album to update (of %(all)s)" msgid_plural "There are <b>%(to-process)s</b> 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:568 msgid "Replay Gain" msgstr "ReplayGain" #: quodlibet/ext/songsmenu/replaygain.py:569 msgid "" "Analyzes and updates ReplayGain information, using GStreamer. Results are " "grouped by album." msgstr "" "Analizuje i aktualizuje informacje ReplayGain za pomocą biblioteki " "GStreamer. Wyniki są grupowane według albumów." #: quodlibet/ext/songsmenu/replaygain.py:607 msgid "always" msgstr "zawsze" #: quodlibet/ext/songsmenu/replaygain.py:608 msgid "if <b>any</b> RG tags are missing" msgstr "jeśli brakuje <b>dowolnych</b> etykiet RG" #: quodlibet/ext/songsmenu/replaygain.py:610 msgid "if <b>album</b> RG tags are missing" msgstr "jeśli brakuje etykiet RG <b>album</b>" #: quodlibet/ext/songsmenu/replaygain.py:627 msgid "_Process albums:" msgstr "_Przetwarzane albumy:" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:639 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 msgid "Tap BPM for the selected song." msgstr "Wystukuje uderzenia na minutę zaznaczonego utworu." #: quodlibet/ext/songsmenu/website_search.py:37 msgid "Website Search" msgstr "Wyszukiwanie na stronie WWW" #: 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-example)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:80 msgid "Search URL patterns" msgstr "Wzorzec adresu URL wyszukiwania" #: quodlibet/ext/songsmenu/website_search.py:90 msgid "Edit search URLs" msgstr "Modyfikowanie adresów URL wyszukiwania" #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:116 msgid "Configure Searches…" msgstr "Skonfiguruj wyszukiwania…" #: quodlibet/ext/songsmenu/wikipedia.py:35 msgid "Search Tag in Wikipedia" msgstr "Wyszukiwanie etykiety w angielskiej Wikipedii" #: quodlibet/ext/songsmenu/wikipedia.py:36 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:56 #, python-format msgid "Search at %(website)s" msgstr "Wyszukaj w serwisie %(website)s" #: quodlibet/ext/songsmenu/wikipedia.py:70 #: quodlibet/ext/songsmenu/wikipedia.py:76 quodlibet/qltk/edittags.py:443 msgid "Edit Tags" msgstr "Modyfikuj etykiety" #: quodlibet/ext/songsmenu/wikipedia.py:111 msgid "Search failed" msgstr "Wyszukanie się nie powiodło" #: quodlibet/ext/songsmenu/wikipedia.py:112 #, python-format msgid "Tag \"%s\" not found." msgstr "Nie odnaleziono etykiety „%s”." #. then (try to) load all new files #: quodlibet/library/libraries.py:651 quodlibet/library/libraries.py:661 #: quodlibet/library/libraries.py:727 quodlibet/library/libraries.py:746 #: quodlibet/qltk/information.py:272 quodlibet/qltk/prefs.py:692 #: quodlibet/util/library.py:123 msgid "Library" msgstr "Kolekcja" #: quodlibet/library/libraries.py:651 msgid "Checking mount points" msgstr "Wyszukiwanie punktów montowania" #: quodlibet/library/libraries.py:661 msgid "Scanning library" msgstr "Skanowanie kolekcji" #: quodlibet/library/libraries.py:726 #, python-format msgid "Scanning %s" msgstr "Skanowanie %s" #: quodlibet/library/libraries.py:746 msgid "Loading files" msgstr "Wczytywanie plików" #: quodlibet/main.py:50 msgid "Music player and music library manager" msgstr "Odtwarzacz muzyki i menedżer kolekcji" #: quodlibet/operon/base.py:70 #, 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:462 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:464 #, 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:336 quodlibet/operon/commands.py:340 #: quodlibet/operon/commands.py:392 quodlibet/operon/commands.py:395 #: quodlibet/operon/commands.py:434 quodlibet/operon/commands.py:469 #: quodlibet/operon/commands.py:509 quodlibet/operon/commands.py:544 #: quodlibet/operon/commands.py:586 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:471 msgid "Too many arguments" msgstr "Za dużo parametrów" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:91 #: quodlibet/operon/commands.py:476 quodlibet/qltk/data_editors.py:352 msgid "Description" msgstr "Opis" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:476 #: quodlibet/qltk/edittags.py:493 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:324 #: quodlibet/operon/commands.py:385 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:304 quodlibet/operon/commands.py:445 #: quodlibet/operon/commands.py:677 #, python-format msgid "Can not set %r" msgstr "Nie można ustawić %r" #: quodlibet/operon/commands.py:319 msgid "Remove tags" msgstr "Usuwa etykiety" #: quodlibet/operon/commands.py:326 quodlibet/operon/commands.py:387 msgid "Value is a regular expression" msgstr "Wartość jest wyrażeniem regularnym" #: quodlibet/operon/commands.py:328 msgid "Remove all tags" msgstr "Usuwa wszystkie etykiety" #: quodlibet/operon/commands.py:332 msgid "Can't combine '--all' with '--regexp'" msgstr "Nie można łączyć „--all” z „--regexp”" #: quodlibet/operon/commands.py:366 #, python-brace-format msgid "Can't remove {tagname} from {filename}" msgstr "Nie można usunąć {tagname} z {filename}" #: quodlibet/operon/commands.py:380 msgid "Remove a tag value" msgstr "Usuwa wartość etykiety" #: quodlibet/operon/commands.py:429 msgid "Add a tag value" msgstr "Dodaje wartość etykiety" #: quodlibet/operon/commands.py:457 msgid "List file information" msgstr "Wyświetla informacje o pliku" #: quodlibet/operon/commands.py:503 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:516 #, python-format msgid "Failed to load image file: %r" msgstr "Wczytanie pliku obrazu się nie powiodło: %r" #: quodlibet/operon/commands.py:523 quodlibet/operon/commands.py:552 #, 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:539 msgid "Remove all embedded images" msgstr "Usuwa wszystkie osadzone obrazy" #: quodlibet/operon/commands.py:569 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "Wydobywa osadzone obrazy do %(filepath)s" #: quodlibet/operon/commands.py:581 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:640 msgid "Rename files based on tags" msgstr "Zmienia nazwy plików na podstawie etykiet" #: quodlibet/operon/commands.py:655 msgid "Fill tags based on the file path" msgstr "Wypełnia etykiety na podstawie ścieżek plików" #: quodlibet/operon/commands.py:705 quodlibet/qltk/information.py:309 #: quodlibet/qltk/properties.py:83 quodlibet/qltk/renamefiles.py:224 #: quodlibet/qltk/tagsfrompath.py:228 quodlibet/qltk/tracknumbers.py:78 msgid "File" msgstr "Plik" #: quodlibet/operon/commands.py:713 msgid "Fill tracknumbers for all files" msgstr "Wypełnia numery ścieżek dla wszystkich plików" #: quodlibet/operon/commands.py:732 msgid "Print tags based on the given pattern" msgstr "Wyświetla etykiety na podstawie podanego wzorca" #: quodlibet/operon/commands.py:769 msgid "Display help information" msgstr "Wyświetla informacje o pomocy" #: quodlibet/operon/util.py:43 #, 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:30 msgid "_Unknown" msgstr "_Nieznane" #: quodlibet/order/__init__.py:142 msgid "In Order" msgstr "W kolejności" #: quodlibet/order/__init__.py:143 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:147 msgid "_Random" msgstr "_Losowo" #: quodlibet/order/reorder.py:40 quodlibet/order/reorder.py:41 msgid "Prefer higher rated" msgstr "Preferowanie wyżej ocenionych" #: quodlibet/order/repeat.py:43 quodlibet/order/repeat.py:44 msgid "Repeat this track" msgstr "Powtarzanie tej ścieżki" #: quodlibet/order/repeat.py:57 quodlibet/order/repeat.py:58 msgid "Repeat all" msgstr "Powtarzanie wszystkich" #: quodlibet/order/repeat.py:73 quodlibet/order/repeat.py:74 msgid "One Song" msgstr "Pojedynczo" #: quodlibet/player/gstbe/player.py:98 msgid "Stream" msgstr "Strumień" #: quodlibet/player/gstbe/player.py:98 msgid "Buffering" msgstr "Buforowanie" #: quodlibet/player/gstbe/player.py:452 msgid "Could not create GStreamer pipeline" msgstr "Nie można utworzyć potoku biblioteki GStreamer" #: quodlibet/player/gstbe/player.py:651 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:652 #, 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:25 msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. In case 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:36 msgid "_Output pipeline:" msgstr "_Potok wyjściowy:" #: quodlibet/player/gstbe/prefs.py:43 #, python-format msgid "%.1f seconds" msgstr "%.1f s" #: quodlibet/player/gstbe/prefs.py:57 msgid "_Buffer duration:" msgstr "Długość _bufora:" #: quodlibet/player/gstbe/prefs.py:66 msgid "Disable _gapless playback" msgstr "Wyłączenie płynnego _odtwarzania" #: quodlibet/player/gstbe/prefs.py:70 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/util.py:101 msgid "No GStreamer audio sink found" msgstr "Nie odnaleziono żadnych odpływów dźwięku biblioteki GStreamer" #: quodlibet/player/gstbe/util.py:120 msgid "Invalid GStreamer output pipeline" msgstr "Nieprawidłowy potok wyjściowy biblioteki GStreamer" #: quodlibet/player/xinebe/player.py:90 msgid "Unable to create audio output" msgstr "Nie można utworzyć wyjścia dźwięku" #: quodlibet/player/xinebe/player.py:91 #, 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:61 #, 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:70 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "Nie można odnaleźć elementu biblioteki GStreamer „{element}”." #: 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:55 #: quodlibet/qltk/songsmenu.py:66 msgid "_Run Plugin" msgstr "_Uruchom wtyczkę" #. 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:40 msgid "_Name:" msgstr "_Nazwa:" #: quodlibet/qltk/cbes.py:48 quodlibet/qltk/edittags.py:350 msgid "_Value:" msgstr "_Wartość:" #: quodlibet/qltk/cbes.py:263 msgid "Saved Values" msgstr "Zapisane wartości" #: quodlibet/qltk/cbes.py:264 msgid "Edit saved values…" msgstr "Modyfikuj zapisane wartości…" #: quodlibet/qltk/controls.py:111 msgid "Auto_matic" msgstr "Auto_matycznie" #: quodlibet/qltk/controls.py:112 msgid "_Track Mode" msgstr "Tryb ś_cieżek" #: quodlibet/qltk/controls.py:113 msgid "_Album Mode" msgstr "Tryb _albumów" #. Translators: player state, no action #: quodlibet/qltk/controls.py:122 msgid "_Mute" msgstr "Wy_ciszenie" #: quodlibet/qltk/controls.py:128 msgid "_Replay Gain Mode" msgstr "_Tryb ReplayGain" #. Set replaygain mode as saved in configuration #: quodlibet/qltk/controls.py:133 msgid "player" msgstr "odtwarzacz" #. Translators: New Command/Entry/Item/... #: quodlibet/qltk/data_editors.py:116 #, python-format msgid "New %s" msgstr "Nowe %s" #: quodlibet/qltk/data_editors.py:215 msgid "(unknown)" msgstr "(nieznany)" #: quodlibet/qltk/data_editors.py:344 msgid "Tag expression" msgstr "Wrażenie etykiety" #: quodlibet/qltk/data_editors.py:371 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:372 msgid "Enter new tag" msgstr "Nowa etykieta" #: 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: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: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/edittags.py:197 msgid "Split into _Multiple Values" msgstr "Rozdziel na _wiele wartości" #: quodlibet/qltk/edittags.py:200 quodlibet/qltk/edittags.py:208 #: quodlibet/qltk/edittags.py:246 quodlibet/qltk/edittags.py:247 #: quodlibet/qltk/edittags.py:261 quodlibet/qltk/edittags.py:262 #: quodlibet/qltk/edittags.py:275 quodlibet/qltk/edittags.py:276 #: quodlibet/qltk/edittags.py:290 quodlibet/qltk/edittags.py:291 #: quodlibet/qltk/tagsfrompath.py:72 msgid "editing" msgstr "modyfikowanie" #: quodlibet/qltk/edittags.py:219 msgid "Split Disc out of _Album" msgstr "Oddziel płytę od al_bumu" #: quodlibet/qltk/edittags.py:243 msgid "Split _Version out of Title" msgstr "Oddziel _wersję od tytułu" #: quodlibet/qltk/edittags.py:298 msgid "Split Arranger out of Ar_tist" msgstr "Oddziel aranżera od _wykonawcy" #: quodlibet/qltk/edittags.py:303 msgid "Split _Performer out of Artist" msgstr "Oddziel _wykonawcę od wykonawcy" #: quodlibet/qltk/edittags.py:309 msgid "Split _Performer out of Title" msgstr "Oddziel _wykonawcę od tytułu" #: quodlibet/qltk/edittags.py:315 msgid "Split _Originalartist out of Title" msgstr "Oddziel p_ierwotnego wykonawcę od tytułu" #: quodlibet/qltk/edittags.py:322 msgid "Add a Tag" msgstr "Dodaj etykietę" #: quodlibet/qltk/edittags.py:341 msgid "_Tag:" msgstr "_Etykieta:" #: quodlibet/qltk/edittags.py:516 msgid "Show _programmatic tags" msgstr "_Wyświetlanie etykiet programistycznych" #: quodlibet/qltk/edittags.py:517 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" #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:547 msgctxt "edittags" msgid "_Revert" msgstr "_Odwrotnie" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:552 msgctxt "edittags" msgid "_Save" msgstr "_Zapisz" #: quodlibet/qltk/edittags.py:681 msgid "_Configure" msgstr "_Konfiguruj" #: quodlibet/qltk/edittags.py:696 msgid "_Split Tag" msgstr "_Rozdziel etykietę" #: quodlibet/qltk/edittags.py:705 msgid "_Copy Value(s)" msgstr "S_kopiuj wartości" #: quodlibet/qltk/edittags.py:736 msgid "Unable to add tag" msgstr "Nie można dodać etykiety" #: quodlibet/qltk/edittags.py:737 #, python-format msgid "Unable to add <b>%s</b>" msgstr "Nie można dodać <b>%s</b>" #: quodlibet/qltk/edittags.py:739 #, python-format msgid "" "The files currently selected do not support multiple values for <b>%s</b>." msgstr "Zaznaczone pliki nie obsługują wielu wartości dla <b>%s</b>." #. Can't add the new tag. #: quodlibet/qltk/edittags.py:766 quodlibet/qltk/edittags.py:947 #: quodlibet/qltk/tagsfrompath.py:211 quodlibet/util/__init__.py:505 #: quodlibet/util/tags.py:243 msgid "Invalid tag" msgstr "Nieprawidłowa etykieta" #: quodlibet/qltk/edittags.py:767 quodlibet/qltk/edittags.py:948 #: quodlibet/qltk/tagsfrompath.py:212 #, python-format msgid "" "Invalid tag <b>%s</b>\n" "\n" "The files currently selected do not support editing this tag." msgstr "" "Nieprawidłowa etykieta <b>%s</b>\n" "\n" "Zaznaczone pliki nie obsługują modyfikowania tej etykiety." #: quodlibet/qltk/edittags.py:918 quodlibet/qltk/edittags.py:959 msgid "Invalid value" msgstr "Nieprawidłowa wartość" #: quodlibet/qltk/edittags.py:919 quodlibet/qltk/edittags.py:960 #, python-format msgid "" "Invalid value: <b>%(value)s</b>\n" "\n" "%(error)s" msgstr "" "Nieprawidłowa wartość: <b>%(value)s</b>\n" "\n" "%(error)s" #: quodlibet/qltk/_editutils.py:29 msgid "Tag may not be accurate" msgstr "Etykieta może być niewłaściwa" #: quodlibet/qltk/_editutils.py:32 #, 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:48 msgid "Unable to save song" msgstr "Nie można zapisać utworu" #: quodlibet/qltk/_editutils.py:51 #, 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:143 msgid "_More options…" msgstr "_Więcej opcji…" #: quodlibet/qltk/entry.py:78 msgid "_Undo" msgstr "C_ofnij" #: quodlibet/qltk/entry.py:80 msgid "_Redo" msgstr "Po_nów" #: quodlibet/qltk/exfalsowindow.py:94 quodlibet/qltk/quodlibetwindow.py:956 msgid "_About" msgstr "_O programie" #: quodlibet/qltk/exfalsowindow.py:98 quodlibet/qltk/quodlibetwindow.py:978 msgid "_Check for Updates…" msgstr "Wy_szukaj aktualizacje…" #: quodlibet/qltk/exfalsowindow.py:104 quodlibet/qltk/quodlibetwindow.py:911 #: quodlibet/qltk/songsmenu.py:289 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:278 msgid "Ex Falso Preferences" msgstr "Preferencje programu Ex Falso" #: quodlibet/qltk/exfalsowindow.py:284 quodlibet/qltk/prefs.py:666 msgid "Tag Editing" msgstr "Modyfikowanie etykiet" #: 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:386 msgid "Unable to create folder" msgstr "Nie można utworzyć katalogu" #: quodlibet/qltk/filesel.py:403 msgid "Unable to delete folder" msgstr "Nie można usunąć katalogu" #: quodlibet/qltk/filesel.py:519 quodlibet/qltk/pluginwin.py:167 msgid "Songs" msgstr "Utwory" #. Translators: As in "by Artist Name" #: quodlibet/qltk/info.py:42 #, python-format msgid "by %s" msgstr " %s" #: quodlibet/qltk/info.py:43 quodlibet/qltk/information.py:171 #: quodlibet/qltk/information.py:452 #, python-format msgid "Disc %s" msgstr "%s. płyta" #: quodlibet/qltk/info.py:44 quodlibet/qltk/information.py:176 #, python-format msgid "Track %s" msgstr "%s. ścieżka" #: quodlibet/qltk/info.py:108 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:342 #: quodlibet/qltk/information.py:475 quodlibet/qltk/information.py:543 msgid "Information" msgstr "Informacje" #: quodlibet/qltk/information.py:127 msgid "Lyrics" msgstr "Tekst utworu" #: quodlibet/qltk/information.py:188 quodlibet/qltk/information.py:400 #, python-format msgid "Produced by %s" msgstr "Wyprodukowane przez %s" #: quodlibet/qltk/information.py:203 quodlibet/util/tags.py:85 msgid "artist" msgstr "wykonawca" #: quodlibet/qltk/information.py:204 quodlibet/qltk/information.py:573 #: quodlibet/util/tags.py:85 msgid "artists" msgstr "wykonawcy" #. for backwards compat #: quodlibet/qltk/information.py:225 quodlibet/util/tags.py:96 #: quodlibet/util/tags.py:124 msgid "performers" msgstr "wykonawcy" #: quodlibet/qltk/information.py:239 quodlibet/qltk/information.py:252 #: quodlibet/qltk/songlistcolumns.py:276 msgid "Never" msgstr "Nigdy" #: quodlibet/qltk/information.py:258 quodlibet/util/tags.py:149 msgid "added" msgstr "dodano" #: quodlibet/qltk/information.py:259 quodlibet/util/tags.py:150 msgid "last played" msgstr "ostatnio odtworzone" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:160 msgid "plays" msgstr "odtwarzań" #: quodlibet/qltk/information.py:261 quodlibet/util/tags.py:161 msgid "skips" msgstr "pominięć" #: quodlibet/qltk/information.py:262 quodlibet/util/tags.py:166 msgid "rating" msgstr "ocena" #: quodlibet/qltk/information.py:291 msgid "path" msgstr "ścieżka" #: quodlibet/qltk/information.py:292 quodlibet/util/tags.py:164 msgid "length" msgstr "długość" #: quodlibet/qltk/information.py:293 msgid "format" msgstr "format" #: quodlibet/qltk/information.py:294 quodlibet/util/tags.py:174 msgid "codec" msgstr "kodek" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:175 msgid "encoding" msgstr "kodowanie" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:171 msgid "bitrate" msgstr "gęstość bitowa" #: quodlibet/qltk/information.py:297 quodlibet/util/tags.py:172 msgid "file size" msgstr "rozmiar pliku" #: quodlibet/qltk/information.py:298 quodlibet/util/tags.py:159 msgid "modified" msgstr "zmodyfikowano" #: quodlibet/qltk/information.py:335 msgid "Additional" msgstr "Dodatkowe" #: quodlibet/qltk/information.py:383 quodlibet/util/collection.py:251 #, 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/qltk/information.py:385 quodlibet/util/collection.py:247 #, 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/qltk/information.py:387 #, 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:462 msgid "Track unavailable" msgstr "Ścieżka jest niedostępna" #: quodlibet/qltk/information.py:468 msgid "Track List" msgstr "Lista ścieżek" #: quodlibet/qltk/information.py:500 quodlibet/qltk/information.py:590 #, 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:503 msgid "Selected Discography" msgstr "Wybrana dyskografia" #: quodlibet/qltk/information.py:570 #, 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:598 quodlibet/util/tags.py:83 msgid "albums" msgstr "albumy" #: quodlibet/qltk/information.py:611 msgid "Total length:" msgstr "Całkowita długość:" #: quodlibet/qltk/information.py:615 msgid "Total size:" msgstr "Całkowity rozmiar:" #: quodlibet/qltk/information.py:618 msgid "Files" msgstr "Pliki" #: quodlibet/qltk/lyrics.py:36 msgid "_View online" msgstr "_Wyświetl w Internecie" #: quodlibet/qltk/lyrics.py:64 msgid "No lyrics found for this song." msgstr "Nie odnaleziono tekstu tego utworu." #: quodlibet/qltk/lyrics.py:75 msgid "Searching for lyrics…" msgstr "Wyszukiwanie tekstu 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/msg.py:41 msgid "Discard tag changes?" msgstr "Odrzucić zmiany w etykietach?" #: quodlibet/qltk/msg.py:42 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:55 quodlibet/qltk/prefs.py:628 #: quodlibet/qltk/prefs.py:635 quodlibet/qltk/textedit.py:63 #: quodlibet/qltk/tracknumbers.py:116 msgid "_Revert" msgstr "_Przywróć" #: quodlibet/qltk/msg.py:104 msgid "File exists" msgstr "Plik istnieje" #: quodlibet/qltk/msg.py:106 #, python-format msgid "Replace %(file-name)s?" msgstr "Zastąpić %(file-name)s?" #: quodlibet/qltk/msg.py:112 msgid "_Replace File" msgstr "_Zastąp plik" #: quodlibet/qltk/notif.py:182 msgid "Active tasks" msgstr "Aktywne zadania" #: quodlibet/qltk/notif.py:188 #, python-format msgid "%d tasks running" msgstr "Uruchomione zadania: %d" #: quodlibet/qltk/playorder.py:256 msgid "Toggle shuffle mode" msgstr "Przełącza tryb losowy" #: quodlibet/qltk/playorder.py:272 msgid "Toggle repeat mode" msgstr "Przełącza tryb powtarzania" #: quodlibet/qltk/pluginwin.py:44 msgid "Plugin Errors" msgstr "Błędy wtyczek" #: quodlibet/qltk/pluginwin.py:124 msgid "Enabled" msgstr "Włączone" #: quodlibet/qltk/pluginwin.py:125 msgid "Disabled" msgstr "Wyłączone" #: quodlibet/qltk/pluginwin.py:131 msgid "No category" msgstr "Brak kategorii" #: quodlibet/qltk/pluginwin.py:169 msgid "Events" msgstr "Wydarzenia" #: quodlibet/qltk/pluginwin.py:170 msgid "Play Order" msgstr "Kolejność odtwarzania" #: quodlibet/qltk/pluginwin.py:171 msgid "Editing" msgstr "Modyfikowanie" #: quodlibet/qltk/pluginwin.py:173 msgid "Covers" msgstr "Okładki" #: quodlibet/qltk/pluginwin.py:309 msgid "No plugins found." msgstr "Nie odnaleziono żadnych wtyczek." #: quodlibet/qltk/pluginwin.py:358 msgid "Plugins" msgstr "Wtyczki" #: quodlibet/qltk/pluginwin.py:382 msgid "Filter by plugin state / tag" msgstr "Filtrowanie według stanu wtyczki/etykiety" #: quodlibet/qltk/pluginwin.py:388 msgid "Filter by plugin type" msgstr "Filtrowanie według typu wtyczki" #: quodlibet/qltk/pluginwin.py:394 msgid "Filter by plugin name or description" msgstr "Filtrowanie według nazwy lub opisu wtyczki" #: quodlibet/qltk/pluginwin.py:403 msgid "Show _Errors" msgstr "Wyświetlanie _błędów" #: quodlibet/qltk/prefs.py:45 msgid "_Disc" msgstr "_Płyta" #: quodlibet/qltk/prefs.py:46 msgid "_Track" msgstr "Ścież_ka" #: quodlibet/qltk/prefs.py:47 msgid "Grou_ping" msgstr "_Grupowanie" #: quodlibet/qltk/prefs.py:50 msgid "Al_bum" msgstr "Al_bum" #: quodlibet/qltk/prefs.py:55 msgid "_Filename" msgstr "_Nazwa pliku" #: quodlibet/qltk/prefs.py:57 msgid "_Length" msgstr "_Długość" #: quodlibet/qltk/prefs.py:64 msgid "_Jump to playing song automatically" msgstr "Automatyczne p_rzechodzenie do odtwarzanego utworu" #: quodlibet/qltk/prefs.py:66 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:82 msgid "_Others:" msgstr "_Inne:" #: quodlibet/qltk/prefs.py:88 msgid "_Edit…" msgstr "_Modyfikuj…" #: quodlibet/qltk/prefs.py:91 msgid "Add or remove additional column headers" msgstr "Dodawanie lub usuwanie dodatkowych nagłówków kolumn" #: quodlibet/qltk/prefs.py:101 msgid "Visible Columns" msgstr "Widoczne kolumny" #: quodlibet/qltk/prefs.py:104 msgid "Title includes _version" msgstr "Tytuł zawiera _wersję" #: quodlibet/qltk/prefs.py:106 msgid "Artist includes all _people" msgstr "Wykonawca zawiera wszystkie _osoby" #: quodlibet/qltk/prefs.py:108 msgid "Album includes _disc subtitle" msgstr "Album zawiera p_odpis płyty" #: quodlibet/qltk/prefs.py:110 msgid "Filename includes _folder" msgstr "Nazwa pliku zawiera _katalog" #: quodlibet/qltk/prefs.py:123 msgid "Column Preferences" msgstr "Preferencje kolumn" #: quodlibet/qltk/prefs.py:129 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:142 quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Lista utworów" #: quodlibet/qltk/prefs.py:222 msgid "Edit Columns" msgstr "Modyfikuj kolumny" #: quodlibet/qltk/prefs.py:259 msgid "Duration totals" msgstr "Całkowity czas trwania" #: quodlibet/qltk/prefs.py:271 msgid "_Global filter:" msgstr "_Filtr globalny:" #: quodlibet/qltk/prefs.py:277 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:283 msgctxt "heading" msgid "Search" msgstr "Wyszukiwanie" #: quodlibet/qltk/prefs.py:287 quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Przeglądarki" #: quodlibet/qltk/prefs.py:293 msgid "Confirm _multiple ratings" msgstr "Potwierdzanie _wielu ocen" #: quodlibet/qltk/prefs.py:295 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:298 msgid "Enable _one-click ratings" msgstr "Oceny jednym _kliknięciem" #: quodlibet/qltk/prefs.py:300 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:306 quodlibet/qltk/prefs.py:669 msgid "Ratings" msgstr "Oceny" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:312 msgid "Prefer _embedded art" msgstr "Preferowanie okładek _osadzonych" #: quodlibet/qltk/prefs.py:314 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:319 msgid "_Fixed image filename:" msgstr "_Stała nazwa pliku obrazu:" #: quodlibet/qltk/prefs.py:321 msgid "The single image filename to use if selected" msgstr "Jedyna używana nazwa pliku obrazu, jeśli zaznaczono" #: quodlibet/qltk/prefs.py:327 msgid "The album art image file to use when forced (supports wildcards)" msgstr "Obraz okładki używany podczas wymuszania (obsługuje wieloznaczniki)" #: quodlibet/qltk/prefs.py:337 msgid "Album Art" msgstr "Okładki" #: quodlibet/qltk/prefs.py:358 msgid "Playback" msgstr "Odtwarzanie" #: quodlibet/qltk/prefs.py:363 msgid "Output Configuration" msgstr "Konfiguracja wyjścia" #: quodlibet/qltk/prefs.py:374 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:377 msgid "_Fall-back gain (dB):" msgstr "Wzmocnienie _zapasowe (dB):" #: quodlibet/qltk/prefs.py:388 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:391 msgid "_Pre-amp gain (dB):" msgstr "_Przedwzmocnienie (dB):" #: quodlibet/qltk/prefs.py:396 msgid "_Enable Replay Gain volume adjustment" msgstr "Dopasowywanie głośności _ReplayGain" #: quodlibet/qltk/prefs.py:421 msgid "Replay Gain Volume Adjustment" msgstr "Dopasowywanie głośności ReplayGain" #: quodlibet/qltk/prefs.py:428 msgid "_Continue playback on startup" msgstr "_Kontynuowanie odtwarzania po uruchomieniu" #: quodlibet/qltk/prefs.py:430 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:434 msgid "Startup" msgstr "Uruchamianie" #: quodlibet/qltk/prefs.py:461 msgid "_Default rating:" msgstr "_Domyślna ocena:" #: quodlibet/qltk/prefs.py:504 msgid "Rating _scale:" msgstr "_Skala ocen:" #: quodlibet/qltk/prefs.py:553 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:558 msgid "_Bayesian averaging amount:" msgstr "Ilość uśredniania _Bayesa:" #: quodlibet/qltk/prefs.py:567 msgid "Save ratings and play _counts in tags" msgstr "Zapisywanie ocen i _liczby odtworzeń w etykietach" #: quodlibet/qltk/prefs.py:575 msgid "_Email:" msgstr "Adres _e-mail:" #: quodlibet/qltk/prefs.py:577 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:597 msgid "Auto-save tag changes" msgstr "Automatyczne zapisywanie zmian etykiet" #: quodlibet/qltk/prefs.py:599 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:608 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:618 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:631 msgid "Split _tag on:" msgstr "_Rozdzielanie etykiety przy:" #: quodlibet/qltk/prefs.py:638 msgid "Split _subtag on:" msgstr "Rozdzielanie _etykiety podrzędnej przy:" #: quodlibet/qltk/prefs.py:663 msgid "Tags" msgstr "Etykiety" #: quodlibet/qltk/prefs.py:684 msgid "Updating for new ratings" msgstr "Aktualizowanie dla nowych ocen" #: quodlibet/qltk/prefs.py:694 msgid "Scan library _on start" msgstr "_Skanowanie kolekcji podczas uruchamiania" #: quodlibet/qltk/prefs.py:704 quodlibet/qltk/quodlibetwindow.py:990 msgid "_Scan Library" msgstr "_Skanuj kolekcję" #: quodlibet/qltk/prefs.py:706 quodlibet/qltk/quodlibetwindow.py:1052 msgid "Check for changes in your library" msgstr "Wyszukuje zmiany w kolekcji" #: quodlibet/qltk/prefs.py:711 msgid "Re_build Library" msgstr "_Ponownie zbuduj kolekcję" #: quodlibet/qltk/prefs.py:714 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:724 msgid "Scan Directories" msgstr "Skanowane katalogów" #: quodlibet/qltk/prefs.py:730 msgid "Hidden Songs" msgstr "Ukryte utwory" #: quodlibet/qltk/properties.py:157 quodlibet/util/collection.py:403 #, 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:104 msgid "_Queue" msgstr "_Kolejka" #: quodlibet/qltk/queue.py:124 msgid "Ephemeral" msgstr "Nietrwała" #: quodlibet/qltk/queue.py:125 msgid "Remove songs from the queue after playing them" msgstr "Usuwa utwory z kolejki po ich odtworzeniu" #: quodlibet/qltk/queue.py:133 msgid "Persistent" msgstr "Trwała" #: quodlibet/qltk/queue.py:134 msgid "Keep songs in the queue after playing them" msgstr "Nie usuwa utworów z kolejki po ich odtworzeniu" #: quodlibet/qltk/queue.py:142 msgid "Mode" msgstr "Tryb" #: quodlibet/qltk/queue.py:153 msgid "Stop at End" msgstr "Zatrzymanie na końcu" #: quodlibet/qltk/queue.py:157 msgid "_Clear Queue" msgstr "Wy_czyść kolejkę" #: quodlibet/qltk/queue.py:178 msgid "Disable queue - the queue will be ignored when playing" msgstr "Wyłącza kolejkę — kolejka będzie ignorowana podczas odtwarzania" #: quodlibet/qltk/queue.py:290 #, 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:198 msgid "_Browse Library" msgstr "_Przeglądaj kolekcję" #: quodlibet/qltk/quodlibetwindow.py:348 msgid "Toggle queue visibility" msgstr "Przełącza widoczność kolejki" #: quodlibet/qltk/quodlibetwindow.py:376 msgid "Playback Error" msgstr "Błąd odtwarzania" #: quodlibet/qltk/quodlibetwindow.py:384 msgid "Set up library directories?" msgstr "Ustawić katalogi kolekcji?" #: quodlibet/qltk/quodlibetwindow.py:385 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:391 msgid "_Not Now" msgstr "_Nie teraz" #: quodlibet/qltk/quodlibetwindow.py:392 msgid "_Set Up" msgstr "_Ustaw" #: quodlibet/qltk/quodlibetwindow.py:845 msgid "Unable to add songs" msgstr "Nie można dodać utworów" #: quodlibet/qltk/quodlibetwindow.py:846 quodlibet/qltk/quodlibetwindow.py:1286 #, python-format msgid "%s uses an unsupported protocol." msgstr "%s używa nieobsługiwanego protokołu." #: quodlibet/qltk/quodlibetwindow.py:869 msgid "_Jump to Playing Song" msgstr "_Przejdź do odtwarzanego utworu" #: quodlibet/qltk/quodlibetwindow.py:876 msgid "_File" msgstr "_Plik" #: quodlibet/qltk/quodlibetwindow.py:877 msgid "_Song" msgstr "_Utwór" #: quodlibet/qltk/quodlibetwindow.py:878 msgid "_View" msgstr "_Widok" #: quodlibet/qltk/quodlibetwindow.py:879 msgid "_Browse" msgstr "P_rzeglądaj" #: quodlibet/qltk/quodlibetwindow.py:880 msgid "_Control" msgstr "_Sterowanie" #: quodlibet/qltk/quodlibetwindow.py:881 msgid "_Help" msgstr "Pomo_c" #: quodlibet/qltk/quodlibetwindow.py:887 msgid "_Add a Folder…" msgstr "_Dodaj katalog…" #: quodlibet/qltk/quodlibetwindow.py:892 msgid "_Add a File…" msgstr "_Dodaj plik…" #: quodlibet/qltk/quodlibetwindow.py:897 msgid "_Add a Location…" msgstr "_Dodaj położenie…" #: quodlibet/qltk/quodlibetwindow.py:926 msgid "Edit Bookmarks…" msgstr "Modyfikuj zakładki…" #: quodlibet/qltk/quodlibetwindow.py:946 msgid "Stop After This Song" msgstr "Zatrzymaj po tym utworze" #: quodlibet/qltk/quodlibetwindow.py:952 msgid "_Keyboard Shortcuts" msgstr "_Skróty klawiszowe" #: quodlibet/qltk/quodlibetwindow.py:961 msgid "Online Help" msgstr "Pomoc online" #: quodlibet/qltk/quodlibetwindow.py:970 msgid "Search Help" msgstr "Przeszukiwanie pomocy" #: quodlibet/qltk/quodlibetwindow.py:1274 msgid "Add a Location" msgstr "Dodaj położenie" #: quodlibet/qltk/quodlibetwindow.py:1275 msgid "Enter the location of an audio file:" msgstr "Położenie pliku dźwiękowego:" #: quodlibet/qltk/quodlibetwindow.py:1280 #: quodlibet/qltk/quodlibetwindow.py:1285 msgid "Unable to add location" msgstr "Nie można dodać położenia" #: quodlibet/qltk/quodlibetwindow.py:1281 #, python-format msgid "%s is not a valid location." msgstr "%s nie jest prawidłowym położeniem." #: quodlibet/qltk/quodlibetwindow.py:1294 #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "Add Music" msgstr "Dodaj muzykę" #: quodlibet/qltk/quodlibetwindow.py:1294 quodlibet/qltk/scanbox.py:99 msgid "_Add Folders" msgstr "_Dodaj katalogi" #: quodlibet/qltk/quodlibetwindow.py:1301 msgid "Music Files" msgstr "Pliki muzyczne" #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "_Add Files" msgstr "_Dodaj pliki" #: quodlibet/qltk/ratingsmenu.py:24 #, 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:26 msgid "The saved ratings will be removed" msgstr "Zapisane oceny zostaną usunięte" #: quodlibet/qltk/ratingsmenu.py:27 #, 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:57 quodlibet/qltk/ratingsmenu.py:111 msgid "_Remove Rating" msgstr "_Usuń oceny" #: quodlibet/qltk/renamefiles.py:51 msgid "Replace spaces with _underscores" msgstr "Zmienianie spacji na p_odkreślenia" #: quodlibet/qltk/renamefiles.py:61 msgid "Strip _Windows-incompatible characters" msgstr "Usuwanie znaków niezgodnych z systemem _Windows" #: quodlibet/qltk/renamefiles.py:79 msgid "Strip _diacritical marks" msgstr "Usuwanie znaków _diakrytycznych" #: quodlibet/qltk/renamefiles.py:90 msgid "Strip non-_ASCII characters" msgstr "Usuwanie znaków spoza zestawu _ASCII" #: quodlibet/qltk/renamefiles.py:100 msgid "Use only _lowercase characters" msgstr "Używanie tylko _małych znaków" #: quodlibet/qltk/renamefiles.py:128 msgid "Rename Files" msgstr "Zmień nazwy plików" #: quodlibet/qltk/renamefiles.py:146 quodlibet/qltk/tagsfrompath.py:115 msgid "Path Patterns" msgstr "Wzorzec ścieżki" #: quodlibet/qltk/renamefiles.py:147 quodlibet/qltk/tagsfrompath.py:116 msgid "Edit saved patterns…" msgstr "Modyfikuj zapisane wzorce…" #: quodlibet/qltk/renamefiles.py:150 quodlibet/qltk/tagsfrompath.py:119 #: quodlibet/qltk/tracknumbers.py:57 msgid "_Preview" msgstr "_Podgląd" #: quodlibet/qltk/renamefiles.py:177 msgid "File names" msgstr "Nazwy plików" #: quodlibet/qltk/renamefiles.py:187 msgid "_Move album art" msgstr "_Przenoszenie okładki albumu" #: quodlibet/qltk/renamefiles.py:190 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:195 msgid "_Overwrite album art at target" msgstr "_Zastępowanie okładki w miejscu docelowym" #: quodlibet/qltk/renamefiles.py:203 msgid "_Remove empty directories" msgstr "_Usuwanie pustych katalogów" #: quodlibet/qltk/renamefiles.py:209 msgid "Album art" msgstr "Okładka" #: quodlibet/qltk/renamefiles.py:238 msgid "New Name" msgstr "Nowa nazwa" #: quodlibet/qltk/renamefiles.py:315 msgid "Unable to rename file" msgstr "Nie można zmienić nazwy pliku" #: quodlibet/qltk/renamefiles.py:316 #, python-format msgid "" "Renaming <b>%(old-name)s</b> to <b>%(new-name)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." 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:324 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:325 quodlibet/qltk/wlw.py:49 msgid "_Stop" msgstr "Za_trzymaj" #: quodlibet/qltk/renamefiles.py:327 msgid "_Continue" msgstr "_Kontynuuj" #: quodlibet/qltk/renamefiles.py:440 msgid "Path is not absolute" msgstr "Ścieżka nie jest bezwzględna" #: quodlibet/qltk/renamefiles.py:441 #, python-format msgid "" "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 ~/." 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:47 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:99 msgid "Select Directories" msgstr "Wybierz katalogi" #: quodlibet/qltk/searchbar.py:57 msgid "Saved Searches" msgstr "Zapisane wyszukiwania" #: quodlibet/qltk/searchbar.py:58 msgid "Edit saved searches…" msgstr "Modyfikuj zapisane wyszukiwania…" #: quodlibet/qltk/searchbar.py:82 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:144 msgid "Search after _typing" msgstr "Wy_szukiwanie podczas pisania" #: quodlibet/qltk/searchbar.py:147 msgid "Show search results after the user stops typing" msgstr "Wyświetla wyniki wyszukiwania, kiedy użytkownik przestaje pisać" #: quodlibet/qltk/searchbar.py:215 msgid "_Limit:" msgstr "_Ograniczenie:" #: quodlibet/qltk/searchbar.py:228 msgid "_Weight" msgstr "_Waga" #: quodlibet/qltk/searchbar.py:355 msgid "Add query" msgstr "Dodanie zapytania" #: quodlibet/qltk/searchbar.py:356 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:375 #, python-format msgid "_Filter on %s" msgstr "_Filtrowanie według %s" #: quodlibet/qltk/songlist.py:1093 msgid "All _Headers" msgstr "Wszystkie _nagłówki" #: quodlibet/qltk/songlist.py:1094 msgid "_Track Headers" msgstr "Nagłówki ś_cieżek" #: quodlibet/qltk/songlist.py:1095 msgid "_Album Headers" msgstr "Nagłówki _albumów" #: quodlibet/qltk/songlist.py:1096 msgid "_People Headers" msgstr "Nagłówki _osób" #: quodlibet/qltk/songlist.py:1097 msgid "_Date Headers" msgstr "Nagłówki _dat" #: quodlibet/qltk/songlist.py:1098 msgid "_File Headers" msgstr "Nagłówki p_lików" #: quodlibet/qltk/songlist.py:1099 msgid "_Production Headers" msgstr "Nagłówki p_rodukcji" #: quodlibet/qltk/songlist.py:1114 msgid "_Customize Headers…" msgstr "_Dostosuj nagłówki…" #: quodlibet/qltk/songlist.py:1119 msgid "_Expand Column" msgstr "_Rozwiń kolumnę" #: quodlibet/qltk/songsmenu.py:40 #, python-format msgid "Remove track: \"%%(title)s\" from library?" msgid_plural "Remove %(count)d tracks from library?" msgstr[0] "Usunąć ścieżkę „%%(title)s” z kolekcji?" msgstr[1] "Usunąć %(count)d ścieżki z kolekcji?" msgstr[2] "Usunąć %(count)d ścieżek z kolekcji?" #: quodlibet/qltk/songsmenu.py:46 msgid "Remove from Library" msgstr "Usunięcie z kolekcji" #: quodlibet/qltk/songsmenu.py:51 #, 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:62 #, 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:134 msgid "Configure Plugins…" msgstr "Skonfiguruj wtyczki…" #: quodlibet/qltk/songsmenu.py:329 msgid "Add to _Queue" msgstr "Dodaj do _kolejki" #: quodlibet/qltk/songsmenu.py:349 msgid "_Remove from Library…" msgstr "_Usuń z kolekcji…" #: quodlibet/qltk/songsmenu.py:414 msgid "Unable to show files" msgstr "Nie można wyświetlić plików" #: quodlibet/qltk/songsmenu.py:415 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:422 #, 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/tagsfrompath.py:46 msgid "Replace _underscores with spaces" msgstr "Zmienianie p_odkreśleń na spacje" #: quodlibet/qltk/tagsfrompath.py:56 msgid "_Title-case tags" msgstr "Wielkie litery Jak W _Tytule" #: quodlibet/qltk/tagsfrompath.py:66 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 #, python-format msgid "" "The pattern\n" "\t<b>%s</b>\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/tagsfrompath.py:215 msgid "Invalid tags" msgstr "Nieprawidłowe etykiety" #: quodlibet/qltk/tagsfrompath.py:216 #, 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." #: 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:923 #, python-format msgid "and %d more…" msgstr "i %d więcej…" #: quodlibet/qltk/wlw.py:199 msgid "Saving the songs you changed." msgstr "Zapisywanie zmienionych utworów." #: quodlibet/qltk/wlw.py:200 #, 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:233 #, 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:425 msgid "Playlists must have a name" msgstr "Listy odtwarzania muszą mieć nazwy" #: quodlibet/util/collection.py:608 #, python-format msgid "A playlist named %s already exists." msgstr "Lista odtwarzania o nazwie %s już istnieje." #: quodlibet/util/cover/built_in.py:32 msgid "Embedded album covers" msgstr "Osadzone okładki albumów" #: quodlibet/util/cover/built_in.py:33 msgid "Uses covers embedded into audio files." msgstr "Używa okładek osadzonych w plikach dźwiękowych." #: quodlibet/util/cover/built_in.py:55 msgid "Filesystem cover" msgstr "Okładka w systemie plików" #: quodlibet/util/cover/built_in.py:56 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:76 msgid "Display brief usage information" msgstr "Wyświetla skrócone informacje o użyciu" #: quodlibet/util/__init__.py:78 msgid "Display version and copyright" msgstr "Wyświetla wersję i prawa autorskie" #: quodlibet/util/__init__.py:79 msgid "Print debugging information" msgstr "Wyświetla informacje debugowania" #: quodlibet/util/__init__.py:118 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "Użycie: %(program)s %(usage)s" #: quodlibet/util/__init__.py:120 msgid "[options]" msgstr "[opcje]" #: quodlibet/util/__init__.py:165 #, python-format msgid "Option %r not recognized." msgstr "Opcja %r nie została rozpoznana." #: quodlibet/util/__init__.py:168 #, python-format msgid "Option %r requires an argument." msgstr "Opcja %r wymaga parametru." #: quodlibet/util/__init__.py:171 #, python-format msgid "%r is not a unique prefix." msgstr "%r nie jest unikalnym przedrostkiem." #: quodlibet/util/__init__.py:347 #, python-format msgid "%d kbps" msgstr "%d kb/s" #: quodlibet/util/__init__.py:402 #, 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:415 msgid "No time information" msgstr "Brak informacji o czasie" #: quodlibet/util/__init__.py:418 #, 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:419 #, 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:420 #, 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:421 #, 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:422 #, 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:514 msgctxt "check" msgid "titlecase?" msgstr "no_capitalize" #: quodlibet/util/massagers.py:114 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:129 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:150 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:172 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:194 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:207 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:116 msgid "Unable to edit song" msgstr "Nie można zmodyfikować utworu" #: quodlibet/util/songwrapper.py:117 #, python-format msgid "" "Saving <b>%s</b> 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: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:151 msgid "disc" msgstr "płyta" #: quodlibet/util/tags.py:115 quodlibet/util/tags.py:153 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" #. 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:130 msgid "MusicBrainz recording ID" msgstr "Identyfikator nagrania MusicBrainz" #: quodlibet/util/tags.py:131 msgid "MusicBrainz release track ID" msgstr "Identyfikator ścieżki wydania MusicBrainz" #: quodlibet/util/tags.py:132 msgid "MusicBrainz release ID" msgstr "Identyfikator wydania MusicBrainz" #: quodlibet/util/tags.py:133 msgid "MusicBrainz artist ID" msgstr "Identyfikator wykonawcy MusicBrainz" #: quodlibet/util/tags.py:134 msgid "MusicBrainz release artist ID" msgstr "Identyfikator wykonawcy wydania MusicBrainz" #: quodlibet/util/tags.py:135 msgid "MusicBrainz TRM ID" msgstr "Identyfikator TRM MusicBrainz" #: quodlibet/util/tags.py:136 msgid "MusicIP PUID" msgstr "PUID MusicIP" #: quodlibet/util/tags.py:137 msgid "MusicBrainz album status" msgstr "Stan albumu MusicBrainz" #: quodlibet/util/tags.py:138 msgid "MusicBrainz album type" msgstr "Typ albumu MusicBrainz" #: quodlibet/util/tags.py:139 msgid "MusicBrainz release group ID" msgstr "Identyfikator grupy wydania MusicBrainz" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:142 msgid "track gain" msgstr "wzmocnienie ścieżki" #: quodlibet/util/tags.py:143 msgid "track peak" msgstr "szczyt ścieżki" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:145 msgid "album gain" msgstr "wzmocnienie albumu" #: quodlibet/util/tags.py:146 msgid "album peak" msgstr "szczyt albumu" #: quodlibet/util/tags.py:147 msgid "reference loudness" msgstr "punkt odniesienia głośności" #: quodlibet/util/tags.py:152 msgid "discs" msgstr "płyty" #: quodlibet/util/tags.py:154 msgid "tracks" msgstr "ścieżki" #: quodlibet/util/tags.py:155 msgid "last started" msgstr "ostatnio rozpoczęte" #: quodlibet/util/tags.py:156 msgid "full name" msgstr "pełna nazwa" #: quodlibet/util/tags.py:163 msgid "mount point" msgstr "punkt montowania" #: quodlibet/util/tags.py:165 msgid "people" msgstr "osoby" #: quodlibet/util/tags.py:167 msgid "year" msgstr "rok" #: quodlibet/util/tags.py:168 msgid "original release year" msgstr "data pierwszego wydania" #: quodlibet/util/tags.py:169 msgid "bookmark" msgstr "zakładka" #: quodlibet/util/tags.py:170 msgid "bitdepth" msgstr "głębia bitowa" #: quodlibet/util/tags.py:173 msgid "file format" msgstr "format pliku" #: quodlibet/util/tags.py:176 msgid "playlists" msgstr "listy odtwarzania" #: quodlibet/util/tags.py:177 msgid "sample rate" msgstr "częstotliwość próbkowania" #: quodlibet/util/tags.py:178 msgid "channel count" msgstr "liczba kanałów" #. Translators: e.g. "artist (sort)" #: quodlibet/util/tags.py:268 msgid "sort" msgstr "porządkowanie" #. Translators: e.g. "performer (roles)" #: quodlibet/util/tags.py:276 msgid "roles" msgstr "role" ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9711857 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/po/pt.po����������������������������������������������������������������������������0000644�0001750�0001750�00000705432�00000000000�014112� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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: 2019-02-08 00:53-0200\n" "PO-Revision-Date: 2019-02-12 00:32-0200\n" "Last-Translator: Hugo Musso Gualandi <hugo_musso_gualandi@hotmail.com>\n" "Language-Team: Portuguese/Brazil <gnome-l10n-br@listas.cipspa.org.br>\n" "Language: pt_BR\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" #: quodlibet/browsers/albums/main.py:206 #: quodlibet/browsers/covergrid/main.py:54 msgid "_Title" msgstr "_Título" #: quodlibet/browsers/albums/main.py:207 #: quodlibet/browsers/covergrid/main.py:55 quodlibet/qltk/prefs.py:49 msgid "_Artist" msgstr "_Artista" #: quodlibet/browsers/albums/main.py:208 #: quodlibet/browsers/covergrid/main.py:56 quodlibet/qltk/prefs.py:54 msgid "_Date" msgstr "_Data" #: quodlibet/browsers/albums/main.py:209 msgid "_Original Date" msgstr "Data _original" #: quodlibet/browsers/albums/main.py:210 #: quodlibet/browsers/covergrid/main.py:57 quodlibet/qltk/prefs.py:53 msgid "_Genre" msgstr "_Gênero" #: quodlibet/browsers/albums/main.py:211 #: quodlibet/browsers/covergrid/main.py:58 quodlibet/qltk/prefs.py:58 #: quodlibet/qltk/ratingsmenu.py:39 msgid "_Rating" msgstr "_Avaliação" #: quodlibet/browsers/albums/main.py:212 msgid "_Playcount" msgstr "_Número de reproduções" #: quodlibet/browsers/albums/main.py:218 #: quodlibet/browsers/covergrid/main.py:64 msgid "Sort _by…" msgstr "_Ordenar por…" #: quodlibet/browsers/albums/main.py:239 #: quodlibet/browsers/covergrid/main.py:85 #: quodlibet/browsers/paned/prefs.py:203 #: quodlibet/browsers/playlists/main.py:667 quodlibet/qltk/exfalsowindow.py:108 #: quodlibet/qltk/pluginwin.py:341 quodlibet/qltk/quodlibetwindow.py:906 msgid "_Preferences" msgstr "_Preferências" #: quodlibet/browsers/albums/main.py:409 msgid "Album List" msgstr "Lista de álbuns" #: quodlibet/browsers/albums/main.py:410 msgid "_Album List" msgstr "_Lista de álbuns" #: quodlibet/browsers/albums/main.py:524 #: quodlibet/browsers/covergrid/main.py:285 #: quodlibet/browsers/covergrid/main.py:501 msgid "All Albums" msgstr "Todos os álbuns" #: quodlibet/browsers/albums/main.py:525 #: quodlibet/browsers/covergrid/main.py:286 #: quodlibet/browsers/covergrid/main.py:502 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d álbum" msgstr[1] "%d álbuns" #: quodlibet/browsers/albums/main.py:706 #: quodlibet/browsers/covergrid/main.py:480 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:16 #: 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:385 quodlibet/util/collection.py:247 #, 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:383 quodlibet/util/collection.py:251 #, 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:124 #: quodlibet/ext/songsmenu/cover_download.py:243 msgid "Options" msgstr "Opções" #: quodlibet/browsers/albums/prefs.py:74 #: quodlibet/browsers/covergrid/prefs.py:127 msgid "Album Display" msgstr "Visualização do álbum" #: quodlibet/browsers/albums/prefs.py:78 #: quodlibet/browsers/covergrid/prefs.py:131 #: quodlibet/browsers/playlists/prefs.py:56 #: quodlibet/ext/songsmenu/albumart.py:328 #: quodlibet/ext/songsmenu/duplicates.py:347 #: quodlibet/ext/songsmenu/filterall.py:48 quodlibet/qltk/bookmarks.py:101 #: quodlibet/qltk/cbes.py:93 quodlibet/qltk/data_editors.py:96 #: quodlibet/qltk/data_editors.py:321 quodlibet/qltk/exfalsowindow.py:286 #: quodlibet/qltk/pluginwin.py:79 quodlibet/qltk/pluginwin.py:428 #: quodlibet/qltk/prefs.py:764 quodlibet/qltk/textedit.py:163 #: quodlibet/update.py:149 msgid "_Close" msgstr "_Fechar" #: quodlibet/browsers/audiofeeds.py:52 quodlibet/browsers/audiofeeds.py:64 #: quodlibet/browsers/audiofeeds.py:66 quodlibet/browsers/audiofeeds.py:156 #: quodlibet/browsers/paned/models.py:85 #: quodlibet/ext/songsmenu/fingerprint/search.py:46 #: quodlibet/formats/_audio.py:488 quodlibet/order/__init__.py:27 #: quodlibet/qltk/information.py:244 quodlibet/qltk/information.py:251 #: quodlibet/qltk/information.py:277 quodlibet/qltk/wlw.py:69 msgid "Unknown" msgstr "Desconhecido" #: quodlibet/browsers/audiofeeds.py:247 msgid "New Feed" msgstr "Novo feed" #: quodlibet/browsers/audiofeeds.py:248 msgid "Enter the location of an audio feed:" msgstr "Insira o endereço de um feed de áudio:" #: quodlibet/browsers/audiofeeds.py:249 #: quodlibet/browsers/collection/prefs.py:89 quodlibet/browsers/iradio.py:356 #: quodlibet/browsers/paned/prefs.py:120 #: quodlibet/browsers/playlists/menu.py:96 #: quodlibet/browsers/playlists/util.py:52 quodlibet/qltk/bookmarks.py:62 #: quodlibet/qltk/cbes.py:55 quodlibet/qltk/data_editors.py:308 #: quodlibet/qltk/edittags.py:327 quodlibet/qltk/edittags.py:527 #: quodlibet/qltk/quodlibetwindow.py:1276 quodlibet/qltk/scanbox.py:61 msgid "_Add" msgstr "_Adicionar" #: quodlibet/browsers/audiofeeds.py:303 msgid "Audio Feeds" msgstr "Feeds de áudio" #: quodlibet/browsers/audiofeeds.py:304 msgid "_Audio Feeds" msgstr "_Feeds de áudio" #: quodlibet/browsers/audiofeeds.py:407 quodlibet/qltk/data_editors.py:93 msgid "_New" msgstr "_Novo" #: quodlibet/browsers/audiofeeds.py:467 quodlibet/browsers/audiofeeds.py:526 msgid "Unable to add feed" msgstr "Não foi possível adicionar o feed" #: quodlibet/browsers/audiofeeds.py:468 quodlibet/browsers/audiofeeds.py:527 #, python-format msgid "" "%s could not be added. The server may be down, or the location may not be an " "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/audiofeeds.py:475 quodlibet/qltk/filesel.py:260 #: quodlibet/qltk/pluginwin.py:414 msgid "_Refresh" msgstr "Atuali_zar" #: quodlibet/browsers/audiofeeds.py:476 #: quodlibet/browsers/playlists/main.py:487 #: quodlibet/browsers/playlists/util.py:43 quodlibet/qltk/delete.py:143 #: quodlibet/qltk/filesel.py:257 quodlibet/qltk/lyrics.py:35 #: quodlibet/qltk/maskedbox.py:28 quodlibet/qltk/songsmenu.py:364 msgid "_Delete" msgstr "_Excluir" #: quodlibet/browsers/audiofeeds.py:543 msgid "" "The current audio backend does not support URLs, Audio Feeds browser " "disabled." msgstr "" "O backend atual de áudio não suporta URLs. Assim, o navegador de feeds de " "áudio está desabilitado." #: quodlibet/browsers/_base.py:146 quodlibet/browsers/_base.py:149 msgid "Library Browser" msgstr "Navegador da biblioteca" #: quodlibet/browsers/_base.py:273 quodlibet/ext/songsmenu/console.py:45 #: quodlibet/ext/songsmenu/refresh.py:30 quodlibet/qltk/exfalsowindow.py:240 #: quodlibet/qltk/information.py:554 quodlibet/qltk/maskedbox.py:68 #: quodlibet/util/collection.py:532 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d música" msgstr[1] "%d músicas" #: quodlibet/browsers/_base.py:401 quodlibet/browsers/_base.py:406 #: quodlibet/qltk/tagsfrompath.py:193 quodlibet/qltk/textedit.py:140 #: quodlibet/util/__init__.py:573 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:23 #, python-format msgid "Unknown %s" msgstr "%s desconhecido" #: quodlibet/browsers/collection/models.py:24 #, 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" #. Remove button #: quodlibet/browsers/collection/prefs.py:93 #: quodlibet/browsers/paned/prefs.py:124 #: quodlibet/browsers/playlists/menu.py:97 #: quodlibet/ext/playlist/remove_duplicates.py:60 #: quodlibet/qltk/bookmarks.py:97 quodlibet/qltk/bookmarks.py:127 #: quodlibet/qltk/cbes.py:82 quodlibet/qltk/cbes.py:89 #: quodlibet/qltk/data_editors.py:78 quodlibet/qltk/data_editors.py:91 #: quodlibet/qltk/data_editors.py:298 quodlibet/qltk/data_editors.py:311 #: quodlibet/qltk/data_editors.py:319 quodlibet/qltk/edittags.py:533 #: quodlibet/qltk/edittags.py:710 quodlibet/qltk/maskedbox.py:48 #: quodlibet/qltk/maskedbox.py:88 quodlibet/qltk/queue.py:427 #: quodlibet/qltk/scanbox.py:36 quodlibet/qltk/scanbox.py:63 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:470 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:247 #: quodlibet/ext/songsmenu/editplaycount.py:45 #: quodlibet/ext/songsmenu/exact_rating.py:38 #: quodlibet/player/gstbe/prefs.py:40 quodlibet/qltk/prefs.py:127 #: quodlibet/qltk/textedit.py:64 msgid "_Apply" msgstr "_Aplicar" #: quodlibet/browsers/collection/prefs.py:197 #: quodlibet/browsers/paned/prefs.py:251 #: quodlibet/browsers/playlists/menu.py:95 #: quodlibet/browsers/playlists/util.py:42 quodlibet/errorreport/ui.py:103 #: quodlibet/ext/playlist/export_to_folder.py:38 #: 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:44 #: quodlibet/ext/songsmenu/fingerprint/search.py:281 #: quodlibet/ext/songsmenu/fingerprint/submit.py:90 #: quodlibet/ext/songsmenu/importexport.py:40 #: quodlibet/ext/songsmenu/lastfmsync.py:218 #: quodlibet/ext/songsmenu/playlist.py:50 #: 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:326 #: quodlibet/qltk/_editutils.py:39 quodlibet/qltk/getstring.py:28 #: quodlibet/qltk/maskedbox.py:27 quodlibet/qltk/msg.py:54 #: quodlibet/qltk/msg.py:93 quodlibet/qltk/msg.py:111 #: quodlibet/qltk/ratingsmenu.py:33 quodlibet/update.py:95 msgid "_Cancel" msgstr "_Cancelar" #: quodlibet/browsers/covergrid/main.py:126 msgid "Cover Grid" msgstr "Grade de capas" #: quodlibet/browsers/covergrid/main.py:127 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:71 msgid "Show \"All Albums\" Item" msgstr "Incluir item \"Todos os álbuns\" na grade" #: quodlibet/browsers/covergrid/prefs.py:82 msgid "Wide Mode" msgstr "Modo largo" #: quodlibet/browsers/covergrid/prefs.py:114 #: quodlibet/browsers/covergrid/prefs.py:115 msgid "Cover Magnification" msgstr "Ampliação das capas" #: quodlibet/browsers/filesystem.py:39 msgid "File System" msgstr "Sistema de arquivos" #: quodlibet/browsers/filesystem.py:40 msgid "_File System" msgstr "_Sistema de arquivos" #: quodlibet/browsers/filesystem.py:124 quodlibet/qltk/songlist.py:255 msgid "Unable to copy songs" msgstr "Não copiar músicas" #: quodlibet/browsers/filesystem.py:125 quodlibet/qltk/songlist.py:256 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "" "Os arquivos selecionados não puderam ser copiados para outras listas de " "músicas ou para a fila de reprodução." #: quodlibet/browsers/filesystem.py:197 msgid "_Add to Library" msgstr "_Adicionar à biblioteca" #: quodlibet/browsers/iradio.py:181 msgid "Unsupported file type" msgstr "Não há suporte para este formato de arquivo" #: quodlibet/browsers/iradio.py:182 #, 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:229 quodlibet/browsers/iradio.py:242 #: quodlibet/browsers/iradio.py:835 msgid "Unable to add station" msgstr "Não foi possível adicionar a estação" #: quodlibet/browsers/iradio.py:253 quodlibet/browsers/iradio.py:486 msgid "Internet Radio" msgstr "Rádio via Internet" #: quodlibet/browsers/iradio.py:253 msgid "Downloading station list" msgstr "Baixando lista de estações" #: quodlibet/browsers/iradio.py:354 msgid "New Station" msgstr "Nova estação" #: quodlibet/browsers/iradio.py:355 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:373 msgid "Electronic" msgstr "Eletrônica" #: quodlibet/browsers/iradio.py:376 msgid "Hip Hop / Rap" msgstr "Hip Hop / Rap" #: quodlibet/browsers/iradio.py:377 msgid "Oldies" msgstr "Oldies" #: quodlibet/browsers/iradio.py:378 msgid "R&B" msgstr "R&B" #: quodlibet/browsers/iradio.py:379 msgid "Japanese" msgstr "Japonesa" #: quodlibet/browsers/iradio.py:380 msgid "Indian" msgstr "Indiana" #: quodlibet/browsers/iradio.py:382 msgid "Religious" msgstr "Religiosa" #: quodlibet/browsers/iradio.py:384 msgid "Charts" msgstr "Parada de sucessos" #: quodlibet/browsers/iradio.py:385 msgid "Turkish" msgstr "Turca" #: quodlibet/browsers/iradio.py:386 msgid "Reggae / Dancehall" msgstr "Reggae / Dancehall" #: quodlibet/browsers/iradio.py:387 msgid "Latin" msgstr "Latino-americana" #: quodlibet/browsers/iradio.py:388 msgid "College Radio" msgstr "Universitária" #: quodlibet/browsers/iradio.py:389 msgid "Talk / News" msgstr "" #: quodlibet/browsers/iradio.py:390 msgid "Ambient" msgstr "Ambiente" #: quodlibet/browsers/iradio.py:391 msgid "Jazz" msgstr "Jazz" #: quodlibet/browsers/iradio.py:392 quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "Clássica" #: quodlibet/browsers/iradio.py:393 quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "Pop" #: quodlibet/browsers/iradio.py:394 msgid "Alternative" msgstr "Alternativa" #: quodlibet/browsers/iradio.py:395 msgid "Metal" msgstr "Metal" #: quodlibet/browsers/iradio.py:396 msgid "Country" msgstr "Country" #: quodlibet/browsers/iradio.py:397 msgid "News" msgstr "Notícias" #: quodlibet/browsers/iradio.py:398 msgid "Schlager" msgstr "Schlager" #: quodlibet/browsers/iradio.py:399 msgid "Funk" msgstr "Funk" #: quodlibet/browsers/iradio.py:400 msgid "Indie" msgstr "Indie" #: quodlibet/browsers/iradio.py:401 msgid "Blues" msgstr "Blues" #: quodlibet/browsers/iradio.py:402 msgid "Soul" msgstr "Soul" #: quodlibet/browsers/iradio.py:403 msgid "Lounge" msgstr "Lounge" #: quodlibet/browsers/iradio.py:404 msgid "Punk" msgstr "Punk" #: quodlibet/browsers/iradio.py:405 msgid "Reggaeton" msgstr "Reggaeton" #: quodlibet/browsers/iradio.py:407 msgid "Slavic" msgstr "Eslávica" #: quodlibet/browsers/iradio.py:409 msgid "Greek" msgstr "Grega" #: quodlibet/browsers/iradio.py:410 msgid "Gothic" msgstr "Gótica" #: quodlibet/browsers/iradio.py:411 quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "Rock" #: quodlibet/browsers/iradio.py:464 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:470 msgid "_Load Stations" msgstr "_Baixar lista" #: quodlibet/browsers/iradio.py:487 msgid "_Internet Radio" msgstr "_Rádio via internet" #: quodlibet/browsers/iradio.py:560 msgid "_New Station…" msgstr "_Nova estação…" #: quodlibet/browsers/iradio.py:563 msgid "_Update Stations" msgstr "_Atualizar estações" #: quodlibet/browsers/iradio.py:590 msgid "All Stations" msgstr "Todas as estações" #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:594 quodlibet/browsers/soundcloud/main.py:65 msgid "Favorites" msgstr "Favoritos" #: quodlibet/browsers/iradio.py:602 msgid "No Category" msgstr "Nenhuma categoria" #: quodlibet/browsers/iradio.py:827 msgid "No stations found" msgstr "Nenhuma estação encontrada" #: quodlibet/browsers/iradio.py:828 #, 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:836 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:853 msgid "Add to Favorites" msgstr "_Adicionar aos favoritos" #: quodlibet/browsers/iradio.py:857 msgid "Remove from Favorites" msgstr "_Remover dos favoritos" #: quodlibet/browsers/iradio.py:957 #, 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:103 quodlibet/qltk/pluginwin.py:122 #: quodlibet/qltk/pluginwin.py:164 msgid "All" msgstr "Todos" #: quodlibet/browsers/paned/prefs.py:41 #: quodlibet/ext/songsmenu/cover_download.py:118 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 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "<tt>%s</tt>" msgstr "" "Padrão de etiqueta com marcação opcional. Por exemplo, <tt>composer</tt> ou\n" "<tt>%s</tt>" #: quodlibet/browsers/paned/prefs.py:231 msgid "Paned Browser Preferences" msgstr "Preferências da navegação por painéis" #: quodlibet/browsers/paned/prefs.py:236 msgid "Column layout" msgstr "Configuração dos painéis" #: quodlibet/browsers/paned/prefs.py:240 msgid "Column content" msgstr "Conteúdo dos painéis" #: quodlibet/browsers/paned/prefs.py:242 msgid "Equal pane width" msgstr "Igualar largura dos painéis" #: quodlibet/browsers/playlists/main.py:48 #: quodlibet/browsers/playlists/main.py:603 quodlibet/qltk/pluginwin.py:168 msgid "Playlists" msgstr "Listas de reprodução" #: quodlibet/browsers/playlists/main.py:49 msgid "_Playlists" msgstr "Listas de re_produção" #: quodlibet/browsers/playlists/main.py:152 msgid "_Remove from Playlist" msgstr "_Remover da lista de reprodução" #: quodlibet/browsers/playlists/main.py:217 msgid "New" msgstr "Nova" #: quodlibet/browsers/playlists/main.py:221 msgid "Import" msgstr "Importar" #: quodlibet/browsers/playlists/main.py:443 msgid "Unable to import playlist" msgstr "Não foi possível importar a lista de reprodução" #: quodlibet/browsers/playlists/main.py:444 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:494 msgid "_Rename" msgstr "_Renomear" #: quodlibet/browsers/playlists/main.py:592 msgid "Unable to rename playlist" msgstr "Não foi possível renomear a lista de reprodução" #: quodlibet/browsers/playlists/main.py:604 msgid "Import Playlist" msgstr "Importar lista de reprodução" #: quodlibet/browsers/playlists/main.py:604 msgid "_Import" msgstr "_Importar" #: quodlibet/browsers/playlists/menu.py:25 msgid "_New Playlist…" msgstr "_Nova lista de reprodução…" #: quodlibet/browsers/playlists/menu.py:86 #, 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:90 #, 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:33 #, 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:35 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:50 #: quodlibet/browsers/playlists/util.py:125 quodlibet/util/collection.py:575 msgid "New Playlist" msgstr "Nova lista de reprodução" #: quodlibet/browsers/playlists/util.py:51 msgid "Enter a name for the new playlist:" msgstr "Digite um nome da nova lista de reprodução:" #: quodlibet/browsers/playlists/util.py:89 #, 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/search.py:32 msgid "_Limit Results" msgstr "_Restringir resultados" #: quodlibet/browsers/search.py:37 msgid "_Allow multiple queries" msgstr "_Permitir múltiplas consultas" #: quodlibet/browsers/search.py:53 msgid "Search Library" msgstr "Pesquisar na biblioteca" #: quodlibet/browsers/search.py:54 msgid "_Search Library" msgstr "_Pesquisar na biblioteca" #: quodlibet/browsers/soundcloud/main.py:39 msgid "Soundcloud Browser" msgstr "Navegador para Soundclound" #: quodlibet/browsers/soundcloud/main.py:40 msgid "Sound_cloud" msgstr "Sound_cloud" #: quodlibet/browsers/soundcloud/main.py:60 quodlibet/qltk/searchbar.py:81 msgid "Search" msgstr "Procurar" #: quodlibet/browsers/soundcloud/main.py:69 msgid "My tracks" msgstr "Minhas faixas" #: quodlibet/browsers/soundcloud/main.py:141 #, python-format msgid "Go to %s" msgstr "Ir para %s" #: quodlibet/browsers/soundcloud/main.py:443 msgid "Connected" msgstr "Conectado" #: quodlibet/browsers/soundcloud/main.py:444 #, python-format msgid "Quod Libet is now connected, <b>%s</b>!" msgstr "Quod Libet está conectado, <b>%s</b>!" #: quodlibet/browsers/soundcloud/main.py:456 #, python-format msgid "Log out of %s" msgstr "Sair de %s" #: quodlibet/browsers/soundcloud/main.py:458 msgid "Enter code…" msgstr "Inserir código…" #: quodlibet/browsers/soundcloud/main.py:459 #, python-format msgid "Log in to %s" msgstr "Conectar a %s" #: quodlibet/browsers/soundcloud/util.py:86 msgid "Soundcloud authorisation" msgstr "Credenciais do Soundcloud" #: quodlibet/browsers/soundcloud/util.py:87 msgid "Enter Soundcloud auth code:" msgstr "Insira o código de autorização do Soundcloud:" #: quodlibet/cli.py:50 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:86 msgid "a music library and player" msgstr "um gerenciador e reprodutor de músicas" # Usado em `quodlibet --help` #: quodlibet/cli.py:87 msgid "[option]" msgstr "[opção]" #: quodlibet/cli.py:89 msgid "Print the playing song and exit" msgstr "Exibe a música em reprodução e sai" #: quodlibet/cli.py:90 msgid "Begin playing immediately" msgstr "Começa a reproduzir imediatamente" #: quodlibet/cli.py:91 msgid "Don't show any windows on start" msgstr "Não mostra janelas ao iniciar" #: quodlibet/cli.py:94 msgid "Jump to next song" msgstr "Vai para a próxima música" #: quodlibet/cli.py:96 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:97 msgid "Jump to previous song" msgstr "Vai para a música anterior" #: quodlibet/cli.py:98 msgid "Start playback" msgstr "Reproduz" #: quodlibet/cli.py:99 msgid "Pause playback" msgstr "Pausa a reproução" #: quodlibet/cli.py:100 msgid "Toggle play/pause mode" msgstr "Altera o estado tocando/pausado" #: quodlibet/cli.py:101 msgid "Stop playback" msgstr "Para a reprodução" #: quodlibet/cli.py:102 msgid "Turn up volume" msgstr "Aumenta o volume" #: quodlibet/cli.py:103 msgid "Turn down volume" msgstr "Diminui o volume" #: quodlibet/cli.py:104 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:105 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:106 msgid "Print player status" msgstr "Escreve o status (tocando/pausado)" #: quodlibet/cli.py:107 msgid "Hide main window" msgstr "Oculta a janela principal" #: quodlibet/cli.py:108 msgid "Show main window" msgstr "Mostra a janela principal" #: quodlibet/cli.py:109 msgid "Toggle main window visibility" msgstr "Altera a visibilidade da janela principal (visível/invisível)" #: quodlibet/cli.py:110 msgid "Focus the running player" msgstr "Foca no tocador atual" #: quodlibet/cli.py:111 msgid "Remove active browser filters" msgstr "Remove filtros de navegação ativos" #: quodlibet/cli.py:112 msgid "Refresh and rescan library" msgstr "Atualiza e re-escaneia a biblioteca" #: quodlibet/cli.py:113 msgid "List available browsers" msgstr "Lista os navegadores disponíveis" #: quodlibet/cli.py:114 msgid "Print the current playlist" msgstr "Exibe a lista de reprodução atual" #: quodlibet/cli.py:115 msgid "Print the contents of the queue" msgstr "Exibe o conteúdo da fila" #: quodlibet/cli.py:116 msgid "Print the active text query" msgstr "Exibe a consulta de texto ativa" #: quodlibet/cli.py:117 msgid "Start without plugins" msgstr "Inicia sem plugins" #: quodlibet/cli.py:118 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:119 msgid "Exit Quod Libet" msgstr "Sai do Quod Libet" #: quodlibet/cli.py:124 msgid "Seek within the playing song" msgstr "Avança/recua na música em reprodução" #: quodlibet/cli.py:124 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: quodlibet/cli.py:125 msgid "Set or toggle shuffle mode" msgstr "Desliga, liga, ou altera o modo de embaralhamento" #: quodlibet/cli.py:126 msgid "Set shuffle mode type" msgstr "Altera o modo de embaralhamento" #: quodlibet/cli.py:127 msgid "Turn repeat off, on, or toggle it" msgstr "Desliga, liga, ou altera o modo repetição" #: quodlibet/cli.py:128 msgid "Set repeat mode type" msgstr "Altera o modo de repetição" #: quodlibet/cli.py:129 msgid "Set the volume" msgstr "Ajusta o volume" #: quodlibet/cli.py:130 msgid "Search your audio library" msgstr "Pesquise na sua biblioteca" #: quodlibet/cli.py:130 quodlibet/cli.py:140 quodlibet/cli.py:144 #: quodlibet/cli.py:146 msgid "query" msgstr "busca" #: quodlibet/cli.py:131 msgid "Play a file" msgstr "Reproduz um arquivo" #: quodlibet/cli.py:131 quodlibet/cli.py:140 quodlibet/cli.py:146 msgctxt "command" msgid "filename" msgstr "arquivo" #: quodlibet/cli.py:132 msgid "Set rating of playing song" msgstr "Ajusta a avaliação da música em reprodução" #: quodlibet/cli.py:133 msgid "Set the current browser" msgstr "Altera o navegador atual" #: quodlibet/cli.py:134 msgid "Stop after the playing song" msgstr "Parar após esta música" #: quodlibet/cli.py:135 msgid "Open a new browser" msgstr "Abre um novo navegador" #: quodlibet/cli.py:136 msgid "Show or hide the queue" msgstr "Mostra ou oculta a fila" #: quodlibet/cli.py:137 msgid "Filter on a random value" msgstr "Filtra por um valor aleatório" #: quodlibet/cli.py:137 msgctxt "command" msgid "tag" msgstr "etiqueta" #: quodlibet/cli.py:138 msgid "Filter on a tag value" msgstr "Filtrar pelo valor de uma etiqueta" #: quodlibet/cli.py:138 msgid "tag=value" msgstr "etiqueta=valor" #: quodlibet/cli.py:139 msgid "Enqueue a file or query" msgstr "Enfileira um arquivo ou busca" #: quodlibet/cli.py:141 msgid "Enqueue comma-separated files" msgstr "Enfileira arquivos separados por vírgula" #: quodlibet/cli.py:142 quodlibet/util/tags.py:157 msgid "filename" msgstr "arquivo" #: quodlibet/cli.py:143 msgid "Print filenames of results of query to stdout" msgstr "Exibe nomes de arquivo do resultado da busca em stdout" #: quodlibet/cli.py:145 msgid "Unqueue a file or query" msgstr "Desenfileira um arquivo ou busca" #: quodlibet/cli.py:147 msgid "Add a file or directory to the library" msgstr "Adiciona um arquivo ou pasta à biblioteca" #: quodlibet/cli.py:148 quodlibet/util/tags.py:100 msgid "location" msgstr "endereço" #: quodlibet/cli.py:213 #, python-format msgid "Invalid argument for '%s'." msgstr "Argumento inválido para \"%s\"." #: quodlibet/cli.py:214 quodlibet/util/__init__.py:173 #, 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 "Quit Program" msgstr "Sair do programa" #: 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:34 msgid "an audio tag editor" msgstr "um editor de metadados de áudio" #: quodlibet/exfalso.py:34 quodlibet/util/tags.py:158 msgid "directory" msgstr "pasta" #: quodlibet/exfalso.py:41 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:20 msgid "" "Downloads covers linked to by the artwork_url tag. This works with the " "Soundcloud browser." 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 "Baixa imagens de capa de álbum pelo Last.fm." #: quodlibet/ext/covers/musicbrainz.py:20 msgid "MusicBrainz Cover Source" msgstr "Fonte de capas MusicBrainz" #: quodlibet/ext/covers/musicbrainz.py:21 msgid "Downloads covers from MusicBrainz's cover art archive." msgstr "Baixa 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:19 msgid "" "Allows arbitrary regex substitutions (s///) when tagging or renaming files." msgstr "" "Permite substituições por expressões regulares (s///) ao etiquetar ou " "renomear arquivos." #: quodlibet/ext/editing/titlecase.py:20 msgid "Title Case" msgstr "Capitalização de títulos" #: quodlibet/ext/editing/titlecase.py:21 msgid "Title-cases tag values in the tag editor." msgstr "" "Capitaliza etiquetas no editor de etiquetas, pelas regras de capitalização " "de títulos." #: quodlibet/ext/editing/titlecase.py:40 msgid "Title-_case Value" msgstr "_Capitalizar valor como título" #: quodlibet/ext/editing/titlecase.py:51 msgid "Allow _ALL-CAPS in tags" msgstr "Permitir _ALL-CAPS em etiquetas" #: quodlibet/ext/editing/titlecase.py:52 msgid "_Human title case" msgstr "Capitalizaçã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 capitalização de títulos em inglês, como em \"Dark " "Night of the Soul\"" #: quodlibet/ext/events/advanced_preferences.py:67 msgid "Advanced Preferences" msgstr "Preferências avançadas" #: quodlibet/ext/events/advanced_preferences.py:68 msgid "Allow editing of advanced config settings." msgstr "Permite editar configurações mais avançadas." #: quodlibet/ext/events/advanced_preferences.py:180 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/ext/events/weblyrics.py:318 quodlibet/qltk/prefs.py:266 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:66 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:172 msgid "Effects" msgstr "Efeitos" #: quodlibet/ext/events/animosd/prefs.py:288 msgid "Ed_it Display Pattern…" msgstr "_Editar formato…" #: quodlibet/ext/events/animosd/prefs.py:292 #: quodlibet/ext/events/trayicon/prefs.py:86 msgid "Preview" msgstr "Visualizar" #: quodlibet/ext/events/appinfo.py:28 msgid "Application Information" msgstr "Informações sobre este aplicativo" #: quodlibet/ext/events/appinfo.py:29 msgid "Various information about the application and its environment." msgstr "Informações diversas sobre este aplicativo e seu ambiente de execução." #: 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_library_update.py:136 msgid "Automatic Library Update" msgstr "Atualização automática da biblioteca" #: quodlibet/ext/events/auto_library_update.py:137 #, python-format msgid "Keeps your library up to date with inotify. Requires %s." msgstr "Mantém sua biblioteca atualizada via inotify. Requer %s." #: 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 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." #: 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." #: 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 mouse 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:93 #: quodlibet/ext/gstreamer/karaoke.py:95 #, python-format msgid "%d Hz" msgstr "%d Hz" #: quodlibet/ext/events/equalizer.py:198 #: quodlibet/ext/gstreamer/crossfeed.py:112 #, 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/playlist/export_to_squeezebox.py:80 #: quodlibet/ext/songsmenu/albumart.py:324 #: quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/cover_download.py:309 #: quodlibet/ext/songsmenu/fingerprint/search.py:278 #: quodlibet/ext/songsmenu/html.py:75 quodlibet/ext/songsmenu/lastfmsync.py:219 #: quodlibet/ext/songsmenu/playlist.py:51 #: quodlibet/ext/songsmenu/replaygain.py:354 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/_editutils.py:40 #: quodlibet/qltk/lyrics.py:34 quodlibet/qltk/msg.py:52 #: quodlibet/qltk/renamefiles.py:216 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 status do Gajim de acordo com o que você está escutando." #: 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 status, separadas por " "espaço. Se nenhuma for especificada, a mensagem de status 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:42 msgid "Inhibit Screensaver" msgstr "Inibir o protetor de tela" #: quodlibet/ext/events/inhibit.py:43 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." #: quodlibet/ext/events/inhibit.py:52 msgid "Music is playing" msgstr "Música está sendo reproduzida" #: quodlibet/ext/events/iradiolog.py:16 msgid "Internet Radio Log" msgstr "Log de rádio de internet" #: quodlibet/ext/events/iradiolog.py:17 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:31 msgid "Outputs a Jabber User Tunes file to ~/.quodlibet/jabber." msgstr "Produz um arquivo \"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 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 arquivo 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 gerenciamento 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:37 msgid "MPRIS D-Bus Support" msgstr "Suporte a MPRIS" #: quodlibet/ext/events/mpris/__init__.py:38 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." #: quodlibet/ext/events/mpris/__init__.py:44 #: quodlibet/ext/events/trayicon/prefs.py:36 msgid "Hide main window on close" msgstr "Esconder janela principal ao fechar" #: quodlibet/ext/events/mpris/__init__.py:47 #: quodlibet/ext/events/themeswitcher.py:84 #: quodlibet/ext/gstreamer/compressor.py:99 #: quodlibet/ext/gstreamer/crossfeed.py:136 #: quodlibet/ext/gstreamer/karaoke.py:99 quodlibet/ext/gstreamer/pitch.py:89 #: quodlibet/qltk/prefs.py:741 msgid "Preferences" msgstr "Preferências" #: quodlibet/ext/events/mqtt.py:54 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "Aceita padrões QL. Por exemplo, %s" #: quodlibet/ext/events/mqtt.py:60 msgid "MQTT Publisher" msgstr "Publicador MQTT" #: quodlibet/ext/events/mqtt.py:61 msgid "Publishes status messages to an MQTT topic." msgstr "Publica mensagens de status para um tópico MQTT." #: quodlibet/ext/events/mqtt.py:128 msgid "Broker hostname" msgstr "" #: quodlibet/ext/events/mqtt.py:129 msgid "broker hostname / IP (defaults to localhost)" msgstr "" #: quodlibet/ext/events/mqtt.py:131 msgid "Broker port" msgstr "" #: quodlibet/ext/events/mqtt.py:131 msgid "broker port (defaults to 1883" msgstr "" #: quodlibet/ext/events/mqtt.py:133 msgid "Topic" msgstr "" #: quodlibet/ext/events/mqtt.py:135 msgid "Playing Pattern" msgstr "" #: quodlibet/ext/events/mqtt.py:137 msgid "Status text when a song is started." msgstr "" #: quodlibet/ext/events/mqtt.py:139 msgid "Paused Pattern" msgstr "" #: quodlibet/ext/events/mqtt.py:141 msgid "Text when a song is paused." msgstr "" #: quodlibet/ext/events/mqtt.py:143 msgid "No-song Text" msgstr "" #: quodlibet/ext/events/mqtt.py:145 msgid "Plain text for when there is no current song" msgstr "" #: quodlibet/ext/events/mqtt.py:156 msgid "MQTT Configuration" msgstr "" #: quodlibet/ext/events/mqtt.py:160 msgid "Status Text" msgstr "" #: quodlibet/ext/events/mqtt.py:192 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "" #: quodlibet/ext/events/mqtt.py:196 #, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s)" msgstr "" #: quodlibet/ext/events/mqtt.py:199 msgid "Connection error" msgstr "Erro de conexão" #: 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/qlscrobbler.py:175 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:252 #, 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:258 msgid "Authentication failed: invalid URL." msgstr "Autenticação falhou: URL inválido." #: quodlibet/ext/events/qlscrobbler.py:275 #, 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:280 msgid "Client is banned. Contact the author." msgstr "O cliente foi banido. Entre em contato com o autor." #: quodlibet/ext/events/qlscrobbler.py:284 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:349 msgid "AudioScrobbler Submission" msgstr "Submeter ao AudioScrobbler" #: quodlibet/ext/events/qlscrobbler.py:350 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:455 msgid "Authentication successful." msgstr "Autenticação realizada com sucesso." #: quodlibet/ext/events/qlscrobbler.py:467 msgid "_Service:" msgstr "_Serviço:" #: quodlibet/ext/events/qlscrobbler.py:467 msgid "_URL:" msgstr "_URL:" #: quodlibet/ext/events/qlscrobbler.py:467 msgid "User_name:" msgstr "_Nome de usuário:" #: quodlibet/ext/events/qlscrobbler.py:468 msgid "_Password:" msgstr "_Senha:" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:484 msgid "Other…" msgstr "Outros…" #. verify data #: quodlibet/ext/events/qlscrobbler.py:522 msgid "_Verify account data" msgstr "_Verificar conta" #: quodlibet/ext/events/qlscrobbler.py:527 #: quodlibet/ext/songsmenu/lastfmsync.py:312 msgid "Account" msgstr "Conta" #: quodlibet/ext/events/qlscrobbler.py:535 msgid "_Artist pattern:" msgstr "Padrão para _artista:" #: quodlibet/ext/events/qlscrobbler.py:535 msgid "_Title pattern:" msgstr "Padrão para _título:" #: quodlibet/ext/events/qlscrobbler.py:536 msgid "Exclude _filter:" msgstr "Filtro de _exclusão:" #: quodlibet/ext/events/qlscrobbler.py:554 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:564 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:573 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:581 msgid "_Offline mode (don't submit anything)" msgstr "Modo _offline (não enviar nada)" #: quodlibet/ext/events/qlscrobbler.py:585 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:28 msgid "Random Album Playback" msgstr "Reproduzir álbum aleatório" #: quodlibet/ext/events/randomalbum.py:29 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:39 msgid "Rated higher" msgstr "Melhor avaliado" #: quodlibet/ext/events/randomalbum.py:40 msgid "Played more often" msgstr "Mais reproduzido" #: quodlibet/ext/events/randomalbum.py:41 msgid "Skipped more often" msgstr "Mais ignorado" #: quodlibet/ext/events/randomalbum.py:42 msgid "Played more recently" msgstr "Reproduzido mais recentemente" #: quodlibet/ext/events/randomalbum.py:43 msgid "Started more recently" msgstr "Iniciado mais recentemente" #: quodlibet/ext/events/randomalbum.py:44 msgid "Added more recently" msgstr "Adicionado mais recentemente" #: quodlibet/ext/events/randomalbum.py:45 msgid "Longer albums" msgstr "Mais longo" #: quodlibet/ext/events/randomalbum.py:84 msgid "seconds before starting next album" msgstr "segundos antes de começar o próximo álbum" #: quodlibet/ext/events/randomalbum.py:88 msgid "Weights" msgstr "Pesos" #: quodlibet/ext/events/randomalbum.py:90 msgid "Play some albums more than others" msgstr "Reproduzir alguns álbuns mais que os outros" #: quodlibet/ext/events/randomalbum.py:104 msgid "avoid" msgstr "evitar" #: quodlibet/ext/events/randomalbum.py:115 msgid "prefer" msgstr "preferir" #: quodlibet/ext/events/randomalbum.py:219 msgid "Random Album" msgstr "Álbum aleatório" #: quodlibet/ext/events/randomalbum.py:220 #, python-format msgid "Waiting to start %s" msgstr "Esperando para começar a reproduzir %s" #: quodlibet/ext/events/rbimport.py:114 msgid "Import Failed" msgstr "Falha ao importar" #: quodlibet/ext/events/rbimport.py:119 #, 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:127 msgid "Rhythmbox Import" msgstr "Importar do Rhythmbox" #: quodlibet/ext/events/rbimport.py:128 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "Importa avaliações e estatísticas de música do Rhythmbox." #: quodlibet/ext/events/rbimport.py:132 msgid "Start Import" msgstr "_Importar" #: 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:73 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:79 msgid "GNOME Search Provider" msgstr "Provedor de pesquisa GNOME" #: quodlibet/ext/events/searchprovider.py:80 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 msgid "" "Store Seekpoints A and/or B for tracks. Skip to time A and stop after time B " "when track is played.\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:29 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" "Espelha a saída do Quod Libet em um Squeezebox da Logitech, desde que ambos " "possam ler de uma biblioteca idêntica." #: quodlibet/ext/events/squeezebox_sync.py:57 #: quodlibet/ext/playlist/export_to_squeezebox.py:89 msgid "Error finding Squeezebox server" msgstr "Não foi possível encontrar o servidor Squeezebox" #: quodlibet/ext/events/squeezebox_sync.py:58 #: quodlibet/ext/playlist/export_to_squeezebox.py:90 #, 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/synchronizedlyrics.py:34 msgid "Synchronized Lyrics" msgstr "Sincronizar letras" #: quodlibet/ext/events/synchronizedlyrics.py:35 msgid "Shows synchronized lyrics from .lrc file with same name as the track." msgstr "" "Exibe letras sincronizadas a partir de um arquivo \".lrc\" com o mesmo nome " "do usado na faixa." #: quodlibet/ext/events/synchronizedlyrics.py:69 msgid "Text:" msgstr "Texto:" #: quodlibet/ext/events/synchronizedlyrics.py:79 msgid "Background:" msgstr "Fundo:" #: quodlibet/ext/events/synchronizedlyrics.py:90 msgid "Font" msgstr "Fonte" #: quodlibet/ext/events/synchronizedlyrics.py:93 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 com uma mensagem de status 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 status quando uma música começa a ser reproduzida. Aceita " "padrões QL. Por exemplo, %s" #: quodlibet/ext/events/telepathy_status.py:145 msgid "Paused:" msgstr "Pausado:" #: quodlibet/ext/events/telepathy_status.py:146 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "" "Mensagem de status quando uma música está pausada. Aceita padrões QL. Por " "exemplo, %s" #: quodlibet/ext/events/telepathy_status.py:162 msgid "Plain text for status when there is no current song" msgstr "" "Mensagem de status quando não há uma música sendo reproduzida. (Texto " "simples, sem padroẽs QL)" #: quodlibet/ext/events/telepathy_status.py:163 msgid "No song:" msgstr "Nenhuma música:" #. Frame #: quodlibet/ext/events/telepathy_status.py:170 msgid "Status Patterns" msgstr "Padrões da mensagem de status" #: 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:93 msgid "Thumb Rating" msgstr "Avaliação por curtidas" #: quodlibet/ext/events/thumbrating.py:94 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 '~#score'." 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:47 msgid "Not playing" msgstr "Não está reproduzindo" #: quodlibet/ext/events/trayicon/__init__.py:53 msgid "Tray Icon" msgstr "Ícone na área de notificação" #: quodlibet/ext/events/trayicon/__init__.py:54 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:183 quodlibet/qltk/quodlibetwindow.py:936 #: quodlibet/qltk/quodlibetwindow.py:1142 msgid "_Play" msgstr "_Reproduzir" #: quodlibet/ext/events/trayicon/menu.py:63 #: quodlibet/qltk/quodlibetwindow.py:185 quodlibet/qltk/quodlibetwindow.py:1144 #: quodlibet/qltk/wlw.py:50 msgid "P_ause" msgstr "_Pausar" #: quodlibet/ext/events/trayicon/menu.py:68 #: quodlibet/qltk/quodlibetwindow.py:190 quodlibet/qltk/quodlibetwindow.py:931 msgid "Pre_vious" msgstr "_Anterior" #: quodlibet/ext/events/trayicon/menu.py:71 #: quodlibet/qltk/quodlibetwindow.py:194 quodlibet/qltk/quodlibetwindow.py:941 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:902 msgid "Open _Browser" msgstr "Abrir _Navegador" #: quodlibet/ext/events/trayicon/menu.py:103 #: quodlibet/qltk/quodlibetwindow.py:921 quodlibet/qltk/songsmenu.py:383 msgid "Edit _Tags" msgstr "Editar _etiquetas" #: quodlibet/ext/events/trayicon/menu.py:112 #: quodlibet/qltk/quodlibetwindow.py:864 quodlibet/qltk/songsmenu.py:396 msgid "_Information" msgstr "_Informações" #: quodlibet/ext/events/trayicon/menu.py:114 quodlibet/qltk/songsmenu.py:324 msgid "Play_lists" msgstr "_Listas de reprodução" #: quodlibet/ext/events/trayicon/menu.py:132 #: quodlibet/qltk/quodlibetwindow.py:916 msgid "_Quit" msgstr "_Sair" #: quodlibet/ext/events/trayicon/prefs.py:38 quodlibet/qltk/prefs.py:69 msgid "Behavior" msgstr "Comportamento" #: quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel adjusts volume" msgstr "Roda do mouse ajusta volume" #: quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll wheel changes song" msgstr "Roda do mouse troca de música" #: quodlibet/ext/events/trayicon/prefs.py:62 msgid "Scroll _Wheel" msgstr "_Roda do mouse" #: 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 arquivos." #: 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 quodlibet/ext/events/weblyrics.py:193 msgid "No active song" msgstr "Nenhuma música está sendo 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:603 msgid "Waveform Seek Bar" msgstr "Barra de forma de onda" #: quodlibet/ext/events/waveformseekbar.py:607 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:676 msgid "Override foreground color:" msgstr "Cor de fundo:" #: quodlibet/ext/events/waveformseekbar.py:680 msgid "Override hover color:" msgstr "Cor ao passar o mouse:" #: quodlibet/ext/events/waveformseekbar.py:684 msgid "Override remaining color:" msgstr "Cor restante:" #: quodlibet/ext/events/waveformseekbar.py:688 msgid "Show current position" msgstr "Mostrar a posição atual" #: quodlibet/ext/events/waveformseekbar.py:693 msgid "Show time labels" msgstr "Mostrar tempo" #: quodlibet/ext/events/waveformseekbar.py:701 msgid "Seek amount when scrolling (milliseconds):" msgstr "" "Quantidade de tempo para avançar/retroceder com o roda do mouse " "(milissegundos)" #: quodlibet/ext/events/weblyrics.py:208 msgid "No lyrics found" msgstr "Nenhuma letra foi encontrada" #: quodlibet/ext/events/weblyrics.py:268 msgid "_Zoom level:" msgstr "_Ampliação:" #: quodlibet/ext/events/weblyrics.py:286 msgid "URL:" msgstr "URL:" #: quodlibet/ext/events/weblyrics.py:291 msgid "Revert to default" msgstr "Reverter ao padrão" #: quodlibet/ext/events/weblyrics.py:306 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." #: quodlibet/ext/events/weblyrics.py:323 msgid "Alternate search" msgstr "Pesquisa alternativa" #: quodlibet/ext/events/weblyrics.py:332 msgid "Web Lyrics" msgstr "Letras online" #: quodlibet/ext/events/weblyrics.py:333 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." #: 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 em um arquivo." #: quodlibet/ext/events/write_cover.py:67 msgid "File:" msgstr "Arquivo:" #: quodlibet/ext/gstreamer/compressor.py:20 msgid "_Threshold:" msgstr "_Limite:" #: quodlibet/ext/gstreamer/compressor.py:21 msgid "Threshold until the filter is activated" msgstr "Limite após o qual o filtro é ativado" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "R_atio:" msgstr "_Razão:" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "Compression ratio" msgstr "Razão de compressão" #: quodlibet/ext/gstreamer/compressor.py:74 #: quodlibet/ext/gstreamer/karaoke.py:91 #, python-format msgid "%d %%" msgstr "%d %%" #: quodlibet/ext/gstreamer/compressor.py:105 msgid "Audio Compressor" msgstr "Compressor de áudio" #: quodlibet/ext/gstreamer/compressor.py:106 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:19 msgid "_Preset:" msgstr "_Predefinição:" #: quodlibet/ext/gstreamer/crossfeed.py:19 msgid "Filter preset" msgstr "Predefinição do filtro" #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Frequency cut:" msgstr "_Frequência de corte:" #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Low-pass filter cut frequency" msgstr "Frequência de corte do filtro de passa-baixa" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed _level:" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed level" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:25 msgid "Default" msgstr "Padrão" #: quodlibet/ext/gstreamer/crossfeed.py:26 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:27 msgid "Chu Moy" msgstr "Chu Moy" #: quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "Similar a Chu Moy (popular)" #: quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Jan Meier" msgstr "Jan Meier" #: quodlibet/ext/gstreamer/crossfeed.py:30 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:31 msgid "Custom" msgstr "Customizado" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Custom settings" msgstr "Configurações customizadas" #: quodlibet/ext/gstreamer/crossfeed.py:152 msgid "Crossfeed" msgstr "" #: quodlibet/ext/gstreamer/crossfeed.py:153 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:20 msgid "Filter _band:" msgstr "_Banda de filtragem:" #: quodlibet/ext/gstreamer/karaoke.py:21 msgid "The Frequency band of the filter" msgstr "Banda de frequência a ser fitrada" #: quodlibet/ext/gstreamer/karaoke.py:22 msgid "Filter _width:" msgstr "_Largura do filtro:" #: quodlibet/ext/gstreamer/karaoke.py:23 msgid "The Frequency width of the filter" msgstr "Largura da banda de frequência a ser filtrada" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "_Level:" msgstr "_Nível:" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "Level of the effect" msgstr "Nível do efeito" #: quodlibet/ext/gstreamer/karaoke.py:105 msgid "Karaoke" msgstr "Karaokê" #: quodlibet/ext/gstreamer/karaoke.py:106 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:21 msgid "R_ate:" msgstr "_Taxa de amostragem:" #: quodlibet/ext/gstreamer/pitch.py:22 msgid "_Tempo:" msgstr "_Velocidade:" #: quodlibet/ext/gstreamer/pitch.py:23 msgid "_Pitch:" msgstr "_Altura (tom):" #: quodlibet/ext/gstreamer/pitch.py:95 msgid "Audio Pitch / Speed" msgstr "Afinação e velocidade" #: quodlibet/ext/gstreamer/pitch.py:96 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:147 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 arquivo:" #: quodlibet/ext/playlist/export_to_folder.py:100 msgid "Exports a playlist by copying files to a folder." msgstr "Exporta uma lista de reprodução, copiando arquivos para uma pasta." #: quodlibet/ext/playlist/export_to_folder.py:121 #: quodlibet/ext/songsmenu/playlist.py:132 msgid "Unable to export playlist" msgstr "Não foi possível exportar a lista de reprodução" #: quodlibet/ext/playlist/export_to_folder.py:122 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:165 msgid "Default filename pattern:" msgstr "Formato padrão de _nome de arquivo:" #: quodlibet/ext/playlist/export_to_squeezebox.py:22 msgid "Export to Squeezebox" msgstr "Exportar para Squeezebox" #: quodlibet/ext/playlist/export_to_squeezebox.py:24 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 "" "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: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:96 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 msgid "" "Playback 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/playcounteq.py:21 msgid "Playcount Equalizer" msgstr "Equalizador de reproduções" #: quodlibet/ext/playorder/playcounteq.py:22 msgid "Shuffle, preferring 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:24 msgid "Prefer less played" msgstr "Preferir menos reproduzidas" #: quodlibet/ext/playorder/queue.py:19 msgid "Queue Only" msgstr "Apenas enfileirar" #: quodlibet/ext/playorder/queue.py:21 msgid "" "Limits playing of songs to the queue. 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/reverse.py:14 msgid "Reverse" msgstr "Reverter" #: quodlibet/ext/playorder/reverse.py:16 msgid "Reverses the play order of songs." msgstr "Reverte a ordem de reprodução das músicas." #: quodlibet/ext/playorder/shufflebygrouping.py:31 #: quodlibet/ext/playorder/shufflebygrouping.py:93 msgid "Shuffle by Grouping" msgstr "Embaralhar por agrupamento" #: quodlibet/ext/playorder/shufflebygrouping.py:32 msgid "" "Shuffles by a grouping of songs defined by a common tag instead of by track, " "similar to album shuffle. This is useful for shuffling multi-movement " "classical works while 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:38 msgid "Shuffle by grouping" msgstr "Por agrupamento" #: quodlibet/ext/playorder/shufflebygrouping.py:94 msgid "Waiting to start new group…" msgstr "Esperando para iniciar o próximo agrupamento…" #: quodlibet/ext/playorder/shufflebygrouping.py:144 msgid "Grouping tag:" msgstr "Etiqueta de agrupamento:" #: quodlibet/ext/playorder/shufflebygrouping.py:148 msgid "Tag to group songs by" msgstr "Etiqueta para agrupar músicas" #: quodlibet/ext/playorder/shufflebygrouping.py:150 msgid "Filter tag:" msgstr "Etiqueta de filtragem:" #: quodlibet/ext/playorder/shufflebygrouping.py:155 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:160 msgid "Delay:" msgstr "Intervalo:" #: quodlibet/ext/playorder/shufflebygrouping.py:166 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:182 msgid "Reset to defaults" msgstr "Restaurar para o padrão" #: quodlibet/ext/playorder/skip_songs.py:25 msgid "Skip Songs" msgstr "Ignorar músicas" #: quodlibet/ext/playorder/skip_songs.py:27 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." #: quodlibet/ext/playorder/track_repeat.py:30 msgid "Repeat Each Track" msgstr "Repetir cada faixa" #: quodlibet/ext/playorder/track_repeat.py:32 msgid "Shuffle songs, but repeat 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:51 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 msgid "" "Chooses the query to match based on a condition query. Syntax is '@(if: " "condition, then, else)'." msgstr "" "Habilita sintaxe para de consultas condicionais. A sintaxe é \"@(if: " "condition, then, else)\"." #: quodlibet/ext/query/missing.py:15 msgid "Missing Query" msgstr "Pesquisa inclui etiquetas vazias" #: quodlibet/ext/query/missing.py:16 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:27 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. Syntax is '@(python: expression)'. The " "variable 's' (or 'a') is the song / album being matched. '_ts' is a (real " "number) timestamp at start of query. Modules 'time' and 'random' are also " "available, and the class 'Random' (==random.Random) 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:19 msgid "Include Saved Search" msgstr "Incluir consulta salva" #: quodlibet/ext/query/savedsearch.py:20 msgid "" "Include the results of a saved search as part of another query. Syntax is " "'@(saved: search name)'." msgstr "" "Inclui os resultados de uma consulta salva como parte de outra consulta. A " "sintaxe é \"@(saved: search name)\"." #: 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:116 msgid "Port:" msgstr "Porta:" #: quodlibet/ext/_shared/squeezebox/base.py:121 msgid "Username:" msgstr "Nome de usuário:" #: quodlibet/ext/_shared/squeezebox/base.py:126 msgid "Password:" msgstr "Senha:" #: quodlibet/ext/_shared/squeezebox/base.py:130 msgid "Library directory the server connects to" msgstr "Pasta de biblioteca que o servidor se conecta" #: quodlibet/ext/_shared/squeezebox/base.py:132 msgid "Library path:" msgstr "Caminho da biblioteca:" #. Add verify button #: quodlibet/ext/_shared/squeezebox/base.py:141 msgid "_Verify settings" msgstr "_Verificar configuração" #. Server settings Frame #: quodlibet/ext/_shared/squeezebox/base.py:147 msgid "Squeezebox Server" msgstr "Servidor Squeezebox" #: quodlibet/ext/_shared/squeezebox/base.py:150 msgid "Debug" msgstr "Depurar" #: quodlibet/ext/_shared/squeezebox/server.py:26 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "Servidor Squeezebox em {hostname}:{port}" #: quodlibet/ext/_shared/squeezebox/server.py:28 msgid "unidentified Squeezebox server" msgstr "servidor Squeezebox não identificado" #: quodlibet/ext/_shared/squeezebox/server.py:37 #, 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:20 #: quodlibet/ext/songsmenu/importexport.py:39 quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "_OK" #: 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:331 msgid "Fit image to _window" msgstr "Ajustar à _janela" #: quodlibet/ext/songsmenu/albumart.py:337 msgid "See '[plugins] cover_filenames' config entry for image filename strings" msgstr "" "Refira-se à entrada \"[plugins] cover_filenames\", no arquivo de configuração" #. Both labels #: quodlibet/ext/songsmenu/albumart.py:343 msgid "_Program:" msgstr "_Programa:" #: quodlibet/ext/songsmenu/albumart.py:348 msgid "_Edit image after saving" msgstr "_Editar imagem após salvar" #: quodlibet/ext/songsmenu/albumart.py:350 msgid "File_name:" msgstr "_Nome do arquivo:" #: quodlibet/ext/songsmenu/albumart.py:466 msgid "Saving failed" msgstr "Falha ao salvar" #: quodlibet/ext/songsmenu/albumart.py:467 #, python-format msgid "Unable to save \"%s\"." msgstr "Não foi possível salvar \"%s\"." #: quodlibet/ext/songsmenu/albumart.py:565 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "Erro HTTP: %s" #: quodlibet/ext/songsmenu/albumart.py:622 msgid "Album Art Downloader" msgstr "Baixar capa de álbum" #: quodlibet/ext/songsmenu/albumart.py:675 #, python-format msgid "from %(source)s" msgstr "obtido de %(source)s" #: quodlibet/ext/songsmenu/albumart.py:678 #, python-format msgid "Resolution: %s" msgstr "Resolução: %s" #: quodlibet/ext/songsmenu/albumart.py:681 #, python-format msgid "Size: %s" msgstr "Tamanho: %s" #: quodlibet/ext/songsmenu/albumart.py:727 msgid "Per engine 'at best' results limit" msgstr "Limite de capas por fonte" #: quodlibet/ext/songsmenu/albumart.py:737 msgid "_Search" msgstr "_Procurar" #: quodlibet/ext/songsmenu/albumart.py:819 #: quodlibet/ext/songsmenu/brainz/widgets.py:451 msgid "Searching…" msgstr "Procurando…" #: quodlibet/ext/songsmenu/albumart.py:884 #: quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "Concluído" #: quodlibet/ext/songsmenu/albumart.py:1006 msgid "Download Album Art" msgstr "Baixar capas de álbum" #: quodlibet/ext/songsmenu/albumart.py:1007 msgid "Downloads album covers from various websites." msgstr "Baixa capas de álbum de diversos websites." #: quodlibet/ext/songsmenu/albumart.py:1020 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 "Gerencia marcadores nos arquivos 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 arquivo" #: quodlibet/ext/songsmenu/brainz/widgets.py:130 msgid "Disc" msgstr "_Disco" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 #: quodlibet/ext/songsmenu/replaygain.py:393 quodlibet/qltk/tracknumbers.py:91 msgid "Track" msgstr "Faixa" #: quodlibet/ext/songsmenu/brainz/widgets.py:132 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:447 msgid "Please enter a query." msgstr "Por favor, entre com uma consulta." #: quodlibet/ext/songsmenu/brainz/widgets.py:465 #: quodlibet/ext/songsmenu/brainz/widgets.py:496 msgid "Error encountered. Please retry." msgstr "Erro encontrado. Favor tentar novamente." #: quodlibet/ext/songsmenu/brainz/widgets.py:472 #: quodlibet/ext/songsmenu/brainz/widgets.py:488 msgid "Loading result…" msgstr "Carregando resultado…" #: quodlibet/ext/songsmenu/brainz/widgets.py:475 msgid "No results found." msgstr "Nenhum resultado encontrado." #: quodlibet/ext/songsmenu/console.py:40 msgid "Python Console" msgstr "Console Python" #: quodlibet/ext/songsmenu/console.py:41 msgid "Interactive Python console. Opens a new window." msgstr "Um console interativo Python. Abre em nova janela." #: quodlibet/ext/songsmenu/console.py:48 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "{plugin_name} para {songs} ({app})" #: quodlibet/ext/songsmenu/console.py:55 msgid "Python Console Sidebar" msgstr "Console Python (barra lateral)" #: quodlibet/ext/songsmenu/console.py:56 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:75 msgid "You can access the following objects by default:" msgstr "Você pode acessar os seguintes objetos por padrao:" #: quodlibet/ext/songsmenu/console.py:85 msgid "Your current working directory is:" msgstr "O diretório de trabalho atual é:" #: quodlibet/ext/songsmenu/cover_download.py:119 msgid "Classic" msgstr "Clássico" #: quodlibet/ext/songsmenu/cover_download.py:120 msgid "Large" msgstr "Grande" #: quodlibet/ext/songsmenu/cover_download.py:121 msgid "HD" msgstr "HD" #: quodlibet/ext/songsmenu/cover_download.py:122 msgid "Full HD" msgstr "Full HD" #: quodlibet/ext/songsmenu/cover_download.py:123 msgid "WQXGA" msgstr "WQXGA" #: quodlibet/ext/songsmenu/cover_download.py:124 msgid "4K UHD" msgstr "4K UHD" #: quodlibet/ext/songsmenu/cover_download.py:129 msgid "Cover Art Download" msgstr "Baixar capa de álbum" #: quodlibet/ext/songsmenu/cover_download.py:180 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "Carregando %(source)s - %(dimensions)s…" #: quodlibet/ext/songsmenu/cover_download.py:231 #, python-format msgid "" "Nothing found for albums:\n" "<i>%(albums)s</i>.\n" "\n" "Providers used:\n" "<tt>%(providers)s</tt>" 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:234 msgid "No covers found" msgstr "Nenhuma capa foi encontrada" #: quodlibet/ext/songsmenu/cover_download.py:254 #, python-format msgid "%(size)d ✕ %(size)d px" msgstr "%(size)d ✕ %(size)d px" #: quodlibet/ext/songsmenu/cover_download.py:267 msgid "Preview size" msgstr "Tamanho da visualização" #: quodlibet/ext/songsmenu/cover_download.py:276 msgid "Save destination" msgstr "Caminho de destino" #: quodlibet/ext/songsmenu/cover_download.py:336 msgid "Download Cover Art" msgstr "Baixar capas de álbum" #: quodlibet/ext/songsmenu/cover_download.py:337 msgid "Downloads high-quality album covers using cover plugins." msgstr "Baixa capas de álbum de alta qualidade, através de plug-ins." #: 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:55 msgid "pattern" msgstr "padrão" #: 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:91 msgid "Input value" msgstr "Valor de entrada" #: quodlibet/ext/songsmenu/custom_commands.py:92 #, python-format msgid "Value for %s?" msgstr "Valor para %s?" #: quodlibet/ext/songsmenu/custom_commands.py:136 msgid "Custom Commands" msgstr "Comandos personalizados" #: quodlibet/ext/songsmenu/custom_commands.py:137 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:190 #: quodlibet/ext/songsmenu/custom_commands.py:200 #: quodlibet/ext/songsmenu/custom_commands.py:254 msgid "Edit Custom Commands" msgstr "Editar comandos personalizados" #: quodlibet/ext/songsmenu/custom_commands.py:201 msgid "" "Supports QL patterns\n" "eg <tt><~artist~title></tt>" msgstr "" "Há suporte para padrões QL\n" "Por exemplo, <tt><~artist~title></tt>" #: quodlibet/ext/songsmenu/custom_commands.py:285 #, 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:287 #, 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:340 msgid "Collapse / Expand all" msgstr "Colapsar/expandir todos" #: quodlibet/ext/songsmenu/duplicates.py:344 #, python-format msgid "Duplicate key expression is '%s'" msgstr "A expressão chave é \"%s\"" #: quodlibet/ext/songsmenu/duplicates.py:369 msgid "Duplicates Browser" msgstr "Navegador de duplicatas" #: quodlibet/ext/songsmenu/duplicates.py:370 msgid "Finds and displays similarly tagged versions of songs." msgstr "Encontra e exibe músicas com etiquetas semelhantes." #: quodlibet/ext/songsmenu/duplicates.py:408 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:410 msgid "_Group duplicates by:" msgstr "_Agrupar duplicatas por:" #: quodlibet/ext/songsmenu/duplicates.py:415 msgid "Duplicate Key" msgstr "Expressão chave" #: quodlibet/ext/songsmenu/duplicates.py:420 msgid "Remove _Whitespace" msgstr "Remover espaços em branco" #: quodlibet/ext/songsmenu/duplicates.py:421 msgid "Remove _Diacritics" msgstr "Remover acentos e diacríticos" #: quodlibet/ext/songsmenu/duplicates.py:422 msgid "Remove _Punctuation" msgstr "Remover pontuação" #: quodlibet/ext/songsmenu/duplicates.py:423 msgid "Case _Insensitive" msgstr "Não diferenciar maiúsculas de minúsculas" #: quodlibet/ext/songsmenu/duplicates.py:431 msgid "Matching options" msgstr "Opções de emparelhamento" #. Create a dialog. #: quodlibet/ext/songsmenu/editplaycount.py:19 #: quodlibet/ext/songsmenu/editplaycount.py:41 msgid "Edit Playcount" msgstr "Editar contagem de reproduções" #: quodlibet/ext/songsmenu/editplaycount.py:20 msgid "" "Edit a song's ~#playcount and ~#skipcount.\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's ~#playcount to 0, the ~#lastplayed and ~#laststarted " "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:68 msgid "Play Count" msgstr "Número de reproduções" #: quodlibet/ext/songsmenu/editplaycount.py:69 msgid "Skip Count" msgstr "Número de ignoradas" #: quodlibet/ext/songsmenu/embedded.py:25 msgid "Edit Embedded Images" msgstr "Editar imagens embutidas" #: quodlibet/ext/songsmenu/embedded.py:26 msgid "Removes or replaces embedded images." msgstr "Remove ou substitui imagens embutidas." #: quodlibet/ext/songsmenu/embedded.py:81 msgid "_Remove all Images" msgstr "_Remover todas as imagens" #: quodlibet/ext/songsmenu/embedded.py:85 msgid "_Embed Current Image" msgstr "_Embutir a imagem atual" #: 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/exact_rating.py:54 quodlibet/qltk/ratingsmenu.py:98 msgid "Change _Rating" msgstr "Alterar _avaliação" #: 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" #: quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" msgstr "Status" #. 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 arquivos" #: 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 arquivos correspondentes " "automaticamente. Isso garante que contagens de reprodução e avaliações estão " "sempre em dia." #: quodlibet/ext/songsmenu/html.py:65 quodlibet/ext/songsmenu/html.py:75 msgid "Export to HTML" msgstr "Exportar para HTML" #: quodlibet/ext/songsmenu/html.py:66 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:62 msgid "Error uploading" msgstr "Erro no envio" #: quodlibet/ext/songsmenu/ifp.py:63 #, python-format msgid "" "Unable to upload <b>%s</b>. 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/importexport.py:60 msgid "Export Metadata" msgstr "Exportar metadados" #: quodlibet/ext/songsmenu/importexport.py:61 msgid "Exports metadata of selected songs as a .tags file." msgstr "Exporta os metadados das músicas selecionadas em um arquivo \".tags\"." #: quodlibet/ext/songsmenu/importexport.py:105 msgid "Import Metadata" msgstr "Importar metadados" #: quodlibet/ext/songsmenu/importexport.py:106 msgid "Imports metadata for selected songs from a .tags file." msgstr "" "Importa metadados para as músicas selecionadas de um arquivo \".tags\"." #: quodlibet/ext/songsmenu/k3b.py:23 msgid "Burn CD" msgstr "Gravar em CD" #: quodlibet/ext/songsmenu/k3b.py:24 msgid "Burns CDs with K3b, Brasero or xfburn." msgstr "Grava em CDs com K3b, Brasero ou xfburn." #: quodlibet/ext/songsmenu/lastfmsync.py:97 msgid "Updating chart list." msgstr "Atualizando lista de músicas favoritas." #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:116 msgid "Already up-to-date." msgstr "Já está atualizada." #: quodlibet/ext/songsmenu/lastfmsync.py:124 #, 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:146 msgid "Sync complete." msgstr "Sincronização completa." #: quodlibet/ext/songsmenu/lastfmsync.py:152 msgid "Error during sync" msgstr "Erro durante a sincronização" #: quodlibet/ext/songsmenu/lastfmsync.py:217 #: quodlibet/ext/songsmenu/lastfmsync.py:247 msgid "Last.fm Sync" msgstr "Sincronizar com Last.fm" #: quodlibet/ext/songsmenu/lastfmsync.py:248 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:301 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." #. Create a dialog. #: quodlibet/ext/songsmenu/migratemetadata.py:36 #: quodlibet/ext/songsmenu/migratemetadata.py:45 msgid "Migrate Metadata" msgstr "Migrar metadados" #: quodlibet/ext/songsmenu/migratemetadata.py:39 msgid "Copies the quodlibet-specific metadata between songs." msgstr "Copia metadados específicos ao Quod Libet de uma música para a outra." #: quodlibet/ext/songsmenu/migratemetadata.py:52 msgid "_Copy" msgstr "_Copiar" #: quodlibet/ext/songsmenu/migratemetadata.py:54 msgid "_Paste" msgstr "_Colar" #. Create the tag table. #: quodlibet/ext/songsmenu/migratemetadata.py:64 msgid "Information to copy/paste" msgstr "Informação a copiar/colar" #. Create the indexing box. #: quodlibet/ext/songsmenu/migratemetadata.py:86 msgid "Map tracks by disc and track number" msgstr "Mapear faixas por disco e número da faixa" #: quodlibet/ext/songsmenu/migratemetadata.py:87 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." #: quodlibet/ext/songsmenu/migratemetadata.py:103 #, python-format msgid "There is %d stored track." msgid_plural "There are %d stored tracks." msgstr[0] "%d faixa armazenada." msgstr[1] "%d faixas armazenadas." #: quodlibet/ext/songsmenu/playlist.py:31 msgid "Export as Playlist" msgstr "Exportar como lista de reprodução" #: quodlibet/ext/songsmenu/playlist.py:32 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:77 msgid "Use relative paths" msgstr "Usar caminhos relativos" #: quodlibet/ext/songsmenu/playlist.py:77 msgid "Use absolute paths" msgstr "Usar caminhos absolutos" #: quodlibet/ext/songsmenu/playlist.py:133 #, python-format msgid "Writing to <b>%s</b> 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 arquivos 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" #: quodlibet/ext/songsmenu/replaygain.py:407 msgid "Progress" msgstr "Progresso" #: quodlibet/ext/songsmenu/replaygain.py:422 msgid "Gain" msgstr "Ganho" #: quodlibet/ext/songsmenu/replaygain.py:437 msgid "Peak" msgstr "Pico" #: quodlibet/ext/songsmenu/replaygain.py:452 #, python-format msgid "There is <b>%(to-process)s</b> album to update (of %(all)s)" msgid_plural "There are <b>%(to-process)s</b> 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:568 msgid "Replay Gain" msgstr "Replay Gain" #: quodlibet/ext/songsmenu/replaygain.py:569 msgid "" "Analyzes and updates ReplayGain information, using GStreamer. Results are " "grouped by album." msgstr "" "Analisa e atualiza a os metadados do Replay Gain, usando o GStreamer. Os " "resultados são agrupados por álbum." #: quodlibet/ext/songsmenu/replaygain.py:607 msgid "always" msgstr "sempre" #: quodlibet/ext/songsmenu/replaygain.py:608 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:610 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:627 msgid "_Process albums:" msgstr "_Processar álbuns:" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:639 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 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:37 msgid "Website Search" msgstr "Pesquisa em website" #: 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-example)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:80 msgid "Search URL patterns" msgstr "Padrões de URL para pesquisa" #: quodlibet/ext/songsmenu/website_search.py:90 msgid "Edit search URLs" msgstr "Editar URLs" #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:116 msgid "Configure Searches…" msgstr "Configurar pesquisas…" #: quodlibet/ext/songsmenu/wikipedia.py:35 msgid "Search Tag in Wikipedia" msgstr "Pesquisar etiqueta na Wikipedia" #: quodlibet/ext/songsmenu/wikipedia.py:36 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:56 #, python-format msgid "Search at %(website)s" msgstr "Pesquisar em %(website)s" #: quodlibet/ext/songsmenu/wikipedia.py:70 #: quodlibet/ext/songsmenu/wikipedia.py:76 quodlibet/qltk/edittags.py:443 msgid "Edit Tags" msgstr "Editar etiquetas" #: quodlibet/ext/songsmenu/wikipedia.py:111 msgid "Search failed" msgstr "A pesquisa falhou" #: quodlibet/ext/songsmenu/wikipedia.py:112 #, python-format msgid "Tag \"%s\" not found." msgstr "A etiqueta\"%s\" não foi encontrada." #. then (try to) load all new files #: quodlibet/library/libraries.py:651 quodlibet/library/libraries.py:661 #: quodlibet/library/libraries.py:727 quodlibet/library/libraries.py:746 #: quodlibet/qltk/information.py:272 quodlibet/qltk/prefs.py:692 #: quodlibet/util/library.py:123 msgid "Library" msgstr "Biblioteca" #: quodlibet/library/libraries.py:651 msgid "Checking mount points" msgstr "Verificando pontos de montagem" #: quodlibet/library/libraries.py:661 msgid "Scanning library" msgstr "Escaneando biblioteca" #: quodlibet/library/libraries.py:726 #, python-format msgid "Scanning %s" msgstr "Escaneando %s" #: quodlibet/library/libraries.py:746 msgid "Loading files" msgstr "Carregando arquivos" #: quodlibet/main.py:50 msgid "Music player and music library manager" msgstr "Reprodutor de música e gerenciador de biblioteca de música" #: quodlibet/operon/base.py:70 #, python-format msgid "Failed to load file: %r" msgstr "Falha ao carregar o arquivo: %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:462 msgid "Print terse output" msgstr "Imprime saída concisa" #: quodlibet/operon/commands.py:43 quodlibet/operon/commands.py:82 #: quodlibet/operon/commands.py:464 #, 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:336 quodlibet/operon/commands.py:340 #: quodlibet/operon/commands.py:392 quodlibet/operon/commands.py:395 #: quodlibet/operon/commands.py:434 quodlibet/operon/commands.py:469 #: quodlibet/operon/commands.py:509 quodlibet/operon/commands.py:544 #: quodlibet/operon/commands.py:586 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:471 msgid "Too many arguments" msgstr "Argumentos de mais" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:91 #: quodlibet/operon/commands.py:476 quodlibet/qltk/data_editors.py:352 msgid "Description" msgstr "Descrição" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:476 #: quodlibet/qltk/edittags.py:493 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 arquivo para o outro" #: quodlibet/operon/commands.py:122 quodlibet/operon/commands.py:164 #: quodlibet/operon/commands.py:289 quodlibet/operon/commands.py:324 #: quodlibet/operon/commands.py:385 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 arquivo: {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:304 quodlibet/operon/commands.py:445 #: quodlibet/operon/commands.py:677 #, python-format msgid "Can not set %r" msgstr "Não foi possível redefinir o valor de %r" #: quodlibet/operon/commands.py:319 msgid "Remove tags" msgstr "Remove etiquetas" #: quodlibet/operon/commands.py:326 quodlibet/operon/commands.py:387 msgid "Value is a regular expression" msgstr "O valor é uma expressão regular" #: quodlibet/operon/commands.py:328 msgid "Remove all tags" msgstr "Remove todas as etiquetas" #: quodlibet/operon/commands.py:332 msgid "Can't combine '--all' with '--regexp'" msgstr "Não é permitido combinar as opções \"--all\" com \"--regexp\"" #: quodlibet/operon/commands.py:366 #, 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:380 msgid "Remove a tag value" msgstr "Remove valores de certas etiquetas" #: quodlibet/operon/commands.py:429 msgid "Add a tag value" msgstr "Adiciona etiquetas" #: quodlibet/operon/commands.py:457 msgid "List file information" msgstr "Lista informações do arquivo" #: quodlibet/operon/commands.py:503 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:516 #, python-format msgid "Failed to load image file: %r" msgstr "Falha ao carregar arquivo de imagem: %r" #: quodlibet/operon/commands.py:523 quodlibet/operon/commands.py:552 #, 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:539 msgid "Remove all embedded images" msgstr "Remove todas as imagens embutidas" #: quodlibet/operon/commands.py:569 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "Extrai as imagens embutidas para %(filepath)s" #: quodlibet/operon/commands.py:581 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:640 msgid "Rename files based on tags" msgstr "Renomeia arquivos baseado nas etiquetas" #: quodlibet/operon/commands.py:655 msgid "Fill tags based on the file path" msgstr "Preenche etiquetas baseado no nome do arquivo" #: quodlibet/operon/commands.py:705 quodlibet/qltk/information.py:309 #: quodlibet/qltk/properties.py:83 quodlibet/qltk/renamefiles.py:224 #: quodlibet/qltk/tagsfrompath.py:228 quodlibet/qltk/tracknumbers.py:78 msgid "File" msgstr "Arquivo" #: quodlibet/operon/commands.py:713 msgid "Fill tracknumbers for all files" msgstr "Preenche números de faixa para todos os arquivos" #: quodlibet/operon/commands.py:732 msgid "Print tags based on the given pattern" msgstr "Imprime etiquetas baseado no padrão escolhido" #: quodlibet/operon/commands.py:769 msgid "Display help information" msgstr "Mostra a ajuda" #: quodlibet/operon/util.py:42 #, 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:30 msgid "_Unknown" msgstr "_Desconhecido" #: quodlibet/order/__init__.py:142 msgid "In Order" msgstr "Em ordem" #: quodlibet/order/__init__.py:143 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:147 msgid "_Random" msgstr "A_leatória" #: quodlibet/order/reorder.py:40 quodlibet/order/reorder.py:41 msgid "Prefer higher rated" msgstr "Preferir a melhor avaliada" #: quodlibet/order/repeat.py:43 quodlibet/order/repeat.py:44 msgid "Repeat this track" msgstr "Repetir esta música" #: quodlibet/order/repeat.py:57 quodlibet/order/repeat.py:58 msgid "Repeat all" msgstr "Repetir todas" #: quodlibet/order/repeat.py:73 quodlibet/order/repeat.py:74 msgid "One Song" msgstr "Uma música" #: quodlibet/player/gstbe/player.py:98 msgid "Stream" msgstr "Stream" #: quodlibet/player/gstbe/player.py:98 msgid "Buffering" msgstr "Preenchimento do buffer" #: quodlibet/player/gstbe/player.py:452 msgid "Could not create GStreamer pipeline" msgstr "Não foi possível criar a fila de processamento do GStreamer" #: quodlibet/player/gstbe/player.py:651 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:652 #, 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:25 msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. In case 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:36 msgid "_Output pipeline:" msgstr "Fila de processamento de _saída:" #: quodlibet/player/gstbe/prefs.py:43 #, python-format msgid "%.1f seconds" msgstr "%.1f segundos" #: quodlibet/player/gstbe/prefs.py:57 msgid "_Buffer duration:" msgstr "Duração do _buffer:" #: quodlibet/player/gstbe/prefs.py:66 msgid "Disable _gapless playback" msgstr "Desativar reprodução sem intervalos" #: quodlibet/player/gstbe/prefs.py:70 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/util.py:101 msgid "No GStreamer audio sink found" msgstr "Nenhum consumidor de áudio do GStreamer foi encontrado" #: quodlibet/player/gstbe/util.py:120 msgid "Invalid GStreamer output pipeline" msgstr "A fila de processamento de saída do GStreamer é inválida" #: quodlibet/player/xinebe/player.py:90 msgid "Unable to create audio output" msgstr "Não foi possível criar a saída de áudio" #: quodlibet/player/xinebe/player.py:91 #, 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:61 #, 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:70 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "Não foi encontrado o elemento do GStreamer \"{element}\"." #: 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:55 #: quodlibet/qltk/songsmenu.py:66 msgid "_Run Plugin" msgstr "_Executar plug-in" #. 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:40 msgid "_Name:" msgstr "_Nome:" #: quodlibet/qltk/cbes.py:48 quodlibet/qltk/edittags.py:350 msgid "_Value:" msgstr "_Valor:" #: quodlibet/qltk/cbes.py:263 msgid "Saved Values" msgstr "Valores gravados" #: quodlibet/qltk/cbes.py:264 msgid "Edit saved values…" msgstr "Editar valores gravados…" #: quodlibet/qltk/controls.py:111 msgid "Auto_matic" msgstr "Auto_mático" #: quodlibet/qltk/controls.py:112 msgid "_Track Mode" msgstr "Por _faixa" #: quodlibet/qltk/controls.py:113 msgid "_Album Mode" msgstr "Por _álbum" #. Translators: player state, no action #: quodlibet/qltk/controls.py:122 msgid "_Mute" msgstr "_Mudo" #: quodlibet/qltk/controls.py:128 msgid "_Replay Gain Mode" msgstr "Modo do Replay Gain" #. Translators: New Command/Entry/Item/... #: quodlibet/qltk/data_editors.py:116 #, python-format msgid "New %s" msgstr "Novo %s" #: quodlibet/qltk/data_editors.py:215 msgid "(unknown)" msgstr "(desconhecido)" #: quodlibet/qltk/data_editors.py:344 msgid "Tag expression" msgstr "Expressão de etiqueta" #: quodlibet/qltk/data_editors.py:371 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:372 msgid "Enter new tag" msgstr "Insira uma nova 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 arquivos serão " "removidos do disco." #: quodlibet/qltk/delete.py:72 msgid "The selected files will be deleted from disk." msgstr "Os arquivos selecionados serão excluídos do 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] "Excluir %(file_count)d arquivo permanentemente?" msgstr[1] "Excluir %(file_count)d arquivos permanentemente?" #: quodlibet/qltk/delete.py:91 msgid "_Delete Files" msgstr "Exclui_r arquivos" #: 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 seus arquivos serão " "movidos para a lixeira." #: quodlibet/qltk/delete.py:115 msgid "The selected files will be moved to the trash." msgstr "Os arquivos selecionados serão movidos para a lixeira." #: 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 arquivo para a lixeira?" msgstr[1] "Mover %(file_count)d arquivos para a lixeira?" #: quodlibet/qltk/delete.py:134 quodlibet/qltk/delete.py:141 msgid "_Move to Trash" msgstr "_Mover para a lixeira" #: 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 a lixeira" #: 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 arquivos para a lixeira." #: 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 arquivos" #: quodlibet/qltk/delete.py:237 quodlibet/qltk/delete.py:270 msgid "Deleting one or more files failed." msgstr "Falha ao excluir um ou mais 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:197 msgid "Split into _Multiple Values" msgstr "Divide em vári_os valores" #: quodlibet/qltk/edittags.py:219 msgid "Split Disc out of _Album" msgstr "Separar disco de á_lbum" #: quodlibet/qltk/edittags.py:243 msgid "Split _Version out of Title" msgstr "Separar _versão de título" #: quodlibet/qltk/edittags.py:298 msgid "Split Arranger out of Ar_tist" msgstr "Separar arranjador de ar_tista" #: quodlibet/qltk/edittags.py:303 msgid "Split _Performer out of Artist" msgstr "Separar _intérprete do artista" #: quodlibet/qltk/edittags.py:309 msgid "Split _Performer out of Title" msgstr "Separar _intérprete de título" #: quodlibet/qltk/edittags.py:315 msgid "Split _Originalartist out of Title" msgstr "Separar _artistaoriginal de título" #: quodlibet/qltk/edittags.py:322 msgid "Add a Tag" msgstr "Adicionar uma etiqueta" #: quodlibet/qltk/edittags.py:341 msgid "_Tag:" msgstr "Etique_ta:" #: quodlibet/qltk/edittags.py:516 msgid "Show _programmatic tags" msgstr "Mostrar etiquetas geradas _automaticamente" #: quodlibet/qltk/edittags.py:517 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" #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:547 msgctxt "edittags" msgid "_Revert" msgstr "_Reverter" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:552 msgctxt "edittags" msgid "_Save" msgstr "_Salvar" #: quodlibet/qltk/edittags.py:681 msgid "_Configure" msgstr "_Configurar" #: quodlibet/qltk/edittags.py:696 msgid "_Split Tag" msgstr "Dividir etiqueta" #: quodlibet/qltk/edittags.py:705 msgid "_Copy Value(s)" msgstr "_Copiar valor(es)" #: quodlibet/qltk/edittags.py:736 msgid "Unable to add tag" msgstr "Não foi possível adicionar a etiqueta" #: quodlibet/qltk/edittags.py:737 #, python-format msgid "Unable to add <b>%s</b>" msgstr "Não foi possível adicionar <b>%s</b>" #: quodlibet/qltk/edittags.py:739 #, python-format msgid "" "The files currently selected do not support multiple values for <b>%s</b>." msgstr "" "Os arquivos selecionados não dão suporte a múltiplos valores de <b>%s</b>." #. Can't add the new tag. #: quodlibet/qltk/edittags.py:766 quodlibet/qltk/edittags.py:947 #: quodlibet/qltk/tagsfrompath.py:211 quodlibet/util/__init__.py:505 #: quodlibet/util/tags.py:243 msgid "Invalid tag" msgstr "Etiqueta inválida" #: quodlibet/qltk/edittags.py:767 quodlibet/qltk/edittags.py:948 #: quodlibet/qltk/tagsfrompath.py:212 #, python-format msgid "" "Invalid tag <b>%s</b>\n" "\n" "The files currently selected do not support editing this tag." msgstr "" "Etiqueta <b>%s</b> inválida\n" "\n" "Os arquivos selecionados não suportam a edição desta etiqueta." #: quodlibet/qltk/edittags.py:918 quodlibet/qltk/edittags.py:959 msgid "Invalid value" msgstr "Valor inválido" #: quodlibet/qltk/edittags.py:919 quodlibet/qltk/edittags.py:960 #, python-format msgid "" "Invalid value: <b>%(value)s</b>\n" "\n" "%(error)s" msgstr "" "Valor inválido: <b>%(value)s</b>\n" "\n" "%(error)s" #: quodlibet/qltk/_editutils.py:29 msgid "Tag may not be accurate" msgstr "Etiqueta pode não estar correta" #: quodlibet/qltk/_editutils.py:32 #, 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:48 msgid "Unable to save song" msgstr "Não foi possível salvar a música" #: quodlibet/qltk/_editutils.py:51 #, 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 arquivo pode ser somente leitura, estar " "corrompido , ou você pode não ter permissão para editá-lo." #: quodlibet/qltk/_editutils.py:143 msgid "_More options…" msgstr "_Mais opções…" #: quodlibet/qltk/entry.py:78 msgid "_Undo" msgstr "_Desfazer" #: quodlibet/qltk/entry.py:80 msgid "_Redo" msgstr "_Refazer" #: quodlibet/qltk/exfalsowindow.py:94 quodlibet/qltk/quodlibetwindow.py:956 msgid "_About" msgstr "_Sobre" #: quodlibet/qltk/exfalsowindow.py:98 quodlibet/qltk/quodlibetwindow.py:978 msgid "_Check for Updates…" msgstr "_Verificar por atualizações…" #: quodlibet/qltk/exfalsowindow.py:104 quodlibet/qltk/quodlibetwindow.py:911 #: quodlibet/qltk/songsmenu.py:289 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:278 msgid "Ex Falso Preferences" msgstr "Preferências do Ex Falso" #: quodlibet/qltk/exfalsowindow.py:284 quodlibet/qltk/prefs.py:666 msgid "Tag Editing" msgstr "Edição de etiquetas" #: 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:386 msgid "Unable to create folder" msgstr "Não foi possível criar a pasta" #: quodlibet/qltk/filesel.py:403 msgid "Unable to delete folder" msgstr "Não foi possível excluir a pasta" #: quodlibet/qltk/filesel.py:519 quodlibet/qltk/pluginwin.py:167 msgid "Songs" msgstr "Músicas" #. Translators: As in "by Artist Name" #: quodlibet/qltk/info.py:42 #, python-format msgid "by %s" msgstr "por %s" #: quodlibet/qltk/info.py:43 quodlibet/qltk/information.py:171 #: quodlibet/qltk/information.py:452 #, python-format msgid "Disc %s" msgstr "Disco %s" #: quodlibet/qltk/info.py:44 quodlibet/qltk/information.py:176 #, python-format msgid "Track %s" msgstr "Faixa %s" #: quodlibet/qltk/info.py:108 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:342 #: quodlibet/qltk/information.py:475 quodlibet/qltk/information.py:543 msgid "Information" msgstr "Informação" #: quodlibet/qltk/information.py:127 msgid "Lyrics" msgstr "Letra" #: quodlibet/qltk/information.py:188 quodlibet/qltk/information.py:400 #, python-format msgid "Produced by %s" msgstr "Produzido por %s" #: quodlibet/qltk/information.py:203 quodlibet/util/tags.py:85 msgid "artist" msgstr "artista" #: quodlibet/qltk/information.py:204 quodlibet/qltk/information.py:573 #: quodlibet/util/tags.py:85 msgid "artists" msgstr "artistas" #. for backwards compat #: quodlibet/qltk/information.py:225 quodlibet/util/tags.py:96 #: quodlibet/util/tags.py:124 msgid "performers" msgstr "intérpretes" #: quodlibet/qltk/information.py:239 quodlibet/qltk/information.py:252 #: quodlibet/qltk/songlistcolumns.py:276 msgid "Never" msgstr "Nunca" #: quodlibet/qltk/information.py:240 #, 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:258 quodlibet/util/tags.py:149 msgid "added" msgstr "adicionada" #: quodlibet/qltk/information.py:259 quodlibet/util/tags.py:150 msgid "last played" msgstr "última reprodução" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:160 msgid "plays" msgstr "reproduções" #: quodlibet/qltk/information.py:261 quodlibet/util/tags.py:161 msgid "skips" msgstr "ignorada" #: quodlibet/qltk/information.py:262 quodlibet/util/tags.py:166 msgid "rating" msgstr "avaliação" #: quodlibet/qltk/information.py:291 msgid "path" msgstr "caminho" #: quodlibet/qltk/information.py:292 quodlibet/util/tags.py:164 msgid "length" msgstr "duração" #: quodlibet/qltk/information.py:293 msgid "format" msgstr "formato" #: quodlibet/qltk/information.py:294 quodlibet/util/tags.py:174 msgid "codec" msgstr "codec" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:175 msgid "encoding" msgstr "codificação" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:171 msgid "bitrate" msgstr "taxa de bits" #: quodlibet/qltk/information.py:297 quodlibet/util/tags.py:172 msgid "file size" msgstr "tamanho" #: quodlibet/qltk/information.py:298 quodlibet/util/tags.py:159 msgid "modified" msgstr "modificado" #: quodlibet/qltk/information.py:335 msgid "Additional" msgstr "Adicional" #: quodlibet/qltk/information.py:387 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d selecionado" msgstr[1] "%d selecionados" #: quodlibet/qltk/information.py:462 msgid "Track unavailable" msgstr "Faixa indisponível" #: quodlibet/qltk/information.py:468 msgid "Track List" msgstr "Lista de faixas" #: quodlibet/qltk/information.py:500 quodlibet/qltk/information.py:590 #, 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:503 msgid "Selected Discography" msgstr "Discografia selecionada" #: quodlibet/qltk/information.py:570 #, 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:598 quodlibet/util/tags.py:83 msgid "albums" msgstr "álbums" #: quodlibet/qltk/information.py:611 msgid "Total length:" msgstr "Duração total:" #: quodlibet/qltk/information.py:615 msgid "Total size:" msgstr "Tamanho total:" #: quodlibet/qltk/information.py:618 msgid "Files" msgstr "Arquivos" #: quodlibet/qltk/lyrics.py:36 msgid "_View online" msgstr "_Procurar na internet" #: quodlibet/qltk/lyrics.py:64 msgid "No lyrics found for this song." msgstr "Não foram encontradas letras para esta música." #: quodlibet/qltk/lyrics.py:75 msgid "Searching for lyrics…" msgstr "Procurando por letras…" #: 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/msg.py:41 msgid "Discard tag changes?" msgstr "Descartar alterações nas etiquetas?" #: quodlibet/qltk/msg.py:42 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 arquivos, ou " "reverter e descartar as alterações?" #: quodlibet/qltk/msg.py:55 quodlibet/qltk/prefs.py:628 #: quodlibet/qltk/prefs.py:635 quodlibet/qltk/textedit.py:63 #: quodlibet/qltk/tracknumbers.py:116 msgid "_Revert" msgstr "_Reverter" #: quodlibet/qltk/msg.py:104 msgid "File exists" msgstr "Arquivo existe" #: quodlibet/qltk/msg.py:106 #, python-format msgid "Replace %(file-name)s?" msgstr "Sobrescrever %(file-name)s?" #: quodlibet/qltk/msg.py:112 msgid "_Replace File" msgstr "_Sobrescrever arquivo" #: quodlibet/qltk/notif.py:182 msgid "Active tasks" msgstr "Tarefas ativas" #: quodlibet/qltk/notif.py:188 #, python-format msgid "%d tasks running" msgstr "%d tarefas ativas" #: quodlibet/qltk/playorder.py:256 msgid "Toggle shuffle mode" msgstr "Ativar/desativar o embaralhamento" #: quodlibet/qltk/playorder.py:272 msgid "Toggle repeat mode" msgstr "Ativar/desativar a repetição" #: quodlibet/qltk/pluginwin.py:44 msgid "Plugin Errors" msgstr "Plug-ins with errors" #: quodlibet/qltk/pluginwin.py:124 msgid "Enabled" msgstr "Ativado" #: quodlibet/qltk/pluginwin.py:125 msgid "Disabled" msgstr "Desativado" #: quodlibet/qltk/pluginwin.py:131 msgid "No category" msgstr "Nenhuma categoria" #: quodlibet/qltk/pluginwin.py:169 msgid "Events" msgstr "Eventos" #: quodlibet/qltk/pluginwin.py:170 msgid "Play Order" msgstr "Ordem de Reprodução" #: quodlibet/qltk/pluginwin.py:171 msgid "Editing" msgstr "Edição" #: quodlibet/qltk/pluginwin.py:173 msgid "Covers" msgstr "Capas" #: quodlibet/qltk/pluginwin.py:309 msgid "No plugins found." msgstr "Nenhum plug-in foi encontrado." #: quodlibet/qltk/pluginwin.py:358 msgid "Plugins" msgstr "Plug-ins" #: quodlibet/qltk/pluginwin.py:382 msgid "Filter by plugin state / tag" msgstr "Filtrar pelo estado do plug-in" #: quodlibet/qltk/pluginwin.py:388 msgid "Filter by plugin type" msgstr "Filtrar pelo tipo do plug-in" #: quodlibet/qltk/pluginwin.py:394 msgid "Filter by plugin name or description" msgstr "Filtrar pelo nome ou descrição do plug-in" #: quodlibet/qltk/pluginwin.py:403 msgid "Show _Errors" msgstr "Mostrar _erros" #: quodlibet/qltk/prefs.py:45 msgid "_Disc" msgstr "_Disco" #: quodlibet/qltk/prefs.py:46 msgid "_Track" msgstr "_Faixa" #: quodlibet/qltk/prefs.py:47 msgid "Grou_ping" msgstr "A_grupamento" #: quodlibet/qltk/prefs.py:50 msgid "Al_bum" msgstr "Ál_bum" #: quodlibet/qltk/prefs.py:55 msgid "_Filename" msgstr "_Nome de arquivo" #: quodlibet/qltk/prefs.py:57 msgid "_Length" msgstr "Du_ração" #: quodlibet/qltk/prefs.py:64 msgid "_Jump to playing song automatically" msgstr "_Ir automaticamente para a música em reprodução" #: quodlibet/qltk/prefs.py:66 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:82 msgid "_Others:" msgstr "_Outros:" #: quodlibet/qltk/prefs.py:88 msgid "_Edit…" msgstr "_Editar…" #: quodlibet/qltk/prefs.py:91 msgid "Add or remove additional column headers" msgstr "Adicionar ou remover colunas" #: quodlibet/qltk/prefs.py:101 msgid "Visible Columns" msgstr "Colunas visíveis" #: quodlibet/qltk/prefs.py:104 msgid "Title includes _version" msgstr "Título inclui _versão" #: quodlibet/qltk/prefs.py:106 msgid "Artist includes all _people" msgstr "Busca por artista inclui todas as _pessoas" #: quodlibet/qltk/prefs.py:108 msgid "Album includes _disc subtitle" msgstr "Álbum inclui subtítulo do _disco" #: quodlibet/qltk/prefs.py:110 msgid "Filename includes _folder" msgstr "Nome do arquivo inclui a _pasta" #: quodlibet/qltk/prefs.py:123 msgid "Column Preferences" msgstr "Preferências das colunas" #: quodlibet/qltk/prefs.py:129 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:142 quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Lista de músicas" #: quodlibet/qltk/prefs.py:222 msgid "Edit Columns" msgstr "Editar colunas" #: quodlibet/qltk/prefs.py:259 msgid "Duration totals" msgstr "Durações" #: quodlibet/qltk/prefs.py:271 msgid "_Global filter:" msgstr "_Filtro global:" #: quodlibet/qltk/prefs.py:277 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:283 msgctxt "heading" msgid "Search" msgstr "Pesquisa" #: quodlibet/qltk/prefs.py:287 quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Navegadores" #: quodlibet/qltk/prefs.py:293 msgid "Confirm _multiple ratings" msgstr "Confirmar avaliações _conjuntas" #: quodlibet/qltk/prefs.py:295 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:298 msgid "Enable _one-click ratings" msgstr "Habilitar avaliação de _um clique" #: quodlibet/qltk/prefs.py:300 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:306 quodlibet/qltk/prefs.py:669 msgid "Ratings" msgstr "Avaliações" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:312 msgid "Prefer _embedded art" msgstr "Preferir arte _embutida" #: quodlibet/qltk/prefs.py:314 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:319 msgid "_Fixed image filename:" msgstr "Nome _fixo para arquivo de imagem:" #: quodlibet/qltk/prefs.py:321 msgid "The single image filename to use if selected" msgstr "Usar apenas este nome de arquivo para imagem" #: quodlibet/qltk/prefs.py:327 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." #: quodlibet/qltk/prefs.py:337 msgid "Album Art" msgstr "Capa de álbuns" #: quodlibet/qltk/prefs.py:358 msgid "Playback" msgstr "Reprodução" #: quodlibet/qltk/prefs.py:363 msgid "Output Configuration" msgstr "Configuração da saída" #: quodlibet/qltk/prefs.py:374 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:377 msgid "_Fall-back gain (dB):" msgstr "Ganho padrão (dB):" #: quodlibet/qltk/prefs.py:388 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:391 msgid "_Pre-amp gain (dB):" msgstr "Ganho pré-amp (dB):" #: quodlibet/qltk/prefs.py:396 msgid "_Enable Replay Gain volume adjustment" msgstr "Habilitar o ajuste de volume Replay Gain" #: quodlibet/qltk/prefs.py:421 msgid "Replay Gain Volume Adjustment" msgstr "Ajuste de volume Replay Gain" #: quodlibet/qltk/prefs.py:428 msgid "_Continue playback on startup" msgstr "_Continuar reprodução ao iniciar" #: quodlibet/qltk/prefs.py:430 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:434 msgid "Startup" msgstr "Inicialização" #: quodlibet/qltk/prefs.py:461 msgid "_Default rating:" msgstr "Avaliação _padrão:" #: quodlibet/qltk/prefs.py:504 msgid "Rating _scale:" msgstr "Escala de avaliação:" #: quodlibet/qltk/prefs.py:553 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" "Para um dado fator C, efetivamente adiciona C elementos com avaliação padrão " "antes de tirar a média.\n" "0 corresponde à média aritmética usual. Valores mais altos significam que " "álbuns com poucas faixas tem avaliações menos extremas.\n" "Alterar este valor resulta em um recálculo da avaliação de todos os álbuns." #: quodlibet/qltk/prefs.py:558 msgid "_Bayesian averaging amount:" msgstr "Fator da média _bayesiana:" #: quodlibet/qltk/prefs.py:567 msgid "Save ratings and play _counts in tags" msgstr "Salvar avaliações e _contagem de reproduções em etiquetas" #: quodlibet/qltk/prefs.py:575 msgid "_Email:" msgstr "_Email:" #: quodlibet/qltk/prefs.py:577 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:597 msgid "Auto-save tag changes" msgstr "Salvar alterações automaticamente" #: quodlibet/qltk/prefs.py:599 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 " "arquivos" #: quodlibet/qltk/prefs.py:608 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:618 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:631 msgid "Split _tag on:" msgstr "Separar _etiquetas em:" #: quodlibet/qltk/prefs.py:638 msgid "Split _subtag on:" msgstr "Separar _sub-etiquetas em:" #: quodlibet/qltk/prefs.py:663 msgid "Tags" msgstr "Etiquetas" #: quodlibet/qltk/prefs.py:684 msgid "Updating for new ratings" msgstr "Atualizando para novas avaliações" #: quodlibet/qltk/prefs.py:694 msgid "Scan library _on start" msgstr "Atualizar biblioteca ao _iniciar" #: quodlibet/qltk/prefs.py:704 quodlibet/qltk/quodlibetwindow.py:990 msgid "_Scan Library" msgstr "Atuali_zar biblioteca" #: quodlibet/qltk/prefs.py:706 quodlibet/qltk/quodlibetwindow.py:1052 msgid "Check for changes in your library" msgstr "Verificar por alterações na biblioteca" #: quodlibet/qltk/prefs.py:711 msgid "Re_build Library" msgstr "Re_construir biblioteca" #: quodlibet/qltk/prefs.py:714 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:724 msgid "Scan Directories" msgstr "Pastas a escanear" #: quodlibet/qltk/prefs.py:730 msgid "Hidden Songs" msgstr "Músicas escondidas" #: quodlibet/qltk/properties.py:157 quodlibet/util/collection.py:403 #, 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:104 msgid "_Queue" msgstr "_Fila de reprodução" #: quodlibet/qltk/queue.py:124 msgid "Ephemeral" msgstr "Efêmero" #: quodlibet/qltk/queue.py:125 msgid "Remove songs from the queue after playing them" msgstr "Remover músicas da fila após reproduzí-las" #: quodlibet/qltk/queue.py:133 msgid "Persistent" msgstr "Persistente" #: quodlibet/qltk/queue.py:134 msgid "Keep songs in the queue after playing them" msgstr "Manter músicas na fila após reproduzí-las" #: quodlibet/qltk/queue.py:142 msgid "Mode" msgstr "Modo" #: quodlibet/qltk/queue.py:153 msgid "Stop at End" msgstr "Parar no fim" #: quodlibet/qltk/queue.py:157 msgid "_Clear Queue" msgstr "_Esvaziar fila" #: quodlibet/qltk/queue.py:178 msgid "Disable queue - the queue will be ignored when playing" msgstr "Desativar a fila – a fila será ignorada pelo tocador" #: quodlibet/qltk/queue.py:290 #, 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:198 msgid "_Browse Library" msgstr "_Navegar pela biblioteca" #: quodlibet/qltk/quodlibetwindow.py:348 msgid "Toggle queue visibility" msgstr "Mostra/esconde a fila" #: quodlibet/qltk/quodlibetwindow.py:376 msgid "Playback Error" msgstr "Erro de reprodução" #: quodlibet/qltk/quodlibetwindow.py:384 msgid "Set up library directories?" msgstr "Configurar pastas da biblioteca?" #: quodlibet/qltk/quodlibetwindow.py:385 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:391 msgid "_Not Now" msgstr "Agora _não" #: quodlibet/qltk/quodlibetwindow.py:392 msgid "_Set Up" msgstr "_Configurar" #: quodlibet/qltk/quodlibetwindow.py:845 msgid "Unable to add songs" msgstr "Não foi possível adicionar as músicas" #: quodlibet/qltk/quodlibetwindow.py:846 quodlibet/qltk/quodlibetwindow.py:1286 #, python-format msgid "%s uses an unsupported protocol." msgstr "%s utiliza um protocolo para qual não há suporte." #: quodlibet/qltk/quodlibetwindow.py:869 msgid "_Jump to Playing Song" msgstr "Ir para a música em reprodução" #: quodlibet/qltk/quodlibetwindow.py:876 msgid "_File" msgstr "_Arquivo" #: quodlibet/qltk/quodlibetwindow.py:877 msgid "_Song" msgstr "_Músicas" #: quodlibet/qltk/quodlibetwindow.py:878 msgid "_View" msgstr "_Ver" #: quodlibet/qltk/quodlibetwindow.py:879 msgid "_Browse" msgstr "_Navegar" #: quodlibet/qltk/quodlibetwindow.py:880 msgid "_Control" msgstr "_Controle" #: quodlibet/qltk/quodlibetwindow.py:881 msgid "_Help" msgstr "A_juda" #: quodlibet/qltk/quodlibetwindow.py:887 msgid "_Add a Folder…" msgstr "Adicionar uma _pasta…" #: quodlibet/qltk/quodlibetwindow.py:892 msgid "_Add a File…" msgstr "Adicionar um _arquivo…" #: quodlibet/qltk/quodlibetwindow.py:897 msgid "_Add a Location…" msgstr "Adicionar um _endereço…" #: quodlibet/qltk/quodlibetwindow.py:926 msgid "Edit Bookmarks…" msgstr "Editar _marcadores…" #: quodlibet/qltk/quodlibetwindow.py:946 msgid "Stop After This Song" msgstr "Parar após esta música" #: quodlibet/qltk/quodlibetwindow.py:952 msgid "_Keyboard Shortcuts" msgstr "Atalhos de _teclado" #: quodlibet/qltk/quodlibetwindow.py:961 msgid "Online Help" msgstr "_Ajuda online" #: quodlibet/qltk/quodlibetwindow.py:970 msgid "Search Help" msgstr "Como _pesquisar na biblioteca" #: quodlibet/qltk/quodlibetwindow.py:1274 msgid "Add a Location" msgstr "Adicionar um endereço" #: quodlibet/qltk/quodlibetwindow.py:1275 msgid "Enter the location of an audio file:" msgstr "Insira o endereço de um arquivo de áudio:" #: quodlibet/qltk/quodlibetwindow.py:1280 #: quodlibet/qltk/quodlibetwindow.py:1285 msgid "Unable to add location" msgstr "Não foi possível adicionar o endereço" #: quodlibet/qltk/quodlibetwindow.py:1281 #, python-format msgid "%s is not a valid location." msgstr "%s não é um endereço válido." #: quodlibet/qltk/quodlibetwindow.py:1294 #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "Add Music" msgstr "Adicionar música" #: quodlibet/qltk/quodlibetwindow.py:1294 quodlibet/qltk/scanbox.py:99 msgid "_Add Folders" msgstr "_Adicionar pastas" #: quodlibet/qltk/quodlibetwindow.py:1301 msgid "Music Files" msgstr "Arquivos de música" #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "_Add Files" msgstr "_Adicionar arquivos" #: quodlibet/qltk/ratingsmenu.py:24 #, 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:26 msgid "The saved ratings will be removed" msgstr "As avaliações salvas serão excluidas" #: quodlibet/qltk/ratingsmenu.py:27 #, 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:57 quodlibet/qltk/ratingsmenu.py:111 msgid "_Remove Rating" msgstr "_Remover avaliação" #: quodlibet/qltk/renamefiles.py:51 msgid "Replace spaces with _underscores" msgstr "Substituir espaços por _sublinhados (\"_\")" #: quodlibet/qltk/renamefiles.py:61 msgid "Strip _Windows-incompatible characters" msgstr "Remover caracteres incompatíveis com o _Windows" #: quodlibet/qltk/renamefiles.py:79 msgid "Strip _diacritical marks" msgstr "Remover acentos e diacríticos" #: quodlibet/qltk/renamefiles.py:90 msgid "Strip non-_ASCII characters" msgstr "Remover caracteres não-_ASCII" #: quodlibet/qltk/renamefiles.py:100 msgid "Use only _lowercase characters" msgstr "Usar apenas letras minúsculas" #: quodlibet/qltk/renamefiles.py:128 msgid "Rename Files" msgstr "Renomear arquivos" #: quodlibet/qltk/renamefiles.py:146 quodlibet/qltk/tagsfrompath.py:115 msgid "Path Patterns" msgstr "Padrões de caminho" #: quodlibet/qltk/renamefiles.py:147 quodlibet/qltk/tagsfrompath.py:116 msgid "Edit saved patterns…" msgstr "Editar padrões salvos…" #: quodlibet/qltk/renamefiles.py:150 quodlibet/qltk/tagsfrompath.py:119 #: quodlibet/qltk/tracknumbers.py:57 msgid "_Preview" msgstr "_Visualizar" #: quodlibet/qltk/renamefiles.py:177 msgid "File names" msgstr "Nomes de arquivo" #: quodlibet/qltk/renamefiles.py:187 msgid "_Move album art" msgstr "_Mover capas de álbum" #: quodlibet/qltk/renamefiles.py:190 msgid "See '[albumart] filenames' config entry for image search strings" msgstr "" "Os nomes de arquivos usados na busca são descritos na entrada \"[albumart] " "filenames\" do arquivo de configuração" #: quodlibet/qltk/renamefiles.py:195 msgid "_Overwrite album art at target" msgstr "_Sobrescrever capa do álbum no destino" #: quodlibet/qltk/renamefiles.py:203 msgid "_Remove empty directories" msgstr "E_xcluir pastas vazias" #: quodlibet/qltk/renamefiles.py:209 msgid "Album art" msgstr "Capas de álbum" #: quodlibet/qltk/renamefiles.py:238 msgid "New Name" msgstr "Novo nome" #: quodlibet/qltk/renamefiles.py:315 msgid "Unable to rename file" msgstr "Não foi possível renomear o arquivo" #: quodlibet/qltk/renamefiles.py:316 #, python-format msgid "" "Renaming <b>%(old-name)s</b> to <b>%(new-name)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." msgstr "" "Renomear <b>%(old-name)s</b> para <b>%(new-name)s</b> falhou. Possivelmente " "o novo nome é já está sendo usado, ou você não tem permissão para criar o " "novo arquivo ou apagar o antigo." #: quodlibet/qltk/renamefiles.py:324 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:325 quodlibet/qltk/wlw.py:49 msgid "_Stop" msgstr "_Parar" #: quodlibet/qltk/renamefiles.py:327 msgid "_Continue" msgstr "_Continue" #: quodlibet/qltk/renamefiles.py:440 msgid "Path is not absolute" msgstr "O caminho não é absoluto" #: quodlibet/qltk/renamefiles.py:441 #, python-format msgid "" "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 ~/." 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:47 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:99 msgid "Select Directories" msgstr "Selecionar pastas" #: quodlibet/qltk/searchbar.py:57 msgid "Saved Searches" msgstr "Consultas salvas" #: quodlibet/qltk/searchbar.py:58 msgid "Edit saved searches…" msgstr "Editar consultas salvas…" #: quodlibet/qltk/searchbar.py:82 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:144 msgid "Search after _typing" msgstr "Pesquise após digi_tar" #: quodlibet/qltk/searchbar.py:147 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:215 msgid "_Limit:" msgstr "_Limite:" #: quodlibet/qltk/searchbar.py:228 msgid "_Weight" msgstr "_Peso" #: quodlibet/qltk/searchbar.py:355 msgid "Add query" msgstr "Adicionar consulta" #: quodlibet/qltk/searchbar.py:356 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 em um 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:375 #, python-format msgid "_Filter on %s" msgstr "_Filtrar por %s" #: quodlibet/qltk/songlist.py:1093 msgid "All _Headers" msgstr "Todos os _cabeçalhos" #: quodlibet/qltk/songlist.py:1094 msgid "_Track Headers" msgstr "Cabeçalhos de _faixa" #: quodlibet/qltk/songlist.py:1095 msgid "_Album Headers" msgstr "Cabeçalhos de ál_buns" #: quodlibet/qltk/songlist.py:1096 msgid "_People Headers" msgstr "Cabeçalhos de _pessoas" #: quodlibet/qltk/songlist.py:1097 msgid "_Date Headers" msgstr "Cabeçalhos de _data" #: quodlibet/qltk/songlist.py:1098 msgid "_File Headers" msgstr "Cabeçalhos de _arquivos" #: quodlibet/qltk/songlist.py:1099 msgid "_Production Headers" msgstr "Cabeçalhos de _produção" #: quodlibet/qltk/songlist.py:1114 msgid "_Customize Headers…" msgstr "_Personalizar cabeçalhos…" #: quodlibet/qltk/songlist.py:1119 msgid "_Expand Column" msgstr "_Expandir coluna" #: quodlibet/qltk/songsmenu.py:40 #, python-format msgid "Remove track: \"%%(title)s\" from library?" msgid_plural "Remove %(count)d tracks from library?" msgstr[0] "Remover a faixa \"%%(title)s\" da biblioteca?" msgstr[1] "Remover %(count)d faixas da biblioteca?" #: quodlibet/qltk/songsmenu.py:46 msgid "Remove from Library" msgstr "_Remover da biblioteca" #: quodlibet/qltk/songsmenu.py:51 #, 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:62 #, 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:134 msgid "Configure Plugins…" msgstr "Configurar plug-ins…" #: quodlibet/qltk/songsmenu.py:329 msgid "Add to _Queue" msgstr "Adicionar à _fila" #: quodlibet/qltk/songsmenu.py:349 msgid "_Remove from Library…" msgstr "_Remover da biblioteca…" #: quodlibet/qltk/songsmenu.py:414 msgid "Unable to show files" msgstr "Não foi possível exibir os arquivos" #: quodlibet/qltk/songsmenu.py:415 msgid "Error showing files, or no program available to show them." msgstr "" "Falha ao exibir arquivos, ou não há um programa disponível para exibi-los." #: quodlibet/qltk/songsmenu.py:422 #, python-format msgid "_Show in File Manager" msgid_plural "_Show %(total)d Files in File Manager" msgstr[0] "_Exibir no gerenciador de arquivos" msgstr[1] "_Exibir %(total)d arquivos no gerenciador de arquivos" #: quodlibet/qltk/tagsfrompath.py:46 msgid "Replace _underscores with spaces" msgstr "Substituir _sublinhados (\"__\") por espaços" #: quodlibet/qltk/tagsfrompath.py:56 msgid "_Title-case tags" msgstr "_Capitalizar com Title-case" #: quodlibet/qltk/tagsfrompath.py:66 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 #, python-format msgid "" "The pattern\n" "\t<b>%s</b>\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/tagsfrompath.py:215 msgid "Invalid tags" msgstr "Etiquetas inválidas" #: quodlibet/qltk/tagsfrompath.py:216 #, 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 arquivos selecionados não tem suporte a estas etiquetas." #: 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:923 #, python-format msgid "and %d more…" msgstr "e %d mais…" #: quodlibet/qltk/wlw.py:199 msgid "Saving the songs you changed." msgstr "Salvando as músicas que você alterou." #: quodlibet/qltk/wlw.py:200 #, 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:233 #, 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:425 msgid "Playlists must have a name" msgstr "A lista de reprodução deve ter um nome" #: quodlibet/util/collection.py:608 #, python-format msgid "A playlist named %s already exists." msgstr "Uma lista de reprodução chamada %s já existe." #: quodlibet/util/cover/built_in.py:32 msgid "Embedded album covers" msgstr "Capas de álbum embutidas" #: quodlibet/util/cover/built_in.py:33 msgid "Uses covers embedded into audio files." msgstr "Usa capas de álbum embutidas nos arquivos de áudio." #: quodlibet/util/cover/built_in.py:55 msgid "Filesystem cover" msgstr "Capa de álbum pelo sistema de arquivos" #: quodlibet/util/cover/built_in.py:56 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:76 msgid "Display brief usage information" msgstr "Mostra a ajuda" #: quodlibet/util/__init__.py:78 msgid "Display version and copyright" msgstr "Mostra versão e direitos autorais" #: quodlibet/util/__init__.py:79 msgid "Print debugging information" msgstr "Imprime informação de depuração" #: quodlibet/util/__init__.py:118 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "Uso: %(program)s %(usage)s" #: quodlibet/util/__init__.py:120 msgid "[options]" msgstr "[opções]" #: quodlibet/util/__init__.py:165 #, python-format msgid "Option %r not recognized." msgstr "A opção %r não é reconhecida." #: quodlibet/util/__init__.py:168 #, python-format msgid "Option %r requires an argument." msgstr "A opção %r requer um parâmetro." #: quodlibet/util/__init__.py:171 #, python-format msgid "%r is not a unique prefix." msgstr "%r não é um prefixo único." #: quodlibet/util/__init__.py:347 #, python-format msgid "%d kbps" msgstr "%d kbps" #: quodlibet/util/__init__.py:402 #, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%s segundo" msgstr[1] "%s segundos" #: quodlibet/util/__init__.py:415 msgid "No time information" msgstr "Informação de tempo ausente" #: quodlibet/util/__init__.py:418 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d segundo" msgstr[1] "%d segundos" #: quodlibet/util/__init__.py:419 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d minuto" msgstr[1] "%d minutos" #: quodlibet/util/__init__.py:420 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d hora" msgstr[1] "%d horas" #: quodlibet/util/__init__.py:421 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d dia" msgstr[1] "%d dias" #: quodlibet/util/__init__.py:422 #, 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:514 msgctxt "check" msgid "titlecase?" msgstr "" "apenas a primeira letra deve ser maiúscula em português\n" "#?" #: quodlibet/util/massagers.py:114 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:129 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:150 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:172 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:194 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:207 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:116 msgid "Unable to edit song" msgstr "Não foi possível editar a música" #: quodlibet/util/songwrapper.py:117 #, python-format msgid "" "Saving <b>%s</b> 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 arquivo 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:151 msgid "disc" msgstr "disco" #: quodlibet/util/tags.py:115 quodlibet/util/tags.py:153 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" #. 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:130 msgid "MusicBrainz recording ID" msgstr "" #: quodlibet/util/tags.py:131 msgid "MusicBrainz release track ID" msgstr "" #: quodlibet/util/tags.py:132 msgid "MusicBrainz release ID" msgstr "" #: quodlibet/util/tags.py:133 msgid "MusicBrainz artist ID" msgstr "" #: quodlibet/util/tags.py:134 msgid "MusicBrainz release artist ID" msgstr "" #: quodlibet/util/tags.py:135 msgid "MusicBrainz TRM ID" msgstr "" #: quodlibet/util/tags.py:136 msgid "MusicIP PUID" msgstr "" #: quodlibet/util/tags.py:137 msgid "MusicBrainz album status" msgstr "" #: quodlibet/util/tags.py:138 msgid "MusicBrainz album type" msgstr "" #: quodlibet/util/tags.py:139 msgid "MusicBrainz release group ID" msgstr "" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:142 msgid "track gain" msgstr "ganho da faixa" #: quodlibet/util/tags.py:143 msgid "track peak" msgstr "pico da faixa" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:145 msgid "album gain" msgstr "ganho do álbum" #: quodlibet/util/tags.py:146 msgid "album peak" msgstr "pico do álbum" #: quodlibet/util/tags.py:147 msgid "reference loudness" msgstr "referência de sonoridade" #: quodlibet/util/tags.py:152 msgid "discs" msgstr "discos" #: quodlibet/util/tags.py:154 msgid "tracks" msgstr "faixas" #: quodlibet/util/tags.py:155 msgid "last started" msgstr "último inicio" #: quodlibet/util/tags.py:156 msgid "full name" msgstr "nome completo" #: quodlibet/util/tags.py:163 msgid "mount point" msgstr "ponto de montagem" #: quodlibet/util/tags.py:165 msgid "people" msgstr "pessoas" #: quodlibet/util/tags.py:167 msgid "year" msgstr "ano" #: quodlibet/util/tags.py:168 msgid "original release year" msgstr "ano de lançamento original" #: quodlibet/util/tags.py:169 msgid "bookmark" msgstr "marcador" #: quodlibet/util/tags.py:170 msgid "bitdepth" msgstr "profundidade de bits" #: quodlibet/util/tags.py:173 msgid "file format" msgstr "formato de arquivo" #: quodlibet/util/tags.py:176 msgid "playlists" msgstr "listas de reprodução" #: quodlibet/util/tags.py:177 msgid "sample rate" msgstr "taxa de amostragem" #: quodlibet/util/tags.py:178 msgid "channel count" msgstr "número de canais" #. Translators: e.g. "artist (sort)" #: quodlibet/util/tags.py:268 msgid "sort" msgstr "ordenação" #. Translators: e.g. "performer (roles)" #: quodlibet/util/tags.py:276 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 arquivos 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 arquivos 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 arquivos de áudio, com a " "mesma interface do Quod Libet. Ele permite visualizar e alterar qualquer " "etiqueta, para qualquer arquivo em um 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 arquivos 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 gerenciamento de músicas. Ele disponibiliza " "diversas maneiras de visualizar 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." #~ msgid "_Download…" #~ msgstr "_Baixar…" #~ msgid "Download Files" #~ msgstr "Baixar arquivos" #~ msgid "Download File" #~ msgstr "Baixar arquivo" #~ 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 "Could not find '%s'." #~ msgstr "Não foi possível encontrar \"%s\"." #~ 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" #, fuzzy #~ msgid "_Edit" #~ msgstr "_Editar display..." #~ 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 "Watch this folder for new songs" #~ msgstr "Buscar nessa pasta por novas músicas" #~ 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:" #~ msgid "Removing orphaned iPod track" #~ msgstr "Removendo faixa órfã do iPod" #, 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 "Unable to open input files" #~ msgstr "Impossível abrir arquivos de entrada" #~ 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 "Deleting %d/%d." #~ msgstr "Apagando %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 "Tag by Filename" #~ msgstr "Tag por arquivo" #~ 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9711857 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/po/ro.po����������������������������������������������������������������������������0000644�0001750�0001750�00000525366�00000000000�014115� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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: 2017-05-17 18:58+0200\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" #: ../data/exfalso.appdata.xml.in.h:1 ../data/exfalso.desktop.in.h:2 msgid "Edit tags in your audio files" msgstr "Editare etichete fişiere audio" #: ../data/exfalso.appdata.xml.in.h:2 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/exfalso.appdata.xml.in.h:3 ../data/quodlibet.appdata.xml.in.h:3 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/exfalso.desktop.in.h:1 msgid "Audio tag editor" msgstr "Editor pentru etichete audio" #: ../data/quodlibet.appdata.xml.in.h:1 ../data/quodlibet.desktop.in.h:2 msgid "Listen to, browse, or edit your audio collection" msgstr "Ascultaţi, editaţi sau cautaţi în propria colecţie audio" #: ../data/quodlibet.appdata.xml.in.h:2 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 "" #: ../data/quodlibet.desktop.in.h:1 msgid "Music Player" msgstr "Redare audio" #: ../quodlibet/browsers/albums/main.py:168 #: ../quodlibet/browsers/covergrid/main.py:54 #, fuzzy msgid "_Title" msgstr "Titlu" #: ../quodlibet/browsers/albums/main.py:169 #: ../quodlibet/browsers/covergrid/main.py:55 ../quodlibet/qltk/prefs.py:49 msgid "_Artist" msgstr "_Artist" #: ../quodlibet/browsers/albums/main.py:170 #: ../quodlibet/browsers/covergrid/main.py:56 ../quodlibet/qltk/prefs.py:54 msgid "_Date" msgstr "_Dată" #: ../quodlibet/browsers/albums/main.py:171 #: ../quodlibet/browsers/covergrid/main.py:57 ../quodlibet/qltk/prefs.py:53 #, fuzzy msgid "_Genre" msgstr "gen" #: ../quodlibet/browsers/albums/main.py:172 #: ../quodlibet/browsers/covergrid/main.py:58 ../quodlibet/qltk/prefs.py:58 #: ../quodlibet/qltk/ratingsmenu.py:39 msgid "_Rating" msgstr "E_valuare" #: ../quodlibet/browsers/albums/main.py:178 #: ../quodlibet/browsers/covergrid/main.py:64 #, fuzzy msgid "Sort _by…" msgstr "Sortează după dată" #: ../quodlibet/browsers/albums/main.py:199 #: ../quodlibet/browsers/covergrid/main.py:85 #: ../quodlibet/browsers/paned/prefs.py:166 #: ../quodlibet/browsers/playlists/main.py:629 #: ../quodlibet/qltk/exfalsowindow.py:109 ../quodlibet/qltk/pluginwin.py:341 #: ../quodlibet/qltk/quodlibetwindow.py:1016 #, fuzzy msgid "_Preferences" msgstr "Preferinţe" #: ../quodlibet/browsers/albums/main.py:361 msgid "Album List" msgstr "Listă albume" #: ../quodlibet/browsers/albums/main.py:362 msgid "_Album List" msgstr "Listă _albume" #: ../quodlibet/browsers/albums/main.py:472 #: ../quodlibet/browsers/covergrid/main.py:279 #: ../quodlibet/browsers/covergrid/main.py:488 msgid "All Albums" msgstr "Toate albumele" #: ../quodlibet/browsers/albums/main.py:473 #: ../quodlibet/browsers/covergrid/main.py:280 #: ../quodlibet/browsers/covergrid/main.py:489 #, 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:650 #: ../quodlibet/browsers/covergrid/main.py:467 #, 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:381 ../quodlibet/util/collection.py:245 #, 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:379 ../quodlibet/util/collection.py:249 #, 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:120 #, fuzzy msgid "Options" msgstr "[opţiuni]" #: ../quodlibet/browsers/albums/prefs.py:74 #: ../quodlibet/browsers/covergrid/prefs.py:123 msgid "Album Display" msgstr "Afişare albume" #: ../quodlibet/browsers/albums/prefs.py:78 #: ../quodlibet/browsers/covergrid/prefs.py:127 #: ../quodlibet/browsers/media.py:39 #: ../quodlibet/browsers/playlists/prefs.py:56 #: ../quodlibet/ext/songsmenu/albumart.py:326 #: ../quodlibet/ext/songsmenu/duplicates.py:350 #: ../quodlibet/ext/songsmenu/filterall.py:48 #: ../quodlibet/qltk/bookmarks.py:101 ../quodlibet/qltk/cbes.py:93 #: ../quodlibet/qltk/data_editors.py:99 ../quodlibet/qltk/data_editors.py:324 #: ../quodlibet/qltk/exfalsowindow.py:297 ../quodlibet/qltk/pluginwin.py:79 #: ../quodlibet/qltk/pluginwin.py:427 ../quodlibet/qltk/prefs.py:707 #: ../quodlibet/qltk/textedit.py:164 ../quodlibet/update.py:148 msgid "_Close" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:55 #: ../quodlibet/browsers/audiofeeds.py:67 #: ../quodlibet/browsers/audiofeeds.py:69 #: ../quodlibet/browsers/audiofeeds.py:159 #: ../quodlibet/browsers/paned/models.py:86 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:46 #: ../quodlibet/formats/_audio.py:495 ../quodlibet/order/__init__.py:27 #: ../quodlibet/qltk/information.py:240 ../quodlibet/qltk/information.py:247 #: ../quodlibet/qltk/information.py:273 ../quodlibet/qltk/wlw.py:70 msgid "Unknown" msgstr "Necunoscut" #: ../quodlibet/browsers/audiofeeds.py:246 msgid "New Feed" msgstr "Flux nou" #: ../quodlibet/browsers/audiofeeds.py:247 msgid "Enter the location of an audio feed:" msgstr "Introduceţi locaţia unui flux audio:" #: ../quodlibet/browsers/audiofeeds.py:248 #: ../quodlibet/browsers/collection/prefs.py:90 #: ../quodlibet/browsers/iradio.py:341 ../quodlibet/browsers/paned/prefs.py:78 #: ../quodlibet/browsers/playlists/menu.py:96 #: ../quodlibet/browsers/playlists/util.py:52 ../quodlibet/qltk/bookmarks.py:62 #: ../quodlibet/qltk/cbes.py:55 ../quodlibet/qltk/data_editors.py:311 #: ../quodlibet/qltk/edittags.py:288 ../quodlibet/qltk/edittags.py:488 #: ../quodlibet/qltk/quodlibetwindow.py:1354 ../quodlibet/qltk/scanbox.py:61 msgid "_Add" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:265 msgid "Audio Feeds" msgstr "Fluxuri audio" #: ../quodlibet/browsers/audiofeeds.py:266 msgid "_Audio Feeds" msgstr "Fluxuri a_udio" #: ../quodlibet/browsers/audiofeeds.py:345 #: ../quodlibet/browsers/audiofeeds.py:350 #, fuzzy msgid "_Download…" msgstr "_Caută" #: ../quodlibet/browsers/audiofeeds.py:359 msgid "Download Files" msgstr "Descarcă fişierele" #. Save button #: ../quodlibet/browsers/audiofeeds.py:359 #: ../quodlibet/browsers/audiofeeds.py:371 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:81 #: ../quodlibet/ext/songsmenu/albumart.py:322 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:355 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:278 #: ../quodlibet/ext/songsmenu/html.py:76 #: ../quodlibet/ext/songsmenu/lastfmsync.py:216 #: ../quodlibet/ext/songsmenu/playlist.py:51 #: ../quodlibet/ext/songsmenu/replaygain.py:365 #: ../quodlibet/ext/songsmenu/tapbpm.py:182 ../quodlibet/qltk/_editutils.py:39 #: ../quodlibet/qltk/lyrics.py:38 ../quodlibet/qltk/msg.py:52 #: ../quodlibet/qltk/renamefiles.py:168 ../quodlibet/qltk/tracknumbers.py:113 msgid "_Save" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:371 msgid "Download File" msgstr "Descarcă fişierul" #: ../quodlibet/browsers/audiofeeds.py:394 #: ../quodlibet/browsers/playlists/main.py:213 #: ../quodlibet/qltk/data_editors.py:96 msgid "_New" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:454 #: ../quodlibet/browsers/audiofeeds.py:513 msgid "Unable to add feed" msgstr "Nu s-a putut adăuga fluxul" #: ../quodlibet/browsers/audiofeeds.py:455 #: ../quodlibet/browsers/audiofeeds.py:514 #, fuzzy, python-format msgid "" "%s could not be added. The server may be down, or the location may not be an " "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." #. refresh button #: ../quodlibet/browsers/audiofeeds.py:462 ../quodlibet/browsers/media.py:217 #: ../quodlibet/browsers/media.py:386 ../quodlibet/qltk/filesel.py:259 #: ../quodlibet/qltk/pluginwin.py:413 #, fuzzy msgid "_Refresh" msgstr "Reactualizare c_olecţie" #: ../quodlibet/browsers/audiofeeds.py:463 #: ../quodlibet/browsers/playlists/main.py:457 #: ../quodlibet/browsers/playlists/util.py:43 ../quodlibet/qltk/delete.py:143 #: ../quodlibet/qltk/filesel.py:256 ../quodlibet/qltk/lyrics.py:39 #: ../quodlibet/qltk/maskedbox.py:28 ../quodlibet/qltk/songsmenu.py:392 #, fuzzy msgid "_Delete" msgstr "Ştergere fişiere" #: ../quodlibet/browsers/audiofeeds.py:530 msgid "" "The current audio backend does not support URLs, Audio Feeds browser " "disabled." msgstr "" #: ../quodlibet/browsers/_base.py:147 ../quodlibet/browsers/_base.py:150 msgid "Library Browser" msgstr "Navigator colecţie" #: ../quodlibet/browsers/_base.py:274 ../quodlibet/ext/songsmenu/refresh.py:30 #: ../quodlibet/qltk/exfalsowindow.py:241 ../quodlibet/qltk/information.py:542 #: ../quodlibet/qltk/maskedbox.py:68 ../quodlibet/util/collection.py:527 #, 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:402 ../quodlibet/browsers/_base.py:407 #: ../quodlibet/qltk/tagsfrompath.py:194 ../quodlibet/qltk/textedit.py:141 #: ../quodlibet/util/__init__.py:622 msgid "Invalid pattern" msgstr "Şablon invalid" #: ../quodlibet/browsers/collection/main.py:78 msgid "Album Collection" msgstr "" #: ../quodlibet/browsers/collection/main.py:79 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:66 #: ../quodlibet/browsers/paned/prefs.py:51 msgid "_Custom" msgstr "_Personalizat" #. Remove button #: ../quodlibet/browsers/collection/prefs.py:94 #: ../quodlibet/browsers/paned/prefs.py:82 #: ../quodlibet/browsers/playlists/menu.py:97 #: ../quodlibet/ext/playlist/remove_duplicates.py:60 #: ../quodlibet/qltk/bookmarks.py:97 ../quodlibet/qltk/bookmarks.py:127 #: ../quodlibet/qltk/cbes.py:82 ../quodlibet/qltk/cbes.py:89 #: ../quodlibet/qltk/data_editors.py:81 ../quodlibet/qltk/data_editors.py:94 #: ../quodlibet/qltk/data_editors.py:301 ../quodlibet/qltk/data_editors.py:314 #: ../quodlibet/qltk/data_editors.py:322 ../quodlibet/qltk/edittags.py:494 #: ../quodlibet/qltk/edittags.py:634 ../quodlibet/qltk/maskedbox.py:48 #: ../quodlibet/qltk/maskedbox.py:88 ../quodlibet/qltk/queue.py:350 #: ../quodlibet/qltk/scanbox.py:36 ../quodlibet/qltk/scanbox.py:63 #, fuzzy msgid "_Remove" msgstr "E_valuare" #: ../quodlibet/browsers/collection/prefs.py:122 #: ../quodlibet/ext/songsmenu/filterall.py:34 #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:92 #: ../quodlibet/qltk/edittags.py:431 msgid "Tag" msgstr "Etichetă" #: ../quodlibet/browsers/collection/prefs.py:128 msgid "Merge" msgstr "" #: ../quodlibet/browsers/collection/prefs.py:188 #, fuzzy msgid "Album Collection Preferences" msgstr "Preferinţe listă albume" #: ../quodlibet/browsers/collection/prefs.py:195 #: ../quodlibet/browsers/paned/prefs.py:209 #: ../quodlibet/ext/songsmenu/editplaycount.py:45 #: ../quodlibet/ext/songsmenu/exact_rating.py:38 #: ../quodlibet/player/gstbe/prefs.py:40 ../quodlibet/qltk/prefs.py:127 #: ../quodlibet/qltk/textedit.py:65 msgid "_Apply" msgstr "" #: ../quodlibet/browsers/collection/prefs.py:198 #: ../quodlibet/browsers/paned/prefs.py:213 #: ../quodlibet/browsers/playlists/menu.py:95 #: ../quodlibet/browsers/playlists/util.py:42 #: ../quodlibet/errorreport/ui.py:108 #: ../quodlibet/ext/playlist/export_to_folder.py:37 #: ../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:44 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:281 #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:88 #: ../quodlibet/ext/songsmenu/importexport.py:35 #: ../quodlibet/ext/songsmenu/lastfmsync.py:215 #: ../quodlibet/ext/songsmenu/playlist.py:50 #: ../quodlibet/ext/songsmenu/replaygain.py:364 #: ../quodlibet/ext/songsmenu/tapbpm.py:181 ../quodlibet/plugins/playlist.py:39 #: ../quodlibet/qltk/chooser.py:184 ../quodlibet/qltk/chooser.py:205 #: ../quodlibet/qltk/chooser.py:229 ../quodlibet/qltk/chooser.py:253 #: ../quodlibet/qltk/delete.py:90 ../quodlibet/qltk/delete.py:133 #: ../quodlibet/qltk/edittags.py:287 ../quodlibet/qltk/_editutils.py:38 #: ../quodlibet/qltk/getstring.py:28 ../quodlibet/qltk/maskedbox.py:27 #: ../quodlibet/qltk/msg.py:54 ../quodlibet/qltk/msg.py:93 #: ../quodlibet/qltk/ratingsmenu.py:33 ../quodlibet/qltk/songsmenu.py:45 #: ../quodlibet/qltk/songsmenu.py:73 ../quodlibet/update.py:94 msgid "_Cancel" msgstr "" #: ../quodlibet/browsers/covergrid/main.py:125 #, fuzzy msgid "Cover Grid" msgstr "Mărime totală:" #: ../quodlibet/browsers/covergrid/main.py:126 #, 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:71 #, fuzzy msgid "Show \"All Albums\" Item" msgstr "Toate albumele" #: ../quodlibet/browsers/covergrid/prefs.py:78 msgid "Vertical Split" msgstr "" #: ../quodlibet/browsers/covergrid/prefs.py:110 #: ../quodlibet/browsers/covergrid/prefs.py:111 #, fuzzy msgid "Cover Magnification" msgstr "organizaţie" #: ../quodlibet/browsers/filesystem.py:40 msgid "File System" msgstr "Sistem de fişiere" #: ../quodlibet/browsers/filesystem.py:41 msgid "_File System" msgstr "Sistem de _fişiere" #: ../quodlibet/browsers/filesystem.py:113 ../quodlibet/browsers/media.py:491 #: ../quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "Nu s-au putut copia piesele" #: ../quodlibet/browsers/filesystem.py:114 ../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:189 msgid "_Add to Library" msgstr "_Adaugă la colecţie" #: ../quodlibet/browsers/iradio.py:178 msgid "Unsupported file type" msgstr "Tip nesuportat de fişier" #: ../quodlibet/browsers/iradio.py:179 #, 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:219 ../quodlibet/browsers/iradio.py:232 #: ../quodlibet/browsers/iradio.py:810 msgid "Unable to add station" msgstr "Nu s-a putut adăuga staţia" #: ../quodlibet/browsers/iradio.py:243 ../quodlibet/browsers/iradio.py:471 msgid "Internet Radio" msgstr "Radio Internet" #: ../quodlibet/browsers/iradio.py:243 #, fuzzy msgid "Downloading station list" msgstr "Descarcă fişierele" #: ../quodlibet/browsers/iradio.py:339 msgid "New Station" msgstr "Staţie nouă" #: ../quodlibet/browsers/iradio.py:340 msgid "Enter the location of an Internet radio station:" msgstr "Introduceţi locaţia unei staţii radio Internet:" #: ../quodlibet/browsers/iradio.py:358 msgid "Electronic" msgstr "" #: ../quodlibet/browsers/iradio.py:361 msgid "Hip Hop / Rap" msgstr "" #: ../quodlibet/browsers/iradio.py:362 msgid "Oldies" msgstr "" #: ../quodlibet/browsers/iradio.py:363 msgid "R&B" msgstr "" #: ../quodlibet/browsers/iradio.py:364 msgid "Japanese" msgstr "" #: ../quodlibet/browsers/iradio.py:365 msgid "Indian" msgstr "" #: ../quodlibet/browsers/iradio.py:367 msgid "Religious" msgstr "" #: ../quodlibet/browsers/iradio.py:369 msgid "Charts" msgstr "" #: ../quodlibet/browsers/iradio.py:370 msgid "Turkish" msgstr "" #: ../quodlibet/browsers/iradio.py:371 msgid "Reggae / Dancehall" msgstr "" #: ../quodlibet/browsers/iradio.py:372 #, fuzzy msgid "Latin" msgstr "evaluare" #: ../quodlibet/browsers/iradio.py:373 msgid "College Radio" msgstr "" #: ../quodlibet/browsers/iradio.py:374 msgid "Talk / News" msgstr "" #: ../quodlibet/browsers/iradio.py:375 msgid "Ambient" msgstr "" #: ../quodlibet/browsers/iradio.py:376 msgid "Jazz" msgstr "" #: ../quodlibet/browsers/iradio.py:377 ../quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "" #: ../quodlibet/browsers/iradio.py:378 ../quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "" #: ../quodlibet/browsers/iradio.py:379 msgid "Alternative" msgstr "" #: ../quodlibet/browsers/iradio.py:380 msgid "Metal" msgstr "" #: ../quodlibet/browsers/iradio.py:381 msgid "Country" msgstr "" #: ../quodlibet/browsers/iradio.py:382 msgid "News" msgstr "" #: ../quodlibet/browsers/iradio.py:383 msgid "Schlager" msgstr "" #: ../quodlibet/browsers/iradio.py:384 msgid "Funk" msgstr "" #: ../quodlibet/browsers/iradio.py:385 msgid "Indie" msgstr "" #: ../quodlibet/browsers/iradio.py:386 msgid "Blues" msgstr "" #: ../quodlibet/browsers/iradio.py:387 msgid "Soul" msgstr "" #: ../quodlibet/browsers/iradio.py:388 msgid "Lounge" msgstr "" #: ../quodlibet/browsers/iradio.py:389 msgid "Punk" msgstr "" #: ../quodlibet/browsers/iradio.py:390 msgid "Reggaeton" msgstr "" #: ../quodlibet/browsers/iradio.py:392 msgid "Slavic" msgstr "" #: ../quodlibet/browsers/iradio.py:394 msgid "Greek" msgstr "" #: ../quodlibet/browsers/iradio.py:395 msgid "Gothic" msgstr "" #: ../quodlibet/browsers/iradio.py:396 ../quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "" #: ../quodlibet/browsers/iradio.py:449 msgid "Would you like to load a list of popular radio stations?" msgstr "" #: ../quodlibet/browsers/iradio.py:455 #, fuzzy msgid "_Load Stations" msgstr "Staţie _nouă" #: ../quodlibet/browsers/iradio.py:472 msgid "_Internet Radio" msgstr "Radio _Internet" #: ../quodlibet/browsers/iradio.py:538 #, fuzzy msgid "_New Station…" msgstr "Staţie nouă" #: ../quodlibet/browsers/iradio.py:541 #, fuzzy msgid "_Update Stations" msgstr "Staţie _nouă" #: ../quodlibet/browsers/iradio.py:568 #, fuzzy msgid "All Stations" msgstr "Staţie nouă" #. TODO: support for ~#rating=!None etc (#1940) #: ../quodlibet/browsers/iradio.py:572 #: ../quodlibet/browsers/soundcloud/main.py:64 msgid "Favorites" msgstr "" #: ../quodlibet/browsers/iradio.py:580 msgid "No Category" msgstr "" #: ../quodlibet/browsers/iradio.py:802 msgid "No stations found" msgstr "Nici s-a găsit nici o staţie" #: ../quodlibet/browsers/iradio.py:803 #, 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:811 msgid "All stations listed are already in your library." msgstr "Toate staţiile listate sunt deja în colecţie." #: ../quodlibet/browsers/iradio.py:828 #, fuzzy msgid "Add to Favorites" msgstr "_Adaugă în listă" #: ../quodlibet/browsers/iradio.py:832 #, fuzzy msgid "Remove from Favorites" msgstr "Şte_rge din listă" #: ../quodlibet/browsers/iradio.py:932 #, 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/media.py:36 msgid "Device Properties" msgstr "Proprietăţi dispozitiv" #: ../quodlibet/browsers/media.py:52 msgid "Device:" msgstr "Dispozitiv:" #: ../quodlibet/browsers/media.py:54 msgid "Not mounted" msgstr "Nu este montat" #: ../quodlibet/browsers/media.py:55 #, fuzzy msgid "Mount point:" msgstr "Punct de montare:" #: ../quodlibet/browsers/media.py:61 ../quodlibet/qltk/cbes.py:40 msgid "_Name:" msgstr "_Nume:" #: ../quodlibet/browsers/media.py:135 msgid "Media Devices" msgstr "Dispozitive media" #: ../quodlibet/browsers/media.py:136 msgid "_Media Devices" msgstr "Dispozitive _media" #. eject button #: ../quodlibet/browsers/media.py:224 ../quodlibet/browsers/media.py:378 msgid "_Eject" msgstr "_Ejectare" #: ../quodlibet/browsers/media.py:360 #, fuzzy msgid "_Properties" msgstr "Proprietăţi" #: ../quodlibet/browsers/media.py:365 #: ../quodlibet/browsers/playlists/main.py:464 msgid "_Rename" msgstr "_Redenumeşte" #: ../quodlibet/browsers/media.py:461 #, fuzzy, python-format msgid "%(used-size)s used, %(free-size)s available" msgstr "<b>%s</b> folosit, <b>%s</b> disponibil" #: ../quodlibet/browsers/media.py:479 #, fuzzy, python-format msgid "%s is not connected." msgstr "<b>%s</b> nu este conectat." #: ../quodlibet/browsers/media.py:499 #, fuzzy, python-format msgid "Copying %(song)s" msgstr "Copiez <b>%s</b>" #: ../quodlibet/browsers/media.py:513 ../quodlibet/browsers/media.py:529 msgid "Unable to copy song" msgstr "Nu s-a putut copia piesa" #: ../quodlibet/browsers/media.py:514 msgid "There is not enough free space for this song." msgstr "Nu există suficient spaţiu disponibil pentru această piesă." #: ../quodlibet/browsers/media.py:526 #, fuzzy, python-format msgid "%s could not be copied." msgstr "<b>%s</b> nu a putut fi copiat." #: ../quodlibet/browsers/media.py:545 msgid "Unable to delete songs" msgstr "Nu s-au putut şterge piesele" #: ../quodlibet/browsers/media.py:557 #, fuzzy, python-format msgid "Deleting %(song)s" msgstr "Şterg <b>%s</b>" #: ../quodlibet/browsers/media.py:575 #, fuzzy, python-format msgid "%s could not be deleted." msgstr "<b>%s</b> nu a putut fi şters." #: ../quodlibet/browsers/media.py:579 msgid "Unable to delete song" msgstr "Nu s-a putut şterge piesa" #: ../quodlibet/browsers/media.py:594 #, fuzzy, python-format msgid "Ejecting %s failed." msgstr "Ejectarea <b>%s</b> a eşuat." #: ../quodlibet/browsers/media.py:597 msgid "Unable to eject device" msgstr "Nu s-a putut ejecta dispozitivul" #: ../quodlibet/browsers/media.py:603 msgid "No device backend, Media Devices browser disabled." msgstr "" #: ../quodlibet/browsers/paned/main.py:40 ../quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "Navigator încastrat" #: ../quodlibet/browsers/paned/main.py:41 msgid "_Paned Browser" msgstr "_Navigator încastrat" #: ../quodlibet/browsers/paned/main.py:90 msgid "Select _All" msgstr "Selectează t_ot" #: ../quodlibet/browsers/paned/models.py:104 ../quodlibet/qltk/pluginwin.py:122 #: ../quodlibet/qltk/pluginwin.py:164 msgid "All" msgstr "Toate" #: ../quodlibet/browsers/paned/prefs.py:67 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "<tt>%s</tt>" msgstr "" #: ../quodlibet/browsers/paned/prefs.py:162 msgid "_Wide Mode" msgstr "" #: ../quodlibet/browsers/paned/prefs.py:197 msgid "Paned Browser Preferences" msgstr "Preferinţe navigator încastrat" #: ../quodlibet/browsers/paned/prefs.py:204 msgid "Equal pane width" msgstr "" #: ../quodlibet/browsers/playlists/main.py:48 #: ../quodlibet/browsers/playlists/main.py:575 #: ../quodlibet/qltk/pluginwin.py:168 msgid "Playlists" msgstr "Liste" #: ../quodlibet/browsers/playlists/main.py:49 msgid "_Playlists" msgstr "_Liste" #: ../quodlibet/browsers/playlists/main.py:152 msgid "_Remove from Playlist" msgstr "Şte_rge din listă" #: ../quodlibet/browsers/playlists/main.py:215 #: ../quodlibet/browsers/playlists/main.py:576 msgid "_Import" msgstr "_Importă" #: ../quodlibet/browsers/playlists/main.py:391 #: ../quodlibet/browsers/playlists/util.py:50 #: ../quodlibet/util/collection.py:570 msgid "New Playlist" msgstr "Listă nouă" #: ../quodlibet/browsers/playlists/main.py:413 msgid "Unable to import playlist" msgstr "Nu s-a putut importa lista de redare" #: ../quodlibet/browsers/playlists/main.py:414 msgid "Quod Libet can only import playlists in the M3U and PLS formats." msgstr "" "Quod Libet poate importa liste de redare doar în formatele M3U sau PLS." #: ../quodlibet/browsers/playlists/main.py:565 msgid "Unable to rename playlist" msgstr "Nu s-a putut redenumi lista" #: ../quodlibet/browsers/playlists/main.py:576 msgid "Import Playlist" msgstr "Importă lista" #: ../quodlibet/browsers/playlists/menu.py:25 #, fuzzy msgid "_New Playlist…" msgstr "Listă _nouă" #: ../quodlibet/browsers/playlists/menu.py:86 #, 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:90 #, 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:33 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "" #: ../quodlibet/browsers/playlists/util.py:35 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" #: ../quodlibet/browsers/playlists/util.py:51 #, fuzzy msgid "Enter a name for the new playlist:" msgstr "Introduceţi un nume pentru noul director:" #: ../quodlibet/browsers/playlists/util.py:102 #, 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/search.py:33 msgid "_Limit Results" msgstr "_Limitează rezultatele" #: ../quodlibet/browsers/search.py:48 msgid "Search Library" msgstr "Căutare în colecţie" #: ../quodlibet/browsers/search.py:49 msgid "_Search Library" msgstr "Caută în c_olecţie" #: ../quodlibet/browsers/soundcloud/main.py:38 #, fuzzy msgid "Soundcloud Browser" msgstr "Navigator încastrat" #: ../quodlibet/browsers/soundcloud/main.py:39 msgid "Sound_cloud" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:59 #: ../quodlibet/qltk/searchbar.py:73 msgid "Search" msgstr "Caută" #: ../quodlibet/browsers/soundcloud/main.py:136 #, python-format msgid "Go to %s" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:380 #, fuzzy msgid "Connected" msgstr "locaţie" #: ../quodlibet/browsers/soundcloud/main.py:381 #, python-format msgid "Quod Libet is now connected, <b>%s</b>!" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:393 #, python-format msgid "Log out of %s" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:395 msgid "Enter code…" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:396 #, python-format msgid "Log in to %s" msgstr "" #: ../quodlibet/browsers/soundcloud/util.py:86 msgid "Soundcloud authorisation" msgstr "" #: ../quodlibet/browsers/soundcloud/util.py:87 msgid "Enter Soundcloud auth code:" msgstr "" #: ../quodlibet/cli.py:50 #, fuzzy msgid "Quod Libet is not running (add '--run' to start it)" msgstr "Quod Libet nu este pornit." #: ../quodlibet/cli.py:85 msgid "a music library and player" msgstr "redare audio pentru colecţii de muzică" #: ../quodlibet/cli.py:86 #, fuzzy msgid "[option]" msgstr "[opţiuni]" #: ../quodlibet/cli.py:88 msgid "Print the playing song and exit" msgstr "Afişare piesă redată curent" #: ../quodlibet/cli.py:89 msgid "Begin playing immediately" msgstr "Cu pornire imediată a redării" #: ../quodlibet/cli.py:90 msgid "Don't show any windows on start" msgstr "" #: ../quodlibet/cli.py:93 msgid "Jump to next song" msgstr "Salt la piesa următoare" #: ../quodlibet/cli.py:95 msgid "Jump to previous song or restart if near the beginning" msgstr "" #: ../quodlibet/cli.py:96 msgid "Jump to previous song" msgstr "Salt la piesa precedentă" #: ../quodlibet/cli.py:97 msgid "Start playback" msgstr "Start redare" #: ../quodlibet/cli.py:98 msgid "Pause playback" msgstr "Pauză redare" #: ../quodlibet/cli.py:99 msgid "Toggle play/pause mode" msgstr "Comutare între start şi pauză redare" #: ../quodlibet/cli.py:100 #, fuzzy msgid "Stop playback" msgstr "Start redare" #: ../quodlibet/cli.py:101 msgid "Turn up volume" msgstr "Volum mai mare" #: ../quodlibet/cli.py:102 msgid "Turn down volume" msgstr "Volum mai mic" #: ../quodlibet/cli.py:103 msgid "Print player status" msgstr "Afişare status curent" #: ../quodlibet/cli.py:104 msgid "Hide main window" msgstr "Ascundere fereastră principală" #: ../quodlibet/cli.py:105 msgid "Show main window" msgstr "Afişare fereastră principală" #: ../quodlibet/cli.py:106 msgid "Toggle main window visibility" msgstr "Comutare a vizibilităţii ferestrei principale" #: ../quodlibet/cli.py:107 msgid "Focus the running player" msgstr "Focalizare a ferestrei de redare" #: ../quodlibet/cli.py:108 msgid "Remove active browser filters" msgstr "" #: ../quodlibet/cli.py:109 #, fuzzy msgid "Refresh and rescan library" msgstr "Reactualizare c_olecţie" #: ../quodlibet/cli.py:110 #, fuzzy msgid "List available browsers" msgstr "Dezactivează navigatorul" #: ../quodlibet/cli.py:111 msgid "Print the current playlist" msgstr "Afişare a listei curente" #: ../quodlibet/cli.py:112 msgid "Print the contents of the queue" msgstr "Afişare a cozii curente" #: ../quodlibet/cli.py:113 #, fuzzy msgid "Print the active text query" msgstr "Afişare a cozii curente" #: ../quodlibet/cli.py:114 msgid "Start without plugins" msgstr "" #: ../quodlibet/cli.py:115 #, fuzzy msgid "Start Quod Libet if it isn't running" msgstr "Quod Libet nu este pornit." #: ../quodlibet/cli.py:116 msgid "Exit Quod Libet" msgstr "Ieşire Quod Libet" #: ../quodlibet/cli.py:121 msgid "Seek within the playing song" msgstr "Derulare în piesa redată curent" #: ../quodlibet/cli.py:121 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: ../quodlibet/cli.py:122 #, fuzzy msgid "Set or toggle shuffle mode" msgstr "Comutare între start şi pauză redare" #: ../quodlibet/cli.py:123 msgid "Turn repeat off, on, or toggle it" msgstr "Anulare, activare sau comutare a repetării" #: ../quodlibet/cli.py:124 msgid "Set the volume" msgstr "Setare volum" #: ../quodlibet/cli.py:125 msgid "Search your audio library" msgstr "Căutare în colecţia muzicală" #: ../quodlibet/cli.py:125 ../quodlibet/cli.py:137 ../quodlibet/cli.py:141 #: ../quodlibet/cli.py:143 msgid "query" msgstr "căutare" #: ../quodlibet/cli.py:126 msgid "Play a file" msgstr "Redare fişier" #: ../quodlibet/cli.py:126 ../quodlibet/cli.py:137 ../quodlibet/cli.py:143 #, fuzzy msgctxt "command" msgid "filename" msgstr "nume" #: ../quodlibet/cli.py:127 msgid "Rate the playing song" msgstr "Evaluare a piesei redate curent" #: ../quodlibet/cli.py:128 msgid "Set the current browser" msgstr "Setare a navigatorului web utilizat" #: ../quodlibet/cli.py:129 #, fuzzy msgid "Stop after the playing song" msgstr "Evaluare a piesei redate curent" #: ../quodlibet/cli.py:130 msgid "Open a new browser" msgstr "Deschidere nou navigator web" #: ../quodlibet/cli.py:131 msgid "Show or hide the queue" msgstr "Afişare/ascundere a cozii" #: ../quodlibet/cli.py:133 #, fuzzy msgid "Show or hide the main song list (deprecated)" msgstr "Afişare/ascundere a listei principale de piese" #: ../quodlibet/cli.py:134 msgid "Filter on a random value" msgstr "Filtrare după o valoare aleatoare" #: ../quodlibet/cli.py:134 #, fuzzy msgctxt "command" msgid "tag" msgstr "Etichetă" #: ../quodlibet/cli.py:135 msgid "Filter on a tag value" msgstr "Filtrare dupa o valoare din etichetă" #: ../quodlibet/cli.py:135 msgid "tag=value" msgstr "etichetă=valoare" #: ../quodlibet/cli.py:136 msgid "Enqueue a file or query" msgstr "Punere fişier în coadă sau căutare" #: ../quodlibet/cli.py:138 msgid "Enqueue comma-separated files" msgstr "" #: ../quodlibet/cli.py:139 ../quodlibet/util/tags.py:147 msgid "filename" msgstr "nume" #: ../quodlibet/cli.py:140 msgid "Print filenames of results of query to stdout" msgstr "" #: ../quodlibet/cli.py:142 #, fuzzy msgid "Unqueue a file or query" msgstr "Punere fişier în coadă sau căutare" #: ../quodlibet/cli.py:203 #, fuzzy, python-format msgid "Invalid argument for '%s'." msgstr "E: Argument invalid pentru „%s”." #: ../quodlibet/cli.py:204 ../quodlibet/util/__init__.py:190 #, fuzzy, python-format msgid "Try %s --help." msgstr "E: Încercaţi %s --help." #: ../quodlibet/devices/_base.py:65 msgid "Unknown Device" msgstr "Dispozitiv necunoscut" #: ../quodlibet/devices/__init__.py:32 #, python-format msgid "Could not import %s, which is needed for device support." msgstr "" #: ../quodlibet/devices/__init__.py:153 #, fuzzy, python-format msgid "%r is not a supported device." msgstr "E: „%s” nu este un prefix unic." #: ../quodlibet/devices/__init__.py:245 ../quodlibet/devices/__init__.py:251 #, python-format msgid "Could not find '%s'." msgstr "" #: ../quodlibet/devices/__init__.py:450 #, fuzzy msgid "Initializing device backend." msgstr "Valoare invalidă" #: ../quodlibet/devices/__init__.py:451 #, python-format msgid "Trying '%s'" msgstr "" #: ../quodlibet/devices/__init__.py:461 msgid "Couldn't connect to a device backend." msgstr "" #: ../quodlibet/devices/__init__.py:463 msgid "Device backend initialized." msgstr "" #: ../quodlibet/devices/storage.py:57 #, fuzzy msgid "_Filename pattern:" msgstr "Model nume _fişier:" #: ../quodlibet/devices/storage.py:61 msgid "Copy _album covers" msgstr "Copiază coperţile _albumelor" #: ../quodlibet/devices/storage.py:65 msgid "_Remove unused covers and directories" msgstr "Ş_terge directoarele şi coperţile nefolosite" #: ../quodlibet/errorreport/ui.py:60 msgid "An Error Occurred" msgstr "" #: ../quodlibet/errorreport/ui.py:62 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:72 msgid "File Bug Report" msgstr "" #: ../quodlibet/errorreport/ui.py:74 ../quodlibet/errorreport/ui.py:90 msgid "Submit Error Report" msgstr "" #: ../quodlibet/errorreport/ui.py:75 msgid "Quit Program" msgstr "" #: ../quodlibet/errorreport/ui.py:76 #, fuzzy msgid "Ignore Error" msgstr "Arată _erorile" #: ../quodlibet/errorreport/ui.py:80 msgid "Error details:" msgstr "" #: ../quodlibet/errorreport/ui.py:92 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:100 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "" #: ../quodlibet/errorreport/ui.py:109 msgid "_Send" msgstr "" #: ../quodlibet/errorreport/ui.py:115 #, fuzzy msgid "Short description…" msgstr "descriere" #: ../quodlibet/errorreport/ui.py:118 msgid "Data to be sent:" msgstr "" #: ../quodlibet/exfalso.py:34 msgid "an audio tag editor" msgstr "un editor de etichete audio" #: ../quodlibet/exfalso.py:34 ../quodlibet/util/tags.py:148 msgid "directory" msgstr "director" #: ../quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "" #: ../quodlibet/ext/covers/artwork_url.py:20 msgid "" "Downloads covers linked to by the artwork_url tag.This works with the " "Soundcloud browser." msgstr "" #: ../quodlibet/ext/covers/discogs.py:25 #, fuzzy msgid "Discogs Cover Source" msgstr "ID pistă MusicBrainz" #: ../quodlibet/ext/covers/discogs.py:26 msgid "Downloads covers from Discogs." msgstr "" #: ../quodlibet/ext/covers/lastfm.py:22 msgid "Last.fm Cover Source" msgstr "" #: ../quodlibet/ext/covers/lastfm.py:23 msgid "Downloads covers from Last.fm's cover art archive." msgstr "" #: ../quodlibet/ext/covers/musicbrainz.py:19 #, fuzzy msgid "MusicBrainz Cover Source" msgstr "ID pistă MusicBrainz" #: ../quodlibet/ext/covers/musicbrainz.py:20 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:25 msgid "Kana/Kanji Simple Inverter" msgstr "" #: ../quodlibet/ext/editing/kakasi.py:26 msgid "Converts kana/kanji to romaji before renaming." msgstr "" #: ../quodlibet/ext/editing/kakasi.py:35 msgid "Romanize _Japanese text" msgstr "" #: ../quodlibet/ext/editing/kakasi.py:63 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:19 msgid "" "Allows arbitrary regex substitutions (s///) 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:69 #, fuzzy msgid "Advanced Preferences" msgstr "Preferinţe navigator încastrat" #: ../quodlibet/ext/events/advanced_preferences.py:70 msgid "Allow editing of advanced config settings." msgstr "" #: ../quodlibet/ext/events/advanced_preferences.py:162 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:153 msgid "Top of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:154 msgid "Middle of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:155 msgid "Bottom of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:158 msgid "_Position:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:171 #, fuzzy msgid "_Cover size:" msgstr "Mărime totală:" #: ../quodlibet/ext/events/animosd/prefs.py:177 #: ../quodlibet/ext/events/lyricswindow.py:334 ../quodlibet/qltk/prefs.py:266 #, fuzzy msgid "Display" msgstr "Editare afişare" #: ../quodlibet/ext/events/animosd/prefs.py:190 msgid "_Font:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:195 msgid "Left" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:196 msgid "Center" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:197 #, fuzzy msgid "Right" msgstr "_Pondere" #: ../quodlibet/ext/events/animosd/prefs.py:200 msgid "_Align text:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:206 msgid "Text" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:217 msgid "_Text:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:227 msgid "_Fill:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:232 #: ../quodlibet/ext/events/synchronizedlyrics.py:63 msgid "Colors" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:240 msgid "_Shadows" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:241 msgid "_Outline" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:242 msgid "Rou_nded Corners" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:258 msgid "_Delay:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:264 #: ../quodlibet/qltk/pluginwin.py:172 msgid "Effects" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:270 #, fuzzy msgid "Ed_it Display Pattern…" msgstr "Editare afişare" #: ../quodlibet/ext/events/animosd/prefs.py:274 #: ../quodlibet/ext/events/trayicon/prefs.py:78 #, fuzzy msgid "Preview" msgstr "_Previzualizare" #: ../quodlibet/ext/events/auto_library_update.py:136 msgid "Automatic Library Update" msgstr "" #: ../quodlibet/ext/events/auto_library_update.py:137 #, python-format msgid "Keeps your library up to date with inotify. Requires %s." 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 by Brian Nelson." 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/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:97 msgid "Equalizer" msgstr "" #: ../quodlibet/ext/events/equalizer.py:98 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:132 msgid "The current backend does not support equalization." msgstr "" #: ../quodlibet/ext/events/equalizer.py:138 #, python-format msgid "%.1f kHz" msgstr "" #: ../quodlibet/ext/events/equalizer.py:139 #: ../quodlibet/ext/gstreamer/crossfeed.py:93 #: ../quodlibet/ext/gstreamer/karaoke.py:95 #, python-format msgid "%d Hz" msgstr "" #: ../quodlibet/ext/events/equalizer.py:173 #: ../quodlibet/ext/gstreamer/crossfeed.py:112 #, fuzzy, python-format msgid "%.1f dB" msgstr "%d secundă" #: ../quodlibet/ext/events/equalizer.py:192 #: ../quodlibet/ext/gstreamer/crossfeed.py:31 #, fuzzy msgid "Custom" msgstr "_Personalizat" #: ../quodlibet/ext/events/equalizer.py:199 #, fuzzy msgid "_Clear" msgstr "Erori module" #. Translators: statuses relating to Instant Messenger apps #: ../quodlibet/ext/events/gajim_status.py:27 msgid "online" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:28 msgid "offline" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:29 msgid "chat" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:30 msgid "away" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:31 msgid "xa" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:32 msgid "invisible" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:37 msgid "Gajim Status Message" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:38 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:45 #: ../quodlibet/ext/events/telepathy_status.py:69 msgid "paused" 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:160 msgid "Add '[paused]'" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:163 msgid "If checked, '[paused]' will be added to status message on pause." msgstr "" #: ../quodlibet/ext/events/gajim_status.py:187 msgid "Statuses for which message will be changed" msgstr "" #: ../quodlibet/ext/events/headphonemon.py:156 msgid "Pause on Headphone Unplug" msgstr "" #: ../quodlibet/ext/events/headphonemon.py:157 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" #: ../quodlibet/ext/events/inhibit.py:41 msgid "Inhibit Screensaver" msgstr "" #: ../quodlibet/ext/events/inhibit.py:42 msgid "Prevents the GNOME screensaver from activating while a song is playing." msgstr "" #: ../quodlibet/ext/events/inhibit.py:51 #, fuzzy msgid "Music is playing" msgstr "Redare audio" #: ../quodlibet/ext/events/iradiolog.py:16 #, fuzzy msgid "Internet Radio Log" msgstr "Radio Internet" #: ../quodlibet/ext/events/iradiolog.py:17 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" #: ../quodlibet/ext/events/jep118.py:29 msgid "JEP-118" msgstr "" #: ../quodlibet/ext/events/jep118.py:30 msgid "Outputs a Jabber User Tunes file to ~/.quodlibet/jabber." 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 msgid "A restart is required for any changes to take effect" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:199 #, fuzzy msgid "No active song" msgstr "Nu s-a putut salva piesa" #: ../quodlibet/ext/events/lyricswindow.py:215 #, fuzzy msgid "No lyrics found" msgstr "Nici un modul nu a fost găsit." #: ../quodlibet/ext/events/lyricswindow.py:227 #, fuzzy msgid "Lyrics:" msgstr "Versuri" #: ../quodlibet/ext/events/lyricswindow.py:284 msgid "_Zoom level:" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:302 msgid "URL:" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:307 msgid "Revert to default" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:322 msgid "Search via above URL if the lyrics couldn't be found in LyricsWikia." msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:339 #, fuzzy msgid "Alternate search" msgstr "Şterge căutarea" #: ../quodlibet/ext/events/lyricswindow.py:347 #, fuzzy msgid "Lyrics Window" msgstr "Versuri" #: ../quodlibet/ext/events/lyricswindow.py:348 msgid "Shows a window containing lyrics of the playing song." msgstr "" #: ../quodlibet/ext/events/mediaserver.py:38 msgid "UPnP AV Media Server" msgstr "" #: ../quodlibet/ext/events/mediaserver.py:39 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." 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:39 msgid "" "Allows control of Quod Libet using the MPRIS 1.0/2.0 D-Bus Interface " "Specification." msgstr "" #: ../quodlibet/ext/events/mpris/__init__.py:45 #: ../quodlibet/ext/events/trayicon/prefs.py:30 #, fuzzy msgid "Hide main window on close" msgstr "Ascundere fereastră principală" #: ../quodlibet/ext/events/mpris/__init__.py:48 #: ../quodlibet/ext/events/themeswitcher.py:84 #: ../quodlibet/ext/gstreamer/compressor.py:99 #: ../quodlibet/ext/gstreamer/crossfeed.py:136 #: ../quodlibet/ext/gstreamer/karaoke.py:99 #: ../quodlibet/ext/gstreamer/pitch.py:83 ../quodlibet/qltk/prefs.py:688 #, fuzzy msgid "Preferences" msgstr "Preferinţe" #: ../quodlibet/ext/events/mqtt.py:50 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/mqtt.py:56 msgid "MQTT Publisher" msgstr "" #: ../quodlibet/ext/events/mqtt.py:57 msgid "Publishes status messages to an MQTT topic." msgstr "" #: ../quodlibet/ext/events/mqtt.py:122 msgid "Broker hostname" msgstr "" #: ../quodlibet/ext/events/mqtt.py:122 msgid "broker hostname / IP" msgstr "" #: ../quodlibet/ext/events/mqtt.py:124 msgid "Broker port" msgstr "" #: ../quodlibet/ext/events/mqtt.py:124 msgid "broker port" msgstr "" #: ../quodlibet/ext/events/mqtt.py:126 msgid "Topic" msgstr "" #: ../quodlibet/ext/events/mqtt.py:128 #, fuzzy msgid "Playing Pattern" msgstr "şablon" #: ../quodlibet/ext/events/mqtt.py:130 msgid "Status text when a song is started." msgstr "" #: ../quodlibet/ext/events/mqtt.py:132 #, fuzzy msgid "Paused Pattern" msgstr "şablon" #: ../quodlibet/ext/events/mqtt.py:134 msgid "Text when a song is paused." msgstr "" #: ../quodlibet/ext/events/mqtt.py:136 #, fuzzy msgid "No-song Text" msgstr "%d piesă" #: ../quodlibet/ext/events/mqtt.py:138 msgid "Plain text for when there is no current song" msgstr "" #: ../quodlibet/ext/events/mqtt.py:149 #, fuzzy msgid "MQTT Configuration" msgstr "Informaţii" #: ../quodlibet/ext/events/mqtt.py:153 #, fuzzy msgid "Status Text" msgstr "şablon" #: ../quodlibet/ext/events/mqtt.py:185 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "" #: ../quodlibet/ext/events/mqtt.py:189 #, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s" msgstr "" #: ../quodlibet/ext/events/mqtt.py:192 #, fuzzy msgid "Connection error" msgstr "locaţie" #: ../quodlibet/ext/events/notify.py:80 msgid "Notification text" msgstr "" #: ../quodlibet/ext/events/notify.py:88 #, fuzzy msgid "_Title:" msgstr "Titlu" #: ../quodlibet/ext/events/notify.py:99 ../quodlibet/ext/events/notify.py:128 msgid "Revert to default pattern" msgstr "" #: ../quodlibet/ext/events/notify.py:118 msgid "_Body:" msgstr "" #: ../quodlibet/ext/events/notify.py:138 msgid "_Show notification" msgstr "" #: ../quodlibet/ext/events/notify.py:156 msgid "Show notifications" msgstr "" #: ../quodlibet/ext/events/notify.py:162 msgid "Only on <i>_manual</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:170 msgid "Only on <i>_automatic</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:178 msgid "On <i>a_ll</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:196 msgid "Only when the main window is not _focused" msgstr "" #: ../quodlibet/ext/events/notify.py:204 msgid "Show \"_Next\" button" msgstr "" #: ../quodlibet/ext/events/notify.py:236 msgid "Connection Error" msgstr "" #: ../quodlibet/ext/events/notify.py:237 ../quodlibet/ext/events/notify.py:391 #: ../quodlibet/ext/events/notify.py:433 msgid "Couldn't connect to notification daemon." msgstr "" #: ../quodlibet/ext/events/notify.py:251 msgid "Song Notifications" msgstr "" #: ../quodlibet/ext/events/notify.py:252 msgid "Displays a notification when the song changes." msgstr "" #: ../quodlibet/ext/events/notify.py:415 ../quodlibet/qltk/unity.py:65 msgid "Next" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:178 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:254 #, python-format msgid "Could not contact service '%s'." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:260 msgid "Authentication failed: invalid URL." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:277 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:282 msgid "Client is banned. Contact the author." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:286 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:351 msgid "AudioScrobbler Submission" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:352 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:450 msgid "Authentication successful." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:462 #, fuzzy msgid "_Service:" msgstr "Dispozitiv:" #: ../quodlibet/ext/events/qlscrobbler.py:462 msgid "_URL:" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:462 #, fuzzy msgid "User_name:" msgstr "_Nume:" #: ../quodlibet/ext/events/qlscrobbler.py:463 msgid "_Password:" msgstr "" #. Translators: Other service #: ../quodlibet/ext/events/qlscrobbler.py:479 #, fuzzy msgid "Other…" msgstr "Alt_ele:" #. verify data #: ../quodlibet/ext/events/qlscrobbler.py:517 msgid "_Verify account data" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:522 #: ../quodlibet/ext/songsmenu/lastfmsync.py:304 msgid "Account" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:530 #, fuzzy msgid "_Artist pattern:" msgstr "_Artist" #: ../quodlibet/ext/events/qlscrobbler.py:530 #, fuzzy msgid "_Title pattern:" msgstr "Model nume _fişier:" #: ../quodlibet/ext/events/qlscrobbler.py:531 msgid "Exclude _filter:" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:549 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:559 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:568 msgid "Songs matching this filter will not be submitted." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:576 msgid "_Offline mode (don't submit anything)" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:580 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:27 #, fuzzy msgid "Random Album Playback" msgstr "A_lbum aleator" #: ../quodlibet/ext/events/randomalbum.py:28 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:38 msgid "Rated higher" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:39 msgid "Played more often" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:40 msgid "Skipped more often" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:41 msgid "Played more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:42 msgid "Started more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:43 msgid "Added more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:44 #, fuzzy msgid "Longer albums" msgstr "albume" #: ../quodlibet/ext/events/randomalbum.py:83 msgid "seconds before starting next album" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:87 #, fuzzy msgid "Weights" msgstr "_Pondere" #: ../quodlibet/ext/events/randomalbum.py:89 msgid "Play some albums more than others" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:103 msgid "avoid" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:114 msgid "prefer" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:201 #, fuzzy msgid "Random Album" msgstr "A_lbum aleator" #: ../quodlibet/ext/events/randomalbum.py:202 #, python-format msgid "Waiting to start %s" msgstr "" #: ../quodlibet/ext/events/rbimport.py:114 #, fuzzy msgid "Import Failed" msgstr "Importă lista" #: ../quodlibet/ext/events/rbimport.py:119 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "" #: ../quodlibet/ext/events/rbimport.py:127 msgid "Rhythmbox Import" msgstr "" #: ../quodlibet/ext/events/rbimport.py:128 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "" #: ../quodlibet/ext/events/rbimport.py:132 #, fuzzy msgid "Start Import" msgstr "_Importă" #: ../quodlibet/ext/events/screensaver.py:25 msgid "Screensaver Pause" msgstr "" #: ../quodlibet/ext/events/screensaver.py:26 msgid "Pauses playback while the GNOME screensaver is active." msgstr "" #: ../quodlibet/ext/events/searchprovider.py:73 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "" #: ../quodlibet/ext/events/searchprovider.py:79 msgid "GNOME Search Provider" msgstr "" #: ../quodlibet/ext/events/searchprovider.py:80 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/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:29 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:57 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:58 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:34 #, fuzzy msgid "Synchronized Lyrics" msgstr "Versuri" #: ../quodlibet/ext/events/synchronizedlyrics.py:35 msgid "Shows synchronized lyrics from .lrc file with same name as the track." msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:66 msgid "Text:" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:76 msgid "Background:" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:87 msgid "Font" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:90 msgid "Size (px):" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:62 msgid "Telepathy Status Messages" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:63 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:122 #, fuzzy msgid "Playing:" msgstr "Oprit" #: ../quodlibet/ext/events/telepathy_status.py:123 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:139 msgid "Paused:" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:140 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:156 msgid "Plain text for status when there is no current song" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:157 #, fuzzy msgid "No song:" msgstr "%d piesă" #. Frame #: ../quodlibet/ext/events/telepathy_status.py:164 #, 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/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:77 #: ../quodlibet/ext/events/trayicon/prefs.py:98 #: ../quodlibet/ext/events/trayicon/systemtray.py:177 #: ../quodlibet/qltk/info.py:47 msgid "Not playing" msgstr "Oprit" #: ../quodlibet/ext/events/trayicon/__init__.py:53 msgid "Tray Icon" msgstr "" #: ../quodlibet/ext/events/trayicon/__init__.py:54 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:183 #: ../quodlibet/qltk/quodlibetwindow.py:1046 #: ../quodlibet/qltk/quodlibetwindow.py:1238 #, fuzzy msgid "_Play" msgstr "_Liste" #: ../quodlibet/ext/events/trayicon/menu.py:63 #: ../quodlibet/qltk/quodlibetwindow.py:185 #: ../quodlibet/qltk/quodlibetwindow.py:1240 ../quodlibet/qltk/wlw.py:51 #, fuzzy msgid "P_ause" msgstr "Redare" #: ../quodlibet/ext/events/trayicon/menu.py:68 #: ../quodlibet/qltk/quodlibetwindow.py:190 #: ../quodlibet/qltk/quodlibetwindow.py:1041 #, fuzzy msgid "Pre_vious" msgstr "_Previzualizare" #: ../quodlibet/ext/events/trayicon/menu.py:71 #: ../quodlibet/qltk/quodlibetwindow.py:194 #: ../quodlibet/qltk/quodlibetwindow.py:1051 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:1012 #, fuzzy msgid "Open _Browser" msgstr "Deschidere nou navigator web" #: ../quodlibet/ext/events/trayicon/menu.py:103 #: ../quodlibet/qltk/quodlibetwindow.py:1031 ../quodlibet/qltk/songsmenu.py:411 msgid "Edit _Tags" msgstr "Editare _etichete" #: ../quodlibet/ext/events/trayicon/menu.py:112 #: ../quodlibet/qltk/quodlibetwindow.py:975 ../quodlibet/qltk/songsmenu.py:424 msgid "_Information" msgstr "_Informaţii" #: ../quodlibet/ext/events/trayicon/menu.py:114 #: ../quodlibet/qltk/songsmenu.py:340 #, fuzzy msgid "Play_lists" msgstr "Liste" #: ../quodlibet/ext/events/trayicon/menu.py:132 #: ../quodlibet/qltk/quodlibetwindow.py:1026 msgid "_Quit" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:32 ../quodlibet/qltk/prefs.py:69 msgid "Behavior" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:42 msgid "Scroll wheel adjusts volume" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel changes song" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll _Wheel" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:84 #, fuzzy msgid "Tooltip Display" msgstr "Editare afişare" #: ../quodlibet/ext/events/viewlyrics.py:23 #, fuzzy msgid "View Lyrics" msgstr "Versuri" #: ../quodlibet/ext/events/viewlyrics.py:24 msgid "Automatically displays lyrics beneath the song list in the main window." msgstr "" #: ../quodlibet/ext/events/viewlyrics.py:29 #, fuzzy msgid "_Lyrics" msgstr "Versuri" #: ../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:406 msgid "Waveform Seek Bar" msgstr "" #: ../quodlibet/ext/events/waveformseekbar.py:410 msgid "A seekbar in the shape of the waveform of the current song." msgstr "" #: ../quodlibet/ext/events/waveformseekbar.py:443 msgid "Override foreground color:" msgstr "" #: ../quodlibet/ext/events/write_cover.py:32 msgid "Picture Saver" msgstr "" #: ../quodlibet/ext/events/write_cover.py:33 msgid "Saves the cover image of the current song to a file." msgstr "" #: ../quodlibet/ext/events/write_cover.py:66 #, fuzzy msgid "File:" msgstr "Fişiere" #: ../quodlibet/ext/gstreamer/compressor.py:20 msgid "_Threshold:" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:21 msgid "Threshold until the filter is activated" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:22 msgid "R_atio:" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:22 msgid "Compression ratio" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:74 #: ../quodlibet/ext/gstreamer/karaoke.py:91 #, python-format msgid "%d %%" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:105 msgid "Audio Compressor" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:106 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:19 #, fuzzy msgid "_Preset:" msgstr "_Previzualizare" #: ../quodlibet/ext/gstreamer/crossfeed.py:19 #, fuzzy msgid "Filter preset" msgstr "Filtrare după _artist" #: ../quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Frequency cut:" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Low-pass filter cut frequency" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed _level:" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed level" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:25 msgid "Default" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Chu Moy" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Jan Meier" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:31 #, fuzzy msgid "Custom settings" msgstr "_Personalizat" #: ../quodlibet/ext/gstreamer/crossfeed.py:152 msgid "Crossfeed" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:153 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:20 #, fuzzy msgid "Filter _band:" msgstr "Filtrare după _gen" #: ../quodlibet/ext/gstreamer/karaoke.py:21 msgid "The Frequency band of the filter" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:22 #, fuzzy msgid "Filter _width:" msgstr "Filtrare după _artist" #: ../quodlibet/ext/gstreamer/karaoke.py:23 msgid "The Frequency width of the filter" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:24 msgid "_Level:" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:24 msgid "Level of the effect" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:105 msgid "Karaoke" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:106 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:20 msgid "R_ate:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:21 msgid "_Tempo:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:22 msgid "_Pitch:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:89 #, fuzzy msgid "Audio Pitch / Speed" msgstr "Fluxuri audio" #: ../quodlibet/ext/gstreamer/pitch.py:90 #, fuzzy msgid "Controls the pitch of an audio stream." msgstr "Introduceţi locaţia unui flux audio:" #: ../quodlibet/ext/playlist/export_to_folder.py:29 #: ../quodlibet/ext/playlist/export_to_folder.py:97 #: ../quodlibet/ext/playlist/export_to_folder.py:138 #, fuzzy msgid "Export Playlist to Folder" msgstr "Importă lista" #: ../quodlibet/ext/playlist/export_to_folder.py:38 #, fuzzy msgid "_Export" msgstr "_Importă" #: ../quodlibet/ext/playlist/export_to_folder.py:43 #, fuzzy msgid "Destination folder:" msgstr "Nici s-a găsit nici o staţie" #: ../quodlibet/ext/playlist/export_to_folder.py:58 #, 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:156 #, fuzzy msgid "Default filename pattern:" msgstr "Model nume _fişier:" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:23 msgid "Export to Squeezebox" msgstr "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:25 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 "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Export playlist to Squeezebox" msgstr "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:80 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 "" "Playback follows your selection, or the next song in the list once exhausted." msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:22 msgid "Playcount Equalizer" msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:23 msgid "Shuffle, preferring songs with fewer total plays." msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:25 #, fuzzy msgid "Prefer less played" msgstr "ultima redare" #: ../quodlibet/ext/playorder/queue.py:19 #, fuzzy msgid "Queue Only" msgstr "_Coadă" #: ../quodlibet/ext/playorder/queue.py:21 msgid "" "Limits playing of songs to the queue. Select this play order in the main " "window, then double-clicking any song will enqueue it instead of playing." msgstr "" #: ../quodlibet/ext/playorder/reverse.py:14 #, fuzzy msgid "Reverse" msgstr "Niciodată" #: ../quodlibet/ext/playorder/reverse.py:16 msgid "Reverses the play order of songs." msgstr "" #: ../quodlibet/ext/playorder/skip_songs.py:25 #, fuzzy msgid "Skip Songs" msgstr "Nici o piesă" #: ../quodlibet/ext/playorder/skip_songs.py:27 msgid "" "Playback skips over songs with a rating equal or below a given threshold." msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:30 msgid "Repeat Each Track" msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:32 msgid "Shuffle songs, but repeat every track a set number of times." msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:51 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. Syntax is '@(if: " "condition, then, else)'." msgstr "" #: ../quodlibet/ext/query/pythonexpression.py:14 msgid "Python Query" msgstr "" #: ../quodlibet/ext/query/pythonexpression.py:15 msgid "" "Use Python expressions in queries. Syntax is '@(python: expression)'. The " "variable 's' is the song being matched." msgstr "" #: ../quodlibet/ext/query/savedsearch.py:19 #, fuzzy msgid "Include Saved Search" msgstr "Valori salvate" #: ../quodlibet/ext/query/savedsearch.py:20 msgid "" "Include the results of a saved search as part of another query. Syntax is " "'@(saved: search name)'." 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:116 msgid "Port:" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:121 #, fuzzy msgid "Username:" msgstr "_Redenumeşte" #: ../quodlibet/ext/_shared/squeezebox/base.py:126 msgid "Password:" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:130 msgid "Library directory the server connects to." msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:132 #, fuzzy msgid "Library path:" msgstr "Colecţie" #. Add verify button #: ../quodlibet/ext/_shared/squeezebox/base.py:141 msgid "_Verify settings" msgstr "" #. Server settings Frame #: ../quodlibet/ext/_shared/squeezebox/base.py:147 msgid "Squeezebox Server" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:150 msgid "Debug" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:26 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:28 msgid "unidentified Squeezebox server" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:37 #, 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:20 #: ../quodlibet/ext/songsmenu/importexport.py:34 #: ../quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:329 #, fuzzy msgid "Fit image to _window" msgstr "Ascundere fereastră principală" #. Both labels #: ../quodlibet/ext/songsmenu/albumart.py:338 msgid "_Program:" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:343 msgid "_Edit image after saving" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:345 #, fuzzy msgid "File_name:" msgstr "Nume fişier" #: ../quodlibet/ext/songsmenu/albumart.py:457 msgid "Saving failed" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:458 #, fuzzy, python-format msgid "Unable to save \"%s\"." msgstr "Nu s-a putut salva piesa" #: ../quodlibet/ext/songsmenu/albumart.py:556 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:613 #, fuzzy msgid "Album Art Downloader" msgstr "Listă albume" #: ../quodlibet/ext/songsmenu/albumart.py:666 #, python-format msgid "from %(source)s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:669 #, python-format msgid "Resolution: %s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:672 #, fuzzy, python-format msgid "Size: %s" msgstr "Mărime" #: ../quodlibet/ext/songsmenu/albumart.py:690 #, fuzzy msgid "_Search" msgstr "_Caută:" #: ../quodlibet/ext/songsmenu/albumart.py:741 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:451 #, fuzzy msgid "Searching…" msgstr "Caută" #: ../quodlibet/ext/songsmenu/albumart.py:804 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:922 #, fuzzy msgid "Download Album Art" msgstr "Listă albume" #: ../quodlibet/ext/songsmenu/albumart.py:923 msgid "Downloads album covers from various websites." msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:936 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 #: ../quodlibet/qltk/downloader.py:52 msgid "Filename" msgstr "Nume fişier" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:130 #, fuzzy msgid "Disc" msgstr "Di_sc" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:131 #: ../quodlibet/ext/songsmenu/replaygain.py:404 #: ../quodlibet/qltk/tracknumbers.py:92 msgid "Track" msgstr "Pistă" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:132 #, 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:447 msgid "Please enter a query." msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:465 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:496 msgid "Error encountered. Please retry." msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:472 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:488 msgid "Loading result…" msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:475 #, fuzzy msgid "No results found." msgstr "Nici un modul nu a fost găsit." #: ../quodlibet/ext/songsmenu/browsefolders.py:159 #, fuzzy msgid "Browse Folders" msgstr "Navigatoare" #: ../quodlibet/ext/songsmenu/browsefolders.py:160 msgid "Opens the songs' folders in a file manager." msgstr "" #: ../quodlibet/ext/songsmenu/browsefolders.py:172 #, fuzzy msgid "Unable to open folders" msgstr "Nu s-a putut crea directorul" #: ../quodlibet/ext/songsmenu/browsefolders.py:173 msgid "No program available to open folders." msgstr "" #: ../quodlibet/ext/songsmenu/console.py:40 msgid "Python Console" msgstr "" #: ../quodlibet/ext/songsmenu/console.py:41 msgid "Interactive Python console." msgstr "" #: ../quodlibet/ext/songsmenu/console.py:72 msgid "You can access the following objects by default:" msgstr "" #: ../quodlibet/ext/songsmenu/console.py:82 msgid "Your current working directory is:" 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:55 #, fuzzy msgid "pattern" msgstr "Şablon invalid" #: ../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:91 #, fuzzy msgid "Input value" msgstr "Valoare invalidă" #: ../quodlibet/ext/songsmenu/custom_commands.py:92 #, python-format msgid "Value for %s?" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:136 #, fuzzy msgid "Custom Commands" msgstr "_Personalizat" #: ../quodlibet/ext/songsmenu/custom_commands.py:137 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:188 #: ../quodlibet/ext/songsmenu/custom_commands.py:198 #: ../quodlibet/ext/songsmenu/custom_commands.py:252 msgid "Edit Custom Commands" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:199 msgid "" "Supports QL patterns\n" "eg <tt><~artist~title></tt>" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:283 #, fuzzy, python-format msgid "Unable to run custom command %s" msgstr "Nu s-au putut copia piesele" #: ../quodlibet/ext/songsmenu/duplicates.py:290 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: ../quodlibet/ext/songsmenu/duplicates.py:343 msgid "Collapse / Expand all" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:347 #, python-format msgid "Duplicate key expression is '%s'" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:363 #, fuzzy msgid "Duplicates Browser" msgstr "Dezactivează navigatorul" #: ../quodlibet/ext/songsmenu/duplicates.py:364 msgid "Finds and displays similarly tagged versions of songs." msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:407 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:409 msgid "_Group duplicates by:" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:414 msgid "Duplicate Key" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:419 msgid "Remove _Whitespace" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:420 #, fuzzy msgid "Remove _Diacritics" msgstr "E_valuare" #: ../quodlibet/ext/songsmenu/duplicates.py:421 #, fuzzy msgid "Remove _Punctuation" msgstr "E_valuare" #: ../quodlibet/ext/songsmenu/duplicates.py:422 msgid "Case _Insensitive" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:430 msgid "Matching options" msgstr "" #. Create a dialog. #: ../quodlibet/ext/songsmenu/editplaycount.py:19 #: ../quodlibet/ext/songsmenu/editplaycount.py:41 #, fuzzy msgid "Edit Playcount" msgstr "Editare afişare" #: ../quodlibet/ext/songsmenu/editplaycount.py:20 msgid "" "Edit a song's ~#playcount and ~#skipcount.\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's ~#playcount to 0, the ~#lastplayed and ~#laststarted " "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:68 msgid "Play Count" msgstr "" #: ../quodlibet/ext/songsmenu/editplaycount.py:69 msgid "Skip Count" msgstr "" #: ../quodlibet/ext/songsmenu/embedded.py:24 msgid "Edit Embedded Images" msgstr "" #: ../quodlibet/ext/songsmenu/embedded.py:25 msgid "Removes or replaces embedded images." msgstr "" #: ../quodlibet/ext/songsmenu/embedded.py:78 #, fuzzy msgid "_Remove all Images" msgstr "E_valuare" #: ../quodlibet/ext/songsmenu/embedded.py:82 msgid "_Embed Current 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:41 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 #: ../quodlibet/qltk/downloader.py:67 #, 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" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" 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 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:49 msgid "Generating fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:63 msgid "_Details" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:85 msgid "_Submit" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:115 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:118 msgid "Fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Songs with MBIDs:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with sufficient tags:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs to submit:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:162 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:178 msgid "Submitting fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:186 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/id3tlen.py:21 msgid "Fix MP3 Duration" msgstr "" #: ../quodlibet/ext/songsmenu/id3tlen.py:22 msgid "" "Removes TLEN frames from ID3 tags which can be the cause for invalid song " "durations." msgstr "" #: ../quodlibet/ext/songsmenu/ifp.py:20 msgid "Send to iFP" msgstr "" #: ../quodlibet/ext/songsmenu/ifp.py:21 msgid "Uploads songs to an iRiver iFP device." msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:51 msgid "Export Metadata" msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:52 msgid "Exports metadata of selected songs as a .tags file." msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:92 #, fuzzy msgid "Import Metadata" msgstr "Importă lista" #: ../quodlibet/ext/songsmenu/importexport.py:93 msgid "Imports metadata for selected songs from a .tags file." msgstr "" #: ../quodlibet/ext/songsmenu/k3b.py:23 msgid "Burn CD" msgstr "" #: ../quodlibet/ext/songsmenu/k3b.py:24 msgid "Burns CDs with K3b, Brasero or xfburn." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:96 msgid "Updating chart list." msgstr "" #. No charts to fetch, no update scheduled. #: ../quodlibet/ext/songsmenu/lastfmsync.py:114 msgid "Already up-to-date." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:121 #, python-format msgid "Fetching chart for week of %s." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:143 msgid "Sync complete." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:149 msgid "Error during sync" msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:214 #: ../quodlibet/ext/songsmenu/lastfmsync.py:244 msgid "Last.fm Sync" msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:245 msgid "Updates your library's statistics from your Last.fm profile." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:293 #, 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 "" #. Create a dialog. #: ../quodlibet/ext/songsmenu/migratemetadata.py:29 #: ../quodlibet/ext/songsmenu/migratemetadata.py:38 #, fuzzy msgid "Migrate Metadata" msgstr "Importă lista" #: ../quodlibet/ext/songsmenu/migratemetadata.py:32 msgid "Copies the quodlibet-specific metadata between songs." msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:45 msgid "_Copy" msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:47 msgid "_Paste" msgstr "" #. Create the tag table. #: ../quodlibet/ext/songsmenu/migratemetadata.py:57 #, fuzzy msgid "Information to copy/paste" msgstr "Informaţii" #. Create the indexing box. #: ../quodlibet/ext/songsmenu/migratemetadata.py:79 msgid "Map tracks by disc and track number" msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:80 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 "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:96 #, python-format msgid "There is %d stored track." msgid_plural "There are %d stored tracks." msgstr[0] "" msgstr[1] "" msgstr[2] "" #: ../quodlibet/ext/songsmenu/playlist.py:31 #, fuzzy msgid "Export as Playlist" msgstr "Importă lista" #: ../quodlibet/ext/songsmenu/playlist.py:32 msgid "Exports songs to an M3U or PLS playlist." msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:77 msgid "Use relative paths" msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:77 msgid "Use absolute paths" msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:132 #, fuzzy msgid "Unable to export playlist" msgstr "Nu s-a putut importa lista de redare" #: ../quodlibet/ext/songsmenu/playlist.py:133 #, fuzzy, python-format msgid "Writing to <b>%s</b> 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:362 msgid "ReplayGain Analyzer" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:418 msgid "Progress" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:433 msgid "Gain" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:448 msgid "Peak" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:463 #, python-format msgid "There is <b>%(to-process)s</b> album to update (of %(all)s)" msgid_plural "There are <b>%(to-process)s</b> albums to update (of %(all)s)" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: ../quodlibet/ext/songsmenu/replaygain.py:578 msgid "Replay Gain" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:579 msgid "" "Analyzes and updates ReplayGain information, using GStreamer. Results are " "grouped by album." msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:617 msgid "always" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:618 msgid "if <b>any</b> RG tags are missing" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:620 msgid "if <b>album</b> RG tags are missing" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:637 msgid "_Process albums:" msgstr "" #. Server settings Frame #: ../quodlibet/ext/songsmenu/replaygain.py:649 #, 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 "" #. TRANSLATORS: BPM mean "beats per minute" #: ../quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "" #: ../quodlibet/ext/songsmenu/tapbpm.py:32 #: ../quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" 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:172 #: ../quodlibet/ext/songsmenu/tapbpm.py:179 msgid "Tap BPM" msgstr "" #: ../quodlibet/ext/songsmenu/tapbpm.py:173 #, fuzzy msgid "Tap BPM for the selected song." msgstr "Nu s-au putut şterge piesele" #: ../quodlibet/ext/songsmenu/website_search.py:35 #, fuzzy msgid "Website Search" msgstr "Caută" #: ../quodlibet/ext/songsmenu/website_search.py:36 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern-example)s." msgstr "" #: ../quodlibet/ext/songsmenu/website_search.py:78 #, fuzzy msgid "Search URL patterns" msgstr "şablon" #: ../quodlibet/ext/songsmenu/website_search.py:88 #, fuzzy msgid "Edit search URLs" msgstr "Editare valori salvate..." #. Add link to editor #: ../quodlibet/ext/songsmenu/website_search.py:114 #, fuzzy msgid "Configure Searches…" msgstr "Colorează termenii de _căutare" #: ../quodlibet/ext/songsmenu/wikipedia.py:46 #, python-format msgid "Search at %(website)s" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:63 msgid "Search Artist in Wikipedia" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:64 msgid "" "Opens a browser window with Wikipedia article on the playing song artist." msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:71 msgid "Search Album in Wikipedia" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:72 msgid "" "Opens a browser window with Wikipedia article on the playing song album." msgstr "" #. then (try to) load all new files #: ../quodlibet/library/libraries.py:650 ../quodlibet/library/libraries.py:660 #: ../quodlibet/library/libraries.py:726 ../quodlibet/library/libraries.py:745 #: ../quodlibet/qltk/information.py:268 ../quodlibet/qltk/prefs.py:639 #: ../quodlibet/util/library.py:124 msgid "Library" msgstr "Colecţie" #: ../quodlibet/library/libraries.py:650 msgid "Checking mount points" msgstr "Se verifică punctele de montare" #: ../quodlibet/library/libraries.py:660 msgid "Scanning library" msgstr "Se verifică colecţia" #: ../quodlibet/library/libraries.py:725 #, python-format msgid "Scanning %s" msgstr "Se verifică %s" #: ../quodlibet/library/libraries.py:745 msgid "Loading files" msgstr "" #: ../quodlibet/operon/base.py:70 #, python-format msgid "Failed to load file: %r" msgstr "" #: ../quodlibet/operon/commands.py:37 msgid "List tags" msgstr "" #: ../quodlibet/operon/commands.py:42 ../quodlibet/operon/commands.py:81 #: ../quodlibet/operon/commands.py:461 msgid "Print terse output" msgstr "" #: ../quodlibet/operon/commands.py:44 ../quodlibet/operon/commands.py:83 #: ../quodlibet/operon/commands.py:463 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "" #: ../quodlibet/operon/commands.py:47 ../quodlibet/operon/commands.py:86 #, fuzzy msgid "Also list programmatic tags" msgstr "Arată etichetele _programatice" #: ../quodlibet/operon/commands.py:51 ../quodlibet/operon/commands.py:129 #: ../quodlibet/operon/commands.py:220 ../quodlibet/operon/commands.py:293 #: ../quodlibet/operon/commands.py:336 ../quodlibet/operon/commands.py:340 #: ../quodlibet/operon/commands.py:391 ../quodlibet/operon/commands.py:394 #: ../quodlibet/operon/commands.py:433 ../quodlibet/operon/commands.py:468 #: ../quodlibet/operon/commands.py:508 ../quodlibet/operon/commands.py:543 #: ../quodlibet/operon/commands.py:585 msgid "Not enough arguments" msgstr "" #: ../quodlibet/operon/commands.py:53 ../quodlibet/operon/commands.py:90 #: ../quodlibet/operon/commands.py:131 ../quodlibet/operon/commands.py:222 #: ../quodlibet/operon/commands.py:470 msgid "Too many arguments" msgstr "" #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:92 #: ../quodlibet/operon/commands.py:475 ../quodlibet/qltk/data_editors.py:363 #, fuzzy msgid "Description" msgstr "descriere" #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:475 #: ../quodlibet/qltk/edittags.py:454 msgid "Value" msgstr "Valoare" #: ../quodlibet/operon/commands.py:76 msgid "List all common tags" msgstr "" #: ../quodlibet/operon/commands.py:118 msgid "Copy tags from one file to another" msgstr "" #: ../quodlibet/operon/commands.py:123 ../quodlibet/operon/commands.py:164 #: ../quodlibet/operon/commands.py:289 ../quodlibet/operon/commands.py:324 #: ../quodlibet/operon/commands.py:384 msgid "Show changes, don't apply them" msgstr "" #: ../quodlibet/operon/commands.py:125 msgid "Skip tags that can't be written" msgstr "" #: ../quodlibet/operon/commands.py:145 #, python-format msgid "Can't copy tag %r to file: %r" 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:304 ../quodlibet/operon/commands.py:444 #: ../quodlibet/operon/commands.py:676 #, python-format msgid "Can not set %r" msgstr "" #: ../quodlibet/operon/commands.py:319 msgid "Remove tags" msgstr "" #: ../quodlibet/operon/commands.py:326 ../quodlibet/operon/commands.py:386 msgid "Value is a regular expression" msgstr "" #: ../quodlibet/operon/commands.py:328 msgid "Remove all tags" msgstr "" #: ../quodlibet/operon/commands.py:332 msgid "Can't combine '--all' with '--regexp'" msgstr "" #: ../quodlibet/operon/commands.py:366 #, python-format msgid "Can't remove %r from %r" msgstr "" #: ../quodlibet/operon/commands.py:379 #, fuzzy msgid "Remove a tag value" msgstr "Filtrare dupa o valoare din etichetă" #: ../quodlibet/operon/commands.py:428 #, fuzzy msgid "Add a tag value" msgstr "Filtrare dupa o valoare din etichetă" #: ../quodlibet/operon/commands.py:456 #, fuzzy msgid "List file information" msgstr "Durată necunoscută" #: ../quodlibet/operon/commands.py:502 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" #: ../quodlibet/operon/commands.py:515 #, fuzzy, python-format msgid "Failed to load image file: %r" msgstr "Nu s-a putut redenumi fişierul" #: ../quodlibet/operon/commands.py:522 ../quodlibet/operon/commands.py:551 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" #: ../quodlibet/operon/commands.py:538 msgid "Remove all embedded images" msgstr "" #: ../quodlibet/operon/commands.py:568 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "" #: ../quodlibet/operon/commands.py:580 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" #: ../quodlibet/operon/commands.py:639 msgid "Rename files based on tags" msgstr "" #: ../quodlibet/operon/commands.py:654 msgid "Fill tags based on the file path" msgstr "" #: ../quodlibet/operon/commands.py:704 ../quodlibet/qltk/information.py:305 #: ../quodlibet/qltk/properties.py:84 ../quodlibet/qltk/renamefiles.py:176 #: ../quodlibet/qltk/tagsfrompath.py:229 ../quodlibet/qltk/tracknumbers.py:79 msgid "File" msgstr "Fişier" #: ../quodlibet/operon/commands.py:712 msgid "Fill tracknumbers for all files" msgstr "" #: ../quodlibet/operon/commands.py:731 msgid "Print tags based on the given pattern" msgstr "" #: ../quodlibet/operon/commands.py:768 #, fuzzy msgid "Display help information" msgstr "Arată pe scurt informaţiile de utilizare" #: ../quodlibet/operon/util.py:40 #, 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:30 #, fuzzy msgid "_Unknown" msgstr "Necunoscut" #: ../quodlibet/order/__init__.py:142 msgid "In Order" msgstr "În ordine" #: ../quodlibet/order/__init__.py:143 msgid "_In Order" msgstr "În _ordine" #: ../quodlibet/order/reorder.py:23 #, fuzzy msgid "Random" msgstr "_Aleator" #: ../quodlibet/order/reorder.py:24 ../quodlibet/qltk/queue.py:119 msgid "_Random" msgstr "_Aleator" #: ../quodlibet/order/reorder.py:39 ../quodlibet/order/reorder.py:40 msgid "Prefer higher rated" msgstr "" #: ../quodlibet/order/repeat.py:43 ../quodlibet/order/repeat.py:44 msgid "Repeat this track" msgstr "" #: ../quodlibet/order/repeat.py:57 ../quodlibet/order/repeat.py:58 #, fuzzy msgid "Repeat all" msgstr "_Repetare" #: ../quodlibet/order/repeat.py:73 ../quodlibet/order/repeat.py:74 msgid "One Song" msgstr "O singură piesă" #: ../quodlibet/player/gstbe/player.py:98 msgid "Stream" msgstr "" #: ../quodlibet/player/gstbe/player.py:98 msgid "Buffering" msgstr "" #: ../quodlibet/player/gstbe/player.py:319 msgid "Could not create GStreamer pipeline" msgstr "" #: ../quodlibet/player/gstbe/player.py:560 msgid "No GStreamer element found to handle media format" msgstr "" #: ../quodlibet/player/gstbe/player.py:561 #, 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:25 msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. In case the pipeline contains a sink, it will be used instead of " "the default one." msgstr "" #: ../quodlibet/player/gstbe/prefs.py:36 msgid "_Output pipeline:" msgstr "" #: ../quodlibet/player/gstbe/prefs.py:43 #, fuzzy, python-format msgid "%.1f seconds" msgstr "%d secundă" #: ../quodlibet/player/gstbe/prefs.py:57 msgid "_Buffer duration:" msgstr "" #: ../quodlibet/player/gstbe/prefs.py:66 msgid "Disable _gapless playback" msgstr "" #: ../quodlibet/player/gstbe/prefs.py:70 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions." msgstr "" #: ../quodlibet/player/gstbe/util.py:93 #, fuzzy msgid "No GStreamer audio sink found" msgstr "Nici s-a găsit nici o staţie" #: ../quodlibet/player/gstbe/util.py:112 msgid "Invalid GStreamer output pipeline" msgstr "" #: ../quodlibet/player/xinebe/player.py:90 #, fuzzy msgid "Unable to create audio output" msgstr "Nu s-a putut crea directorul" #: ../quodlibet/player/xinebe/player.py:91 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "" #: ../quodlibet/plugins/__init__.py:62 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" #: ../quodlibet/plugins/__init__.py:71 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "" #: ../quodlibet/plugins/playlist.py:30 #, 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:41 ../quodlibet/qltk/songsmenu.py:46 #: ../quodlibet/qltk/songsmenu.py:74 #, fuzzy msgid "_Run Plugin" msgstr "_Module" #: ../quodlibet/qltk/about.py:40 #, python-format msgid "Supported formats: %s" msgstr "Formate suportate: %s" #: ../quodlibet/qltk/about.py:43 #, python-format msgid "Audio device: %s" msgstr "Dispozitiv audio: %s" #. 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:207 ../quodlibet/qltk/information.py:131 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:48 ../quodlibet/qltk/edittags.py:311 msgid "_Value:" msgstr "_Valoare:" #: ../quodlibet/qltk/cbes.py:262 msgid "Saved Values" msgstr "Valori salvate" #: ../quodlibet/qltk/cbes.py:263 #, fuzzy msgid "Edit saved values…" msgstr "Editare valori salvate..." #: ../quodlibet/qltk/controls.py:111 msgid "Auto_matic" msgstr "" #: ../quodlibet/qltk/controls.py:112 #, fuzzy msgid "_Track Mode" msgstr "Coloane _pistă" #: ../quodlibet/qltk/controls.py:113 #, fuzzy msgid "_Album Mode" msgstr "Coloane _album" #. Translators: player state, no action #: ../quodlibet/qltk/controls.py:122 msgid "_Mute" msgstr "" #: ../quodlibet/qltk/controls.py:128 #, fuzzy msgid "_Replay Gain Mode" msgstr "Ajustare de volum _replay gain" #. Translators: New Command/Entry/Item/... #: ../quodlibet/qltk/data_editors.py:119 #, python-format msgid "New %s" msgstr "" #: ../quodlibet/qltk/data_editors.py:218 #, fuzzy msgid "(unknown)" msgstr "Necunoscut" #: ../quodlibet/qltk/data_editors.py:355 msgid "Tag expression" msgstr "" #: ../quodlibet/qltk/data_editors.py:382 msgid "Tag expression e.g. people:real or ~album~year." msgstr "" #: ../quodlibet/qltk/data_editors.py:383 #, fuzzy msgid "Enter new tag" msgstr "Filtrare dupa o valoare din etichetă" #: ../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/downloader.py:38 msgid "Downloads" msgstr "Transferuri" #: ../quodlibet/qltk/downloader.py:62 msgid "Size" msgstr "Mărime" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: ../quodlibet/qltk/downloader.py:94 ../quodlibet/qltk/renamefiles.py:265 #: ../quodlibet/qltk/wlw.py:50 msgid "_Stop" msgstr "" #: ../quodlibet/qltk/edittags.py:63 ../quodlibet/qltk/edittags.py:74 #, 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:67 ../quodlibet/qltk/edittags.py:71 #, 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:193 msgid "Split into _Multiple Values" msgstr "Separă în valori _multiple" #: ../quodlibet/qltk/edittags.py:211 msgid "Split Disc out of _Album" msgstr "Separă discul de _album" #: ../quodlibet/qltk/edittags.py:228 msgid "Split _Version out of Title" msgstr "Separă _versiunea de titlu" #: ../quodlibet/qltk/edittags.py:259 msgid "Split Arranger out of Ar_tist" msgstr "Separă aranjorul de ar_tist" #: ../quodlibet/qltk/edittags.py:264 msgid "Split _Performer out of Artist" msgstr "Separă _interpretul de artist" #: ../quodlibet/qltk/edittags.py:270 #, fuzzy msgid "Split _Performer out of Title" msgstr "Separă _interpretul de artist" #: ../quodlibet/qltk/edittags.py:276 #, fuzzy msgid "Split _Originalartist out of Title" msgstr "Separă _versiunea de titlu" #: ../quodlibet/qltk/edittags.py:283 msgid "Add a Tag" msgstr "Adaugă o etichetă" #: ../quodlibet/qltk/edittags.py:302 msgid "_Tag:" msgstr "_Etichetă:" #: ../quodlibet/qltk/edittags.py:404 msgid "Edit Tags" msgstr "Editare etichete" #: ../quodlibet/qltk/edittags.py:477 msgid "Show _programmatic tags" msgstr "Arată etichetele _programatice" #: ../quodlibet/qltk/edittags.py:478 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" #. Translators: Revert button in the tag editor #: ../quodlibet/qltk/edittags.py:508 #, fuzzy msgctxt "edittags" msgid "_Revert" msgstr "Niciodată" #. Translators: Save button in the tag editor #: ../quodlibet/qltk/edittags.py:513 msgctxt "edittags" msgid "_Save" msgstr "" #: ../quodlibet/qltk/edittags.py:659 msgid "Unable to add tag" msgstr "Nu s-a putut adăuga eticheta" #: ../quodlibet/qltk/edittags.py:660 #, fuzzy, python-format msgid "Unable to add <b>%s</b>" msgstr "Nu s-a putut adăuga piesa" #: ../quodlibet/qltk/edittags.py:662 #, fuzzy, python-format msgid "" "The files currently selected do not support multiple values for <b>%s</b>." 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:689 ../quodlibet/qltk/edittags.py:856 #: ../quodlibet/qltk/tagsfrompath.py:212 ../quodlibet/util/__init__.py:554 #: ../quodlibet/util/tags.py:231 msgid "Invalid tag" msgstr "Etichetă invalidă" #: ../quodlibet/qltk/edittags.py:690 ../quodlibet/qltk/edittags.py:857 #: ../quodlibet/qltk/tagsfrompath.py:213 #, python-format msgid "" "Invalid tag <b>%s</b>\n" "\n" "The files currently selected do not support editing this tag." msgstr "" "Etichetă invalidă <b>%s</b>\n" "\n" "Fişierle selectate curent nu suportă editarea acestei etichete." #: ../quodlibet/qltk/edittags.py:828 ../quodlibet/qltk/edittags.py:868 msgid "Invalid value" msgstr "Valoare invalidă" #: ../quodlibet/qltk/edittags.py:829 ../quodlibet/qltk/edittags.py:869 #, python-format msgid "" "Invalid value: <b>%(value)s</b>\n" "\n" "%(error)s" msgstr "" "Valoare invalidă: <b>%(value)s</b>\n" "\n" "%(error)s" #: ../quodlibet/qltk/_editutils.py:28 msgid "Tag may not be accurate" msgstr "Eticheta ar putea fi imprecisă" #: ../quodlibet/qltk/_editutils.py:31 #, 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:47 msgid "Unable to save song" msgstr "Nu s-a putut salva piesa" #: ../quodlibet/qltk/_editutils.py:50 #, 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:142 #, 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:95 #: ../quodlibet/qltk/quodlibetwindow.py:1066 msgid "_About" msgstr "" #: ../quodlibet/qltk/exfalsowindow.py:99 #: ../quodlibet/qltk/quodlibetwindow.py:1088 msgid "_Check for Updates…" msgstr "" #: ../quodlibet/qltk/exfalsowindow.py:105 #: ../quodlibet/qltk/quodlibetwindow.py:1021 ../quodlibet/qltk/songsmenu.py:304 msgid "_Plugins" msgstr "_Module" #: ../quodlibet/qltk/exfalsowindow.py:267 #, 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:279 msgid "Ex Falso Preferences" msgstr "Preferinţe Ex Falso" #: ../quodlibet/qltk/exfalsowindow.py:289 ../quodlibet/qltk/prefs.py:598 msgid "Split _on:" msgstr "Separare _la:" #: ../quodlibet/qltk/exfalsowindow.py:295 ../quodlibet/qltk/prefs.py:613 msgid "Tag Editing" msgstr "Editare etichete" #: ../quodlibet/qltk/filesel.py:210 msgid "Folders" msgstr "Directoare" #: ../quodlibet/qltk/filesel.py:253 #, fuzzy msgid "_New Folder…" msgstr "Director nou" #: ../quodlibet/qltk/filesel.py:262 #, fuzzy msgid "_Select all Sub-Folders" msgstr "_Selectează toate subdirectoarele" #: ../quodlibet/qltk/filesel.py:374 msgid "New Folder" msgstr "Director nou" #: ../quodlibet/qltk/filesel.py:374 msgid "Enter a name for the new folder:" msgstr "Introduceţi un nume pentru noul director:" #: ../quodlibet/qltk/filesel.py:387 msgid "Unable to create folder" msgstr "Nu s-a putut crea directorul" #: ../quodlibet/qltk/filesel.py:404 msgid "Unable to delete folder" msgstr "Nu s-a putut şterge directorul" #: ../quodlibet/qltk/filesel.py:519 ../quodlibet/qltk/pluginwin.py:167 msgid "Songs" msgstr "Piese" #. Translators: As in "by Artist Name" #: ../quodlibet/qltk/info.py:42 #, python-format msgid "by %s" msgstr "de către %s" #: ../quodlibet/qltk/info.py:43 ../quodlibet/qltk/information.py:167 #: ../quodlibet/qltk/information.py:448 #, python-format msgid "Disc %s" msgstr "Discul %s" #: ../quodlibet/qltk/info.py:44 ../quodlibet/qltk/information.py:172 #, python-format msgid "Track %s" msgstr "Pista %s" #: ../quodlibet/qltk/info.py:108 #, fuzzy msgid "_Edit Display…" msgstr "Editare afişare" #: ../quodlibet/qltk/information.py:105 msgid "No songs are selected." msgstr "Nici o piesă nu este selectată." #: ../quodlibet/qltk/information.py:106 msgid "No Songs" msgstr "Nici o piesă" #: ../quodlibet/qltk/information.py:121 ../quodlibet/qltk/information.py:338 #: ../quodlibet/qltk/information.py:471 ../quodlibet/qltk/information.py:531 msgid "Information" msgstr "Informaţii" #: ../quodlibet/qltk/information.py:126 msgid "Lyrics" msgstr "Versuri" #: ../quodlibet/qltk/information.py:184 ../quodlibet/qltk/information.py:396 #, python-format msgid "Produced by %s" msgstr "Produs de către %s" #: ../quodlibet/qltk/information.py:199 ../quodlibet/util/tags.py:76 msgid "artist" msgstr "artist" #: ../quodlibet/qltk/information.py:200 ../quodlibet/qltk/information.py:561 #: ../quodlibet/util/tags.py:76 msgid "artists" msgstr "artişti" #. for backwards compat #: ../quodlibet/qltk/information.py:221 ../quodlibet/util/tags.py:86 #: ../quodlibet/util/tags.py:114 msgid "performers" msgstr "interpreţi" #: ../quodlibet/qltk/information.py:235 ../quodlibet/qltk/information.py:248 #: ../quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "Niciodată" #: ../quodlibet/qltk/information.py:236 #, 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:254 ../quodlibet/util/tags.py:139 msgid "added" msgstr "adăugat" #: ../quodlibet/qltk/information.py:255 ../quodlibet/util/tags.py:140 msgid "last played" msgstr "ultima redare" #: ../quodlibet/qltk/information.py:256 ../quodlibet/util/tags.py:150 msgid "plays" msgstr "redări" #: ../quodlibet/qltk/information.py:257 ../quodlibet/util/tags.py:151 msgid "skips" msgstr "întreruperi" #: ../quodlibet/qltk/information.py:258 ../quodlibet/util/tags.py:156 msgid "rating" msgstr "evaluare" #: ../quodlibet/qltk/information.py:287 msgid "path" msgstr "" #: ../quodlibet/qltk/information.py:288 ../quodlibet/util/tags.py:154 msgid "length" msgstr "durată" #: ../quodlibet/qltk/information.py:289 #, fuzzy msgid "format" msgstr "Informaţii" #: ../quodlibet/qltk/information.py:290 ../quodlibet/util/tags.py:163 msgid "codec" msgstr "" #: ../quodlibet/qltk/information.py:291 ../quodlibet/util/tags.py:164 #, fuzzy msgid "encoding" msgstr "[Codare invalidă]" #: ../quodlibet/qltk/information.py:292 ../quodlibet/util/tags.py:160 msgid "bitrate" msgstr "rată de biţi" #: ../quodlibet/qltk/information.py:293 ../quodlibet/util/tags.py:161 msgid "file size" msgstr "mărime fişier" #: ../quodlibet/qltk/information.py:294 ../quodlibet/util/tags.py:149 msgid "modified" msgstr "modificat" #: ../quodlibet/qltk/information.py:331 msgid "Additional" msgstr "" #: ../quodlibet/qltk/information.py:383 #, 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:458 msgid "Track unavailable" msgstr "Pistă nedisponibilă" #: ../quodlibet/qltk/information.py:464 msgid "Track List" msgstr "Listă piste" #: ../quodlibet/qltk/information.py:505 ../quodlibet/qltk/information.py:578 #, 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:508 msgid "Selected Discography" msgstr "Discografie selectată" #: ../quodlibet/qltk/information.py:558 #, 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:586 ../quodlibet/util/tags.py:74 msgid "albums" msgstr "albume" #: ../quodlibet/qltk/information.py:599 msgid "Total length:" msgstr "Durată totală:" #: ../quodlibet/qltk/information.py:603 msgid "Total size:" msgstr "Mărime totală:" #: ../quodlibet/qltk/information.py:606 msgid "Files" msgstr "Fişiere" #: ../quodlibet/qltk/lyrics.py:37 msgid "_Download" msgstr "_Caută" #: ../quodlibet/qltk/lyrics.py:40 #, fuzzy msgid "_Edit" msgstr "_Editare afişare..." #. buffer.set_text(_("No lyrics found.\n\nYou can click the " #. "Download button to have Quod Libet search " #. "for lyrics online. You can also enter them " #. "yourself and click save.")) #: ../quodlibet/qltk/lyrics.py:73 ../quodlibet/qltk/lyrics.py:109 msgid "No lyrics found for this song." msgstr "Versurile pentru această piesă nu au putut fi găsite." #: ../quodlibet/qltk/lyrics.py:82 #, fuzzy msgid "Searching for lyrics…" msgstr "Se caută versurile..." #: ../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/msg.py:41 msgid "Discard tag changes?" msgstr "Anulaţi modificarea etichetelor?" #: ../quodlibet/qltk/msg.py:42 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:55 ../quodlibet/qltk/prefs.py:595 #: ../quodlibet/qltk/textedit.py:64 ../quodlibet/qltk/tracknumbers.py:117 #, fuzzy msgid "_Revert" msgstr "Niciodată" #: ../quodlibet/qltk/msg.py:86 msgid "File exists" msgstr "Fişierul există" #: ../quodlibet/qltk/msg.py:88 #, python-format msgid "Replace %(file-name)s?" msgstr "" #: ../quodlibet/qltk/msg.py:94 #, fuzzy msgid "_Replace File" msgstr "Redenumire fişiere" #: ../quodlibet/qltk/notif.py:182 msgid "Active tasks" msgstr "" #: ../quodlibet/qltk/notif.py:188 #, python-format msgid "%d tasks running" msgstr "" #: ../quodlibet/qltk/playorder.py:254 #, fuzzy msgid "Toggle shuffle mode" msgstr "Comutare între start şi pauză redare" #: ../quodlibet/qltk/playorder.py:270 #, fuzzy msgid "Toggle repeat mode" msgstr "Comutare între start şi pauză redare" #: ../quodlibet/qltk/pluginwin.py:44 msgid "Plugin Errors" msgstr "Erori module" #: ../quodlibet/qltk/pluginwin.py:124 msgid "Enabled" msgstr "" #: ../quodlibet/qltk/pluginwin.py:125 #, fuzzy msgid "Disabled" msgstr "Dezactivează navigatorul" #: ../quodlibet/qltk/pluginwin.py:131 msgid "No category" msgstr "" #: ../quodlibet/qltk/pluginwin.py:169 msgid "Events" msgstr "" #: ../quodlibet/qltk/pluginwin.py:170 #, fuzzy msgid "Play Order" msgstr "_Ordine:" #: ../quodlibet/qltk/pluginwin.py:171 #, fuzzy msgid "Editing" msgstr "Editare etichete" #: ../quodlibet/qltk/pluginwin.py:173 #, fuzzy msgid "Covers" msgstr "Mărime totală:" #: ../quodlibet/qltk/pluginwin.py:309 msgid "No plugins found." msgstr "Nici un modul nu a fost găsit." #: ../quodlibet/qltk/pluginwin.py:358 #, fuzzy msgid "Plugins" msgstr "_Module" #: ../quodlibet/qltk/pluginwin.py:402 msgid "Show _Errors" msgstr "Arată _erorile" #: ../quodlibet/qltk/prefs.py:45 msgid "_Disc" msgstr "Di_sc" #: ../quodlibet/qltk/prefs.py:46 msgid "_Track" msgstr "_Pistă" #: ../quodlibet/qltk/prefs.py:47 #, fuzzy msgid "Grou_ping" msgstr "grupare" #: ../quodlibet/qltk/prefs.py:50 msgid "Al_bum" msgstr "Al_bum" #: ../quodlibet/qltk/prefs.py:55 msgid "_Filename" msgstr "Nume _fişier" #: ../quodlibet/qltk/prefs.py:57 msgid "_Length" msgstr "D_urată" #: ../quodlibet/qltk/prefs.py:64 msgid "_Jump to playing song automatically" msgstr "_Sări automat la piesa redată" #: ../quodlibet/qltk/prefs.py:66 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:82 msgid "_Others:" msgstr "Alt_ele:" #: ../quodlibet/qltk/prefs.py:88 #, fuzzy msgid "_Edit…" msgstr "_Editare afişare..." #: ../quodlibet/qltk/prefs.py:91 msgid "Add or remove additional column headers" msgstr "" #: ../quodlibet/qltk/prefs.py:101 msgid "Visible Columns" msgstr "Coloane vizibile" #: ../quodlibet/qltk/prefs.py:104 msgid "Title includes _version" msgstr "Titlul include ver_siunea" #: ../quodlibet/qltk/prefs.py:106 #, fuzzy msgid "Artist includes all _people" msgstr "Titlul include ver_siunea" #: ../quodlibet/qltk/prefs.py:108 #, fuzzy msgid "Album includes _disc subtitle" msgstr "Albumul include pa_rtea" #: ../quodlibet/qltk/prefs.py:110 msgid "Filename includes _folder" msgstr "Numele de fişier include dire_ctorul" #: ../quodlibet/qltk/prefs.py:123 #, fuzzy msgid "Column Preferences" msgstr "Preferinţe" #: ../quodlibet/qltk/prefs.py:129 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "" #: ../quodlibet/qltk/prefs.py:142 ../quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Listă piese" #: ../quodlibet/qltk/prefs.py:222 #, fuzzy msgid "Edit Columns" msgstr "Coloane vizibile" #: ../quodlibet/qltk/prefs.py:259 msgid "Duration totals" msgstr "" #: ../quodlibet/qltk/prefs.py:271 msgid "_Global filter:" msgstr "Filtru _global:" #: ../quodlibet/qltk/prefs.py:277 msgid "Apply this query in addition to all others" msgstr "" #. Translators: The heading of the preference group, no action #: ../quodlibet/qltk/prefs.py:283 #, fuzzy msgctxt "heading" msgid "Search" msgstr "Caută" #: ../quodlibet/qltk/prefs.py:287 ../quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Navigatoare" #: ../quodlibet/qltk/prefs.py:293 msgid "Confirm _multiple ratings" msgstr "" #: ../quodlibet/qltk/prefs.py:295 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "" #: ../quodlibet/qltk/prefs.py:298 msgid "Enable _one-click ratings" msgstr "" #: ../quodlibet/qltk/prefs.py:300 #, 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:306 ../quodlibet/qltk/prefs.py:616 #, fuzzy msgid "Ratings" msgstr "E_valuare" #. Filename choice algorithm config #: ../quodlibet/qltk/prefs.py:312 msgid "Prefer _embedded art" msgstr "" #: ../quodlibet/qltk/prefs.py:314 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" #: ../quodlibet/qltk/prefs.py:319 msgid "_Fixed image filename:" msgstr "" #: ../quodlibet/qltk/prefs.py:321 msgid "The single image filename to use if selected" msgstr "" #: ../quodlibet/qltk/prefs.py:327 msgid "The album art image file to use when forced" msgstr "" #: ../quodlibet/qltk/prefs.py:336 #, fuzzy msgid "Album Art" msgstr "Listă albume" #: ../quodlibet/qltk/prefs.py:357 #, fuzzy msgid "Playback" msgstr "Pauză redare" #: ../quodlibet/qltk/prefs.py:362 msgid "Output Configuration" msgstr "" #: ../quodlibet/qltk/prefs.py:373 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" #: ../quodlibet/qltk/prefs.py:376 #, fuzzy msgid "_Fall-back gain (dB):" msgstr "_Volume Gain (dB):" #: ../quodlibet/qltk/prefs.py:387 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "" #: ../quodlibet/qltk/prefs.py:390 #, fuzzy msgid "_Pre-amp gain (dB):" msgstr "_Volume Gain (dB):" #: ../quodlibet/qltk/prefs.py:395 #, fuzzy msgid "_Enable Replay Gain volume adjustment" msgstr "Ajustare de volum _replay gain" #: ../quodlibet/qltk/prefs.py:420 #, fuzzy msgid "Replay Gain Volume Adjustment" msgstr "Ajustare de volum _replay gain" #: ../quodlibet/qltk/prefs.py:450 msgid "_Default rating:" msgstr "" #: ../quodlibet/qltk/prefs.py:493 #, fuzzy msgid "Rating _scale:" msgstr "E_valuare" #: ../quodlibet/qltk/prefs.py:542 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:547 msgid "_Bayesian averaging amount:" msgstr "" #: ../quodlibet/qltk/prefs.py:556 #, fuzzy msgid "Save ratings and play _counts" msgstr "Salvează evaluarile şi numărul de redări" #: ../quodlibet/qltk/prefs.py:560 msgid "_Email:" msgstr "_Adresă de mail:" #: ../quodlibet/qltk/prefs.py:562 msgid "Ratings and play counts will be set 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:577 #, fuzzy msgid "Auto-save tag changes" msgstr "Anulaţi modificarea etichetelor?" #: ../quodlibet/qltk/prefs.py:579 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "" #: ../quodlibet/qltk/prefs.py:587 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:610 #, fuzzy msgid "Tags" msgstr "Editare etichete" #: ../quodlibet/qltk/prefs.py:631 #, fuzzy msgid "Updating for new ratings" msgstr "Staţie _nouă" #: ../quodlibet/qltk/prefs.py:641 #, fuzzy msgid "Scan library _on start" msgstr "Reactualizare c_olecţie" #: ../quodlibet/qltk/prefs.py:651 ../quodlibet/qltk/quodlibetwindow.py:1100 #, fuzzy msgid "_Scan Library" msgstr "Caută în c_olecţie" #: ../quodlibet/qltk/prefs.py:653 ../quodlibet/qltk/quodlibetwindow.py:1162 msgid "Check for changes in your library" msgstr "Caută noutăţi în colecţie" #: ../quodlibet/qltk/prefs.py:658 #, fuzzy msgid "Re_build Library" msgstr "Reîn_cărcare colecţie" #: ../quodlibet/qltk/prefs.py:661 #, 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:671 #, fuzzy msgid "Scan Directories" msgstr "_Directoare indexate" #: ../quodlibet/qltk/prefs.py:677 #, fuzzy msgid "Hidden Songs" msgstr "Nici o piesă" #: ../quodlibet/qltk/properties.py:158 ../quodlibet/util/collection.py:398 #, 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:162 ../quodlibet/qltk/properties.py:164 msgid "Properties" msgstr "Proprietăţi" #: ../quodlibet/qltk/queue.py:101 msgid "_Queue" msgstr "_Coadă" #: ../quodlibet/qltk/queue.py:126 msgid "Stop Once Empty" msgstr "" #: ../quodlibet/qltk/queue.py:130 #, fuzzy msgid "_Clear Queue" msgstr "Erori module" #: ../quodlibet/qltk/queue.py:242 #, 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:198 msgid "_Browse Library" msgstr "_Navigare în colecţie" #: ../quodlibet/qltk/quodlibetwindow.py:395 #, fuzzy msgid "Toggle queue visibility" msgstr "Comutare a vizibilităţii ferestrei principale" #: ../quodlibet/qltk/quodlibetwindow.py:516 #, fuzzy msgid "Playback Error" msgstr "Pauză redare" #: ../quodlibet/qltk/quodlibetwindow.py:524 #, fuzzy msgid "Set up library directories?" msgstr "Selectare directoare" #: ../quodlibet/qltk/quodlibetwindow.py:525 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:531 msgid "_Not Now" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:532 msgid "_Set Up" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:956 msgid "Unable to add songs" msgstr "Nu s-au putut adăuga piesele" #: ../quodlibet/qltk/quodlibetwindow.py:957 #: ../quodlibet/qltk/quodlibetwindow.py:1364 #, fuzzy, python-format msgid "%s uses an unsupported protocol." msgstr "<b>%s</b> foloseşte un protocol nesuportat." #: ../quodlibet/qltk/quodlibetwindow.py:980 msgid "_Jump to Playing Song" msgstr "_Sări la piesa redată" #: ../quodlibet/qltk/quodlibetwindow.py:986 #, fuzzy msgid "_File" msgstr "Fişier" #: ../quodlibet/qltk/quodlibetwindow.py:987 #, fuzzy msgid "_Song" msgstr "Piese" #: ../quodlibet/qltk/quodlibetwindow.py:988 msgid "_View" msgstr "_Vizualizare" #: ../quodlibet/qltk/quodlibetwindow.py:989 #, fuzzy msgid "_Browse" msgstr "Navigatoare" #: ../quodlibet/qltk/quodlibetwindow.py:990 msgid "_Control" msgstr "_Control" #: ../quodlibet/qltk/quodlibetwindow.py:991 msgid "_Help" msgstr "_Ajutor" #: ../quodlibet/qltk/quodlibetwindow.py:997 #, fuzzy msgid "_Add a Folder…" msgstr "Adăugare _director..." #: ../quodlibet/qltk/quodlibetwindow.py:1002 #, fuzzy msgid "_Add a File…" msgstr "Adăugare _fişier..." #: ../quodlibet/qltk/quodlibetwindow.py:1007 #, fuzzy msgid "_Add a Location…" msgstr "Adăugare locaţie" #: ../quodlibet/qltk/quodlibetwindow.py:1036 #, fuzzy msgid "Edit Bookmarks…" msgstr "_Editare favorite..." #: ../quodlibet/qltk/quodlibetwindow.py:1056 #, fuzzy msgid "Stop After This Song" msgstr "Stop după această piesă" #: ../quodlibet/qltk/quodlibetwindow.py:1062 msgid "_Keyboard Shortcuts" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:1071 msgid "Online Help" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:1080 #, fuzzy msgid "Search Help" msgstr "Caută" #: ../quodlibet/qltk/quodlibetwindow.py:1352 msgid "Add a Location" msgstr "Adăugare locaţie" #: ../quodlibet/qltk/quodlibetwindow.py:1353 msgid "Enter the location of an audio file:" msgstr "Introduceţi locaţia unui fişier audio:" #: ../quodlibet/qltk/quodlibetwindow.py:1358 #: ../quodlibet/qltk/quodlibetwindow.py:1363 msgid "Unable to add location" msgstr "Nu s-a putut adăuga locaţia" #: ../quodlibet/qltk/quodlibetwindow.py:1359 #, fuzzy, python-format msgid "%s is not a valid location." msgstr "<b>%s</b> nu este o locaţie validă." #: ../quodlibet/qltk/quodlibetwindow.py:1372 #: ../quodlibet/qltk/quodlibetwindow.py:1381 msgid "Add Music" msgstr "Adăugare muzică" #: ../quodlibet/qltk/quodlibetwindow.py:1372 ../quodlibet/qltk/scanbox.py:99 #, fuzzy msgid "_Add Folders" msgstr "Adăugare _director..." #: ../quodlibet/qltk/quodlibetwindow.py:1379 #, fuzzy msgid "Music Files" msgstr "Redare audio" #: ../quodlibet/qltk/quodlibetwindow.py:1381 #, fuzzy msgid "_Add Files" msgstr "Adăugare _fişier..." #: ../quodlibet/qltk/ratingsmenu.py:24 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "" #: ../quodlibet/qltk/ratingsmenu.py:26 msgid "The saved ratings will be removed" msgstr "" #: ../quodlibet/qltk/ratingsmenu.py:27 #, python-format msgid "The rating of all selected songs will be changed to '%s'" msgstr "" #: ../quodlibet/qltk/ratingsmenu.py:57 ../quodlibet/qltk/ratingsmenu.py:111 #, fuzzy msgid "_Remove Rating" msgstr "E_valuare" #: ../quodlibet/qltk/ratingsmenu.py:98 #, fuzzy msgid "Change _Rating" msgstr "E_valuare" #: ../quodlibet/qltk/renamefiles.py:46 msgid "Replace spaces with _underscores" msgstr "Înlocuieşte spaţiile cu liniuţe de _subliniere" #: ../quodlibet/qltk/renamefiles.py:56 msgid "Strip _Windows-incompatible characters" msgstr "Şterge caracterele incompatibile cu sistemele _Windows" #: ../quodlibet/qltk/renamefiles.py:74 msgid "Strip _diacritical marks" msgstr "Şterge semnele _diacritice" #: ../quodlibet/qltk/renamefiles.py:85 msgid "Strip non-_ASCII characters" msgstr "Şterge caracterele non-_ASCII" #: ../quodlibet/qltk/renamefiles.py:95 msgid "Use only _lowercase characters" msgstr "" #: ../quodlibet/qltk/renamefiles.py:123 msgid "Rename Files" msgstr "Redenumire fişiere" #: ../quodlibet/qltk/renamefiles.py:139 ../quodlibet/qltk/tagsfrompath.py:116 #, fuzzy msgid "Path Patterns" msgstr "şablon" #: ../quodlibet/qltk/renamefiles.py:140 ../quodlibet/qltk/tagsfrompath.py:117 #, fuzzy msgid "Edit saved patterns…" msgstr "Editare valori salvate..." #: ../quodlibet/qltk/renamefiles.py:143 ../quodlibet/qltk/tagsfrompath.py:120 #: ../quodlibet/qltk/tracknumbers.py:58 msgid "_Preview" msgstr "_Previzualizare" #: ../quodlibet/qltk/renamefiles.py:190 msgid "New Name" msgstr "Nume nou" #: ../quodlibet/qltk/renamefiles.py:255 msgid "Unable to rename file" msgstr "Nu s-a putut redenumi fişierul" #: ../quodlibet/qltk/renamefiles.py:256 #, fuzzy, python-format msgid "" "Renaming <b>%(old-name)s</b> to <b>%(new-name)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." 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:264 #, fuzzy msgid "Ignore _All Errors" msgstr "Arată _erorile" #: ../quodlibet/qltk/renamefiles.py:267 msgid "_Continue" msgstr "_Continuă" #: ../quodlibet/qltk/renamefiles.py:296 msgid "Path is not absolute" msgstr "Calea nu este una absolută" #: ../quodlibet/qltk/renamefiles.py:297 #, python-format msgid "" "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 ~/." 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:47 #, 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:99 msgid "Select Directories" msgstr "Selectare directoare" #: ../quodlibet/qltk/searchbar.py:52 #, fuzzy msgid "Saved Searches" msgstr "Valori salvate" #: ../quodlibet/qltk/searchbar.py:53 #, fuzzy msgid "Edit saved searches…" msgstr "Editare valori salvate..." #: ../quodlibet/qltk/searchbar.py:74 msgid "Search your library, using free text or QL queries" msgstr "" #: ../quodlibet/qltk/searchbar.py:129 #, fuzzy msgid "Search after _typing" msgstr "Stop după această piesă" #: ../quodlibet/qltk/searchbar.py:132 msgid "Show search results after the user stops typing." msgstr "" #: ../quodlibet/qltk/searchbar.py:187 msgid "_Limit:" msgstr "_Limită:" #: ../quodlibet/qltk/searchbar.py:200 msgid "_Weight" msgstr "_Pondere" #: ../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 ../quodlibet/qltk/shortcuts.py:41 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: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:377 #, python-format msgid "_Filter on %s" msgstr "_Filtrare după %s" #: ../quodlibet/qltk/songlist.py:1094 #, fuzzy msgid "All _Headers" msgstr "Coloane _album" #: ../quodlibet/qltk/songlist.py:1095 msgid "_Track Headers" msgstr "Coloane _pistă" #: ../quodlibet/qltk/songlist.py:1096 msgid "_Album Headers" msgstr "Coloane _album" #: ../quodlibet/qltk/songlist.py:1097 msgid "_People Headers" msgstr "Coloane _persoane" #: ../quodlibet/qltk/songlist.py:1098 msgid "_Date Headers" msgstr "Coloane _dată" #: ../quodlibet/qltk/songlist.py:1099 msgid "_File Headers" msgstr "Coloane _fişier" #: ../quodlibet/qltk/songlist.py:1100 msgid "_Production Headers" msgstr "Coloane _producţie" #: ../quodlibet/qltk/songlist.py:1115 #, fuzzy msgid "_Customize Headers…" msgstr "_Personalizează coloanele..." #: ../quodlibet/qltk/songlist.py:1120 msgid "_Expand Column" msgstr "" #: ../quodlibet/qltk/songsmenu.py:36 #, 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:64 #, 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:149 #, fuzzy msgid "Configure Plugins…" msgstr "Colorează termenii de _căutare" #: ../quodlibet/qltk/songsmenu.py:345 msgid "Add to _Queue" msgstr "Adaugă în _coadă" #: ../quodlibet/qltk/songsmenu.py:368 msgid "_Copy to Device" msgstr "_Copiază către dispozitiv" #: ../quodlibet/qltk/songsmenu.py:379 #, fuzzy msgid "_Remove from Library" msgstr "Şte_rge din listă" #: ../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:101 msgid "Tags From Path" msgstr "Etichetare din cale" #: ../quodlibet/qltk/tagsfrompath.py:138 msgid "Tags replace existing ones" msgstr "Etichetele le înlocuiesc pe cele actuale" #: ../quodlibet/qltk/tagsfrompath.py:139 msgid "Tags are added to existing ones" msgstr "Etichetele sunt adăugate la cele actuale" #. Save button #: ../quodlibet/qltk/tagsfrompath.py:153 msgid "Save" msgstr "" #: ../quodlibet/qltk/tagsfrompath.py:195 #, python-format msgid "" "The pattern\n" "\t<b>%s</b>\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/tagsfrompath.py:216 msgid "Invalid tags" msgstr "Etichete invalide" #: ../quodlibet/qltk/tagsfrompath.py:217 #, 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." #: ../quodlibet/qltk/textedit.py:142 #, 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:158 msgid "Edit Display" msgstr "Editare afişare" #: ../quodlibet/qltk/tracknumbers.py:39 msgid "Track Numbers" msgstr "Număr piste" #: ../quodlibet/qltk/tracknumbers.py:42 msgid "Start fro_m:" msgstr "Start _de la:" #: ../quodlibet/qltk/tracknumbers.py:51 msgid "_Total tracks:" msgstr "_Total piste:" #: ../quodlibet/qltk/unity.py:52 #, fuzzy msgid "Play/Pause" msgstr "Redare" #: ../quodlibet/qltk/unity.py:75 #, fuzzy msgid "Previous" msgstr "_Previzualizare" #: ../quodlibet/qltk/views.py:923 #, 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:89 #, fuzzy msgid "Checking for Updates" msgstr "Se verifică punctele de montare" #: ../quodlibet/update.py:124 #, fuzzy msgid "Connection failed" msgstr "locaţie" #: ../quodlibet/update.py:133 #, python-format msgid "You are already using the newest version %(version)s" msgstr "" #: ../quodlibet/update.py:136 #, 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:420 msgid "Playlists must have a name" msgstr "" #: ../quodlibet/util/collection.py:603 #, python-format msgid "A playlist named %s already exists." msgstr "O listă cu numele „%s” există deja." #: ../quodlibet/util/cover/built_in.py:26 #, fuzzy msgid "Embedded album covers" msgstr "Arată _coperţile albumelor" #: ../quodlibet/util/cover/built_in.py:27 msgid "Uses covers embedded into audio files." msgstr "" #: ../quodlibet/util/cover/built_in.py:49 #, fuzzy msgid "Filesystem cover" msgstr "Sistem de fişiere" #: ../quodlibet/util/cover/built_in.py:50 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "" #: ../quodlibet/util/__init__.py:93 msgid "Display brief usage information" msgstr "Arată pe scurt informaţiile de utilizare" #: ../quodlibet/util/__init__.py:95 msgid "Display version and copyright" msgstr "Arată versiunea şi drepturile de autor" #: ../quodlibet/util/__init__.py:135 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "" #: ../quodlibet/util/__init__.py:137 msgid "[options]" msgstr "[opţiuni]" #: ../quodlibet/util/__init__.py:182 #, fuzzy, python-format msgid "Option %r not recognized." msgstr "E: Opţiunea „%s” nu a fost recunoscută." #: ../quodlibet/util/__init__.py:185 #, fuzzy, python-format msgid "Option %r requires an argument." msgstr "E: Opţiunea „%s” necesită un argument." #: ../quodlibet/util/__init__.py:188 #, fuzzy, python-format msgid "%r is not a unique prefix." msgstr "E: „%s” nu este un prefix unic." #: ../quodlibet/util/__init__.py:364 #, python-format msgid "%d kbps" msgstr "%d kbps" #: ../quodlibet/util/__init__.py:419 #, 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:432 msgid "No time information" msgstr "Durată necunoscută" #: ../quodlibet/util/__init__.py:435 #, 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:436 #, 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:437 #, 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:438 #, 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:439 #, 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:563 #, 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 msgid "Unable to edit song" msgstr "Nu s-a putut edita piesa" #: ../quodlibet/util/songwrapper.py:113 #, python-format msgid "" "Saving <b>%s</b> 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:34 #: ../quodlibet/util/string/__init__.py:44 msgid "[Invalid Encoding]" msgstr "[Codare invalidă]" #: ../quodlibet/util/tags.py:74 msgid "album" msgstr "album" #: ../quodlibet/util/tags.py:75 msgid "arranger" msgstr "aranjor" #: ../quodlibet/util/tags.py:75 msgid "arrangers" msgstr "aranjori" #: ../quodlibet/util/tags.py:75 #, fuzzy msgid "arrangement" msgstr "aranjor" #: ../quodlibet/util/tags.py:77 msgid "author" msgstr "autor" #: ../quodlibet/util/tags.py:77 msgid "authors" msgstr "autori" #: ../quodlibet/util/tags.py:78 msgid "composer" msgstr "compozitor" #: ../quodlibet/util/tags.py:78 msgid "composers" msgstr "compozitori" #: ../quodlibet/util/tags.py:78 #, fuzzy msgid "composition" msgstr "compozitor" #. Translators: conducting as in conducting a musical performance #: ../quodlibet/util/tags.py:80 msgid "conductor" msgstr "dirijor" #: ../quodlibet/util/tags.py:80 msgid "conductors" msgstr "dirijori" #: ../quodlibet/util/tags.py:80 #, fuzzy msgid "conducting" msgstr "dirijor" #: ../quodlibet/util/tags.py:81 msgid "contact" msgstr "contact" #: ../quodlibet/util/tags.py:82 msgid "copyright" msgstr "drepturi de autor" #: ../quodlibet/util/tags.py:83 msgid "date" msgstr "dată" #: ../quodlibet/util/tags.py:84 msgid "description" msgstr "descriere" #: ../quodlibet/util/tags.py:85 msgid "genre" msgstr "gen" #: ../quodlibet/util/tags.py:85 #, fuzzy msgid "genres" msgstr "gen" #: ../quodlibet/util/tags.py:86 msgid "performer" msgstr "interpret" #: ../quodlibet/util/tags.py:87 msgid "grouping" msgstr "grupare" #: ../quodlibet/util/tags.py:88 msgid "language" msgstr "limbaj" #: ../quodlibet/util/tags.py:89 msgid "license" msgstr "licenţă" #: ../quodlibet/util/tags.py:90 msgid "location" msgstr "locaţie" #: ../quodlibet/util/tags.py:91 msgid "lyricist" msgstr "textier" #: ../quodlibet/util/tags.py:91 msgid "lyricists" msgstr "textieri" #: ../quodlibet/util/tags.py:91 #, fuzzy msgid "lyrics" msgstr "textier" #. Translators: Also e.g. "record label", "publisher" #: ../quodlibet/util/tags.py:93 msgid "organization" msgstr "organizaţie" #: ../quodlibet/util/tags.py:94 msgid "title" msgstr "titlu" #: ../quodlibet/util/tags.py:95 msgid "version" msgstr "versiune" #: ../quodlibet/util/tags.py:96 msgid "website" msgstr "adresă internet" #: ../quodlibet/util/tags.py:98 msgid "album artist" msgstr "artist album" #: ../quodlibet/util/tags.py:99 msgid "BPM" msgstr "BPM" #. Translators: This used to be called "part". #: ../quodlibet/util/tags.py:102 ../quodlibet/util/tags.py:103 msgid "disc subtitle" msgstr "" #: ../quodlibet/util/tags.py:104 ../quodlibet/util/tags.py:141 msgid "disc" msgstr "disc" #: ../quodlibet/util/tags.py:105 ../quodlibet/util/tags.py:143 msgid "track" msgstr "pistă" #: ../quodlibet/util/tags.py:106 msgid "label ID" msgstr "ID etichetă" #: ../quodlibet/util/tags.py:107 msgid "original release date" msgstr "dată iniţială de lansare" #: ../quodlibet/util/tags.py:108 msgid "original album" msgstr "album iniţial" #: ../quodlibet/util/tags.py:109 msgid "original artist" msgstr "artist iniţial" #: ../quodlibet/util/tags.py:110 msgid "recording date" msgstr "dată de înregistrare" #: ../quodlibet/util/tags.py:111 msgid "release country" msgstr "ţara de lansare" #. 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:120 #, fuzzy msgid "MusicBrainz recording ID" msgstr "ID pistă MusicBrainz" #: ../quodlibet/util/tags.py:121 #, fuzzy msgid "MusicBrainz release track ID" msgstr "ID pistă MusicBrainz" #: ../quodlibet/util/tags.py:122 #, fuzzy msgid "MusicBrainz release ID" msgstr "ID pistă MusicBrainz" #: ../quodlibet/util/tags.py:123 #, fuzzy msgid "MusicBrainz artist ID" msgstr "ID artist MusicBrainz" #: ../quodlibet/util/tags.py:124 #, fuzzy msgid "MusicBrainz release artist ID" msgstr "ID pistă MusicBrainz" #: ../quodlibet/util/tags.py:125 msgid "MusicBrainz TRM ID" msgstr "ID TRM MusicBrainz" #: ../quodlibet/util/tags.py:126 msgid "MusicIP PUID" msgstr "ID PUID MusicBrainz" #: ../quodlibet/util/tags.py:127 msgid "MusicBrainz album status" msgstr "Status album MusicBrainz" #: ../quodlibet/util/tags.py:128 msgid "MusicBrainz album type" msgstr "Tip album MusicBrainz" #: ../quodlibet/util/tags.py:129 #, fuzzy msgid "MusicBrainz release group ID" msgstr "ID pistă MusicBrainz" #. Translators: "gain" means a volume adjustment, not "to acquire". #: ../quodlibet/util/tags.py:132 msgid "track gain" msgstr "corecţie pistă" #: ../quodlibet/util/tags.py:133 msgid "track peak" msgstr "vârf pistă" #. Translators: "gain" means a volume adjustment, not "to acquire". #: ../quodlibet/util/tags.py:135 msgid "album gain" msgstr "corecţie album" #: ../quodlibet/util/tags.py:136 msgid "album peak" msgstr "vârf album" #: ../quodlibet/util/tags.py:137 #, fuzzy msgid "reference loudness" msgstr "Preferinţe" #: ../quodlibet/util/tags.py:142 msgid "discs" msgstr "discuri" #: ../quodlibet/util/tags.py:144 msgid "tracks" msgstr "piste" #: ../quodlibet/util/tags.py:145 msgid "last started" msgstr "ultima lansare" #: ../quodlibet/util/tags.py:146 msgid "full name" msgstr "nume complet" #: ../quodlibet/util/tags.py:153 msgid "mount point" msgstr "punct de montare" #: ../quodlibet/util/tags.py:155 msgid "people" msgstr "persoane" #: ../quodlibet/util/tags.py:157 msgid "year" msgstr "an" #: ../quodlibet/util/tags.py:158 #, fuzzy msgid "original release year" msgstr "dată iniţială de lansare" #: ../quodlibet/util/tags.py:159 #, fuzzy msgid "bookmark" msgstr "Favorite" #: ../quodlibet/util/tags.py:162 #, fuzzy msgid "file format" msgstr "format" #: ../quodlibet/util/tags.py:165 #, fuzzy msgid "playlists" msgstr "Liste" #: ../quodlibet/util/tags.py:166 msgid "channel count" msgstr "" #. Translators: e.g. "artist (sort)" #: ../quodlibet/util/tags.py:256 msgid "sort" msgstr "" #. Translators: e.g. "performer (roles)" #: ../quodlibet/util/tags.py:264 msgid "roles" msgstr "" #, fuzzy #~ msgid "browsers" #~ msgstr "Navigatoare" #~ msgid "Unable to download lyrics." #~ msgstr "Nu s-au putut descărca versurile." #~ msgid "Remove all songs from the queue" #~ msgstr "Şterge toate piesele din coadă" #~ msgid "Watch this folder for new songs" #~ msgstr "Monitorizează acest director pentru piese noi" #~ 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 "Model:" #~ msgstr "Model:" #~ msgid "Capacity:" #~ msgstr "Capacitate:" #~ msgid "Firmware:" #~ msgstr "Firmware:" #, fuzzy #~ msgid "Removing orphaned iPod track" #~ msgstr "W: sterg pista orfană din iPod" #, 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 "Unable to open input files" #~ msgstr "Nu s-au putut deschide fişierele" #, 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 "_Select" #~ msgstr "_Selectează" #~ 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 "Choose New Stations" #~ msgstr "Adăugare staţii noi" #~ msgid "Add" #~ msgstr "Adaugă" #, fuzzy #~ msgid "Bitrate" #~ msgstr "rată de biţi" #~ msgid "_Stations..." #~ msgstr "_Staţii..." #, fuzzy #~ msgid "Quod Libet" #~ msgstr "Ieşire Quod Libet" #~ 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9711857 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/po/ru.po����������������������������������������������������������������������������0000644�0001750�0001750�00000656262�00000000000�014123� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 <xwxvwvxwx@gmail.com>, 2018. # 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: 2018-06-08 18:58+0300\n" "PO-Revision-Date: 2018-06-11 19:32+0300\n" "Last-Translator: wvxwxvw <xwxvwvxwx@gmail.com>\n" "Language-Team: Russian\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: Manually\n" "X-Poedit-Basepath: .\n" #: ../data/exfalso.appdata.xml.in.h:1 ../data/exfalso.desktop.in.h:2 msgid "Edit tags in your audio files" msgstr "Программа для редактирования тегов аудиофайлов" #: ../data/exfalso.appdata.xml.in.h:2 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/exfalso.appdata.xml.in.h:3 #: ../data/io.github.quodlibet.QuodLibet.appdata.xml.in.h:3 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/exfalso.desktop.in.h:1 msgid "Audio tag editor" msgstr "Редактор аудио тегов" #: ../data/io.github.quodlibet.QuodLibet.appdata.xml.in.h:1 #: ../data/io.github.quodlibet.QuodLibet.desktop.in.h:2 msgid "Listen to, browse, or edit your audio collection" msgstr "Программа для прослушивания и управления фонотекой" #: ../data/io.github.quodlibet.QuodLibet.appdata.xml.in.h:2 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 - программа управления музыкой. Доступно несколько способов " "просмотра аудиотеки, а также поддержка интернет-радио и аудио лент. " "Он имеет гибкие возможности редактирования и поиска по аудио тегам." #: ../data/io.github.quodlibet.QuodLibet.desktop.in.h:1 msgid "Music Player" msgstr "Проигрыватель музыки" #: ../quodlibet/browsers/albums/main.py:186 #: ../quodlibet/browsers/covergrid/main.py:55 msgid "_Title" msgstr "_Название" #: ../quodlibet/browsers/albums/main.py:187 #: ../quodlibet/browsers/covergrid/main.py:56 ../quodlibet/qltk/prefs.py:50 msgid "_Artist" msgstr "_Исполнитель" #: ../quodlibet/browsers/albums/main.py:188 #: ../quodlibet/browsers/covergrid/main.py:57 ../quodlibet/qltk/prefs.py:55 msgid "_Date" msgstr "_Дата" #: ../quodlibet/browsers/albums/main.py:189 #: ../quodlibet/browsers/covergrid/main.py:58 ../quodlibet/qltk/prefs.py:54 msgid "_Genre" msgstr "_Жанр" #: ../quodlibet/browsers/albums/main.py:190 #: ../quodlibet/browsers/covergrid/main.py:59 ../quodlibet/qltk/prefs.py:59 #: ../quodlibet/qltk/ratingsmenu.py:40 msgid "_Rating" msgstr "О_ценка" #: ../quodlibet/browsers/albums/main.py:191 msgid "_Playcount" msgstr "Воспроизведени_й" #: ../quodlibet/browsers/albums/main.py:197 #: ../quodlibet/browsers/covergrid/main.py:65 msgid "Sort _by…" msgstr "Сортировать _по…" #: ../quodlibet/browsers/albums/main.py:218 #: ../quodlibet/browsers/covergrid/main.py:86 #: ../quodlibet/browsers/paned/prefs.py:167 #: ../quodlibet/browsers/playlists/main.py:638 #: ../quodlibet/qltk/exfalsowindow.py:110 ../quodlibet/qltk/pluginwin.py:342 #: ../quodlibet/qltk/quodlibetwindow.py:1053 msgid "_Preferences" msgstr "_Настройки" #: ../quodlibet/browsers/albums/main.py:384 msgid "Album List" msgstr "Список альбомов" #: ../quodlibet/browsers/albums/main.py:385 msgid "_Album List" msgstr "Список _альбомов" #: ../quodlibet/browsers/albums/main.py:495 #: ../quodlibet/browsers/covergrid/main.py:281 #: ../quodlibet/browsers/covergrid/main.py:491 msgid "All Albums" msgstr "Все альбомы" #: ../quodlibet/browsers/albums/main.py:496 #: ../quodlibet/browsers/covergrid/main.py:282 #: ../quodlibet/browsers/covergrid/main.py:492 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d альбом" msgstr[1] "%d альбома" msgstr[2] "%d альбомов" #: ../quodlibet/browsers/albums/main.py:674 #: ../quodlibet/browsers/covergrid/main.py:470 msgid "Reload album _cover" msgid_plural "Reload album _covers" msgstr[0] "Перезагрузить _обложку" msgstr[1] "Перезагрузить _обложки" msgstr[2] "Перезагрузить _обложки" #: ../quodlibet/browsers/albums/prefs.py:29 #: ../quodlibet/browsers/collection/models.py:18 #: ../quodlibet/browsers/covergrid/prefs.py:31 msgid "Songs not in an album" msgstr "Треки не в альбоме" #: ../quodlibet/browsers/albums/prefs.py:42 #: ../quodlibet/browsers/covergrid/prefs.py:44 #: ../quodlibet/browsers/playlists/prefs.py:36 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:100 #: ../quodlibet/qltk/information.py:386 ../quodlibet/util/collection.py:246 #, python-format msgid "%d track" msgid_plural "%d tracks" msgstr[0] "%d трек" msgstr[1] "%d трека" msgstr[2] "%d треков" #: ../quodlibet/browsers/albums/prefs.py:43 #: ../quodlibet/browsers/covergrid/prefs.py:45 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:99 #: ../quodlibet/qltk/information.py:384 ../quodlibet/util/collection.py:250 #, python-format msgid "%d disc" msgid_plural "%d discs" msgstr[0] "%d диск" msgstr[1] "%d диска" msgstr[2] "%d дисков" #: ../quodlibet/browsers/albums/prefs.py:45 #: ../quodlibet/browsers/covergrid/prefs.py:47 msgid "An Example Album" msgstr "Пример альбома" #: ../quodlibet/browsers/albums/prefs.py:53 msgid "Album List Preferences" msgstr "Настройка списка альбомов" #: ../quodlibet/browsers/albums/prefs.py:62 msgid "Show album _covers" msgstr "Показывать обложки _альбомов" #: ../quodlibet/browsers/albums/prefs.py:68 msgid "Inline _search includes people" msgstr "При быстром поиске _искать также исполнителей" #: ../quodlibet/browsers/albums/prefs.py:72 #: ../quodlibet/browsers/covergrid/prefs.py:121 #: ../quodlibet/ext/songsmenu/cover_download.py:243 msgid "Options" msgstr "Параметры" #: ../quodlibet/browsers/albums/prefs.py:75 #: ../quodlibet/browsers/covergrid/prefs.py:124 msgid "Album Display" msgstr "Список альбомов" #: ../quodlibet/browsers/albums/prefs.py:79 #: ../quodlibet/browsers/covergrid/prefs.py:128 #: ../quodlibet/browsers/playlists/prefs.py:57 #: ../quodlibet/ext/songsmenu/albumart.py:328 #: ../quodlibet/ext/songsmenu/duplicates.py:349 #: ../quodlibet/ext/songsmenu/filterall.py:49 #: ../quodlibet/qltk/bookmarks.py:102 ../quodlibet/qltk/cbes.py:94 #: ../quodlibet/qltk/data_editors.py:98 ../quodlibet/qltk/data_editors.py:323 #: ../quodlibet/qltk/exfalsowindow.py:298 ../quodlibet/qltk/pluginwin.py:80 #: ../quodlibet/qltk/pluginwin.py:429 ../quodlibet/qltk/prefs.py:718 #: ../quodlibet/qltk/textedit.py:165 ../quodlibet/update.py:149 msgid "_Close" msgstr "_Закрыть" #: ../quodlibet/browsers/audiofeeds.py:53 #: ../quodlibet/browsers/audiofeeds.py:65 #: ../quodlibet/browsers/audiofeeds.py:67 #: ../quodlibet/browsers/audiofeeds.py:157 #: ../quodlibet/browsers/paned/models.py:87 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:47 #: ../quodlibet/formats/_audio.py:501 ../quodlibet/order/__init__.py:28 #: ../quodlibet/qltk/information.py:245 ../quodlibet/qltk/information.py:252 #: ../quodlibet/qltk/information.py:278 ../quodlibet/qltk/wlw.py:71 msgid "Unknown" msgstr "Неизвестно" #: ../quodlibet/browsers/audiofeeds.py:248 msgid "New Feed" msgstr "Новая лента" #: ../quodlibet/browsers/audiofeeds.py:249 msgid "Enter the location of an audio feed:" msgstr "Введите адрес аудио ленты:" #: ../quodlibet/browsers/audiofeeds.py:250 #: ../quodlibet/browsers/collection/prefs.py:91 #: ../quodlibet/browsers/iradio.py:355 ../quodlibet/browsers/paned/prefs.py:79 #: ../quodlibet/browsers/playlists/menu.py:97 #: ../quodlibet/browsers/playlists/util.py:54 ../quodlibet/qltk/bookmarks.py:63 #: ../quodlibet/qltk/cbes.py:56 ../quodlibet/qltk/data_editors.py:310 #: ../quodlibet/qltk/edittags.py:289 ../quodlibet/qltk/edittags.py:489 #: ../quodlibet/qltk/quodlibetwindow.py:1388 ../quodlibet/qltk/scanbox.py:62 msgid "_Add" msgstr "_Добавить" #: ../quodlibet/browsers/audiofeeds.py:304 msgid "Audio Feeds" msgstr "Аудио ленты" #: ../quodlibet/browsers/audiofeeds.py:305 msgid "_Audio Feeds" msgstr "Аудио _ленты" #: ../quodlibet/browsers/audiofeeds.py:408 #: ../quodlibet/browsers/playlists/main.py:216 #: ../quodlibet/qltk/data_editors.py:95 msgid "_New" msgstr "С_оздать" #: ../quodlibet/browsers/audiofeeds.py:468 #: ../quodlibet/browsers/audiofeeds.py:527 msgid "Unable to add feed" msgstr "Не удалось добавить ленту" #: ../quodlibet/browsers/audiofeeds.py:469 #: ../quodlibet/browsers/audiofeeds.py:528 #, python-format msgid "" "%s could not be added. The server may be down, or the location may not be an " "audio feed." msgstr "" "Не удалось добавить %s. Возможно, указанный сервер не работает или адрес не " "является лентой аудиофайлов." #: ../quodlibet/browsers/audiofeeds.py:476 ../quodlibet/qltk/filesel.py:272 #: ../quodlibet/qltk/pluginwin.py:415 msgid "_Refresh" msgstr "Об_новить" #: ../quodlibet/browsers/audiofeeds.py:477 #: ../quodlibet/browsers/playlists/main.py:459 #: ../quodlibet/browsers/playlists/util.py:45 ../quodlibet/qltk/delete.py:144 #: ../quodlibet/qltk/filesel.py:269 ../quodlibet/qltk/lyrics.py:36 #: ../quodlibet/qltk/maskedbox.py:29 ../quodlibet/qltk/songsmenu.py:366 msgid "_Delete" msgstr "_Удалить файлы" #: ../quodlibet/browsers/audiofeeds.py:544 msgid "" "The current audio backend does not support URLs, Audio Feeds browser " "disabled." msgstr "" "Используемая система аудиовывода не поддерживает адреса URL. Поддержка " "аудио лент отключена." #: ../quodlibet/browsers/_base.py:148 ../quodlibet/browsers/_base.py:151 msgid "Library Browser" msgstr "Браузер фонотеки" #: ../quodlibet/browsers/_base.py:275 ../quodlibet/ext/songsmenu/console.py:47 #: ../quodlibet/ext/songsmenu/refresh.py:31 #: ../quodlibet/qltk/exfalsowindow.py:242 ../quodlibet/qltk/information.py:555 #: ../quodlibet/qltk/maskedbox.py:69 ../quodlibet/util/collection.py:532 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d трек" msgstr[1] "%d трека" msgstr[2] "%d треков" #: ../quodlibet/browsers/_base.py:403 ../quodlibet/browsers/_base.py:408 #: ../quodlibet/qltk/tagsfrompath.py:195 ../quodlibet/qltk/textedit.py:142 #: ../quodlibet/util/__init__.py:574 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:25 #, python-format msgid "Unknown %s" msgstr "Неизвестный %s" #: ../quodlibet/browsers/collection/models.py:26 #, python-format msgid "Multiple %s Values" msgstr "Несколько значений %s" #: ../quodlibet/browsers/collection/prefs.py:67 #: ../quodlibet/browsers/paned/prefs.py:52 msgid "_Custom" msgstr "Св_ои" #. Remove button #: ../quodlibet/browsers/collection/prefs.py:95 #: ../quodlibet/browsers/paned/prefs.py:83 #: ../quodlibet/browsers/playlists/menu.py:98 #: ../quodlibet/ext/playlist/remove_duplicates.py:61 #: ../quodlibet/qltk/bookmarks.py:98 ../quodlibet/qltk/bookmarks.py:128 #: ../quodlibet/qltk/cbes.py:83 ../quodlibet/qltk/cbes.py:90 #: ../quodlibet/qltk/data_editors.py:80 ../quodlibet/qltk/data_editors.py:93 #: ../quodlibet/qltk/data_editors.py:300 ../quodlibet/qltk/data_editors.py:313 #: ../quodlibet/qltk/data_editors.py:321 ../quodlibet/qltk/edittags.py:495 #: ../quodlibet/qltk/edittags.py:635 ../quodlibet/qltk/maskedbox.py:49 #: ../quodlibet/qltk/maskedbox.py:89 ../quodlibet/qltk/queue.py:377 #: ../quodlibet/qltk/scanbox.py:37 ../quodlibet/qltk/scanbox.py:64 msgid "_Remove" msgstr "_Удалить" #: ../quodlibet/browsers/collection/prefs.py:123 #: ../quodlibet/ext/songsmenu/filterall.py:35 #: ../quodlibet/operon/commands.py:57 ../quodlibet/operon/commands.py:93 #: ../quodlibet/qltk/edittags.py:432 msgid "Tag" msgstr "Тег" #: ../quodlibet/browsers/collection/prefs.py:129 msgid "Merge" msgstr "Группировать" #: ../quodlibet/browsers/collection/prefs.py:189 msgid "Album Collection Preferences" msgstr "Настройка коллекции альбомов" #: ../quodlibet/browsers/collection/prefs.py:196 #: ../quodlibet/browsers/paned/prefs.py:210 #: ../quodlibet/ext/songsmenu/editplaycount.py:46 #: ../quodlibet/ext/songsmenu/exact_rating.py:39 #: ../quodlibet/player/gstbe/prefs.py:41 ../quodlibet/qltk/prefs.py:128 #: ../quodlibet/qltk/textedit.py:66 msgid "_Apply" msgstr "_Применить" #: ../quodlibet/browsers/collection/prefs.py:199 #: ../quodlibet/browsers/paned/prefs.py:214 #: ../quodlibet/browsers/playlists/menu.py:96 #: ../quodlibet/browsers/playlists/util.py:44 #: ../quodlibet/errorreport/ui.py:104 #: ../quodlibet/ext/playlist/export_to_folder.py:38 #: ../quodlibet/ext/playlist/remove_duplicates.py:60 #: ../quodlibet/ext/_shared/squeezebox/util.py:20 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:356 #: ../quodlibet/ext/songsmenu/editplaycount.py:45 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:282 #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:92 #: ../quodlibet/ext/songsmenu/importexport.py:40 #: ../quodlibet/ext/songsmenu/lastfmsync.py:219 #: ../quodlibet/ext/songsmenu/playlist.py:51 #: ../quodlibet/ext/songsmenu/replaygain.py:355 #: ../quodlibet/ext/songsmenu/tapbpm.py:187 ../quodlibet/qltk/chooser.py:189 #: ../quodlibet/qltk/chooser.py:210 ../quodlibet/qltk/chooser.py:234 #: ../quodlibet/qltk/chooser.py:258 ../quodlibet/qltk/delete.py:91 #: ../quodlibet/qltk/delete.py:134 ../quodlibet/qltk/edittags.py:288 #: ../quodlibet/qltk/_editutils.py:40 ../quodlibet/qltk/getstring.py:29 #: ../quodlibet/qltk/maskedbox.py:28 ../quodlibet/qltk/msg.py:55 #: ../quodlibet/qltk/msg.py:94 ../quodlibet/qltk/msg.py:112 #: ../quodlibet/qltk/ratingsmenu.py:34 ../quodlibet/update.py:95 msgid "_Cancel" msgstr "_Отмена" #: ../quodlibet/browsers/covergrid/main.py:127 msgid "Cover Grid" msgstr "Сетка обложек" #: ../quodlibet/browsers/covergrid/main.py:128 msgid "_Cover Grid" msgstr "Сетка _обложек" #: ../quodlibet/browsers/covergrid/prefs.py:55 msgid "Cover Grid Preferences" msgstr "Параметры сетки" #: ../quodlibet/browsers/covergrid/prefs.py:65 msgid "Show album _text" msgstr "Показывать текст _альбомов" #: ../quodlibet/browsers/covergrid/prefs.py:72 msgid "Show \"All Albums\" Item" msgstr "Показывать пункт \"Все альбомы\" " #: ../quodlibet/browsers/covergrid/prefs.py:79 msgid "Wide Mode" msgstr "Широкий режим" #: ../quodlibet/browsers/covergrid/prefs.py:111 #: ../quodlibet/browsers/covergrid/prefs.py:112 msgid "Cover Magnification" msgstr "Увеличивать обложку" #: ../quodlibet/browsers/filesystem.py:41 msgid "File System" msgstr "Файловая система" #: ../quodlibet/browsers/filesystem.py:42 msgid "_File System" msgstr "_Файловая система" #: ../quodlibet/browsers/filesystem.py:126 ../quodlibet/qltk/songlist.py:256 msgid "Unable to copy songs" msgstr "Не удалось копировать треки" #: ../quodlibet/browsers/filesystem.py:127 ../quodlibet/qltk/songlist.py:257 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "" "Выбранные файлы не могут быть копированы в другой плейлист или очередь." #: ../quodlibet/browsers/filesystem.py:199 msgid "_Add to Library" msgstr "_Добавить в фонотеку" #: ../quodlibet/browsers/iradio.py:182 msgid "Unsupported file type" msgstr "Неподдерживаемый тип файла" #: ../quodlibet/browsers/iradio.py:183 #, 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:228 ../quodlibet/browsers/iradio.py:241 #: ../quodlibet/browsers/iradio.py:824 msgid "Unable to add station" msgstr "Не удалось добавить станцию" #: ../quodlibet/browsers/iradio.py:252 ../quodlibet/browsers/iradio.py:485 msgid "Internet Radio" msgstr "Интернет-радио" #: ../quodlibet/browsers/iradio.py:252 msgid "Downloading station list" msgstr "Загрузка списка станций" #: ../quodlibet/browsers/iradio.py:353 msgid "New Station" msgstr "Новая станция" #: ../quodlibet/browsers/iradio.py:354 msgid "Enter the location of an Internet radio station:" msgstr "Введите адрес интернет-радиостанции:" #: ../quodlibet/browsers/iradio.py:372 msgid "Electronic" msgstr "" #: ../quodlibet/browsers/iradio.py:375 msgid "Hip Hop / Rap" msgstr "" #: ../quodlibet/browsers/iradio.py:376 msgid "Oldies" msgstr "" #: ../quodlibet/browsers/iradio.py:377 msgid "R&B" msgstr "" #: ../quodlibet/browsers/iradio.py:378 msgid "Japanese" msgstr "" #: ../quodlibet/browsers/iradio.py:379 msgid "Indian" msgstr "" #: ../quodlibet/browsers/iradio.py:381 msgid "Religious" msgstr "" #: ../quodlibet/browsers/iradio.py:383 msgid "Charts" msgstr "" #: ../quodlibet/browsers/iradio.py:384 msgid "Turkish" msgstr "" #: ../quodlibet/browsers/iradio.py:385 msgid "Reggae / Dancehall" msgstr "" #: ../quodlibet/browsers/iradio.py:386 msgid "Latin" msgstr "" #: ../quodlibet/browsers/iradio.py:387 msgid "College Radio" msgstr "" #: ../quodlibet/browsers/iradio.py:388 msgid "Talk / News" msgstr "" #: ../quodlibet/browsers/iradio.py:389 msgid "Ambient" msgstr "" #: ../quodlibet/browsers/iradio.py:390 msgid "Jazz" msgstr "" #: ../quodlibet/browsers/iradio.py:391 ../quodlibet/ext/events/equalizer.py:46 msgid "Classical" msgstr "Classic" #: ../quodlibet/browsers/iradio.py:392 ../quodlibet/ext/events/equalizer.py:61 msgid "Pop" msgstr "" #: ../quodlibet/browsers/iradio.py:393 msgid "Alternative" msgstr "" #: ../quodlibet/browsers/iradio.py:394 msgid "Metal" msgstr "" #: ../quodlibet/browsers/iradio.py:395 msgid "Country" msgstr "" #: ../quodlibet/browsers/iradio.py:396 msgid "News" msgstr "Новости" #: ../quodlibet/browsers/iradio.py:397 msgid "Schlager" msgstr "Шлягер" #: ../quodlibet/browsers/iradio.py:398 msgid "Funk" msgstr "" #: ../quodlibet/browsers/iradio.py:399 msgid "Indie" msgstr "" #: ../quodlibet/browsers/iradio.py:400 msgid "Blues" msgstr "" #: ../quodlibet/browsers/iradio.py:401 msgid "Soul" msgstr "" #: ../quodlibet/browsers/iradio.py:402 msgid "Lounge" msgstr "" #: ../quodlibet/browsers/iradio.py:403 msgid "Punk" msgstr "" #: ../quodlibet/browsers/iradio.py:404 msgid "Reggaeton" msgstr "" #: ../quodlibet/browsers/iradio.py:406 msgid "Slavic" msgstr "" #: ../quodlibet/browsers/iradio.py:408 msgid "Greek" msgstr "" #: ../quodlibet/browsers/iradio.py:409 msgid "Gothic" msgstr "" #: ../quodlibet/browsers/iradio.py:410 ../quodlibet/ext/events/equalizer.py:39 msgid "Rock" msgstr "" #: ../quodlibet/browsers/iradio.py:463 msgid "Would you like to load a list of popular radio stations?" msgstr "Загрузить список популярных радиостанций?" #: ../quodlibet/browsers/iradio.py:469 msgid "_Load Stations" msgstr "_Загрузить станции" #: ../quodlibet/browsers/iradio.py:486 msgid "_Internet Radio" msgstr "_Интернет-радио" #: ../quodlibet/browsers/iradio.py:552 msgid "_New Station…" msgstr "_Новая станция…" #: ../quodlibet/browsers/iradio.py:555 msgid "_Update Stations" msgstr "_Обновить станции" #: ../quodlibet/browsers/iradio.py:582 msgid "All Stations" msgstr "Все станции" #. TODO: support for ~#rating=!None etc (#1940) #: ../quodlibet/browsers/iradio.py:586 #: ../quodlibet/browsers/soundcloud/main.py:65 msgid "Favorites" msgstr "Избранное" #: ../quodlibet/browsers/iradio.py:594 msgid "No Category" msgstr "Без категории" #: ../quodlibet/browsers/iradio.py:816 msgid "No stations found" msgstr "Станций не найдено" #: ../quodlibet/browsers/iradio.py:817 #, python-format msgid "No Internet radio stations were found at %s." msgstr "По адресу %s интернет-радиостанций не найдено." #: ../quodlibet/browsers/iradio.py:825 msgid "All stations listed are already in your library." msgstr "Все указанные станции уже в фонотеке." #: ../quodlibet/browsers/iradio.py:842 msgid "Add to Favorites" msgstr "Добавить в избранное" #: ../quodlibet/browsers/iradio.py:846 msgid "Remove from Favorites" msgstr "Удалить из избранного" #: ../quodlibet/browsers/iradio.py:946 #, 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:42 ../quodlibet/qltk/shortcuts.py:45 msgid "Paned Browser" msgstr "Панели обзора" #: ../quodlibet/browsers/paned/main.py:43 msgid "_Paned Browser" msgstr "Панели о_бзора" #: ../quodlibet/browsers/paned/main.py:93 msgid "Select _All" msgstr "В_ыбрать всё" #: ../quodlibet/browsers/paned/models.py:105 ../quodlibet/qltk/pluginwin.py:123 #: ../quodlibet/qltk/pluginwin.py:165 msgid "All" msgstr "Все" #: ../quodlibet/browsers/paned/prefs.py:68 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "<tt>%s</tt>" msgstr "" "Шаблон тега с дополнительной разметкой, например:\n" " <tt>композитор</tt> либо <tt>%s</tt>" #: ../quodlibet/browsers/paned/prefs.py:163 msgid "_Wide Mode" msgstr "_Широкий режим" #: ../quodlibet/browsers/paned/prefs.py:198 msgid "Paned Browser Preferences" msgstr "Параметры панелей" #: ../quodlibet/browsers/paned/prefs.py:205 msgid "Equal pane width" msgstr "Равная ширина панелей" #: ../quodlibet/browsers/playlists/main.py:48 #: ../quodlibet/browsers/playlists/main.py:574 #: ../quodlibet/qltk/pluginwin.py:169 msgid "Playlists" msgstr "Плейлисты" #: ../quodlibet/browsers/playlists/main.py:49 msgid "_Playlists" msgstr "Пле_йлисты" #: ../quodlibet/browsers/playlists/main.py:152 msgid "_Remove from Playlist" msgstr "Удалить из плейли_ста" #: ../quodlibet/browsers/playlists/main.py:218 #: ../quodlibet/browsers/playlists/main.py:575 msgid "_Import" msgstr "_Импортировать" #: ../quodlibet/browsers/playlists/main.py:415 msgid "Unable to import playlist" msgstr "Не удалось импортировать плейлист" #: ../quodlibet/browsers/playlists/main.py:416 msgid "Quod Libet can only import playlists in the M3U and PLS formats." msgstr "" "Quod Libet может импортировать плейлисты только в форматах M3U и PLS." #: ../quodlibet/browsers/playlists/main.py:466 msgid "_Rename" msgstr "_Переименовать" #: ../quodlibet/browsers/playlists/main.py:564 msgid "Unable to rename playlist" msgstr "Не удалось переименовать плейлист" #: ../quodlibet/browsers/playlists/main.py:575 msgid "Import Playlist" msgstr "Импортировать плейлист" #: ../quodlibet/browsers/playlists/menu.py:26 msgid "_New Playlist…" msgstr "_Новый плейлист…" #: ../quodlibet/browsers/playlists/menu.py:87 #, 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:91 #, python-format msgid "Confirm action for playlist \"%s\"" msgstr "Подтвердите действие для плейлиста '%s'" #: ../quodlibet/browsers/playlists/prefs.py:22 msgid "empty" msgstr "пустой" #: ../quodlibet/browsers/playlists/prefs.py:40 msgid "Example Playlist" msgstr "Новый плейлист" #: ../quodlibet/browsers/playlists/prefs.py:48 msgid "Playlist Browser Preferences" msgstr "Параметры вида плейлиста" #: ../quodlibet/browsers/playlists/prefs.py:53 msgid "Playlist display" msgstr "Показать плейлист" #: ../quodlibet/browsers/playlists/util.py:35 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "Удалить плейлист '%s'?" #: ../quodlibet/browsers/playlists/util.py:37 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" "Плейлист будет удалён безвозвратно." #: ../quodlibet/browsers/playlists/util.py:52 #: ../quodlibet/browsers/playlists/util.py:127 #: ../quodlibet/util/collection.py:575 msgid "New Playlist" msgstr "Новый плейлист" #: ../quodlibet/browsers/playlists/util.py:53 msgid "Enter a name for the new playlist:" msgstr "Введите название нового плейлиста:" #: ../quodlibet/browsers/playlists/util.py:91 #, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" "Импорт плейлиста.\n" "\n" "%(current)d/%(total)d треков добавлено." #: ../quodlibet/browsers/search.py:32 msgid "_Limit Results" msgstr "_Ограничить результаты" #: ../quodlibet/browsers/search.py:47 msgid "Search Library" msgstr "Поиск по фонотеке" #: ../quodlibet/browsers/search.py:48 msgid "_Search Library" msgstr "_Поиск по фонотеке" #: ../quodlibet/browsers/soundcloud/main.py:39 msgid "Soundcloud Browser" msgstr "Обзор SoundCloud" #: ../quodlibet/browsers/soundcloud/main.py:40 msgid "Sound_cloud" msgstr "Обзор Sound_cloud" #: ../quodlibet/browsers/soundcloud/main.py:60 #: ../quodlibet/qltk/searchbar.py:78 msgid "Search" msgstr "Найти" #: ../quodlibet/browsers/soundcloud/main.py:69 msgid "My tracks" msgstr "Мои треки" #: ../quodlibet/browsers/soundcloud/main.py:141 #, python-format msgid "Go to %s" msgstr "Перейти к %s" #: ../quodlibet/browsers/soundcloud/main.py:393 msgid "Connected" msgstr "Соединение" #: ../quodlibet/browsers/soundcloud/main.py:394 #, python-format msgid "Quod Libet is now connected, <b>%s</b>!" msgstr "Quod Libet подключен, <b>%s</b>!" #: ../quodlibet/browsers/soundcloud/main.py:406 #, python-format msgid "Log out of %s" msgstr "Выйти из %s" #: ../quodlibet/browsers/soundcloud/main.py:408 msgid "Enter code…" msgstr "Введите код…" #: ../quodlibet/browsers/soundcloud/main.py:409 #, python-format msgid "Log in to %s" msgstr "Вход в %s" #: ../quodlibet/browsers/soundcloud/util.py:87 msgid "Soundcloud authorisation" msgstr "Авторизация в SoundCloud" #: ../quodlibet/browsers/soundcloud/util.py:88 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 "Print player status" msgstr "Показать состояние воспроизведения" #: ../quodlibet/cli.py:106 msgid "Hide main window" msgstr "Скрыть главное окно" #: ../quodlibet/cli.py:107 msgid "Show main window" msgstr "Показать главное окно" #: ../quodlibet/cli.py:108 msgid "Toggle main window visibility" msgstr "Показать/скрыть главное окно" #: ../quodlibet/cli.py:109 msgid "Focus the running player" msgstr "Фокус на окно Quod Libet" #: ../quodlibet/cli.py:110 msgid "Remove active browser filters" msgstr "Убрать текущие фильтры просмотра" #: ../quodlibet/cli.py:111 msgid "Refresh and rescan library" msgstr "Пересканировать фонотеку" #: ../quodlibet/cli.py:112 msgid "List available browsers" msgstr "Список режимов просмотра" #: ../quodlibet/cli.py:113 msgid "Print the current playlist" msgstr "Показать текущий плейлист" #: ../quodlibet/cli.py:114 msgid "Print the contents of the queue" msgstr "Показать содержимое очереди" #: ../quodlibet/cli.py:115 msgid "Print the active text query" msgstr "Показать содержимое очереди" #: ../quodlibet/cli.py:116 msgid "Start without plugins" msgstr "Отключить расширения" #: ../quodlibet/cli.py:117 msgid "Start Quod Libet if it isn't running" msgstr "Запустить Quod Libet, если он не запущен" #: ../quodlibet/cli.py:118 msgid "Exit Quod Libet" msgstr "Выйти из Quod Libet" #: ../quodlibet/cli.py:123 msgid "Seek within the playing song" msgstr "Перемотка по воспроизводимому треку" #: ../quodlibet/cli.py:123 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][ЧЧ:]ММ:СС" #: ../quodlibet/cli.py:124 msgid "Set or toggle shuffle mode" msgstr "Переключить оспроизведение/пауза" #: ../quodlibet/cli.py:125 msgid "Set shuffle mode type" msgstr "Режим случайного порядка" #: ../quodlibet/cli.py:126 msgid "Turn repeat off, on, or toggle it" msgstr "Вкл./выкл. повтор треков" #: ../quodlibet/cli.py:127 msgid "Set repeat mode type" msgstr "Режим типа повтора" #: ../quodlibet/cli.py:128 msgid "Set the volume" msgstr "Установить громкость" #: ../quodlibet/cli.py:129 msgid "Search your audio library" msgstr "Поиск в фонотеке" #: ../quodlibet/cli.py:129 ../quodlibet/cli.py:141 ../quodlibet/cli.py:145 #: ../quodlibet/cli.py:147 msgid "query" msgstr "запрос" #: ../quodlibet/cli.py:130 msgid "Play a file" msgstr "Воспроизвести файл" #: ../quodlibet/cli.py:130 ../quodlibet/cli.py:141 ../quodlibet/cli.py:147 msgctxt "command" msgid "filename" msgstr "имя файла" #: ../quodlibet/cli.py:131 msgid "Rate the playing song" msgstr "Оценить воспроизводимый трек" #: ../quodlibet/cli.py:132 msgid "Set the current browser" msgstr "Режим текущего просмотра" #: ../quodlibet/cli.py:133 msgid "Stop after the playing song" msgstr "Оценить воспроизводимый трек" #: ../quodlibet/cli.py:134 msgid "Open a new browser" msgstr "Открыть новый просмотр" #: ../quodlibet/cli.py:135 msgid "Show or hide the queue" msgstr "Показать/скрыть очередь" #: ../quodlibet/cli.py:137 msgid "Show or hide the main song list (deprecated)" 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:159 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:207 #, python-format msgid "Invalid argument for '%s'." msgstr "Недопустимый аргумент для '%s'." #: ../quodlibet/cli.py:208 ../quodlibet/util/__init__.py:174 #, python-format msgid "Try %s --help." msgstr "Попробуйте '%s --help'." #: ../quodlibet/errorreport/ui.py:59 msgid "An Error Occurred" msgstr "Произошла ошибка" #: ../quodlibet/errorreport/ui.py:61 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:70 ../quodlibet/errorreport/ui.py:86 msgid "Submit Error Report" msgstr "Отправить отчет об ошибке" #: ../quodlibet/errorreport/ui.py:71 msgid "Quit Program" msgstr "Выход из программы:" #: ../quodlibet/errorreport/ui.py:72 msgid "Ignore Error" msgstr "Игнорировать ошибку" #: ../quodlibet/errorreport/ui.py:76 msgid "Error details:" msgstr "Сведения об ошибке:" #: ../quodlibet/errorreport/ui.py:88 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:96 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "" "(не обязательно) Краткое описание ситуации до и во время ошибки:" #: ../quodlibet/errorreport/ui.py:105 msgid "_Send" msgstr "_Отправить" #: ../quodlibet/errorreport/ui.py:111 msgid "Short description…" msgstr "Краткое описание…" #: ../quodlibet/errorreport/ui.py:114 msgid "Data to be sent:" msgstr "Данные для отправки:" #: ../quodlibet/exfalso.py:35 msgid "an audio tag editor" msgstr "в редакторе аудио тегов" #: ../quodlibet/exfalso.py:35 ../quodlibet/util/tags.py:160 msgid "directory" msgstr "папка" #: ../quodlibet/exfalso.py:42 msgid "Audio metadata editor" msgstr "Редактор аудио тегов" #: ../quodlibet/ext/covers/artwork_url.py:20 msgid "Artwork URL Cover Source" msgstr "Загрузка обложек - URL" #: ../quodlibet/ext/covers/artwork_url.py:21 msgid "" "Downloads covers linked to by the artwork_url tag. This works with the " "Soundcloud browser." msgstr "" "Загрузки обложек для тега 'artwork_url'. " "Это работает с обзором Soundcloud." #: ../quodlibet/ext/covers/discogs.py:29 msgid "Discogs Cover Source" msgstr "Загрузка обложек с Discogs" #: ../quodlibet/ext/covers/discogs.py:30 msgid "Downloads covers from Discogs." msgstr "Загружать обложки с Discogs." #: ../quodlibet/ext/covers/lastfm.py:21 msgid "Last.fm Cover Source" msgstr "Загрузка обложек с Last.fm" #: ../quodlibet/ext/covers/lastfm.py:22 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:27 msgid "Convert Encodings" msgstr "Кодировка" #: ../quodlibet/ext/editing/iconv.py:28 msgid "Fixes misinterpreted tag value encodings in the tag editor." msgstr "Исправление ошибочных кодировок значений в тегах, в редакторе тегов." #: ../quodlibet/ext/editing/iconv.py:34 msgid "_Convert Encoding…" msgstr "_Изменить кодировку…" #: ../quodlibet/ext/editing/kakasi.py:27 msgid "Kana/Kanji Simple Inverter" msgstr "Kanji Kana Simple Inverter" #: ../quodlibet/ext/editing/kakasi.py:28 msgid "Converts kana/kanji to romaji before renaming." msgstr "Преобразует кана/кандзи в ромадзи перед переименованием." #: ../quodlibet/ext/editing/kakasi.py:37 msgid "Romanize _Japanese text" msgstr "Латинизировать _японский текст" #: ../quodlibet/ext/editing/kakasi.py:69 msgid "Couldn't find the 'Kanji Kana Simple Inverter' (kakasi)." msgstr "Не удалось найти 'Kanji Kana Simple Inverter' (kakasi)." #: ../quodlibet/ext/editing/resub.py:19 msgid "Regex Substitution" msgstr "Теги - замена по Regex" #: ../quodlibet/ext/editing/resub.py:20 msgid "" "Allows arbitrary regex substitutions (s///) when tagging or renaming files." msgstr "" "Использование регулярных выражений для замены (s///) при получении " "тегов из имени файла или переименовании файла по тегам." #: ../quodlibet/ext/editing/titlecase.py:21 msgid "Title Case" msgstr "Теги - все с заглавных" #: ../quodlibet/ext/editing/titlecase.py:22 msgid "Title-cases tag values in the tag editor." msgstr "" "Все слова с заглавных для английских значений тегов. " "Или вообще для всех значений." #: ../quodlibet/ext/editing/titlecase.py:41 msgid "Title-_case Value" msgstr "'_Все с заглавных'" #: ../quodlibet/ext/editing/titlecase.py:52 msgid "Allow _ALL-CAPS in tags" msgstr "Разрешить _ALL-CAPS в тегах (все заглавными)" #: ../quodlibet/ext/editing/titlecase.py:53 msgid "_Human title case" msgstr "_Соблюдать правила английского языка" #: ../quodlibet/ext/editing/titlecase.py:54 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:69 msgid "Advanced Preferences" msgstr "Расширенные настройки" #: ../quodlibet/ext/events/advanced_preferences.py:70 msgid "Allow editing of advanced config settings." msgstr "Настройка дополнительных параметров." #: ../quodlibet/ext/events/advanced_preferences.py:176 msgid "I know what I'm doing" msgstr "Я знаю, что делаю" #: ../quodlibet/ext/events/animosd/main.py:28 msgid "Animated On-Screen Display" msgstr "Анимация при смене трека" #: ../quodlibet/ext/events/animosd/main.py:29 msgid "Displays song information on your screen when it changes." msgstr "Показывать анимацию при смене трека." #: ../quodlibet/ext/events/animosd/prefs.py:154 msgid "Top of screen" msgstr "Вверху экрана" #: ../quodlibet/ext/events/animosd/prefs.py:155 msgid "Middle of screen" msgstr "Посередине экрана" #: ../quodlibet/ext/events/animosd/prefs.py:156 msgid "Bottom of screen" msgstr "Внизу экрана" #: ../quodlibet/ext/events/animosd/prefs.py:159 msgid "_Position:" msgstr "_Положение:" #: ../quodlibet/ext/events/animosd/prefs.py:172 msgid "_Cover size:" msgstr "Общий размер:" #: ../quodlibet/ext/events/animosd/prefs.py:178 #: ../quodlibet/ext/events/weblyrics.py:318 ../quodlibet/qltk/prefs.py:267 msgid "Display" msgstr "Вид" #: ../quodlibet/ext/events/animosd/prefs.py:191 msgid "_Font:" msgstr "_Шрифт:" #: ../quodlibet/ext/events/animosd/prefs.py:196 msgid "Left" msgstr "По левому краю" #: ../quodlibet/ext/events/animosd/prefs.py:197 msgid "Center" msgstr "По центру" #: ../quodlibet/ext/events/animosd/prefs.py:198 msgid "Right" msgstr "По правому краю" #: ../quodlibet/ext/events/animosd/prefs.py:201 msgid "_Align text:" msgstr "_Выравнивание:" #: ../quodlibet/ext/events/animosd/prefs.py:207 msgid "Text" msgstr "Текст" #: ../quodlibet/ext/events/animosd/prefs.py:218 msgid "_Text:" msgstr "_Текст:" #: ../quodlibet/ext/events/animosd/prefs.py:228 msgid "_Fill:" msgstr "За_ливка:" #: ../quodlibet/ext/events/animosd/prefs.py:233 #: ../quodlibet/ext/events/synchronizedlyrics.py:67 msgid "Colors" msgstr "Цвета" #: ../quodlibet/ext/events/animosd/prefs.py:241 msgid "_Shadows" msgstr "Т_ени" #: ../quodlibet/ext/events/animosd/prefs.py:242 msgid "_Outline" msgstr "_Контуры" #: ../quodlibet/ext/events/animosd/prefs.py:243 msgid "Rou_nded Corners" msgstr "З_акруглённые углы" #: ../quodlibet/ext/events/animosd/prefs.py:259 msgid "_Delay:" msgstr "За_держка:" #: ../quodlibet/ext/events/animosd/prefs.py:265 #: ../quodlibet/qltk/pluginwin.py:173 msgid "Effects" msgstr "Эффекты" #: ../quodlibet/ext/events/animosd/prefs.py:271 msgid "Ed_it Display Pattern…" msgstr "_Изменить шаблон…" #: ../quodlibet/ext/events/animosd/prefs.py:275 #: ../quodlibet/ext/events/trayicon/prefs.py:87 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_library_update.py:137 msgid "Automatic Library Update" msgstr "Автообновление фонотеки" #: ../quodlibet/ext/events/auto_library_update.py:138 #, python-format msgid "Keeps your library up to date with inotify. Requires %s." msgstr "Автоматически обновляет фонотеку с помощью inotify. Требует %s." #: ../quodlibet/ext/events/automask.py:23 msgid "Automatic Masking" msgstr "Автоскрытие дисков" #: ../quodlibet/ext/events/automask.py:24 msgid "" "Automatically masks and unmasks drives when they are unmounted or mounted." msgstr "" "Автоматически показывает и прячет диски при их добавлении или извлечении." #: ../quodlibet/ext/events/autorating.py:16 msgid "Automatic Rating" msgstr "Оценка - авто" #: ../quodlibet/ext/events/autorating.py:17 msgid "" "Rates songs automatically when they are played or skipped. This uses the " "'accelerated' algorithm from vux by Brian Nelson." msgstr "" "Авто-оценка треков в зависимости от того, воспроизведены ли они полностью " "или пропущены. Использует алгоритм vux Брайана Нельсона." #: ../quodlibet/ext/events/clock.py:25 msgid "Alarm Clock" msgstr "Будильник" #: ../quodlibet/ext/events/clock.py:26 msgid "Wakes you up with loud music." msgstr "Включает музыку в заданное время." #: ../quodlibet/ext/events/clock.py:120 msgid "Lullaby" msgstr "Колыбельная" #: ../quodlibet/ext/events/clock.py:121 msgid "Fades out and pauses your music." msgstr "Постепенно убавляет громкость и приостанавливает воспроизведение." #: ../quodlibet/ext/events/equalizer.py:27 msgid "Flat" msgstr "" #: ../quodlibet/ext/events/equalizer.py:28 msgid "Live" msgstr "" #: ../quodlibet/ext/events/equalizer.py:30 msgid "Full Bass & Treble" msgstr "" #: ../quodlibet/ext/events/equalizer.py:33 msgid "Club" msgstr "" #: ../quodlibet/ext/events/equalizer.py:35 msgid "Large Hall" msgstr "" #: ../quodlibet/ext/events/equalizer.py:37 msgid "Party" msgstr "" #: ../quodlibet/ext/events/equalizer.py:41 msgid "Soft" msgstr "" #: ../quodlibet/ext/events/equalizer.py:43 msgid "Full Bass" msgstr "" #: ../quodlibet/ext/events/equalizer.py:49 msgid "Reggae" msgstr "" #: ../quodlibet/ext/events/equalizer.py:51 msgid "Headphones" msgstr "Наушники" #: ../quodlibet/ext/events/equalizer.py:54 msgid "Soft Rock" msgstr "" #: ../quodlibet/ext/events/equalizer.py:56 msgid "Full Treble" msgstr "" #: ../quodlibet/ext/events/equalizer.py:59 msgid "Dance" msgstr "" #: ../quodlibet/ext/events/equalizer.py:63 msgid "Techno" msgstr "" #: ../quodlibet/ext/events/equalizer.py:65 msgid "Ska" msgstr "" #: ../quodlibet/ext/events/equalizer.py:67 msgid "Laptop" msgstr "Ноутбук" #: ../quodlibet/ext/events/equalizer.py:98 msgid "Equalizer" msgstr "Эквалайзер" #: ../quodlibet/ext/events/equalizer.py:99 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:133 msgid "The current backend does not support equalization." msgstr "Текущий аудиовывод не поддерживает коррекцию аудиосигнала." #: ../quodlibet/ext/events/equalizer.py:139 #, python-format msgid "%.1f kHz" msgstr "%.1f кГц" #: ../quodlibet/ext/events/equalizer.py:140 #: ../quodlibet/ext/gstreamer/crossfeed.py:94 #: ../quodlibet/ext/gstreamer/karaoke.py:96 #, python-format msgid "%d Hz" msgstr "%d Гц" #: ../quodlibet/ext/events/equalizer.py:174 #: ../quodlibet/ext/gstreamer/crossfeed.py:113 #, python-format msgid "%.1f dB" msgstr "%.1f дБ" #: ../quodlibet/ext/events/equalizer.py:193 #: ../quodlibet/ext/gstreamer/crossfeed.py:32 msgid "Custom" msgstr "Свое" #: ../quodlibet/ext/events/equalizer.py:200 msgid "_Clear" 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 "Обновляет ваш статус Gaim в соответствии с воспроизводимым треком." #: ../quodlibet/ext/events/gajim_status.py:115 #: ../quodlibet/ext/events/mqtt.py:46 #: ../quodlibet/ext/events/telepathy_status.py:70 msgid "paused" msgstr "пауза" #: ../quodlibet/ext/events/gajim_status.py:146 msgid "Pattern:" msgstr "Пример:" #: ../quodlibet/ext/events/gajim_status.py:155 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:158 msgid "Accounts:" msgstr "Аккаунты:" #: ../quodlibet/ext/events/gajim_status.py:162 msgid "Add '[paused]'" msgstr "Добавлять '[paused]'" #: ../quodlibet/ext/events/gajim_status.py:165 msgid "If checked, '[paused]' will be added to status message on pause" msgstr "Если отмечено, '[paused]' в статус будет добавлено сообщение о паузе" #: ../quodlibet/ext/events/gajim_status.py:189 msgid "Statuses for which message will be changed" msgstr "Статусы, для которых будет изменятся сообщение" #: ../quodlibet/ext/events/headphonemon.py:158 msgid "Pause on Headphone Unplug" msgstr "Пауза при отключении наушников" #: ../quodlibet/ext/events/headphonemon.py:159 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "Пауза при отключении наушников и снятие с нее при их включении." #: ../quodlibet/ext/events/inhibit.py:42 msgid "Inhibit Screensaver" msgstr "Запретить скринсейвер" #: ../quodlibet/ext/events/inhibit.py:43 msgid "Prevents the GNOME screensaver from activating while a song is playing." msgstr "Предотвращает активацию хранителя экрана GNOME при воспроизведении." #: ../quodlibet/ext/events/inhibit.py:52 msgid "Music is playing" 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:31 msgid "JEP-118" msgstr "" #: ../quodlibet/ext/events/jep118.py:32 msgid "Outputs a Jabber User Tunes file to ~/.quodlibet/jabber." msgstr "Выводит файл Jabber User Tunes в ~/.quodlibet/jabber." #: ../quodlibet/ext/events/language.py:22 msgid "Change Language" msgstr "Изменить язык" #: ../quodlibet/ext/events/language.py:23 msgid "Change the user interface language." msgstr "Изменить язык интерфейса." #: ../quodlibet/ext/events/language.py:44 msgid "System Default" msgstr "По умолчанию" #: ../quodlibet/ext/events/language.py:71 msgid "A restart is required for any changes to take effect" msgstr "Для вступления изменений в силу требуется перезапуск" #: ../quodlibet/ext/events/mediaserver.py:38 msgid "UPnP AV Media Server" msgstr "" #: ../quodlibet/ext/events/mediaserver.py:39 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/mpdserver/__init__.py:62 msgid "MPD Server" msgstr "Сервер MPD" #: ../quodlibet/ext/events/mpdserver/__init__.py:63 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:77 msgid "_Port:" msgstr "_Порт:" #: ../quodlibet/ext/events/mpdserver/__init__.py:120 msgid "Local _IP:" msgstr "_Локальный IP:" #: ../quodlibet/ext/events/mpdserver/__init__.py:126 msgid "P_assword:" msgstr "Па_роль:" #: ../quodlibet/ext/events/mpdserver/__init__.py:162 msgid "Connection" msgstr "Соединение" #: ../quodlibet/ext/events/mpdserver/__init__.py:164 msgid "Tested Clients" msgstr "Проверенные клиенты" #: ../quodlibet/ext/events/mpris/__init__.py:39 msgid "MPRIS D-Bus Support" msgstr "" #: ../quodlibet/ext/events/mpris/__init__.py:40 msgid "" "Allows control of Quod Libet using the MPRIS 1.0/2.0 D-Bus Interface " "Specification." msgstr "" "Управление Quod Libet, через MPRIS 1.0/2.0 D-Bus Interface " "Specification." #: ../quodlibet/ext/events/mpris/__init__.py:46 #: ../quodlibet/ext/events/trayicon/prefs.py:37 msgid "Hide main window on close" msgstr "Скрывать главное окно при закрытии" #: ../quodlibet/ext/events/mpris/__init__.py:49 #: ../quodlibet/ext/events/themeswitcher.py:85 #: ../quodlibet/ext/gstreamer/compressor.py:100 #: ../quodlibet/ext/gstreamer/crossfeed.py:137 #: ../quodlibet/ext/gstreamer/karaoke.py:100 #: ../quodlibet/ext/gstreamer/pitch.py:84 ../quodlibet/qltk/prefs.py:699 msgid "Preferences" msgstr "Параметры" #: ../quodlibet/ext/events/mqtt.py:51 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/mqtt.py:57 msgid "MQTT Publisher" msgstr "" #: ../quodlibet/ext/events/mqtt.py:58 msgid "Publishes status messages to an MQTT topic." msgstr "" #: ../quodlibet/ext/events/mqtt.py:123 msgid "Broker hostname" msgstr "" #: ../quodlibet/ext/events/mqtt.py:123 msgid "broker hostname / IP" msgstr "" #: ../quodlibet/ext/events/mqtt.py:125 msgid "Broker port" msgstr "" #: ../quodlibet/ext/events/mqtt.py:125 msgid "broker port" msgstr "" #: ../quodlibet/ext/events/mqtt.py:127 msgid "Topic" msgstr "" #: ../quodlibet/ext/events/mqtt.py:129 msgid "Playing Pattern" msgstr "Шаблоны воспроизведения" #: ../quodlibet/ext/events/mqtt.py:131 msgid "Status text when a song is started." msgstr "Текст статуса при запуске трека." #: ../quodlibet/ext/events/mqtt.py:133 msgid "Paused Pattern" msgstr "Сохранённые шаблоны" #: ../quodlibet/ext/events/mqtt.py:135 msgid "Text when a song is paused." msgstr "Текст при паузе трека." #: ../quodlibet/ext/events/mqtt.py:137 msgid "No-song Text" msgstr "Текст когда нет трека" #: ../quodlibet/ext/events/mqtt.py:139 msgid "Plain text for when there is no current song" msgstr "Обычный текст, когда нет текущего трека" #: ../quodlibet/ext/events/mqtt.py:150 msgid "MQTT Configuration" msgstr "Конфигурация MQTT" #: ../quodlibet/ext/events/mqtt.py:154 msgid "Status Text" msgstr "Текст статуса" #: ../quodlibet/ext/events/mqtt.py:186 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "Подключен к брокеру %(host)s:%(port)d" #: ../quodlibet/ext/events/mqtt.py:190 #, 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:193 msgid "Connection error" msgstr "Ошибка соединения" #: ../quodlibet/ext/events/notify.py:56 msgid "Notification text" msgstr "Текст уведомления" #: ../quodlibet/ext/events/notify.py:67 msgid "_Title:" msgstr "З_аголовок:" #: ../quodlibet/ext/events/notify.py:78 ../quodlibet/ext/events/notify.py:114 msgid "Revert to default pattern" msgstr "Сбросить на шаблон по умолчанию" #: ../quodlibet/ext/events/notify.py:104 msgid "_Body:" msgstr "" #: ../quodlibet/ext/events/notify.py:124 msgid "_Show notification" msgstr "_Показать уведомление" #: ../quodlibet/ext/events/notify.py:142 msgid "Show notifications" msgstr "Показывать уведомления" #: ../quodlibet/ext/events/notify.py:148 msgid "Only on <i>_manual</i> song changes" msgstr "Только при смене трека <i>_вручную</i>" #: ../quodlibet/ext/events/notify.py:156 msgid "Only on <i>_automatic</i> song changes" msgstr "Только при <i>авто_матической</i> смене трека" #: ../quodlibet/ext/events/notify.py:164 msgid "On <i>a_ll</i> song changes" msgstr "При <i>_любой</i> смене трека" #: ../quodlibet/ext/events/notify.py:179 msgid "Only when the main window is not _focused" msgstr "Только когда _фокус не в главном окне" #: ../quodlibet/ext/events/notify.py:187 msgid "Show \"_Next\" button" msgstr "Показать кнопку \"_Следующий\"" #: ../quodlibet/ext/events/notify.py:209 msgid "Connection Error" msgstr "Ошибка соединения" #: ../quodlibet/ext/events/notify.py:210 ../quodlibet/ext/events/notify.py:364 #: ../quodlibet/ext/events/notify.py:406 msgid "Couldn't connect to notification daemon." msgstr "Не удалось подключиться к системе уведомлений." #: ../quodlibet/ext/events/notify.py:224 msgid "Song Notifications" msgstr "Системные уведомления" #: ../quodlibet/ext/events/notify.py:225 msgid "Displays a notification when the song changes." msgstr "Показывать уведомление при смене трека." #: ../quodlibet/ext/events/notify.py:388 ../quodlibet/qltk/unity.py:63 msgid "Next" msgstr "Следующий" #: ../quodlibet/ext/events/qlscrobbler.py:176 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" "Необходимо настроить расширение QLScrobbler в окне расширений. Иначе " "скробблинг треков не будет работать." #: ../quodlibet/ext/events/qlscrobbler.py:253 #, python-format msgid "Could not contact service '%s'." msgstr "Не удалось соединиться с сервисом '%s'." #: ../quodlibet/ext/events/qlscrobbler.py:259 msgid "Authentication failed: invalid URL." msgstr "Авторизация не удалась: неверно указан URL." #: ../quodlibet/ext/events/qlscrobbler.py:276 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "Авторизация не удалась: неверное имя пользователя '%s' или пароль." #: ../quodlibet/ext/events/qlscrobbler.py:281 msgid "Client is banned. Contact the author." msgstr "Клиент заблокирован. Свяжитесь с автором." #: ../quodlibet/ext/events/qlscrobbler.py:285 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" "Неправильное системное время." "Передачи могут завершаться ошибкой, пока не будет исправлено." #: ../quodlibet/ext/events/qlscrobbler.py:350 msgid "AudioScrobbler Submission" msgstr "Скробблинг" #: ../quodlibet/ext/events/qlscrobbler.py:351 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" "Клиент для скробблинга на Last.fm, Libre.fm и других сервисах." #: ../quodlibet/ext/events/qlscrobbler.py:456 msgid "Authentication successful." msgstr "Авторизация прошла успешно." #: ../quodlibet/ext/events/qlscrobbler.py:468 msgid "_Service:" msgstr "_Сервис:" #: ../quodlibet/ext/events/qlscrobbler.py:468 msgid "_URL:" msgstr "_URL:" #: ../quodlibet/ext/events/qlscrobbler.py:468 msgid "User_name:" msgstr "_Имя:" #: ../quodlibet/ext/events/qlscrobbler.py:469 msgid "_Password:" msgstr "_Пароль:" #. Translators: Other service #: ../quodlibet/ext/events/qlscrobbler.py:485 msgid "Other…" msgstr "Другой…" #. verify data #: ../quodlibet/ext/events/qlscrobbler.py:523 msgid "_Verify account data" msgstr "_Проверка учетной записи" #: ../quodlibet/ext/events/qlscrobbler.py:528 #: ../quodlibet/ext/songsmenu/lastfmsync.py:313 msgid "Account" msgstr "Учётная запись" #: ../quodlibet/ext/events/qlscrobbler.py:536 msgid "_Artist pattern:" msgstr "Шаблон _Исполнителя:" #: ../quodlibet/ext/events/qlscrobbler.py:536 msgid "_Title pattern:" msgstr "Шаблон _Имени файла:" #: ../quodlibet/ext/events/qlscrobbler.py:537 msgid "Exclude _filter:" msgstr "И_сключать:" #: ../quodlibet/ext/events/qlscrobbler.py:555 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" "Шаблон форматирования имени исполнителя для отправки. Оставьте пустым для" "значения по умолчанию." #: ../quodlibet/ext/events/qlscrobbler.py:565 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" "Шаблон форматирования заголовка для отправки. Оставьте пустым для" "значения по умолчанию." #: ../quodlibet/ext/events/qlscrobbler.py:574 msgid "Songs matching this filter will not be submitted" msgstr "Треки, соответствующие этому фильтру, не будут отправлены" #: ../quodlibet/ext/events/qlscrobbler.py:582 msgid "_Offline mode (don't submit anything)" msgstr "_Автономный режим (ничего не отправлять)" #: ../quodlibet/ext/events/qlscrobbler.py:586 msgid "Submission" msgstr "Отправка" #: ../quodlibet/ext/events/radioadmute.py:21 msgid "Mute Radio Ads" msgstr "Радио - отключение рекламы" #: ../quodlibet/ext/events/radioadmute.py:22 msgid "" "Mutes output while radio advertisements are playing.\n" "Stations: di.fm." msgstr "" "Выключает звук при воспроизведении рекламы на радио.\n" "Станция: di.fm." #: ../quodlibet/ext/events/randomalbum.py:29 msgid "Random Album Playback" msgstr "Очередность - случайный альбом" #: ../quodlibet/ext/events/randomalbum.py:30 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:40 msgid "Rated higher" msgstr "Выше рейтинг" #: ../quodlibet/ext/events/randomalbum.py:41 msgid "Played more often" msgstr "Чаще воспроизводятся" #: ../quodlibet/ext/events/randomalbum.py:42 msgid "Skipped more often" msgstr "Чаще пропускаются" #: ../quodlibet/ext/events/randomalbum.py:43 msgid "Played more recently" msgstr "Недавно проигрывались" #: ../quodlibet/ext/events/randomalbum.py:44 msgid "Started more recently" msgstr "Недавно запускались" #: ../quodlibet/ext/events/randomalbum.py:45 msgid "Added more recently" msgstr "Недавно добавлены" #: ../quodlibet/ext/events/randomalbum.py:46 msgid "Longer albums" msgstr "Более длинные альбомы" #: ../quodlibet/ext/events/randomalbum.py:85 msgid "seconds before starting next album" msgstr "секунд до начала следующего альбома" #: ../quodlibet/ext/events/randomalbum.py:89 msgid "Weights" msgstr "Вес" #: ../quodlibet/ext/events/randomalbum.py:91 msgid "Play some albums more than others" msgstr "Играть некоторые альбомы чаще, чем другие" #: ../quodlibet/ext/events/randomalbum.py:105 msgid "avoid" msgstr "избегать" #: ../quodlibet/ext/events/randomalbum.py:116 msgid "prefer" msgstr "предпочитать" #: ../quodlibet/ext/events/randomalbum.py:209 msgid "Random Album" msgstr "Случайный альбом" #: ../quodlibet/ext/events/randomalbum.py:210 #, python-format msgid "Waiting to start %s" msgstr "Ожидание до начала %s" #: ../quodlibet/ext/events/rbimport.py:115 msgid "Import Failed" msgstr "Ошибка импорта" #: ../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/rbimport.py:133 msgid "Start Import" 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 "Приостанавливает воспроизведение, когда хранитель экрана GNOME активен." #: ../quodlibet/ext/events/searchprovider.py:74 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "" #: ../quodlibet/ext/events/searchprovider.py:80 msgid "GNOME Search Provider" msgstr "" #: ../quodlibet/ext/events/searchprovider.py:81 msgid "Allows GNOME Shell to search the library." msgstr "Позволяет GNOME Shell искать по фонотеке." #: ../quodlibet/ext/events/seekbar.py:123 msgid "Alternative Seek Bar" msgstr "Панель перемотки" #: ../quodlibet/ext/events/seekbar.py:124 msgid "" "Alternative seek bar which is always visible and spans the whole window " "width." msgstr "" "Альтернативная панель перемотки, всегда видна и охватывает всю ширину окна." #: ../quodlibet/ext/events/seekpoints.py:21 msgid "Seekpoint Bookmarks" msgstr "Закладки перемотки" #: ../quodlibet/ext/events/seekpoints.py:25 msgid "" "Store Seekpoints A and/or B for tracks. Skip to time A and stop after time B " "when track is played.\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:109 msgid "Bookmark name for point A" msgstr "Имя закладки для точки А" #: ../quodlibet/ext/events/seekpoints.py:110 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:125 msgid "Bookmark name for point B" msgstr "Имя закладки для точки B" #: ../quodlibet/ext/events/seekpoints.py:126 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:29 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:58 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "Ошибка поиска сервера Squeezebox" #: ../quodlibet/ext/events/squeezebox_sync.py:59 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "Ошибка поиска %s. Проверьте настройки" #: ../quodlibet/ext/events/synchronizedlyrics.py:35 msgid "Synchronized Lyrics" msgstr "Текст песни - синхронно" #: ../quodlibet/ext/events/synchronizedlyrics.py:36 msgid "Shows synchronized lyrics from .lrc file with same name as the track." msgstr "" "Синхронно показывает текст из файла .lrc, с тем же именем, что и трек." #: ../quodlibet/ext/events/synchronizedlyrics.py:70 msgid "Text:" msgstr "Текст:" #: ../quodlibet/ext/events/synchronizedlyrics.py:80 msgid "Background:" msgstr "Фон:" #: ../quodlibet/ext/events/synchronizedlyrics.py:91 msgid "Font" msgstr "Шрифт:" #: ../quodlibet/ext/events/synchronizedlyrics.py:94 msgid "Size (px):" msgstr "Размер (пикс):" #: ../quodlibet/ext/events/telepathy_status.py:63 msgid "Telepathy Status Messages" msgstr "Статус Telepathy" #: ../quodlibet/ext/events/telepathy_status.py:64 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:123 msgid "Playing:" msgstr "Воспроизведение:" #: ../quodlibet/ext/events/telepathy_status.py:124 #, 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:140 msgid "Paused:" msgstr "Пауза:" #: ../quodlibet/ext/events/telepathy_status.py:141 #, 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:157 msgid "Plain text for status when there is no current song" msgstr "Обычный текст статуса, когда нет текущего трека" #: ../quodlibet/ext/events/telepathy_status.py:158 msgid "No song:" msgstr "Нет трека:" #. Frame #: ../quodlibet/ext/events/telepathy_status.py:165 msgid "Status Patterns" msgstr "Шаблоны состояний" #: ../quodlibet/ext/events/themeswitcher.py:26 msgid "Theme Switcher" msgstr "Тема оформления" #: ../quodlibet/ext/events/themeswitcher.py:27 msgid "Changes the active GTK+ theme." msgstr "Смена используемой темы GTK+." #: ../quodlibet/ext/events/themeswitcher.py:50 msgid "_Theme:" msgstr "_Тема:" #: ../quodlibet/ext/events/themeswitcher.py:55 msgid "Default Theme" msgstr "Тема по умолчанию" #: ../quodlibet/ext/events/themeswitcher.py:67 msgid "Prefer dark theme version" msgstr "Предпочитать тёмную версию темы" #: ../quodlibet/ext/events/toggle_menu.py:19 msgid "Toggle Menu Bar" msgstr "Панель меню - переключение" #: ../quodlibet/ext/events/toggle_menu.py:20 msgid "Toggle the menu bar by pressing the Alt key." msgstr "Переключение отображения строки меню клавишей Alt." #: ../quodlibet/ext/events/trayicon/appindicator.py:78 #: ../quodlibet/ext/events/trayicon/prefs.py:107 #: ../quodlibet/ext/events/trayicon/systemtray.py:178 #: ../quodlibet/qltk/info.py:48 msgid "Not playing" msgstr "Не воспроизводится" #: ../quodlibet/ext/events/trayicon/__init__.py:54 msgid "Tray Icon" msgstr "Значок в трее" #: ../quodlibet/ext/events/trayicon/__init__.py:55 msgid "Controls Quod Libet from the system tray." msgstr "Управление Quod Libet из трея." #: ../quodlibet/ext/events/trayicon/menu.py:42 #, python-format msgid "_Show %(application-name)s" msgstr "_Показать %(application-name)s" #: ../quodlibet/ext/events/trayicon/menu.py:61 #: ../quodlibet/qltk/quodlibetwindow.py:185 #: ../quodlibet/qltk/quodlibetwindow.py:1083 #: ../quodlibet/qltk/quodlibetwindow.py:1275 msgid "_Play" msgstr "_Воспроизвести" #: ../quodlibet/ext/events/trayicon/menu.py:64 #: ../quodlibet/qltk/quodlibetwindow.py:187 #: ../quodlibet/qltk/quodlibetwindow.py:1277 ../quodlibet/qltk/wlw.py:52 msgid "P_ause" msgstr "_Пауза" #: ../quodlibet/ext/events/trayicon/menu.py:69 #: ../quodlibet/qltk/quodlibetwindow.py:192 #: ../quodlibet/qltk/quodlibetwindow.py:1078 msgid "Pre_vious" msgstr "Предыдущий" #: ../quodlibet/ext/events/trayicon/menu.py:72 #: ../quodlibet/qltk/quodlibetwindow.py:196 #: ../quodlibet/qltk/quodlibetwindow.py:1088 msgid "_Next" msgstr "_Следующий" #: ../quodlibet/ext/events/trayicon/menu.py:77 msgid "_Shuffle" msgstr "_Случайно" #: ../quodlibet/ext/events/trayicon/menu.py:82 msgid "_Repeat" msgstr "_Повторять" #: ../quodlibet/ext/events/trayicon/menu.py:87 msgid "Stop _After This Song" msgstr "Стоп после _трека" #: ../quodlibet/ext/events/trayicon/menu.py:93 #: ../quodlibet/qltk/quodlibetwindow.py:1049 msgid "Open _Browser" msgstr "В новом о_кне" #: ../quodlibet/ext/events/trayicon/menu.py:104 #: ../quodlibet/qltk/quodlibetwindow.py:1068 ../quodlibet/qltk/songsmenu.py:385 msgid "Edit _Tags" msgstr "Изменить _теги" #: ../quodlibet/ext/events/trayicon/menu.py:113 #: ../quodlibet/qltk/quodlibetwindow.py:1012 ../quodlibet/qltk/songsmenu.py:398 msgid "_Information" msgstr "_Информация" #: ../quodlibet/ext/events/trayicon/menu.py:115 #: ../quodlibet/qltk/songsmenu.py:326 msgid "Play_lists" msgstr "Плейли_сты" #: ../quodlibet/ext/events/trayicon/menu.py:133 #: ../quodlibet/qltk/quodlibetwindow.py:1063 msgid "_Quit" msgstr "_Выход" #: ../quodlibet/ext/events/trayicon/prefs.py:39 ../quodlibet/qltk/prefs.py:70 msgid "Behavior" msgstr "Поведение" #: ../quodlibet/ext/events/trayicon/prefs.py:49 msgid "Scroll wheel adjusts volume" msgstr "Прокрутка меняет громкость" #: ../quodlibet/ext/events/trayicon/prefs.py:55 msgid "Scroll wheel changes song" msgstr "Прокрутка меняет трек" #: ../quodlibet/ext/events/trayicon/prefs.py:63 msgid "Scroll _Wheel" msgstr "_Колесо мыши" #: ../quodlibet/ext/events/trayicon/prefs.py:93 msgid "Tooltip Display" msgstr "Показывать подсказки" #: ../quodlibet/ext/events/viewlyrics.py:26 msgid "View Lyrics" msgstr "Текст песни" #: ../quodlibet/ext/events/viewlyrics.py:27 msgid "Automatically displays tag or file-based lyrics in a sidebar." msgstr "Отображение тегов или файлов лирики в боковой панели." #: ../quodlibet/ext/events/viewlyrics.py:88 #, python-format msgid "" "No lyrics found for\n" " %s" msgstr "" "Текст трека не найден\n" " %s" #: ../quodlibet/ext/events/viewlyrics.py:118 #: ../quodlibet/ext/events/weblyrics.py:193 msgid "No active song" msgstr "Нет активного трека" #: ../quodlibet/ext/events/visualisations.py:37 msgid "Launch Visualisations" msgstr "Визуализации" #: ../quodlibet/ext/events/visualisations.py:39 msgid "Launch external visualisations." msgstr "Запуск внешних визуализаций." #: ../quodlibet/ext/events/visualisations.py:56 #, python-format msgid "Couldn't run visualisations using '%s'" msgstr "Не удалось запустить визуализацию, используя '%s'" #: ../quodlibet/ext/events/visualisations.py:58 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:45 msgid "Error" msgstr "Ошибка" #: ../quodlibet/ext/events/visualisations.py:77 msgid "Visualiser executable:" msgstr "Исполняемый файл визуализатора:" #: ../quodlibet/ext/events/visualisations.py:92 msgid "Reload" msgstr "Обновить" #: ../quodlibet/ext/events/waveformseekbar.py:567 msgid "Waveform Seek Bar" msgstr "Панель перемотки Waveform " #: ../quodlibet/ext/events/waveformseekbar.py:571 msgid "A seekbar in the shape of the waveform of the current song." msgstr "Панель перемотки в форме волны текущего трека." #: ../quodlibet/ext/events/waveformseekbar.py:628 msgid "Override foreground color:" msgstr "Цвет пройденного :" #: ../quodlibet/ext/events/waveformseekbar.py:632 msgid "Override hover color:" msgstr "Цвет наведения:" #: ../quodlibet/ext/events/waveformseekbar.py:636 msgid "Override remaining color:" msgstr "Цвет оставшегося:" #: ../quodlibet/ext/events/waveformseekbar.py:640 msgid "Show current position" msgstr "Показать текущую позицию" #: ../quodlibet/ext/events/weblyrics.py:208 msgid "No lyrics found" msgstr "Текст песни не найден" #: ../quodlibet/ext/events/weblyrics.py:268 msgid "_Zoom level:" msgstr "_Масштаб:" #: ../quodlibet/ext/events/weblyrics.py:286 msgid "URL:" msgstr "URL:" #: ../quodlibet/ext/events/weblyrics.py:291 msgid "Revert to default" msgstr "Вернуться к умолчанию" #: ../quodlibet/ext/events/weblyrics.py:306 msgid "Search via above URL if the lyrics couldn't be found in LyricsWikia." msgstr "Поиск по URL выше, если текст не может быть найден в LyricsWikia." #: ../quodlibet/ext/events/weblyrics.py:323 msgid "Alternate search" msgstr "Альтернативный поиск" #: ../quodlibet/ext/events/weblyrics.py:332 msgid "Web Lyrics" msgstr "Тексты песен из сети" #: ../quodlibet/ext/events/weblyrics.py:333 msgid "Shows a sidebar containing online lyrics of the playing song." msgstr "Боковая панель, содержащая тексты песни из интернета." #: ../quodlibet/ext/events/write_cover.py:34 msgid "Picture Saver" msgstr "Импорт обложки" #: ../quodlibet/ext/events/write_cover.py:35 msgid "Saves the cover image of the current song to a file." msgstr "Сохраняет обложку текущего трека в файл." #: ../quodlibet/ext/events/write_cover.py:68 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 #, 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 "" #: ../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 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:17 msgid "Mono Downmix" msgstr "" #: ../quodlibet/ext/gstreamer/mono.py:18 msgid "Downmixes audio channels to mono." msgstr "Микширует аудио каналы в моно." #: ../quodlibet/ext/gstreamer/pitch.py:21 msgid "R_ate:" msgstr "_Коэффициент:" #: ../quodlibet/ext/gstreamer/pitch.py:22 msgid "_Tempo:" msgstr "_Темп:" #: ../quodlibet/ext/gstreamer/pitch.py:23 msgid "_Pitch:" msgstr "_Высота:" #: ../quodlibet/ext/gstreamer/pitch.py:90 msgid "Audio Pitch / Speed" msgstr "Audio Pitch / Speed" #: ../quodlibet/ext/gstreamer/pitch.py:91 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:139 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:100 msgid "Exports a playlist by copying files to a folder." msgstr "Экспорт плейлиста путем копирования файлов в папку." #: ../quodlibet/ext/playlist/export_to_folder.py:157 msgid "Default filename pattern:" msgstr "_Шаблон имени файла:" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:23 msgid "Export to Squeezebox" msgstr "Экспорт на Squeezebox" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:25 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 "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Export playlist to Squeezebox" msgstr "Экспорт плейлиста в Squeezebox" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:80 msgid "Playlist name (will overwrite existing)" msgstr "Имя плейлиста (перезапишет существующий)" #. Save button #: ../quodlibet/ext/playlist/export_to_squeezebox.py:81 #: ../quodlibet/ext/songsmenu/albumart.py:324 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:357 #: ../quodlibet/ext/songsmenu/cover_download.py:309 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:279 #: ../quodlibet/ext/songsmenu/html.py:77 #: ../quodlibet/ext/songsmenu/lastfmsync.py:220 #: ../quodlibet/ext/songsmenu/playlist.py:52 #: ../quodlibet/ext/songsmenu/replaygain.py:356 #: ../quodlibet/ext/songsmenu/tapbpm.py:188 ../quodlibet/qltk/_editutils.py:41 #: ../quodlibet/qltk/lyrics.py:35 ../quodlibet/qltk/msg.py:53 #: ../quodlibet/qltk/renamefiles.py:218 ../quodlibet/qltk/tagsfrompath.py:154 #: ../quodlibet/qltk/tracknumbers.py:114 msgid "_Save" msgstr "_Сохранить" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:97 msgid "Export to Squeezebox playlist" msgstr "Экспорт в Squeezebox плейлист" #: ../quodlibet/ext/playlist/remove_duplicates.py:21 msgid "Remove Playlist Duplicates" msgstr "Удалять дубликаты из плейлиста" #: ../quodlibet/ext/playlist/remove_duplicates.py:22 msgid "Removes duplicate entries in a playlist." msgstr "Удалять дубликаты записей из плейлиста." #: ../quodlibet/ext/playlist/remove_duplicates.py:50 #, 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:53 #, python-format msgid "The duplicate songs will be removed from the playlist '%s'." msgstr "Из плейлиста '%s' будут удалены все дубли треков." #: ../quodlibet/ext/playlist/shuffle.py:16 msgid "Shuffle Playlist" msgstr "Тасовать плейлист" #: ../quodlibet/ext/playlist/shuffle.py:17 msgid "Randomly shuffles a playlist." msgstr "Переставляет треки в плейлисте в случайном порядке." #: ../quodlibet/ext/playorder/follow.py:19 msgid "Follow Cursor" msgstr "Очередность - выбор" #: ../quodlibet/ext/playorder/follow.py:21 msgid "" "Playback follows your selection, or the next song in the list once exhausted." msgstr "Воспроизведение выбранных или, если нет выбора, следующего трека." #: ../quodlibet/ext/playorder/playcounteq.py:23 msgid "Playcount Equalizer" msgstr "Тасовать - меньше прослушиваний" #: ../quodlibet/ext/playorder/playcounteq.py:24 msgid "Shuffle, preferring songs with fewer total plays." msgstr "" "Перемешать, предпочитая треки с меньшим колличеством прослушиваний." #: ../quodlibet/ext/playorder/playcounteq.py:26 msgid "Prefer less played" msgstr "Меньше воспроизведений" #: ../quodlibet/ext/playorder/queue.py:20 msgid "Queue Only" msgstr "Очередь - добавлять" #: ../quodlibet/ext/playorder/queue.py:22 msgid "" "Limits playing of songs to the queue. Select this play order in the main " "window, then double-clicking any song will enqueue it instead of playing." msgstr "" "Воспроизведены будут только треки в очереди. Выберите этот порядок " "воспроизведения в главном окне. Двойной щелчек будет ставить трек " "в очередь, а не запускать его воспроизведение." #: ../quodlibet/ext/playorder/reverse.py:15 msgid "Reverse" msgstr "Очередность - реверс" #: ../quodlibet/ext/playorder/reverse.py:17 msgid "Reverses the play order of songs." msgstr "Воспроизвести треки в обратном порядке." #: ../quodlibet/ext/playorder/shufflebygrouping.py:32 #: ../quodlibet/ext/playorder/shufflebygrouping.py:94 msgid "Shuffle by Grouping" msgstr "Тасовать по группе" #: ../quodlibet/ext/playorder/shufflebygrouping.py:33 msgid "" "Shuffles by a grouping of songs defined by a common tag instead of by track, " "similar to album shuffle. This is useful for shuffling multi-movement " "classical works while 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:95 msgid "Waiting to start new group…" msgstr "Ожидание запуска новой группы…" #: ../quodlibet/ext/playorder/shufflebygrouping.py:145 msgid "Grouping tag:" msgstr "Тег группы:" #: ../quodlibet/ext/playorder/shufflebygrouping.py:149 msgid "Tag to group songs by" msgstr "Тег для группировки треков" #: ../quodlibet/ext/playorder/shufflebygrouping.py:151 msgid "Filter tag:" msgstr "Тег фильтра:" #: ../quodlibet/ext/playorder/shufflebygrouping.py:156 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:161 msgid "Delay:" msgstr "Задержка:" #: ../quodlibet/ext/playorder/shufflebygrouping.py:167 msgid "Time delay in seconds before starting next group" msgstr "Задержка в секундах перед началом следующей группы" #: ../quodlibet/ext/playorder/shufflebygrouping.py:183 msgid "Reset to defaults" msgstr "Сброс к значениям по умолчанию" #: ../quodlibet/ext/playorder/skip_songs.py:26 msgid "Skip Songs" msgstr "Очередность - пропуск треков" #: ../quodlibet/ext/playorder/skip_songs.py:28 msgid "" "Playback skips over songs with a rating equal or below a given threshold." msgstr "" "Воспроизведение пропускает песни с рейтингом, равным или ниже " "заданного порога." #: ../quodlibet/ext/playorder/track_repeat.py:31 msgid "Repeat Each Track" msgstr "Тасовать, но повторить N раз" #: ../quodlibet/ext/playorder/track_repeat.py:33 msgid "Shuffle songs, but repeat every track a set number of times." msgstr "" "Воспроизвести треки в случайном порядке, но повторить каждый " "заданное количество раз." #: ../quodlibet/ext/playorder/track_repeat.py:52 msgid "Number of times to play each song:" msgstr "Сколько раз воспроизводить каждый трек:" #: ../quodlibet/ext/query/conditional.py:16 msgid "Conditional Query" msgstr "Поиск - условный запрос" #: ../quodlibet/ext/query/conditional.py:17 msgid "" "Chooses the query to match based on a condition query. Syntax is '@(if: " "condition, then, else)'." msgstr "" "Позволяет запросу получать результаты на основе условия поиска. " "Синтаксис: '@(if: condition, then, else)'." #: ../quodlibet/ext/query/pythonexpression.py:19 msgid "Python Query" msgstr "Python запросы" #: ../quodlibet/ext/query/pythonexpression.py:20 msgid "" "Use Python expressions in queries. Syntax is '@(python: expression)'. The " "variable 's' (or 'a') is the song / album being matched. '_ts' is a (real " "number) timestamp at start of query. Modules 'time' and 'random' are also " "available, and the class 'Random' (==random.Random) too." msgstr "" "Используйте выражения Python в запросах. Синтаксис '@(python: expression)'. " "Переменная 's' (или 'a') это трек / совпадающий альбом. '_ts' это (real " "number) временная метка в начале запроса. Модули 'time' и 'random' , также " "доступны, и класс 'Random' (==random.Random) тоже." #: ../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. Syntax is " "'@(saved: search name)'." msgstr "" "Включайте сохраненные запросы поиска в другие запросы. " "Синтаксис '@(saved: search name)'." #: ../quodlibet/ext/_shared/squeezebox/base.py:78 #, python-format msgid "Squeezebox OK. Using the only player (%s)." msgstr "Squeezebox ОК. Используя только плеер (%s)." #: ../quodlibet/ext/_shared/squeezebox/base.py:87 #, python-format msgid "Couldn't connect to %s" msgstr "Не удалось подключиться к %s" #: ../quodlibet/ext/_shared/squeezebox/base.py:111 msgid "Hostname:" msgstr "Имя машины:" #: ../quodlibet/ext/_shared/squeezebox/base.py:117 msgid "Port:" msgstr "Порт:" #: ../quodlibet/ext/_shared/squeezebox/base.py:122 msgid "Username:" msgstr "Имя пользователя:" #: ../quodlibet/ext/_shared/squeezebox/base.py:127 msgid "Password:" msgstr "Пароль:" #: ../quodlibet/ext/_shared/squeezebox/base.py:131 msgid "Library directory the server connects to" msgstr "Каталог фонотеки, к которому подключается сервер" #: ../quodlibet/ext/_shared/squeezebox/base.py:133 msgid "Library path:" msgstr "Путь к фонотеке:" #. Add verify button #: ../quodlibet/ext/_shared/squeezebox/base.py:142 msgid "_Verify settings" msgstr "_Проверка настроек" #. Server settings Frame #: ../quodlibet/ext/_shared/squeezebox/base.py:148 msgid "Squeezebox Server" msgstr "Squeezebox сервер" #: ../quodlibet/ext/_shared/squeezebox/base.py:151 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:16 msgid "Choose Squeezebox player" msgstr "Выберите Squeezebox плеер" #: ../quodlibet/ext/_shared/squeezebox/util.py:21 #: ../quodlibet/ext/songsmenu/importexport.py:39 #: ../quodlibet/qltk/getstring.py:22 msgid "_OK" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/util.py:27 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" "Найден сервер Squeezebox.\n" "Выберите плеер" #: ../quodlibet/ext/songsmenu/albumart.py:331 msgid "Fit image to _window" msgstr "_Масштаб по размеру окна" #: ../quodlibet/ext/songsmenu/albumart.py:337 msgid "See '[plugins] cover_filenames' config entry for image filename strings" msgstr "" "Смотрите конфигурационную запись '[plugins] cover_filenames' " "для имени файла изображения" #. Both labels #: ../quodlibet/ext/songsmenu/albumart.py:343 msgid "_Program:" msgstr "_Программа:" #: ../quodlibet/ext/songsmenu/albumart.py:348 msgid "_Edit image after saving" msgstr "Из_менить изображение после сохранения" #: ../quodlibet/ext/songsmenu/albumart.py:350 msgid "File_name:" msgstr "_Имя файла:" #: ../quodlibet/ext/songsmenu/albumart.py:466 msgid "Saving failed" msgstr "Не удалось сохранить" #: ../quodlibet/ext/songsmenu/albumart.py:467 #, python-format msgid "Unable to save \"%s\"." msgstr "Не удалось сохранить '%s'." #: ../quodlibet/ext/songsmenu/albumart.py:565 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "[albumart] Ошибка HTTP: %s" #: ../quodlibet/ext/songsmenu/albumart.py:622 msgid "Album Art Downloader" msgstr "Загрузка обложек альбомов" #: ../quodlibet/ext/songsmenu/albumart.py:675 #, python-format msgid "from %(source)s" msgstr "с %(source)s" #: ../quodlibet/ext/songsmenu/albumart.py:678 #, python-format msgid "Resolution: %s" msgstr "Разрешение: %s" #: ../quodlibet/ext/songsmenu/albumart.py:681 #, python-format msgid "Size: %s" msgstr "Размер: %s" #: ../quodlibet/ext/songsmenu/albumart.py:727 msgid "Per engine 'at best' results limit" msgstr "Лимит для каждого поиска" #: ../quodlibet/ext/songsmenu/albumart.py:737 msgid "_Search" msgstr "_Найти" #: ../quodlibet/ext/songsmenu/albumart.py:819 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:453 msgid "Searching…" msgstr "Поиск…" #: ../quodlibet/ext/songsmenu/albumart.py:884 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:43 msgid "Done" msgstr "Готово" #: ../quodlibet/ext/songsmenu/albumart.py:1006 msgid "Download Album Art" msgstr "Загрузить обложку альбома" #: ../quodlibet/ext/songsmenu/albumart.py:1007 msgid "Downloads album covers from various websites." msgstr "Загрузка обложек альбомов с различных веб-сайтов." #: ../quodlibet/ext/songsmenu/albumart.py:1020 msgid "Sources" msgstr "Источники" #: ../quodlibet/ext/songsmenu/ape2id3.py:27 msgid "APEv2 to ID3v2" msgstr "APEv2 в ID3v2" #: ../quodlibet/ext/songsmenu/ape2id3.py:28 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:24 msgid "Go to Bookmark" msgstr "Закладки - переход" #: ../quodlibet/ext/songsmenu/bookmarks.py:25 msgid "Manages bookmarks in the selected files." msgstr "Переход к любой закладке в выделенных файлах." #: ../quodlibet/ext/songsmenu/bookmarks.py:64 #: ../quodlibet/qltk/seekbutton.py:245 msgid "_Edit Bookmarks…" msgstr "_Изменить закладки…" #: ../quodlibet/ext/songsmenu/bookmarks.py:74 msgid "No Bookmarks" msgstr "Нет закладок" #: ../quodlibet/ext/songsmenu/brainz/__init__.py:25 msgid "MusicBrainz Lookup" msgstr "Поиск на MusicBrainz" #: ../quodlibet/ext/songsmenu/brainz/__init__.py:27 msgid "Re-tags an album based on a MusicBrainz search." msgstr "Поиск альбома на MusicBrainz и запись найденных тегов." #: ../quodlibet/ext/songsmenu/brainz/__init__.py:51 msgid "Only use year for \"date\" tag" msgstr "" #: ../quodlibet/ext/songsmenu/brainz/__init__.py:52 msgid "Write \"_albumartist\" when needed" msgstr "" #: ../quodlibet/ext/songsmenu/brainz/__init__.py:53 msgid "Write sort tags for artist names" msgstr "" #: ../quodlibet/ext/songsmenu/brainz/__init__.py:54 msgid "Write _standard MusicBrainz tags" msgstr "Записывать _стандартные теги MusicBrainz" #: ../quodlibet/ext/songsmenu/brainz/__init__.py:55 msgid "Write \"labelid\" tag" msgstr "Записывать \"labelid\" тег" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:131 msgid "Filename" msgstr "Имя файла" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:132 msgid "Disc" msgstr "Диск" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:133 #: ../quodlibet/ext/songsmenu/replaygain.py:395 #: ../quodlibet/qltk/tracknumbers.py:93 msgid "Track" msgstr "Трек" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:134 msgid "Title" msgstr "Название" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:135 msgid "Artist" msgstr "Исполнитель" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:354 msgid "MusicBrainz lookup" msgstr "Поиск на MusicBrainz" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:377 msgid "_Query:" msgstr "_Запрос:" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:380 msgid "S_earch" msgstr "_Найти" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:393 msgid "Results <i>(drag to reorder)</i>" msgstr "Результаты <i>(порядок можно изменить перетаскиванием)</i>" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:449 msgid "Please enter a query." msgstr "Введите запрос." #: ../quodlibet/ext/songsmenu/brainz/widgets.py:467 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:498 msgid "Error encountered. Please retry." msgstr "Обнаружена ошибка. Повторите попытку." #: ../quodlibet/ext/songsmenu/brainz/widgets.py:474 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:490 msgid "Loading result…" msgstr "Загрузка результата…" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:477 msgid "No results found." msgstr "Ничего не найдено." #: ../quodlibet/ext/songsmenu/console.py:42 msgid "Python Console" msgstr "Python консоль" #: ../quodlibet/ext/songsmenu/console.py:43 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 Console, которая следует за выбранными песнями " "в главном окне." #: ../quodlibet/ext/songsmenu/console.py:77 msgid "You can access the following objects by default:" msgstr "По умолчанию доступны следующие объекты:" #: ../quodlibet/ext/songsmenu/console.py:87 msgid "Your current working directory is:" msgstr "Текущий рабочий каталог:" #: ../quodlibet/ext/songsmenu/cover_download.py:119 msgid "Small" msgstr "Маленький" #: ../quodlibet/ext/songsmenu/cover_download.py:120 msgid "Classic" msgstr "Обычный" #: ../quodlibet/ext/songsmenu/cover_download.py:121 msgid "Large" msgstr "Большой" #: ../quodlibet/ext/songsmenu/cover_download.py:122 msgid "HD" msgstr "HD" #: ../quodlibet/ext/songsmenu/cover_download.py:123 msgid "Full HD" msgstr "Full HD" #: ../quodlibet/ext/songsmenu/cover_download.py:124 msgid "WQXGA" msgstr "WQXGA" #: ../quodlibet/ext/songsmenu/cover_download.py:125 msgid "4K UHD" msgstr "4K UHD" #: ../quodlibet/ext/songsmenu/cover_download.py:130 msgid "Cover Art Download" msgstr "Загрузка обложек" #: ../quodlibet/ext/songsmenu/cover_download.py:180 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "Загрузка %(source)s – %(dimensions)s…" #: ../quodlibet/ext/songsmenu/cover_download.py:231 #, python-format msgid "" "Nothing found for albums:\n" "<i>%(albums)s</i>.\n" "\n" "Providers used:\n" "<tt>%(providers)s</tt>" msgstr "" "Нет результатов для следующих альбомов:\n" "<i>%(albums)s</i>.\n" "\n" "Используемые поставщики:\n" "<tt>%(providers)s</tt>" #: ../quodlibet/ext/songsmenu/cover_download.py:234 msgid "No covers found" msgstr "Обложки не найдены" #: ../quodlibet/ext/songsmenu/cover_download.py:254 #, python-format msgid "%(size)d ✕ %(size)d px" msgstr "%(size)d ✕ %(size)d пикс" #: ../quodlibet/ext/songsmenu/cover_download.py:267 msgid "Preview size" msgstr "Размер предпросмотра" #: ../quodlibet/ext/songsmenu/cover_download.py:276 msgid "Save destination" msgstr "Сохранить расположение" #: ../quodlibet/ext/songsmenu/cover_download.py:336 msgid "Download Cover Art" msgstr "Загрузить обложку альбома HD" #: ../quodlibet/ext/songsmenu/cover_download.py:337 msgid "Downloads high-quality album covers using cover plugins." msgstr "Загружает высококачественные обложки альбомов с помощью плагинов." #: ../quodlibet/ext/songsmenu/custom_commands.py:42 msgid "Command" msgstr "Команда" #: ../quodlibet/ext/songsmenu/custom_commands.py:45 msgid "name" msgstr "название" #: ../quodlibet/ext/songsmenu/custom_commands.py:45 msgid "The name of this command" msgstr "Название этой команды" #: ../quodlibet/ext/songsmenu/custom_commands.py:47 msgid "command" msgstr "команда" #: ../quodlibet/ext/songsmenu/custom_commands.py:47 msgid "The shell command syntax to run" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:49 msgid "parameter" msgstr "параметр" #: ../quodlibet/ext/songsmenu/custom_commands.py:50 #, 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 "pattern" msgstr "шаблон" #: ../quodlibet/ext/songsmenu/custom_commands.py:57 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:62 msgid "unique" msgstr "уникальный" #: ../quodlibet/ext/songsmenu/custom_commands.py:63 msgid "If set, this will remove duplicate computed values of the pattern" msgstr "Если установлено, то удалит дубли вычисленных значений шаблона" #: ../quodlibet/ext/songsmenu/custom_commands.py:66 msgid "max args" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:67 msgid "" "The maximum number of argument to pass to the command at one time (like " "xargs)" msgstr "" "Наибольшее количество аргументов, которое будет передано приложению за один " "раз (аналогично xargs)" #: ../quodlibet/ext/songsmenu/custom_commands.py:92 msgid "Input value" msgstr "Введите значение" #: ../quodlibet/ext/songsmenu/custom_commands.py:93 #, python-format msgid "Value for %s?" msgstr "Значение %s?" #: ../quodlibet/ext/songsmenu/custom_commands.py:137 msgid "Custom Commands" msgstr "Пользовательские команды" #: ../quodlibet/ext/songsmenu/custom_commands.py:138 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" "Выполнение пользовательских команд над треками (в пакетном " "режиме, если требуется), используя любые теги в качестве аргументов." #: ../quodlibet/ext/songsmenu/custom_commands.py:191 #: ../quodlibet/ext/songsmenu/custom_commands.py:201 #: ../quodlibet/ext/songsmenu/custom_commands.py:255 msgid "Edit Custom Commands" msgstr "Изменить команды" #: ../quodlibet/ext/songsmenu/custom_commands.py:202 msgid "" "Supports QL patterns\n" "eg <tt><~artist~title></tt>" msgstr "" "Поддерживает QL шаблоны,\n" "например, <tt><~artist~title></tt>" #: ../quodlibet/ext/songsmenu/custom_commands.py:286 #, python-format msgid "Unable to run custom command %s" msgstr "Не удалось выполнить пользовательскую команду %s" #: ../quodlibet/ext/songsmenu/duplicates.py:289 #, 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:342 msgid "Collapse / Expand all" msgstr "Свернуть/развернуть всё" #: ../quodlibet/ext/songsmenu/duplicates.py:346 #, python-format msgid "Duplicate key expression is '%s'" msgstr "Выражение для поиска дублей: '%s'" #: ../quodlibet/ext/songsmenu/duplicates.py:371 msgid "Duplicates Browser" msgstr "Поиск дублей" #: ../quodlibet/ext/songsmenu/duplicates.py:372 msgid "Finds and displays similarly tagged versions of songs." msgstr "Поиск и просмотр треков с похожими тегами." #: ../quodlibet/ext/songsmenu/duplicates.py:410 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:412 msgid "_Group duplicates by:" msgstr "_Группировать повторы по:" #: ../quodlibet/ext/songsmenu/duplicates.py:417 msgid "Duplicate Key" msgstr "Выражение для поиска" #: ../quodlibet/ext/songsmenu/duplicates.py:422 msgid "Remove _Whitespace" msgstr "Удалить _пробелы" #: ../quodlibet/ext/songsmenu/duplicates.py:423 msgid "Remove _Diacritics" msgstr "Удалить _диакритические знаки" #: ../quodlibet/ext/songsmenu/duplicates.py:424 msgid "Remove _Punctuation" msgstr "Удалить п_унктуацию" #: ../quodlibet/ext/songsmenu/duplicates.py:425 msgid "Case _Insensitive" msgstr "Без учета рег_истра" #: ../quodlibet/ext/songsmenu/duplicates.py:433 msgid "Matching options" msgstr "Настройки сравнения" #. Create a dialog. #: ../quodlibet/ext/songsmenu/editplaycount.py:20 #: ../quodlibet/ext/songsmenu/editplaycount.py:42 msgid "Edit Playcount" msgstr "Счетчик воспроизведений" #: ../quodlibet/ext/songsmenu/editplaycount.py:21 msgid "" "Edit a song's ~#playcount and ~#skipcount.\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's ~#playcount to 0, the ~#lastplayed and ~#laststarted " "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 и ~#laststarted записи будут очищены. Однако, если для трека с 0 воспроизведений установлено положительное число, время ~#lastplayed и ~#laststarted не создается." #: ../quodlibet/ext/songsmenu/editplaycount.py:69 msgid "Play Count" msgstr "Счетчик воспроизведений" #: ../quodlibet/ext/songsmenu/editplaycount.py:70 msgid "Skip Count" msgstr "Счетчик пропусков" #: ../quodlibet/ext/songsmenu/embedded.py:25 msgid "Edit Embedded Images" msgstr "Изменить внедренные изображения" #: ../quodlibet/ext/songsmenu/embedded.py:26 msgid "Removes or replaces embedded images." msgstr "Удаление или замена встроенных изображений." #: ../quodlibet/ext/songsmenu/embedded.py:79 msgid "_Remove all Images" msgstr "_Удалить все" #: ../quodlibet/ext/songsmenu/embedded.py:83 msgid "_Embed Current Image" msgstr "_Внедрить текущее" #: ../quodlibet/ext/songsmenu/exact_rating.py:24 msgid "Set Exact Rating" msgstr "Оценка - точная" #: ../quodlibet/ext/songsmenu/exact_rating.py:25 msgid "Allows setting the rating of songs with a number." msgstr "Позволяет дать точную оценку треку в числах." #: ../quodlibet/ext/songsmenu/exact_rating.py:37 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:81 msgid "Filter on Any Tag" msgstr "Поиск - фильтр по тегу" #: ../quodlibet/ext/songsmenu/filterall.py:82 msgid "Creates a search query based on tags of the selected songs." msgstr "Создание поисковых запросов по тегам выбранных треков." #: ../quodlibet/ext/songsmenu/filterbrowser.py:20 msgid "Filter on Directory" msgstr "Фильтр по папке" #: ../quodlibet/ext/songsmenu/filterbrowser.py:21 msgid "Filters on directory in a new browser window." msgstr "Фильтр по папке в новом окне." #: ../quodlibet/ext/songsmenu/fingerprint/__init__.py:31 msgid "Acoustic Fingerprint Lookup" msgstr "Акустические отпечатки - поиск" #: ../quodlibet/ext/songsmenu/fingerprint/__init__.py:32 msgid "Looks up song metadata through acoustic fingerprinting." msgstr "Поиск информации о треках по их акустическим отпечаткам." #: ../quodlibet/ext/songsmenu/fingerprint/__init__.py:52 #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:42 msgid "Submit Acoustic Fingerprints" msgstr "Акустические отпечатки - отправка" #: ../quodlibet/ext/songsmenu/fingerprint/__init__.py:53 msgid "" "Generates acoustic fingerprints using chromaprint and submits them to " "acoustid.org." msgstr "" "Создание акустических отпечатков треков с помощью " "chromaprint и отправка их на acoustid.org." #: ../quodlibet/ext/songsmenu/fingerprint/__init__.py:61 msgid "API Key Missing" msgstr "Требуется ключ API" #: ../quodlibet/ext/songsmenu/fingerprint/__init__.py:62 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:76 msgid "Request API key" msgstr "Запросить ключ" #: ../quodlibet/ext/songsmenu/fingerprint/__init__.py:83 msgid "API _key:" msgstr "_Ключ API:" #: ../quodlibet/ext/songsmenu/fingerprint/__init__.py:90 msgid "AcoustID Web Service" msgstr "Веб-сервис AcoustID" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:37 msgid "Queued" msgstr "В очереди" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:39 msgid "Analyzing" msgstr "Анализ" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:41 msgid "Lookup" msgstr "Поиск" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:117 msgid "Write" msgstr "Записать" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:145 msgid "Status" msgstr "Статус" #. Translators: album release ID #: ../quodlibet/ext/songsmenu/fingerprint/search.py:159 msgid "Release" msgstr "Выпуск" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:291 msgid "Write MusicBrainz tags" msgstr "Записать теги MusicBrainz" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:297 msgid "Group by directory" msgstr "Группировать по папке" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:306 msgid "Album Mode" msgstr "Режим альбома" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:308 msgid "" "Write album related tags and try to reduce the number of different album " "releases" msgstr "" "Создание тегов, связанных с альбомами в попытке уменьшить количество " "версий альбома." #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:50 msgid "Generating fingerprints:" msgstr "Создание отпечатков:" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:66 msgid "_Details" msgstr "_Подробности" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:89 msgid "_Submit" msgstr "_Отправить" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:119 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:122 msgid "Fingerprints:" msgstr "Отпечатки:" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs with MBIDs:" msgstr "Треки с MBID:" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:126 msgid "Songs with sufficient tags:" msgstr "Треки с заполненными тегами:" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:128 msgid "Songs to submit:" msgstr "Треков для отправки:" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:166 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "Готово. %(to-send)d/%(all)d треков для отправки." #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:182 msgid "Submitting fingerprints:" msgstr "Отправка отпечатков:" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:190 msgid "Submitting…" msgstr "Отправка…" #: ../quodlibet/ext/songsmenu/forcewrite.py:18 msgid "Update Tags in Files" msgstr "Теги - обновить" #: ../quodlibet/ext/songsmenu/forcewrite.py:19 msgid "" "Update modified tags in files. This will ensure play counts and ratings are " "up to date." msgstr "" "Обновление измененных тегов в файлах. Это обеспечит атуализацию счетчика " "воспроизведений и рейтинга." #: ../quodlibet/ext/songsmenu/html.py:67 ../quodlibet/ext/songsmenu/html.py:77 msgid "Export to HTML" msgstr "Экспорт списка в HTML" #: ../quodlibet/ext/songsmenu/html.py:68 msgid "Exports the selected song list to HTML." msgstr "Экспорт выбранного списка треков в HTML." #: ../quodlibet/ext/songsmenu/ifp.py:22 msgid "Send to iFP" msgstr "Отправить на iFP" #: ../quodlibet/ext/songsmenu/ifp.py:23 msgid "Uploads songs to an iRiver iFP device." msgstr "Загружает треки на устройства iRiver iFP." #: ../quodlibet/ext/songsmenu/ifp.py:31 msgid "No iFP device found" msgstr "Устройство iFP не найдено" #: ../quodlibet/ext/songsmenu/ifp.py:32 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:40 #, python-format msgid "Uploading %(current)d/%(total)d" msgstr "Загрузка %(current)d/%(total)d" #: ../quodlibet/ext/songsmenu/ifp.py:63 msgid "Error uploading" msgstr "Ошибка загрузки" #: ../quodlibet/ext/songsmenu/ifp.py:64 #, python-format msgid "" "Unable to upload <b>%s</b>. The device may be out of space, or turned off." msgstr "" "Не удается загрузить <b>%s</b>. " "Возможно устройство недоступно или выключено." #: ../quodlibet/ext/songsmenu/importexport.py:60 msgid "Export Metadata" msgstr "Теги - экспорт метаданных" #: ../quodlibet/ext/songsmenu/importexport.py:61 msgid "Exports metadata of selected songs as a .tags file." msgstr "Экспорт метаданных выбранных треков в файл .tags." #: ../quodlibet/ext/songsmenu/importexport.py:105 msgid "Import Metadata" msgstr "Теги - импорт метаданных" #: ../quodlibet/ext/songsmenu/importexport.py:106 msgid "Imports metadata for selected songs from a .tags file." msgstr "Импорт метаданных для выбранных треков из файла .tags." #: ../quodlibet/ext/songsmenu/k3b.py:24 msgid "Burn CD" msgstr "Запись CD" #: ../quodlibet/ext/songsmenu/k3b.py:25 msgid "Burns CDs with K3b, Brasero or xfburn." msgstr "Запись CD с помощью K3b, Brasero или xfburn." #: ../quodlibet/ext/songsmenu/lastfmsync.py:98 msgid "Updating chart list." msgstr "Обновление списка чартов." #. No charts to fetch, no update scheduled. #: ../quodlibet/ext/songsmenu/lastfmsync.py:117 msgid "Already up-to-date." msgstr "Не требует обновления." #: ../quodlibet/ext/songsmenu/lastfmsync.py:125 #, python-format msgid "Fetching chart for week of %s." msgstr "Загрузка чарта за неделю от %s." #: ../quodlibet/ext/songsmenu/lastfmsync.py:147 msgid "Sync complete." msgstr "Синхронизация завершена." #: ../quodlibet/ext/songsmenu/lastfmsync.py:153 msgid "Error during sync" msgstr "Ошибка синхронизации" #: ../quodlibet/ext/songsmenu/lastfmsync.py:218 #: ../quodlibet/ext/songsmenu/lastfmsync.py:248 msgid "Last.fm Sync" msgstr "Синхронизация с Last.fm" #: ../quodlibet/ext/songsmenu/lastfmsync.py:249 msgid "Updates your library's statistics from your Last.fm profile." msgstr "Дополняет статистику фонотеки данными из профиля на Last.fm." #: ../quodlibet/ext/songsmenu/lastfmsync.py:302 msgid "_Username:" msgstr "_Имя пользователя:" #: ../quodlibet/ext/songsmenu/makesorttags.py:37 msgid "Create Sort Tags" msgstr "Создание тегов сортировки" #: ../quodlibet/ext/songsmenu/makesorttags.py:38 msgid "Converts album and artist names to sort names, poorly." msgstr "" "Конвертирует имена альбомов и исполнителей для сортировки по имени, плохо." #. Create a dialog. #: ../quodlibet/ext/songsmenu/migratemetadata.py:37 #: ../quodlibet/ext/songsmenu/migratemetadata.py:46 msgid "Migrate Metadata" msgstr "Теги - миграция метаданных" #: ../quodlibet/ext/songsmenu/migratemetadata.py:40 msgid "Copies the quodlibet-specific metadata between songs." msgstr "Копирует метаданные, специфичные для QuodLibet, между песнями." #: ../quodlibet/ext/songsmenu/migratemetadata.py:53 msgid "_Copy" msgstr "_Копировать" #: ../quodlibet/ext/songsmenu/migratemetadata.py:55 msgid "_Paste" msgstr "_Вставить" #. Create the tag table. #: ../quodlibet/ext/songsmenu/migratemetadata.py:65 msgid "Information to copy/paste" msgstr "Инфо для копирования/вставки" #. Create the indexing box. #: ../quodlibet/ext/songsmenu/migratemetadata.py:87 msgid "Map tracks by disc and track number" msgstr "Карта треков по диску и номеру трека" #: ../quodlibet/ext/songsmenu/migratemetadata.py:88 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> этот параметр должен быть включен при копировании " "метаданных для сохранения сведений о треке." #: ../quodlibet/ext/songsmenu/migratemetadata.py:104 #, python-format msgid "There is %d stored track." msgid_plural "There are %d stored tracks." msgstr[0] "%d трек сохранен" msgstr[1] "%d трека сохранено" msgstr[2] "%d треков сохранено" #: ../quodlibet/ext/songsmenu/playlist.py:32 msgid "Export as Playlist" msgstr "Экспортировать как плейлист" #: ../quodlibet/ext/songsmenu/playlist.py:33 msgid "Exports songs to an M3U or PLS playlist." msgstr "Экспорт треков в файл M3U или PLS." #: ../quodlibet/ext/songsmenu/playlist.py:78 msgid "Use relative paths" msgstr "Относительные пути" #: ../quodlibet/ext/songsmenu/playlist.py:78 msgid "Use absolute paths" msgstr "Абсолютные пути" #: ../quodlibet/ext/songsmenu/playlist.py:133 msgid "Unable to export playlist" msgstr "Не удалось экспортировать плейлист" #: ../quodlibet/ext/songsmenu/playlist.py:134 #, python-format msgid "Writing to <b>%s</b> failed." msgstr "Не удалось записать в <b>%s</b>." #. Translators: Plugin name #: ../quodlibet/ext/songsmenu/refresh.py:23 msgid "Rescan Songs" msgstr "Пересканировать треки" #: ../quodlibet/ext/songsmenu/refresh.py:24 msgid "Checks for file changes and reloads / removes the songs if needed." msgstr "" "Проверка изменений файлов и перезагрузка / удаление треков, " "если это необходимо." #: ../quodlibet/ext/songsmenu/refresh.py:32 msgid "Rescan songs" msgstr "Пересканировать треки" #: ../quodlibet/ext/songsmenu/replaygain.py:353 msgid "ReplayGain Analyzer" msgstr "ReplayGain анализ" #: ../quodlibet/ext/songsmenu/replaygain.py:409 msgid "Progress" msgstr "Прогресс" #: ../quodlibet/ext/songsmenu/replaygain.py:424 msgid "Gain" msgstr "Усиление" #: ../quodlibet/ext/songsmenu/replaygain.py:439 msgid "Peak" msgstr "Пик" #: ../quodlibet/ext/songsmenu/replaygain.py:454 #, python-format msgid "There is <b>%(to-process)s</b> album to update (of %(all)s)" msgid_plural "There are <b>%(to-process)s</b> albums to update (of %(all)s)" msgstr[0] "Обновляется <b>%(to-process)s</b> альбом (из %(all)s)" msgstr[1] "Обновляется <b>%(to-process)s</b> альбома (из %(all)s)" msgstr[2] "Обновляется <b>%(to-process)s</b> альбомов (из %(all)s)" #: ../quodlibet/ext/songsmenu/replaygain.py:570 msgid "Replay Gain" msgstr "Replay Gain регулировка" #: ../quodlibet/ext/songsmenu/replaygain.py:571 msgid "" "Analyzes and updates ReplayGain information, using GStreamer. Results are " "grouped by album." msgstr "" "Анализирует и обновляет информацию ReplayGain с помощью GStreamer, группируя " "результаты по альбомам." #: ../quodlibet/ext/songsmenu/replaygain.py:609 msgid "always" msgstr "всегда" #: ../quodlibet/ext/songsmenu/replaygain.py:610 msgid "if <b>any</b> RG tags are missing" msgstr "Если <b>какие-либо</b> теги ReplayGain отсутствуют" #: ../quodlibet/ext/songsmenu/replaygain.py:612 msgid "if <b>album</b> RG tags are missing" msgstr "Если <b>альбомные</b> теги ReplayGain отсутствуют" #: ../quodlibet/ext/songsmenu/replaygain.py:629 msgid "_Process albums:" msgstr "О_брабатывать альбомы:" #. Server settings Frame #: ../quodlibet/ext/songsmenu/replaygain.py:641 msgid "Existing Tags" msgstr "Существующие теги" #: ../quodlibet/ext/songsmenu/splitting.py:32 msgid "Split Tags" msgstr "Теги - отделить" #: ../quodlibet/ext/songsmenu/splitting.py:33 msgid "" "Splits the disc number from the album and the version from the title at the " "same time." msgstr "" "Отделить номер диска от альбома, а версию от названия." #: ../quodlibet/ext/songsmenu/splitting.py:57 msgid "Split Album" msgstr "Теги - отделить альбом" #: ../quodlibet/ext/songsmenu/splitting.py:58 msgid "Split out disc number." msgstr "Отделить номер диска." #: ../quodlibet/ext/songsmenu/tapbpm.py:24 #: ../quodlibet/ext/songsmenu/tapbpm.py:33 #: ../quodlibet/ext/songsmenu/tapbpm.py:62 msgid "n/a" msgstr "н/д" #. TRANSLATORS: BPM mean "beats per minute" #: ../quodlibet/ext/songsmenu/tapbpm.py:32 msgid "BPM:" msgstr "BPM:" #: ../quodlibet/ext/songsmenu/tapbpm.py:37 msgid "Reset" msgstr "Сброс" #: ../quodlibet/ext/songsmenu/tapbpm.py:43 msgid "Tap" msgstr "Такт" #: ../quodlibet/ext/songsmenu/tapbpm.py:178 #: ../quodlibet/ext/songsmenu/tapbpm.py:185 msgid "Tap BPM" msgstr "Tap BPM (ударов в минуту)" #: ../quodlibet/ext/songsmenu/tapbpm.py:179 msgid "Tap BPM for the selected song." msgstr "Ударов в минуту (Tap BPM) для выбранного трека." #: ../quodlibet/ext/songsmenu/website_search.py:38 msgid "Website Search" msgstr "Поиск в интернете" #: ../quodlibet/ext/songsmenu/website_search.py:39 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern-example)s." msgstr "" "Поиск на любых выбранных веб-сайтах по любым тегам.\n" "Поддерживает шаблоны, например: %(pattern-example)s." #: ../quodlibet/ext/songsmenu/website_search.py:81 msgid "Search URL patterns" msgstr "Шаблоны URL для поиска" #: ../quodlibet/ext/songsmenu/website_search.py:91 msgid "Edit search URLs" msgstr "Изменить поисковые шаблоны" #. Add link to editor #: ../quodlibet/ext/songsmenu/website_search.py:117 msgid "Configure Searches…" msgstr "Настройка поиска…" #: ../quodlibet/ext/songsmenu/wikipedia.py:47 #, python-format msgid "Search at %(website)s" msgstr "Искать на %(website)s" #: ../quodlibet/ext/songsmenu/wikipedia.py:64 msgid "Search Artist in Wikipedia" msgstr "Поиск исполнителя на Википедии" #: ../quodlibet/ext/songsmenu/wikipedia.py:65 msgid "" "Opens a browser window with Wikipedia article on the playing song artist." msgstr "" "Открытие веб-браузера со статьёй об исполнителе на Википедии." #: ../quodlibet/ext/songsmenu/wikipedia.py:72 msgid "Search Album in Wikipedia" msgstr "Поиск альбома на Википедии" #: ../quodlibet/ext/songsmenu/wikipedia.py:73 msgid "" "Opens a browser window with Wikipedia article on the playing song album." msgstr "" "Открытие веб-браузера со статьёй об альбоме на Википедии." #. then (try to) load all new files #: ../quodlibet/library/libraries.py:654 ../quodlibet/library/libraries.py:664 #: ../quodlibet/library/libraries.py:730 ../quodlibet/library/libraries.py:749 #: ../quodlibet/qltk/information.py:273 ../quodlibet/qltk/prefs.py:650 #: ../quodlibet/util/library.py:124 msgid "Library" msgstr "Фонотека" #: ../quodlibet/library/libraries.py:654 msgid "Checking mount points" msgstr "Проверка точек монтирования" #: ../quodlibet/library/libraries.py:664 msgid "Scanning library" msgstr "Сканирование фонотеки" #: ../quodlibet/library/libraries.py:729 #, python-format msgid "Scanning %s" msgstr "Сканирование %s" #: ../quodlibet/library/libraries.py:749 msgid "Loading files" msgstr "Не удалось сохранить" #: ../quodlibet/main.py:51 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:38 msgid "List tags" msgstr "Список тегов" #: ../quodlibet/operon/commands.py:43 ../quodlibet/operon/commands.py:82 #: ../quodlibet/operon/commands.py:462 msgid "Print terse output" msgstr "Показать сокращенный вывод" #: ../quodlibet/operon/commands.py:45 ../quodlibet/operon/commands.py:84 #: ../quodlibet/operon/commands.py:464 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "" "Столбцы и порядок отображения в сокращенном режиме (%s)" #: ../quodlibet/operon/commands.py:48 ../quodlibet/operon/commands.py:87 msgid "Also list programmatic tags" msgstr "Показывать программные теги" #: ../quodlibet/operon/commands.py:52 ../quodlibet/operon/commands.py:130 #: ../quodlibet/operon/commands.py:221 ../quodlibet/operon/commands.py:294 #: ../quodlibet/operon/commands.py:337 ../quodlibet/operon/commands.py:341 #: ../quodlibet/operon/commands.py:392 ../quodlibet/operon/commands.py:395 #: ../quodlibet/operon/commands.py:434 ../quodlibet/operon/commands.py:469 #: ../quodlibet/operon/commands.py:509 ../quodlibet/operon/commands.py:544 #: ../quodlibet/operon/commands.py:586 msgid "Not enough arguments" msgstr "Недостаточно аргументов" #: ../quodlibet/operon/commands.py:54 ../quodlibet/operon/commands.py:91 #: ../quodlibet/operon/commands.py:132 ../quodlibet/operon/commands.py:223 #: ../quodlibet/operon/commands.py:471 msgid "Too many arguments" msgstr "Слишком много аргументов" #: ../quodlibet/operon/commands.py:57 ../quodlibet/operon/commands.py:93 #: ../quodlibet/operon/commands.py:476 ../quodlibet/qltk/data_editors.py:354 msgid "Description" msgstr "Описание" #: ../quodlibet/operon/commands.py:57 ../quodlibet/operon/commands.py:476 #: ../quodlibet/qltk/edittags.py:455 msgid "Value" msgstr "Значение" #: ../quodlibet/operon/commands.py:77 msgid "List all common tags" msgstr "Список всех общих тегов" #: ../quodlibet/operon/commands.py:119 msgid "Copy tags from one file to another" msgstr "Копировать теги из одного файла в другой" #: ../quodlibet/operon/commands.py:124 ../quodlibet/operon/commands.py:165 #: ../quodlibet/operon/commands.py:290 ../quodlibet/operon/commands.py:325 #: ../quodlibet/operon/commands.py:385 msgid "Show changes, don't apply them" msgstr "Показать изменения, но не применять их" #: ../quodlibet/operon/commands.py:126 msgid "Skip tags that can't be written" msgstr "Пропускать теги, которые нельзя записать" #: ../quodlibet/operon/commands.py:146 #, python-format msgid "Can't copy tag %r to file: %r" msgstr "Не удается копировать тег %r в файл: %r" #: ../quodlibet/operon/commands.py:158 msgid "Edit tags in a text editor" msgstr "Изменить теги в текстовом редакторе" #: ../quodlibet/operon/commands.py:252 msgid "Editing aborted" msgstr "Изменение прервано" #: ../quodlibet/operon/commands.py:256 #, python-format msgid "Starting text editor '%(editor-name)s' failed." msgstr "Не удалось запустить текстовый редактор '%(editor-name)s'." #: ../quodlibet/operon/commands.py:261 msgid "No changes detected" msgstr "Изменения не найдены" #: ../quodlibet/operon/commands.py:285 msgid "Set a tag and remove existing values" msgstr "Установка тега и удаление существующих значений" #: ../quodlibet/operon/commands.py:305 ../quodlibet/operon/commands.py:445 #: ../quodlibet/operon/commands.py:677 #, python-format msgid "Can not set %r" msgstr "Не удалось установить %r" #: ../quodlibet/operon/commands.py:320 msgid "Remove tags" msgstr "Удалить теги" #: ../quodlibet/operon/commands.py:327 ../quodlibet/operon/commands.py:387 msgid "Value is a regular expression" msgstr "Значение - регулярное выражение" #: ../quodlibet/operon/commands.py:329 msgid "Remove all tags" msgstr "Удалить все теги" #: ../quodlibet/operon/commands.py:333 msgid "Can't combine '--all' with '--regexp'" msgstr "Не удается объединить '--all' с '--regexp'" #: ../quodlibet/operon/commands.py:367 #, python-format msgid "Can't remove %r from %r" msgstr "Не удается удалить %r из %r" #: ../quodlibet/operon/commands.py:380 msgid "Remove a tag value" msgstr "Удалить значение тега" #: ../quodlibet/operon/commands.py:429 msgid "Add a tag value" msgstr "Добавить значение тега" #: ../quodlibet/operon/commands.py:457 msgid "List file information" msgstr "Вывести информацию о файле" #: ../quodlibet/operon/commands.py:503 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" "Установить полученное изображение в качестве основного внедренного " "изображения и удалить все другие внедренные изображения" #: ../quodlibet/operon/commands.py:516 #, python-format msgid "Failed to load image file: %r" msgstr "Не удалось загрузить файл: %r" #: ../quodlibet/operon/commands.py:523 ../quodlibet/operon/commands.py:552 #, 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:539 msgid "Remove all embedded images" msgstr "Удалить все внедрённые изображения" #: ../quodlibet/operon/commands.py:569 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "Извлечь внедрённые изображения в %(filepath)s" #: ../quodlibet/operon/commands.py:581 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" "Путь к месту сохранения изображений (по умолчанию-рабочий каталог)" #: ../quodlibet/operon/commands.py:640 msgid "Rename files based on tags" msgstr "Переименование файлов на основе тегов" #: ../quodlibet/operon/commands.py:655 msgid "Fill tags based on the file path" msgstr "Заполнение тегов на основе пути к файлу" #: ../quodlibet/operon/commands.py:705 ../quodlibet/qltk/information.py:310 #: ../quodlibet/qltk/properties.py:85 ../quodlibet/qltk/renamefiles.py:226 #: ../quodlibet/qltk/tagsfrompath.py:230 ../quodlibet/qltk/tracknumbers.py:80 msgid "File" msgstr "Файл" #: ../quodlibet/operon/commands.py:713 msgid "Fill tracknumbers for all files" msgstr "Заполнить номер трека для всех файлов" #: ../quodlibet/operon/commands.py:732 msgid "Print tags based on the given pattern" msgstr "Выводить теги на основе указанного шаблона" #: ../quodlibet/operon/commands.py:769 msgid "Display help information" msgstr "Вывести справку" #: ../quodlibet/operon/util.py:43 #, 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:31 msgid "_Unknown" msgstr "_Неизвестно" #: ../quodlibet/order/__init__.py:143 msgid "In Order" msgstr "По порядку" #: ../quodlibet/order/__init__.py:144 msgid "_In Order" msgstr "_По порядку" #: ../quodlibet/order/reorder.py:24 msgid "Random" msgstr "Случайно" #: ../quodlibet/order/reorder.py:25 ../quodlibet/qltk/queue.py:121 msgid "_Random" msgstr "_Случайно" #: ../quodlibet/order/reorder.py:40 ../quodlibet/order/reorder.py:41 msgid "Prefer higher rated" msgstr "По рейтингу" #: ../quodlibet/order/repeat.py:44 ../quodlibet/order/repeat.py:45 msgid "Repeat this track" msgstr "Повторить этот" #: ../quodlibet/order/repeat.py:58 ../quodlibet/order/repeat.py:59 msgid "Repeat all" msgstr "Повторить все" #: ../quodlibet/order/repeat.py:74 ../quodlibet/order/repeat.py:75 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:448 msgid "Could not create GStreamer pipeline" msgstr "Не удалось создать конвейер GStreamer" #: ../quodlibet/player/gstbe/player.py:647 msgid "No GStreamer element found to handle media format" msgstr "Не найден элемент GStreamer для обработки формата мультимедиа" #: ../quodlibet/player/gstbe/player.py:648 #, python-format msgid "Media format: %(format-description)s" msgstr "Формат мультимедиа: %(format-description)s" #: ../quodlibet/player/gstbe/plugins.py:36 #, 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. In case the pipeline contains a sink, it will be used instead of " "the default one." msgstr "" "Конвейер вывода GStreamer. Пустое поле соответствует конвейеру по умолчанию. " "Если будет указано устройство вывода, оно будет использовано вместо " "устройства по умолчанию." #: ../quodlibet/player/gstbe/prefs.py:37 msgid "_Output pipeline:" msgstr "_Конвейер вывода:" #: ../quodlibet/player/gstbe/prefs.py:44 #, python-format msgid "%.1f seconds" msgstr "%.1f секунд" #: ../quodlibet/player/gstbe/prefs.py:58 msgid "_Buffer duration:" msgstr "_Размер буфера:" #: ../quodlibet/player/gstbe/prefs.py:67 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/util.py:103 msgid "No GStreamer audio sink found" msgstr "Не найдено ни одного устройства аудиовывода GStreamer" #: ../quodlibet/player/gstbe/util.py:122 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:63 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" "Не удалось найти модуль '{module}'. Возможно, нужно установить пакет." #: ../quodlibet/plugins/__init__.py:72 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "Не удалось найти элемент GStreamer: '{element}'." #: ../quodlibet/plugins/playlist.py:24 #, 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:28 ../quodlibet/qltk/songsmenu.py:57 #: ../quodlibet/qltk/songsmenu.py:68 msgid "_Run Plugin" msgstr "_Запустить плагин" #. Translators: Refers to the beginning of the playing song. #: ../quodlibet/qltk/bookmarks.py:28 msgid "Beginning" msgstr "Начало" #: ../quodlibet/qltk/bookmarks.py:39 ../quodlibet/qltk/bookmarks.py:79 msgid "N/A" msgstr "Н/Д" #: ../quodlibet/qltk/bookmarks.py:84 msgid "Time" msgstr "Время" #: ../quodlibet/qltk/bookmarks.py:90 ../quodlibet/qltk/bookmarks.py:125 msgid "Bookmark Name" msgstr "Имя закладки" #: ../quodlibet/qltk/bookmarks.py:123 msgid "MM:SS" msgstr "ММ:СС" #: ../quodlibet/qltk/bookmarks.py:211 ../quodlibet/qltk/information.py:133 msgid "Bookmarks" msgstr "Закладки" #: ../quodlibet/qltk/browser.py:57 msgid "_Filters" msgstr "_Фильтры" #: ../quodlibet/qltk/browser.py:58 msgid "Recently _Played" msgstr "Недавно _прослушанные" #: ../quodlibet/qltk/browser.py:60 msgid "Recently _Added" msgstr "Недавно _добавленные" #: ../quodlibet/qltk/browser.py:62 msgid "_Top 40" msgstr "40 _лучших" #: ../quodlibet/qltk/browser.py:64 msgid "All _Songs" msgstr "_Все треки" #: ../quodlibet/qltk/browser.py:72 msgid "On Current _Genre(s)" msgstr "По текущим _жанрам" #: ../quodlibet/qltk/browser.py:73 msgid "On Current _Artist(s)" msgstr "По текущим _исполнителям" #: ../quodlibet/qltk/browser.py:74 msgid "On Current Al_bum" msgstr "По текущему _альбому" #: ../quodlibet/qltk/browser.py:82 msgid "Random _Genre" msgstr "Случайный _жанр" #: ../quodlibet/qltk/browser.py:83 msgid "Random _Artist" msgstr "Случайный _исполнитель" #: ../quodlibet/qltk/browser.py:84 msgid "Random Al_bum" msgstr "Случайный _альбом" #: ../quodlibet/qltk/browser.py:97 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:41 msgid "_Name:" msgstr "_Имя:" #: ../quodlibet/qltk/cbes.py:49 ../quodlibet/qltk/edittags.py:312 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 "_ReplayGain анализ" #. Translators: New Command/Entry/Item/... #: ../quodlibet/qltk/data_editors.py:118 #, python-format msgid "New %s" msgstr "Новый %s" #: ../quodlibet/qltk/data_editors.py:217 msgid "(unknown)" msgstr "(неизвестно)" #: ../quodlibet/qltk/data_editors.py:346 msgid "Tag expression" msgstr "Выражение тега" #: ../quodlibet/qltk/data_editors.py:373 msgid "Tag expression e.g. people:real or ~album~year" msgstr "Выражение тега, например, people:real или ~album~year" #: ../quodlibet/qltk/data_editors.py:374 msgid "Enter new tag" msgstr "Введите новое значение" #: ../quodlibet/qltk/delete.py:38 msgid "Files:" msgstr "Файлы:" #: ../quodlibet/qltk/delete.py:64 msgid "" "The selected songs will be removed from the library and their files deleted " "from disk." msgstr "" "Выбранные треки будут удалены из фонотеки, а их файлы будут удалены с диска." #: ../quodlibet/qltk/delete.py:73 msgid "The selected files will be deleted from disk." msgstr "Выбранные файлы будут удалены с диска." #: ../quodlibet/qltk/delete.py:77 #, 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:92 msgid "_Delete Files" msgstr "_Удалить файлы" #: ../quodlibet/qltk/delete.py:107 msgid "" "The selected songs will be removed from the library and their files moved to " "the trash." msgstr "" "Выбранные треки будут удалены из фонотеки, а их файлы будут " "перемещены в корзину." #: ../quodlibet/qltk/delete.py:116 msgid "The selected files will be moved to the trash." msgstr "Выбранные файлы будут перемещены в корзину." #: ../quodlibet/qltk/delete.py:121 #, 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:135 ../quodlibet/qltk/delete.py:142 msgid "_Move to Trash" msgstr "_Переместить в корзину" #: ../quodlibet/qltk/delete.py:153 ../quodlibet/qltk/delete.py:188 #, python-format msgid "Moving %(current)d/%(total)d." msgstr "Перемещение %(current)d/%(total)d." #: ../quodlibet/qltk/delete.py:174 ../quodlibet/qltk/delete.py:206 msgid "Unable to move to trash" msgstr "Не удалось переместить в корзину" #: ../quodlibet/qltk/delete.py:175 ../quodlibet/qltk/delete.py:207 msgid "Moving one or more files to the trash failed." msgstr "Не удалось переместить в корзину некоторые файлы." #: ../quodlibet/qltk/delete.py:217 ../quodlibet/qltk/delete.py:251 #, python-format msgid "Deleting %(current)d/%(total)d." msgstr "Удаление %(current)d/%(total)d." #: ../quodlibet/qltk/delete.py:237 ../quodlibet/qltk/delete.py:270 msgid "Unable to delete files" msgstr "Не удалось удалить файлы" #: ../quodlibet/qltk/delete.py:238 ../quodlibet/qltk/delete.py:271 msgid "Deleting one or more files failed." msgstr "Не удалось удалить некоторые файлы." #: ../quodlibet/qltk/edittags.py:64 ../quodlibet/qltk/edittags.py:75 #, 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:68 ../quodlibet/qltk/edittags.py:72 #, 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:194 msgid "Split into _Multiple Values" msgstr "_Разделить на несколько значений" #: ../quodlibet/qltk/edittags.py:212 msgid "Split Disc out of _Album" msgstr "Выделить 'Disc' из '_Album'" #: ../quodlibet/qltk/edittags.py:229 msgid "Split _Version out of Title" msgstr "Выделить '_Version' из 'Title'" #: ../quodlibet/qltk/edittags.py:260 msgid "Split Arranger out of Ar_tist" msgstr "Выделить 'Arranger' из 'Ar_tist'" #: ../quodlibet/qltk/edittags.py:265 msgid "Split _Performer out of Artist" msgstr "Выделить '_Performer' из 'Artist'" #: ../quodlibet/qltk/edittags.py:271 msgid "Split _Performer out of Title" msgstr "Выделить 'Performer' из '_Title'" #: ../quodlibet/qltk/edittags.py:277 msgid "Split _Originalartist out of Title" msgstr "Выделить '_Originalartist' из 'Title'" #: ../quodlibet/qltk/edittags.py:284 msgid "Add a Tag" msgstr "Добавить тег" #: ../quodlibet/qltk/edittags.py:303 msgid "_Tag:" msgstr "Т_ег:" #: ../quodlibet/qltk/edittags.py:405 msgid "Edit Tags" msgstr "Изменить теги" #: ../quodlibet/qltk/edittags.py:478 msgid "Show _programmatic tags" msgstr "_Показывать программные теги" #: ../quodlibet/qltk/edittags.py:479 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" "Показывать все теги, включая созданные программно, как например теги " "MusicBrainz или Replay Gain" #. Translators: Revert button in the tag editor #: ../quodlibet/qltk/edittags.py:509 msgctxt "edittags" msgid "_Revert" msgstr "_Сброс" #. Translators: Save button in the tag editor #: ../quodlibet/qltk/edittags.py:513 msgctxt "edittags" msgid "_Save" msgstr "Со_хранить" #: ../quodlibet/qltk/edittags.py:660 msgid "Unable to add tag" msgstr "Не удалось добавить тег" #: ../quodlibet/qltk/edittags.py:661 #, python-format msgid "Unable to add <b>%s</b>" msgstr "Не удалось добавить <b>%s</b>" #: ../quodlibet/qltk/edittags.py:663 #, python-format msgid "" "The files currently selected do not support multiple values for <b>%s</b>." msgstr "" "Выбранные файлы не поддерживают множественные значения для <b>%s</b>." #. Can't add the new tag. #: ../quodlibet/qltk/edittags.py:690 ../quodlibet/qltk/edittags.py:858 #: ../quodlibet/qltk/tagsfrompath.py:213 ../quodlibet/util/__init__.py:506 #: ../quodlibet/util/tags.py:243 msgid "Invalid tag" msgstr "Недопустимый тег" #: ../quodlibet/qltk/edittags.py:691 ../quodlibet/qltk/edittags.py:859 #: ../quodlibet/qltk/tagsfrompath.py:214 #, python-format msgid "" "Invalid tag <b>%s</b>\n" "\n" "The files currently selected do not support editing this tag." msgstr "" "Недопустимый тег <b>%s</b>\n" "\n" "Выбранные файлы не поддерживают изменение этого тега." #: ../quodlibet/qltk/edittags.py:829 ../quodlibet/qltk/edittags.py:870 msgid "Invalid value" msgstr "Недопустимое значение" #: ../quodlibet/qltk/edittags.py:830 ../quodlibet/qltk/edittags.py:871 #, python-format msgid "" "Invalid value: <b>%(value)s</b>\n" "\n" "%(error)s" msgstr "" "Некорректное значение: <b>%(value)s</b>\n" "\n" "%(error)s" #: ../quodlibet/qltk/_editutils.py:30 msgid "Tag may not be accurate" msgstr "Возможно неправильный тег" #: ../quodlibet/qltk/_editutils.py:33 #, 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:49 msgid "Unable to save song" msgstr "Не удалось сохранить трек" #: ../quodlibet/qltk/_editutils.py:52 #, 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:96 #: ../quodlibet/qltk/quodlibetwindow.py:1103 msgid "_About" msgstr "_О программе" #: ../quodlibet/qltk/exfalsowindow.py:100 #: ../quodlibet/qltk/quodlibetwindow.py:1125 msgid "_Check for Updates…" msgstr "_Проверить обновления…" #: ../quodlibet/qltk/exfalsowindow.py:106 #: ../quodlibet/qltk/quodlibetwindow.py:1058 ../quodlibet/qltk/songsmenu.py:291 msgid "_Plugins" msgstr "_Расширения" #: ../quodlibet/qltk/exfalsowindow.py:268 #, 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/exfalsowindow.py:290 ../quodlibet/qltk/prefs.py:609 msgid "Split _on:" msgstr "_Разделять по:" #: ../quodlibet/qltk/exfalsowindow.py:296 ../quodlibet/qltk/prefs.py:624 msgid "Tag Editing" msgstr "Редактор тегов" #: ../quodlibet/qltk/filesel.py:211 msgid "Folders" msgstr "Папки" #: ../quodlibet/qltk/filesel.py:266 msgid "_New Folder…" msgstr "_Создать папку…" #: ../quodlibet/qltk/filesel.py:275 msgid "_Select all Sub-Folders" msgstr "В_ыбрать все вложенные папки" #: ../quodlibet/qltk/filesel.py:381 msgid "New Folder" msgstr "Новая папка" #: ../quodlibet/qltk/filesel.py:381 msgid "Enter a name for the new folder:" msgstr "Введите имя новой папки:" #: ../quodlibet/qltk/filesel.py:394 msgid "Unable to create folder" msgstr "Не удалось создать папку" #: ../quodlibet/qltk/filesel.py:411 msgid "Unable to delete folder" msgstr "Не удалось удалить папку" #: ../quodlibet/qltk/filesel.py:526 ../quodlibet/qltk/pluginwin.py:168 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:172 #: ../quodlibet/qltk/information.py:453 #, python-format msgid "Disc %s" msgstr "Диск %s" #: ../quodlibet/qltk/info.py:45 ../quodlibet/qltk/information.py:177 #, python-format msgid "Track %s" msgstr "Трек %s" #: ../quodlibet/qltk/info.py:109 msgid "_Edit Display…" msgstr "_Изменить вид…" #: ../quodlibet/qltk/information.py:107 msgid "No songs are selected." msgstr "Нет выбранных треков." #: ../quodlibet/qltk/information.py:108 msgid "No Songs" msgstr "Нет треков" #: ../quodlibet/qltk/information.py:123 ../quodlibet/qltk/information.py:343 #: ../quodlibet/qltk/information.py:476 ../quodlibet/qltk/information.py:544 msgid "Information" msgstr "Информация" #: ../quodlibet/qltk/information.py:128 msgid "Lyrics" msgstr "Текст песни" #: ../quodlibet/qltk/information.py:189 ../quodlibet/qltk/information.py:401 #, python-format msgid "Produced by %s" msgstr "Продюсер: %s" #: ../quodlibet/qltk/information.py:204 ../quodlibet/util/tags.py:87 msgid "artist" msgstr "исполнитель" #: ../quodlibet/qltk/information.py:205 ../quodlibet/qltk/information.py:574 #: ../quodlibet/util/tags.py:87 msgid "artists" msgstr "исполнители" #. for backwards compat #: ../quodlibet/qltk/information.py:226 ../quodlibet/util/tags.py:98 #: ../quodlibet/util/tags.py:126 msgid "performers" msgstr "интерпритаторы" #: ../quodlibet/qltk/information.py:240 ../quodlibet/qltk/information.py:253 #: ../quodlibet/qltk/songlistcolumns.py:276 msgid "Never" msgstr "Никогда" #: ../quodlibet/qltk/information.py:241 #, 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:259 ../quodlibet/util/tags.py:151 msgid "added" msgstr "добавлен" #: ../quodlibet/qltk/information.py:260 ../quodlibet/util/tags.py:152 msgid "last played" msgstr "воспроизведен" #: ../quodlibet/qltk/information.py:261 ../quodlibet/util/tags.py:162 msgid "plays" msgstr "воспроизведений" #: ../quodlibet/qltk/information.py:262 ../quodlibet/util/tags.py:163 msgid "skips" msgstr "пропусков" #: ../quodlibet/qltk/information.py:263 ../quodlibet/util/tags.py:168 msgid "rating" msgstr "оценка" #: ../quodlibet/qltk/information.py:292 msgid "path" msgstr "путь" #: ../quodlibet/qltk/information.py:293 ../quodlibet/util/tags.py:166 msgid "length" msgstr "время" #: ../quodlibet/qltk/information.py:294 msgid "format" msgstr "формат" #: ../quodlibet/qltk/information.py:295 ../quodlibet/util/tags.py:175 msgid "codec" msgstr "кодек" #: ../quodlibet/qltk/information.py:296 ../quodlibet/util/tags.py:176 msgid "encoding" msgstr "декодер" #: ../quodlibet/qltk/information.py:297 ../quodlibet/util/tags.py:172 msgid "bitrate" msgstr "битрейт" #: ../quodlibet/qltk/information.py:298 ../quodlibet/util/tags.py:173 msgid "file size" msgstr "размер" #: ../quodlibet/qltk/information.py:299 ../quodlibet/util/tags.py:161 msgid "modified" msgstr "изменён" #: ../quodlibet/qltk/information.py:336 msgid "Additional" msgstr "Дополнительно" #: ../quodlibet/qltk/information.py:388 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d выбран" msgstr[1] "%d выбрано" msgstr[2] "%d выбрано" #: ../quodlibet/qltk/information.py:463 msgid "Track unavailable" msgstr "Трек недоступен" #: ../quodlibet/qltk/information.py:469 msgid "Track List" msgstr "Список треков" #: ../quodlibet/qltk/information.py:501 ../quodlibet/qltk/information.py:591 #, 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:504 msgid "Selected Discography" msgstr "Выбранные альбомы" #: ../quodlibet/qltk/information.py:571 #, 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:599 ../quodlibet/util/tags.py:85 msgid "albums" msgstr "альбомы" #: ../quodlibet/qltk/information.py:612 msgid "Total length:" msgstr "Общая продолжительность:" #: ../quodlibet/qltk/information.py:616 msgid "Total size:" msgstr "Общий размер:" #: ../quodlibet/qltk/information.py:619 msgid "Files" msgstr "Файлы" #: ../quodlibet/qltk/lyrics.py:37 msgid "_View online" msgstr "_Показать онлайн" #: ../quodlibet/qltk/lyrics.py:65 msgid "No lyrics found for this song." msgstr "Текст песни не найден." #: ../quodlibet/qltk/lyrics.py:76 msgid "Searching for lyrics…" msgstr "Идёт поиск текста песни…" #: ../quodlibet/qltk/maskedbox.py:21 msgid "Are you sure you want to remove all songs?" msgstr "Удалить все треки?" #: ../quodlibet/qltk/maskedbox.py:22 msgid "The selected songs will be removed from the library." msgstr "Выбранные треки будут удалены из фонотеки." #: ../quodlibet/qltk/maskedbox.py:45 msgid "Unhide" msgstr "Показать" #: ../quodlibet/qltk/maskedbox.py:87 msgid "_Unhide" msgstr "_Показать" #: ../quodlibet/qltk/msg.py:42 msgid "Discard tag changes?" msgstr "Отменить изменения тегов?" #: ../quodlibet/qltk/msg.py:43 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "" "Теги были изменены, но изменения не были сохранены. Сохранить файлы или " "отменить изменения?" #: ../quodlibet/qltk/msg.py:56 ../quodlibet/qltk/prefs.py:606 #: ../quodlibet/qltk/textedit.py:65 ../quodlibet/qltk/tracknumbers.py:118 msgid "_Revert" msgstr "Сбр_ос" #: ../quodlibet/qltk/msg.py:105 msgid "File exists" msgstr "Файл существует" #: ../quodlibet/qltk/msg.py:107 #, python-format msgid "Replace %(file-name)s?" msgstr "Заменить %(file-name)s?" #: ../quodlibet/qltk/msg.py:113 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:257 msgid "Toggle shuffle mode" msgstr "Перемешать" #: ../quodlibet/qltk/playorder.py:273 msgid "Toggle repeat mode" msgstr "Повторить" #: ../quodlibet/qltk/pluginwin.py:45 msgid "Plugin Errors" msgstr "Ошибки расширений" #: ../quodlibet/qltk/pluginwin.py:125 msgid "Enabled" msgstr "Включённые" #: ../quodlibet/qltk/pluginwin.py:126 msgid "Disabled" msgstr "Отключённые" #: ../quodlibet/qltk/pluginwin.py:132 msgid "No category" msgstr "Без категории" #: ../quodlibet/qltk/pluginwin.py:170 msgid "Events" msgstr "События" #: ../quodlibet/qltk/pluginwin.py:171 msgid "Play Order" msgstr "Очередность" #: ../quodlibet/qltk/pluginwin.py:172 msgid "Editing" msgstr "Редактор тегов" #: ../quodlibet/qltk/pluginwin.py:174 msgid "Covers" msgstr "Обложки" #: ../quodlibet/qltk/pluginwin.py:310 msgid "No plugins found." msgstr "Расширения не найдены." #: ../quodlibet/qltk/pluginwin.py:359 msgid "Plugins" msgstr "Расширения" #: ../quodlibet/qltk/pluginwin.py:383 msgid "Filter by plugin state / tag" msgstr "Фильтр по состоянию/тегу" #: ../quodlibet/qltk/pluginwin.py:389 msgid "Filter by plugin type" msgstr "Фильтр по типу" #: ../quodlibet/qltk/pluginwin.py:395 msgid "Filter by plugin name or description" msgstr "Фильтр по имени/описанию" #: ../quodlibet/qltk/pluginwin.py:404 msgid "Show _Errors" msgstr "_Ошибки" #: ../quodlibet/qltk/prefs.py:46 msgid "_Disc" msgstr "_Диск" #: ../quodlibet/qltk/prefs.py:47 msgid "_Track" msgstr "_Трек" #: ../quodlibet/qltk/prefs.py:48 msgid "Grou_ping" msgstr "_Группировка" #: ../quodlibet/qltk/prefs.py:51 msgid "Al_bum" msgstr "_Альбом" #: ../quodlibet/qltk/prefs.py:56 msgid "_Filename" msgstr "Имя _файла" #: ../quodlibet/qltk/prefs.py:58 msgid "_Length" msgstr "Вре_мя" #: ../quodlibet/qltk/prefs.py:65 msgid "_Jump to playing song automatically" msgstr "_Авто переход к воспроизводимому треку" #: ../quodlibet/qltk/prefs.py:67 msgid "When the playing song changes, scroll to it in the song list" msgstr "" "Когда воспроизведение переходит к другому треку, переходить к нему в " "плейлисте" #: ../quodlibet/qltk/prefs.py:83 msgid "_Others:" msgstr "Д_ругие:" #: ../quodlibet/qltk/prefs.py:89 msgid "_Edit…" msgstr "_Изменить…" #: ../quodlibet/qltk/prefs.py:92 msgid "Add or remove additional column headers" msgstr "Добавить или удалить столбцы" #: ../quodlibet/qltk/prefs.py:102 msgid "Visible Columns" msgstr "Отображаемые столбцы" #: ../quodlibet/qltk/prefs.py:105 msgid "Title includes _version" msgstr "Название содержит _версию" #: ../quodlibet/qltk/prefs.py:107 msgid "Artist includes all _people" msgstr "Исполнитель содержит всех _людей" #: ../quodlibet/qltk/prefs.py:109 msgid "Album includes _disc subtitle" msgstr "Альбом содержит _раздел диска" #: ../quodlibet/qltk/prefs.py:111 msgid "Filename includes _folder" msgstr "Имя файла содержит _путь" #: ../quodlibet/qltk/prefs.py:124 msgid "Column Preferences" msgstr "Параметры столбцов" #: ../quodlibet/qltk/prefs.py:130 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "Применить текущие параметры к списку, добавив новые столбцы в конец" #: ../quodlibet/qltk/prefs.py:143 ../quodlibet/qltk/shortcuts.py:25 msgid "Song List" msgstr "Список треков" #: ../quodlibet/qltk/prefs.py:223 msgid "Edit Columns" msgstr "Изменить столбцы" #: ../quodlibet/qltk/prefs.py:260 msgid "Duration totals" msgstr "Общая длительность" #: ../quodlibet/qltk/prefs.py:272 msgid "_Global filter:" msgstr "_Общий фильтр:" #: ../quodlibet/qltk/prefs.py:278 msgid "Apply this query in addition to all others" msgstr "Применять этот запрос в дополнение ко всем другим" #. Translators: The heading of the preference group, no action #: ../quodlibet/qltk/prefs.py:284 msgctxt "heading" msgid "Search" msgstr "Поиск" #: ../quodlibet/qltk/prefs.py:288 ../quodlibet/qltk/shortcuts.py:22 msgid "Browsers" msgstr "Режимы отображения" #: ../quodlibet/qltk/prefs.py:294 msgid "Confirm _multiple ratings" msgstr "_Запрашивать подтверждение при множественном изменении оценок" #: ../quodlibet/qltk/prefs.py:296 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "" "Подтверждение, перед сменой оценки сразу нескольким трекам" #: ../quodlibet/qltk/prefs.py:299 msgid "Enable _one-click ratings" msgstr "О_ценивать трек одним щелчком" #: ../quodlibet/qltk/prefs.py:301 msgid "Enable rating by clicking on the rating column in the song list" msgstr "Изменять оценку трека при щелчке в соответствующем столбце" #: ../quodlibet/qltk/prefs.py:307 ../quodlibet/qltk/prefs.py:627 msgid "Ratings" msgstr "Оценка" #. Filename choice algorithm config #: ../quodlibet/qltk/prefs.py:313 msgid "Prefer _embedded art" msgstr "_Предпочитать внедрённую обложку" #: ../quodlibet/qltk/prefs.py:315 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "Предпочитать изображение, внедрённое в аудиофайл, если такое есть " #: ../quodlibet/qltk/prefs.py:320 msgid "_Fixed image filename:" msgstr "_Только с указанным именем:" #: ../quodlibet/qltk/prefs.py:322 msgid "The single image filename to use if selected" msgstr "Будут использоваться файлы только с указанным именем" #: ../quodlibet/qltk/prefs.py:328 msgid "The album art image file to use when forced (supports wildcards)" msgstr "Файл изображения, используемый принудительно (подд. подстановки)" #: ../quodlibet/qltk/prefs.py:338 msgid "Album Art" msgstr "Обложки альбома" #: ../quodlibet/qltk/prefs.py:359 msgid "Playback" msgstr "Воспроизведение" #: ../quodlibet/qltk/prefs.py:364 msgid "Output Configuration" msgstr "Параметры воспроизведения" #: ../quodlibet/qltk/prefs.py:375 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" "Если информация Replay Gain для трека отсутствует, изменять уровень " "громкости на это значение" #: ../quodlibet/qltk/prefs.py:378 msgid "_Fall-back gain (dB):" msgstr "_Усиление по умолчанию (дБ):" #: ../quodlibet/qltk/prefs.py:389 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "" "Изменять уровень громкости всех треков на данное значение, если исходное " "значение ниже" #: ../quodlibet/qltk/prefs.py:392 msgid "_Pre-amp gain (dB):" msgstr "_Предусиление громкости (дБ):" #: ../quodlibet/qltk/prefs.py:397 msgid "_Enable Replay Gain volume adjustment" msgstr "Корректировка _громкости Replay Gain" #: ../quodlibet/qltk/prefs.py:422 msgid "Replay Gain Volume Adjustment" msgstr "Настройка Replay Gain" #: ../quodlibet/qltk/prefs.py:452 msgid "_Default rating:" msgstr "_Оценка по умолчанию:" #: ../quodlibet/qltk/prefs.py:495 msgid "Rating _scale:" msgstr "_Шкала оценок:" #: ../quodlibet/qltk/prefs.py:544 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:549 msgid "_Bayesian averaging amount:" msgstr "_Усреднение по Байесу:" #: ../quodlibet/qltk/prefs.py:558 msgid "Save ratings and play _counts in tags" msgstr "Со_хранять оценки и счетчики воспроизведений в тегах" #: ../quodlibet/qltk/prefs.py:566 msgid "_Email:" msgstr "_Электронная почта:" #: ../quodlibet/qltk/prefs.py:568 msgid "Ratings and play counts will be saved in tags for this email address" msgstr "" "Оценки и счётчики воспроизведений будут сохранены в тегах для этого адреса " "электронной почты" #: ../quodlibet/qltk/prefs.py:588 msgid "Auto-save tag changes" msgstr "Сохранять изменения тегов автоматически" #: ../quodlibet/qltk/prefs.py:590 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "" "Сохранять изменения тегов без подтверждения при редактировании нескольких " "файлов" #: ../quodlibet/qltk/prefs.py:598 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:621 msgid "Tags" msgstr "Теги" #: ../quodlibet/qltk/prefs.py:642 msgid "Updating for new ratings" msgstr "Обновлять оценки" #: ../quodlibet/qltk/prefs.py:652 msgid "Scan library _on start" msgstr "Сканировать ф_онотеку при запуске" #: ../quodlibet/qltk/prefs.py:662 ../quodlibet/qltk/quodlibetwindow.py:1137 msgid "_Scan Library" msgstr "_Сканировать" #: ../quodlibet/qltk/prefs.py:664 ../quodlibet/qltk/quodlibetwindow.py:1199 msgid "Check for changes in your library" msgstr "Проверить наличие изменений в фонотеке" #: ../quodlibet/qltk/prefs.py:669 msgid "Re_build Library" msgstr "Пере_загрузить фонотеку" #: ../quodlibet/qltk/prefs.py:672 msgid "Reload all songs in your library. This can take a long time." msgstr "" "Перезагрузить все треки в фонотеке. Это может занять много времени." #: ../quodlibet/qltk/prefs.py:682 msgid "Scan Directories" msgstr "Сканировать папки" #: ../quodlibet/qltk/prefs.py:688 msgid "Hidden Songs" msgstr "Скрытые треки" #: ../quodlibet/qltk/properties.py:159 ../quodlibet/util/collection.py:403 #, 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:163 ../quodlibet/qltk/properties.py:165 msgid "Properties" msgstr "Свойства" #: ../quodlibet/qltk/queue.py:103 msgid "_Queue" msgstr "_Очередь" #: ../quodlibet/qltk/queue.py:127 msgid "Stop Once Empty" msgstr "Стоп, если пусто" #: ../quodlibet/qltk/queue.py:131 msgid "_Clear Queue" msgstr "_Очистить очередь" #: ../quodlibet/qltk/queue.py:242 #, 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:200 msgid "_Browse Library" msgstr "Про_смотр фонотеки" #: ../quodlibet/qltk/quodlibetwindow.py:397 msgid "Toggle queue visibility" msgstr "Показать/скрыть очередь" #: ../quodlibet/qltk/quodlibetwindow.py:518 msgid "Playback Error" msgstr "Ошибка воспроизведения" #: ../quodlibet/qltk/quodlibetwindow.py:526 msgid "Set up library directories?" msgstr "Выбрать расположение фонотеки?" #: ../quodlibet/qltk/quodlibetwindow.py:527 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "Расположение фонотеки ещё не выбрано. Сделать это сейчас?" #: ../quodlibet/qltk/quodlibetwindow.py:533 msgid "_Not Now" msgstr "_Не сейчас" #: ../quodlibet/qltk/quodlibetwindow.py:534 msgid "_Set Up" msgstr "_Выбрать" #: ../quodlibet/qltk/quodlibetwindow.py:993 msgid "Unable to add songs" msgstr "Не удалось добавить треки" #: ../quodlibet/qltk/quodlibetwindow.py:994 #: ../quodlibet/qltk/quodlibetwindow.py:1398 #, python-format msgid "%s uses an unsupported protocol." msgstr "%s использует неподдерживаемый протокол." #: ../quodlibet/qltk/quodlibetwindow.py:1017 msgid "_Jump to Playing Song" msgstr "Перейти _к текущему" #: ../quodlibet/qltk/quodlibetwindow.py:1023 msgid "_File" msgstr "_Файл" #: ../quodlibet/qltk/quodlibetwindow.py:1024 msgid "_Song" msgstr "_Трек" #: ../quodlibet/qltk/quodlibetwindow.py:1025 msgid "_View" msgstr "_Вид" #: ../quodlibet/qltk/quodlibetwindow.py:1026 msgid "_Browse" msgstr "_Просмотр" #: ../quodlibet/qltk/quodlibetwindow.py:1027 msgid "_Control" msgstr "_Управление" #: ../quodlibet/qltk/quodlibetwindow.py:1028 msgid "_Help" msgstr "Помо_щь" #: ../quodlibet/qltk/quodlibetwindow.py:1034 msgid "_Add a Folder…" msgstr "Добавить пап_ку…" #: ../quodlibet/qltk/quodlibetwindow.py:1039 msgid "_Add a File…" msgstr "Добавить _файл…" #: ../quodlibet/qltk/quodlibetwindow.py:1044 msgid "_Add a Location…" msgstr "Добавить _адрес…" #: ../quodlibet/qltk/quodlibetwindow.py:1073 msgid "Edit Bookmarks…" msgstr "Изменить закладки…" #: ../quodlibet/qltk/quodlibetwindow.py:1093 msgid "Stop After This Song" msgstr "Стоп после трека" #: ../quodlibet/qltk/quodlibetwindow.py:1099 msgid "_Keyboard Shortcuts" msgstr "Сочетания клавиш" #: ../quodlibet/qltk/quodlibetwindow.py:1108 msgid "Online Help" msgstr "Справка онлайн" #: ../quodlibet/qltk/quodlibetwindow.py:1117 msgid "Search Help" msgstr "Справка онлайн по поиску" #: ../quodlibet/qltk/quodlibetwindow.py:1386 msgid "Add a Location" msgstr "Добавить адрес" #: ../quodlibet/qltk/quodlibetwindow.py:1387 msgid "Enter the location of an audio file:" msgstr "Введите адрес аудиофайла:" #: ../quodlibet/qltk/quodlibetwindow.py:1392 #: ../quodlibet/qltk/quodlibetwindow.py:1397 msgid "Unable to add location" msgstr "Не удалось добавить адрес" #: ../quodlibet/qltk/quodlibetwindow.py:1393 #, python-format msgid "%s is not a valid location." msgstr "%s не является корректным адресом." #: ../quodlibet/qltk/quodlibetwindow.py:1406 #: ../quodlibet/qltk/quodlibetwindow.py:1415 msgid "Add Music" msgstr "Добавить музыку" #: ../quodlibet/qltk/quodlibetwindow.py:1406 ../quodlibet/qltk/scanbox.py:100 msgid "_Add Folders" msgstr "Добавить пап_ки" #: ../quodlibet/qltk/quodlibetwindow.py:1413 msgid "Music Files" msgstr "Музыкальные файлы" #: ../quodlibet/qltk/quodlibetwindow.py:1415 msgid "_Add Files" msgstr "Добавить _файлы" #: ../quodlibet/qltk/ratingsmenu.py:25 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "Изменить оценку %d треков?" #: ../quodlibet/qltk/ratingsmenu.py:27 msgid "The saved ratings will be removed" msgstr "Сохраненные оценки будут удалены" #: ../quodlibet/qltk/ratingsmenu.py:28 #, python-format msgid "The rating of all selected songs will be changed to '%s'" msgstr "Оценка всех треков будет изменена на '%s'." #: ../quodlibet/qltk/ratingsmenu.py:58 ../quodlibet/qltk/ratingsmenu.py:112 msgid "_Remove Rating" msgstr "_Удалить оценку" #: ../quodlibet/qltk/ratingsmenu.py:99 msgid "Change _Rating" msgstr "Изменить о_ценку" #: ../quodlibet/qltk/renamefiles.py:53 msgid "Replace spaces with _underscores" msgstr "_Заменить пробел подчёркиванием" #: ../quodlibet/qltk/renamefiles.py:63 msgid "Strip _Windows-incompatible characters" msgstr "Заменить _Windows-несовместимые символы" #: ../quodlibet/qltk/renamefiles.py:81 msgid "Strip _diacritical marks" msgstr "_Удалить диакритические знаки" #: ../quodlibet/qltk/renamefiles.py:92 msgid "Strip non-_ASCII characters" msgstr "Заменить не-_ASCII символы" #: ../quodlibet/qltk/renamefiles.py:102 msgid "Use only _lowercase characters" msgstr "_Только строчные символы" #: ../quodlibet/qltk/renamefiles.py:130 msgid "Rename Files" msgstr "Переименовать файлы" #: ../quodlibet/qltk/renamefiles.py:148 ../quodlibet/qltk/tagsfrompath.py:117 msgid "Path Patterns" msgstr "Шаблон пути к файлам" #: ../quodlibet/qltk/renamefiles.py:149 ../quodlibet/qltk/tagsfrompath.py:118 msgid "Edit saved patterns…" msgstr "Изменить сохранённые шаблоны…" #: ../quodlibet/qltk/renamefiles.py:152 ../quodlibet/qltk/tagsfrompath.py:121 #: ../quodlibet/qltk/tracknumbers.py:59 msgid "_Preview" msgstr "_Предпросмотр" #: ../quodlibet/qltk/renamefiles.py:179 msgid "File names" msgstr "Имя файла" #: ../quodlibet/qltk/renamefiles.py:189 msgid "_Move album art" msgstr "Переместить обложку альбома" #: ../quodlibet/qltk/renamefiles.py:192 msgid "See '[albumart] filenames' config entry for image search strings" msgstr "" "Смотрите строку конфигурации '[albumart] filenames' поиска имен файлов" #: ../quodlibet/qltk/renamefiles.py:197 msgid "_Overwrite album art at target" msgstr "Перезаписать _обложку альбома в месте назначения" #: ../quodlibet/qltk/renamefiles.py:205 msgid "_Remove empty directories" msgstr "Удалить пустые папки" #: ../quodlibet/qltk/renamefiles.py:211 msgid "Album art" msgstr "Обложка альбома" #: ../quodlibet/qltk/renamefiles.py:240 msgid "New Name" msgstr "Новое имя" #: ../quodlibet/qltk/renamefiles.py:317 msgid "Unable to rename file" msgstr "Не удалось переименовать файл" #: ../quodlibet/qltk/renamefiles.py:318 #, python-format msgid "" "Renaming <b>%(old-name)s</b> to <b>%(new-name)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." msgstr "" "Не удалось переименовать <b>%(old-name)s</b> в <b>%(new-name)s</b>. " "Возможно, целевой файл уже существует, или вы не имеете прав для создания " "нового или удаления старого файла." #: ../quodlibet/qltk/renamefiles.py:326 msgid "Ignore _All Errors" msgstr "_Пропустить все ошибки" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: ../quodlibet/qltk/renamefiles.py:327 ../quodlibet/qltk/wlw.py:51 msgid "_Stop" msgstr "_Стоп" #: ../quodlibet/qltk/renamefiles.py:329 msgid "_Continue" msgstr "_Продолжить" #: ../quodlibet/qltk/renamefiles.py:442 msgid "Path is not absolute" msgstr "Неабсолютный путь" #: ../quodlibet/qltk/renamefiles.py:443 #, python-format msgid "" "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 ~/." msgstr "" "Шаблон\n" "\t<b>%s</b>\n" "содержит '/', но начинается не с корневого каталога. Чтобы избежать ошибки в " "названиях папок, начните шаблон с '/' или '~/'." #: ../quodlibet/qltk/scanbox.py:48 msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "" "Треки, расположенные в этих папках, будут добавлены в фонотеку" #: ../quodlibet/qltk/scanbox.py:100 msgid "Select Directories" msgstr "Выбор папок" #: ../quodlibet/qltk/searchbar.py:54 msgid "Saved Searches" msgstr "Сохранённые запросы" #: ../quodlibet/qltk/searchbar.py:55 msgid "Edit saved searches…" msgstr "Изменить сохранённые запросы…" #: ../quodlibet/qltk/searchbar.py:79 msgid "Search your library, using free text or QL queries" msgstr "Поиск по фонотеке с помощью свободного текста или запросов QL" #: ../quodlibet/qltk/searchbar.py:141 msgid "Search after _typing" msgstr "_Производить поиск по окончании ввода" #: ../quodlibet/qltk/searchbar.py:144 msgid "Show search results after the user stops typing" msgstr "Производить поиск сразу после прекращения ввода" #: ../quodlibet/qltk/searchbar.py:208 msgid "_Limit:" msgstr "_Ограничение:" #: ../quodlibet/qltk/searchbar.py:221 msgid "_Weight" msgstr "По _оценкам" #: ../quodlibet/qltk/seekbutton.py:239 msgid "Display remaining time" msgstr "Отображать оставшееся время" #: ../quodlibet/qltk/shortcuts.py:17 msgid "Main Window" msgstr "Главное окно" #: ../quodlibet/qltk/shortcuts.py:18 msgid "Seek backwards by 10 seconds" msgstr "Перемотка назад на 10 секунд" #: ../quodlibet/qltk/shortcuts.py:19 msgid "Seek forward by 10 seconds" msgstr "Перемотка вперед на 10 секунд" #: ../quodlibet/qltk/shortcuts.py:20 msgid "Focus the search entry" msgstr "Фокус на строке поиска" #: ../quodlibet/qltk/shortcuts.py:23 msgid "Reset filters and jump to the playing song" msgstr "Сброс фильтров и переход к воспроизводимому треку" #: ../quodlibet/qltk/shortcuts.py:27 msgid "Open the information window for the selected songs" msgstr "Открыть информационное окно для выбранных треков" #: ../quodlibet/qltk/shortcuts.py:28 msgid "Open the tag editor for the selected songs" msgstr "Открыть редактор тегов для выбранных треков" #: ../quodlibet/qltk/shortcuts.py:29 msgid "Queue the selected songs" msgstr "Добавить в очередь выбранные треки" #: ../quodlibet/qltk/shortcuts.py:30 msgid "Delete the selected songs" msgstr "Удалить выбранные треки" #: ../quodlibet/qltk/shortcuts.py:31 msgid "Show the inline search entry" msgstr "Показать строку поиска" #: ../quodlibet/qltk/shortcuts.py:32 msgid "Left click on a column header" msgstr "Щелкните на заголовке столбца" # The line breaks ensures that the keyboard shortcut window fits on a 1280 px width screen #: ../quodlibet/qltk/shortcuts.py:33 msgid "Add the column to the list of columns to sort by" msgstr "Добавить столбец в список столбцов для сортировки" #: ../quodlibet/qltk/shortcuts.py:35 msgid "Tree View" msgstr "В виде дерева" #: ../quodlibet/qltk/shortcuts.py:37 msgid "Collapses the element or select the parent element" msgstr "Свернуть элемент или выбрать родительский элемент" #: ../quodlibet/qltk/shortcuts.py:38 msgid "Expands the element" msgstr "Развернуть элемент" #: ../quodlibet/qltk/shortcuts.py:40 msgid "Text Entries" msgstr "Текстовые поля" #: ../quodlibet/qltk/shortcuts.py:42 msgid "Undo the last change" msgstr "Отменить последнее изменение" #: ../quodlibet/qltk/shortcuts.py:43 msgid "Redo the last undone change" msgstr "Повторить последнее отмененное изменение" #: ../quodlibet/qltk/shortcuts.py:46 msgid "Select all songs in all panes" msgstr "Выбрать все треки на всех панелях" #: ../quodlibet/qltk/songlist.py:366 #, python-format msgid "_Filter on %s" msgstr "Фильтр по %s" #: ../quodlibet/qltk/songlist.py:1083 msgid "All _Headers" msgstr "_Все заголовки" #: ../quodlibet/qltk/songlist.py:1084 msgid "_Track Headers" msgstr "_Трек" #: ../quodlibet/qltk/songlist.py:1085 msgid "_Album Headers" msgstr "_Альбом" #: ../quodlibet/qltk/songlist.py:1086 msgid "_People Headers" msgstr "_Люди" #: ../quodlibet/qltk/songlist.py:1087 msgid "_Date Headers" msgstr "_Дата" #: ../quodlibet/qltk/songlist.py:1088 msgid "_File Headers" msgstr "_Файл" #: ../quodlibet/qltk/songlist.py:1089 msgid "_Production Headers" msgstr "_Производство" #: ../quodlibet/qltk/songlist.py:1104 msgid "_Customize Headers…" msgstr "_Настроить…" #: ../quodlibet/qltk/songlist.py:1109 msgid "_Expand Column" msgstr "Автоши_рина" #: ../quodlibet/qltk/songsmenu.py:42 #, python-format msgid "Remove track: \"%%(title)s\" from library?" msgid_plural "Remove %(count)d tracks from library?" msgstr[0] "Удалить %(count)d трек из фонотеки?" msgstr[1] "Удалить %(count)d трека из фонотеки?" msgstr[2] "Удалить %(count)d треков из фонотеки?" #: ../quodlibet/qltk/songsmenu.py:48 msgid "Remove from Library" msgstr "Удалить из фонотеки" #: ../quodlibet/qltk/songsmenu.py:53 #, 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:64 #, 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:136 msgid "Configure Plugins…" msgstr "Настройки расширений…" #: ../quodlibet/qltk/songsmenu.py:331 msgid "Add to _Queue" msgstr "Добавить в _очередь" #: ../quodlibet/qltk/songsmenu.py:351 msgid "_Remove from Library…" msgstr "Удалить из _фонотеки…" #: ../quodlibet/qltk/songsmenu.py:415 msgid "Unable to show files" msgstr "Не удается отобразить файлы" #: ../quodlibet/qltk/songsmenu.py:416 msgid "Error showing files, or no program available to show them." msgstr "Ошибка отображения файлов, или нет программы для их отображения." #: ../quodlibet/qltk/songsmenu.py:423 #, 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/tagsfrompath.py:48 msgid "Replace _underscores with spaces" msgstr "_Заменить подчёркивание пробелом" #: ../quodlibet/qltk/tagsfrompath.py:58 msgid "_Title-case tags" msgstr "С з_аглавных" #: ../quodlibet/qltk/tagsfrompath.py:68 msgid "Split into multiple _values" msgstr "_Разделить на несколько значений" #: ../quodlibet/qltk/tagsfrompath.py:102 msgid "Tags From Path" msgstr "Теги из пути файла" #: ../quodlibet/qltk/tagsfrompath.py:139 msgid "Tags replace existing ones" msgstr "Теги заменят существующие" #: ../quodlibet/qltk/tagsfrompath.py:140 msgid "Tags are added to existing ones" msgstr "Теги будут добавлены к существующим" #: ../quodlibet/qltk/tagsfrompath.py:196 #, python-format msgid "" "The pattern\n" "\t<b>%s</b>\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" "Шаблон\n" "\t<b>%s</b>\n" "недопустим. Возможно, он содержит незакрытые скобки (< / >) или один и " "тот же тег дважды." #: ../quodlibet/qltk/tagsfrompath.py:217 msgid "Invalid tags" msgstr "Недопустимые теги" #: ../quodlibet/qltk/tagsfrompath.py:218 #, 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" "Выбранные файлы не поддерживают изменение этих тегов." #: ../quodlibet/qltk/textedit.py:143 #, 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:159 msgid "Edit Display" msgstr "Изменить внешний вид" #: ../quodlibet/qltk/tracknumbers.py:40 msgid "Track Numbers" msgstr "Номера треков" #: ../quodlibet/qltk/tracknumbers.py:43 msgid "Start fro_m:" msgstr "_Начинать с:" #: ../quodlibet/qltk/tracknumbers.py:52 msgid "_Total tracks:" msgstr "Всего _треков:" #: ../quodlibet/qltk/unity.py:53 msgid "Play/Pause" msgstr "Воспроизведение/Пауза" #: ../quodlibet/qltk/unity.py:73 msgid "Previous" msgstr "Предыдущий" #: ../quodlibet/qltk/views.py:924 #, python-format msgid "and %d more…" msgstr "и ещё %d…" #: ../quodlibet/qltk/wlw.py:201 msgid "Saving the songs you changed." msgstr "Сохранение изменений." #: ../quodlibet/qltk/wlw.py:202 #, 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:235 #, 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:425 msgid "Playlists must have a name" msgstr "Плейлисты должны иметь имя" #: ../quodlibet/util/collection.py:608 #, python-format msgid "A playlist named %s already exists." msgstr "Плейлист с названием '%s' уже существует." #: ../quodlibet/util/cover/built_in.py:33 msgid "Embedded album covers" msgstr "Встроенные обложки альбомов" #: ../quodlibet/util/cover/built_in.py:34 msgid "Uses covers embedded into audio files." msgstr "Показывает обложки, внедрённые в аудиофайлы." #: ../quodlibet/util/cover/built_in.py:56 msgid "Filesystem cover" msgstr "Обложки из отдельных файлов" #: ../quodlibet/util/cover/built_in.py:57 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "" "Использует стандартно именованные изображения, из папки с треком." #: ../quodlibet/util/cover/manager.py:231 msgid "Cover Art" msgstr "Обложка" #: ../quodlibet/util/cover/manager.py:231 msgid "Querying album art providers" msgstr "Поиск у поставщиков обложек альбомов" #: ../quodlibet/util/__init__.py:77 msgid "Display brief usage information" msgstr "Вывести краткую информацию об использовании" #: ../quodlibet/util/__init__.py:79 msgid "Display version and copyright" msgstr "Вывести версию и информацию об авторских правах" #: ../quodlibet/util/__init__.py:80 msgid "Print debugging information" msgstr "Вывести отладочную информацию" #: ../quodlibet/util/__init__.py:119 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "Используется: %(program)s %(usage)s" #: ../quodlibet/util/__init__.py:121 msgid "[options]" msgstr "[options]" #: ../quodlibet/util/__init__.py:166 #, python-format msgid "Option %r not recognized." msgstr "Неопознанный параметр '%r'." #: ../quodlibet/util/__init__.py:169 #, python-format msgid "Option %r requires an argument." msgstr "Для параметра '%r' требуется аргумент." #: ../quodlibet/util/__init__.py:172 #, python-format msgid "%r is not a unique prefix." msgstr "%r — не уникальный префикс." #: ../quodlibet/util/__init__.py:348 #, python-format msgid "%d kbps" msgstr "%d кбит/с" #: ../quodlibet/util/__init__.py:403 #, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%s секунда" msgstr[1] "%s секунды" msgstr[2] "%s секунд" #: ../quodlibet/util/__init__.py:416 msgid "No time information" msgstr "Нет информации о времени" #: ../quodlibet/util/__init__.py:419 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d секунда" msgstr[1] "%d секунды" msgstr[2] "%d секунд" #: ../quodlibet/util/__init__.py:420 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d минута" msgstr[1] "%d минуты" msgstr[2] "%d минут" #: ../quodlibet/util/__init__.py:421 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d час" msgstr[1] "%d часа" msgstr[2] "%d часов" #: ../quodlibet/util/__init__.py:422 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d день" msgstr[1] "%d дня" msgstr[2] "%d дней" #: ../quodlibet/util/__init__.py:423 #, 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:515 msgctxt "check" msgid "titlecase?" msgstr "firstcapital" #: ../quodlibet/util/massagers.py:116 msgid "" "The date must be entered in 'YYYY', 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS' " "format." msgstr "" "Дата должна быть в формате 'ГГГГ', 'ГГГГ-ММ-ДД' или 'ГГГГ-ММ-ДД ЧЧ:ММ:СС'." #: ../quodlibet/util/massagers.py:131 msgid "Replay Gain gains must be entered in 'x.yy dB' format." msgstr "Значения усилений Replay Gain должны быть в формате 'x.yy dB'." #: ../quodlibet/util/massagers.py:152 msgid "Replay Gain peaks must be entered in 'x.yy' format." msgstr "Значения пиков Replay Gain должны быть введены в формате «x.yy»." #: ../quodlibet/util/massagers.py:174 msgid "MusicBrainz IDs must be in UUID format." msgstr "ID MusicBrainz должны быть в формате UUID." #. Translators: Leave "official", "promotional", and "bootleg" #. untranslated. They are the three possible literal values. #: ../quodlibet/util/massagers.py:196 msgid "" "MusicBrainz release status must be 'official', 'promotional', or 'bootleg'." msgstr "" "Статус выпуска MusicBrainz должен быть 'official', 'promotional' или " "'bootleg'." #: ../quodlibet/util/massagers.py:209 msgid "Language must be an ISO 639-2 three-letter code" msgstr "Язык должен быть трехзначным кодом ISO 639-2" #: ../quodlibet/util/songwrapper.py:117 msgid "Unable to edit song" msgstr "Не удалось изменить трек" #: ../quodlibet/util/songwrapper.py:118 #, python-format msgid "" "Saving <b>%s</b> 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:35 #: ../quodlibet/util/string/__init__.py:45 msgid "[Invalid Encoding]" msgstr "[Неверная кодировка]" #: ../quodlibet/util/tags.py:85 msgid "album" msgstr "альбом" #: ../quodlibet/util/tags.py:86 msgid "arranger" msgstr "аранжировщик" #: ../quodlibet/util/tags.py:86 msgid "arrangers" msgstr "аранжировщики" #: ../quodlibet/util/tags.py:86 msgid "arrangement" msgstr "аранжировка" #: ../quodlibet/util/tags.py:88 msgid "author" msgstr "автор" #: ../quodlibet/util/tags.py:88 msgid "authors" msgstr "авторы" #: ../quodlibet/util/tags.py:89 msgid "comment" msgstr "комментарий" #: ../quodlibet/util/tags.py:90 msgid "composer" msgstr "композитор" #: ../quodlibet/util/tags.py:90 msgid "composers" msgstr "композиторы" #: ../quodlibet/util/tags.py:90 msgid "composition" msgstr "композиция" #. Translators: conducting as in conducting a musical performance #: ../quodlibet/util/tags.py:92 msgid "conductor" msgstr "дирижёр" #: ../quodlibet/util/tags.py:92 msgid "conductors" msgstr "дирижёры" #: ../quodlibet/util/tags.py:92 msgid "conducting" msgstr "дирижирование" #: ../quodlibet/util/tags.py:93 msgid "contact" msgstr "контакты" #: ../quodlibet/util/tags.py:94 msgid "copyright" msgstr "авторское право" #: ../quodlibet/util/tags.py:95 msgid "date" msgstr "дата" #: ../quodlibet/util/tags.py:96 msgid "description" msgstr "описание" #: ../quodlibet/util/tags.py:97 msgid "genre" msgstr "жанр" #: ../quodlibet/util/tags.py:97 msgid "genres" msgstr "жанры" #: ../quodlibet/util/tags.py:98 msgid "performer" msgstr "интерпритатор" #: ../quodlibet/util/tags.py:98 msgid "performance" msgstr "исполнение" #: ../quodlibet/util/tags.py:99 msgid "grouping" msgstr "группировка" #: ../quodlibet/util/tags.py:100 msgid "language" msgstr "язык" #: ../quodlibet/util/tags.py:101 msgid "license" msgstr "лицензия" #: ../quodlibet/util/tags.py:102 msgid "location" msgstr "место записи" #: ../quodlibet/util/tags.py:103 msgid "lyricist" msgstr "автор слов" #: ../quodlibet/util/tags.py:103 msgid "lyricists" msgstr "авторы слов" #: ../quodlibet/util/tags.py:103 msgid "lyrics" msgstr "текст песни" #. Translators: Also e.g. "record label", "publisher" #: ../quodlibet/util/tags.py:105 msgid "organization" msgstr "организация" #: ../quodlibet/util/tags.py:106 msgid "title" msgstr "название" #: ../quodlibet/util/tags.py:107 msgid "version" msgstr "версия" #: ../quodlibet/util/tags.py:108 msgid "website" msgstr "веб-сайт" #: ../quodlibet/util/tags.py:110 msgid "album artist" msgstr "исполнитель альбома" #: ../quodlibet/util/tags.py:111 msgid "BPM" msgstr "BPM" #. Translators: This used to be called "part". #: ../quodlibet/util/tags.py:114 ../quodlibet/util/tags.py:115 msgid "disc subtitle" msgstr "субтитры" #: ../quodlibet/util/tags.py:116 ../quodlibet/util/tags.py:153 msgid "disc" msgstr "диск" #: ../quodlibet/util/tags.py:117 ../quodlibet/util/tags.py:155 msgid "track" msgstr "трек" #: ../quodlibet/util/tags.py:118 msgid "label ID" msgstr "Label-ID" #: ../quodlibet/util/tags.py:119 msgid "original release date" msgstr "дата оригинала" #: ../quodlibet/util/tags.py:120 msgid "original album" msgstr "оригинальный альбом" #: ../quodlibet/util/tags.py:121 msgid "original artist" msgstr "оригинальный исполнитель" #: ../quodlibet/util/tags.py:122 msgid "recording date" msgstr "дата записи" #: ../quodlibet/util/tags.py:123 msgid "release country" 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:132 msgid "MusicBrainz recording ID" msgstr "MusicBrainz ID записи" #: ../quodlibet/util/tags.py:133 msgid "MusicBrainz release track ID" msgstr "MusicBrainz ID трека выпуска" #: ../quodlibet/util/tags.py:134 msgid "MusicBrainz release ID" msgstr "MusicBrainz ID выпуска" #: ../quodlibet/util/tags.py:135 msgid "MusicBrainz artist ID" msgstr "MusicBrainz ID исполнителя" #: ../quodlibet/util/tags.py:136 msgid "MusicBrainz release artist ID" msgstr "MusicBrainz ID исполнителя выпуска" #: ../quodlibet/util/tags.py:137 msgid "MusicBrainz TRM ID" msgstr "MusicBrainz TRM ID" #: ../quodlibet/util/tags.py:138 msgid "MusicIP PUID" msgstr "MusicIP PUID" #: ../quodlibet/util/tags.py:139 msgid "MusicBrainz album status" msgstr "Статус альбома MusicBrainz" #: ../quodlibet/util/tags.py:140 msgid "MusicBrainz album type" msgstr "Тип альбома MusicBrainz" #: ../quodlibet/util/tags.py:141 msgid "MusicBrainz release group ID" msgstr "MusicBrainz ID выпуска" #. Translators: "gain" means a volume adjustment, not "to acquire". #: ../quodlibet/util/tags.py:144 msgid "track gain" msgstr "усиление трека" #: ../quodlibet/util/tags.py:145 msgid "track peak" msgstr "пик трека" #. Translators: "gain" means a volume adjustment, not "to acquire". #: ../quodlibet/util/tags.py:147 msgid "album gain" msgstr "усиление альбома" #: ../quodlibet/util/tags.py:148 msgid "album peak" msgstr "пик альбома" #: ../quodlibet/util/tags.py:149 msgid "reference loudness" msgstr "эталонная громкость" #: ../quodlibet/util/tags.py:154 msgid "discs" msgstr "диски" #: ../quodlibet/util/tags.py:156 msgid "tracks" msgstr "треков" #: ../quodlibet/util/tags.py:157 msgid "last started" msgstr "последний запуск" #: ../quodlibet/util/tags.py:158 msgid "full name" msgstr "полное имя" #: ../quodlibet/util/tags.py:165 msgid "mount point" msgstr "точка монтирования" #: ../quodlibet/util/tags.py:167 msgid "people" msgstr "люди" #: ../quodlibet/util/tags.py:169 msgid "year" msgstr "год" #: ../quodlibet/util/tags.py:170 msgid "original release year" msgstr "год оригинала" #: ../quodlibet/util/tags.py:171 msgid "bookmark" msgstr "закладка" #: ../quodlibet/util/tags.py:174 msgid "file format" msgstr "тип" #: ../quodlibet/util/tags.py:177 msgid "playlists" msgstr "плейлисты" #: ../quodlibet/util/tags.py:178 msgid "channel count" msgstr "каналов" #. Translators: e.g. "artist (sort)" #: ../quodlibet/util/tags.py:268 msgid "sort" msgstr "сортировка" #. Translators: e.g. "performer (roles)" #: ../quodlibet/util/tags.py:276 msgid "roles" msgstr "роли" ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9751859 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/po/sk.po����������������������������������������������������������������������������0000644�0001750�0001750�00000521623�00000000000�014102� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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: 2017-05-17 18:58+0200\n" "PO-Revision-Date: 2006-11-08 19:59+0100\n" "Last-Translator: Lukáš Lalinský <lalinsky@gmail.com>\n" "Language-Team: Slovak <sk@li.org>\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" #: ../data/exfalso.appdata.xml.in.h:1 ../data/exfalso.desktop.in.h:2 msgid "Edit tags in your audio files" msgstr "Upraviť tagy vo vašich audio súboroch" #: ../data/exfalso.appdata.xml.in.h:2 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/exfalso.appdata.xml.in.h:3 ../data/quodlibet.appdata.xml.in.h:3 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/exfalso.desktop.in.h:1 msgid "Audio tag editor" msgstr "Editor audio tagov" #: ../data/quodlibet.appdata.xml.in.h:1 ../data/quodlibet.desktop.in.h:2 msgid "Listen to, browse, or edit your audio collection" msgstr "Počúvajte, prehliadajte, alebo upravujte svoju hudobnú kolekciu" #: ../data/quodlibet.appdata.xml.in.h:2 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 "" #: ../data/quodlibet.desktop.in.h:1 msgid "Music Player" msgstr "Hudobný prehrávač" #: ../quodlibet/browsers/albums/main.py:168 #: ../quodlibet/browsers/covergrid/main.py:54 #, fuzzy msgid "_Title" msgstr "Názov" #: ../quodlibet/browsers/albums/main.py:169 #: ../quodlibet/browsers/covergrid/main.py:55 ../quodlibet/qltk/prefs.py:49 msgid "_Artist" msgstr "_Interpret" #: ../quodlibet/browsers/albums/main.py:170 #: ../quodlibet/browsers/covergrid/main.py:56 ../quodlibet/qltk/prefs.py:54 msgid "_Date" msgstr "_Dátum" #: ../quodlibet/browsers/albums/main.py:171 #: ../quodlibet/browsers/covergrid/main.py:57 ../quodlibet/qltk/prefs.py:53 #, fuzzy msgid "_Genre" msgstr "žáner" #: ../quodlibet/browsers/albums/main.py:172 #: ../quodlibet/browsers/covergrid/main.py:58 ../quodlibet/qltk/prefs.py:58 #: ../quodlibet/qltk/ratingsmenu.py:39 msgid "_Rating" msgstr "_Hodnotenie" #: ../quodlibet/browsers/albums/main.py:178 #: ../quodlibet/browsers/covergrid/main.py:64 #, fuzzy msgid "Sort _by…" msgstr "Podľa dátumu" #: ../quodlibet/browsers/albums/main.py:199 #: ../quodlibet/browsers/covergrid/main.py:85 #: ../quodlibet/browsers/paned/prefs.py:166 #: ../quodlibet/browsers/playlists/main.py:629 #: ../quodlibet/qltk/exfalsowindow.py:109 ../quodlibet/qltk/pluginwin.py:341 #: ../quodlibet/qltk/quodlibetwindow.py:1016 #, fuzzy msgid "_Preferences" msgstr "Nastavenie" #: ../quodlibet/browsers/albums/main.py:361 msgid "Album List" msgstr "Zoznam albumov" #: ../quodlibet/browsers/albums/main.py:362 msgid "_Album List" msgstr "Zoznam _albumov" #: ../quodlibet/browsers/albums/main.py:472 #: ../quodlibet/browsers/covergrid/main.py:279 #: ../quodlibet/browsers/covergrid/main.py:488 msgid "All Albums" msgstr "Všetky albumy" #: ../quodlibet/browsers/albums/main.py:473 #: ../quodlibet/browsers/covergrid/main.py:280 #: ../quodlibet/browsers/covergrid/main.py:489 #, 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:650 #: ../quodlibet/browsers/covergrid/main.py:467 #, fuzzy msgid "Reload album _cover" msgid_plural "Reload album _covers" msgstr[0] "Zobraziť _obaly albumov" msgstr[1] "Zobraziť _obaly albumov" msgstr[2] "Zobraziť _obaly 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 bez 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:381 ../quodlibet/util/collection.py:245 #, python-format msgid "%d track" msgid_plural "%d tracks" msgstr[0] "%d skladba" msgstr[1] "%d skladby" msgstr[2] "%d skladieb" #: ../quodlibet/browsers/albums/prefs.py:42 #: ../quodlibet/browsers/covergrid/prefs.py:44 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:97 #: ../quodlibet/qltk/information.py:379 ../quodlibet/util/collection.py:249 #, 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 #, fuzzy msgid "An Example Album" msgstr "Všetky albumy" #: ../quodlibet/browsers/albums/prefs.py:52 msgid "Album List Preferences" msgstr "Nastavenie 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 "" #: ../quodlibet/browsers/albums/prefs.py:71 #: ../quodlibet/browsers/covergrid/prefs.py:120 #, fuzzy msgid "Options" msgstr "[možnosti]" #: ../quodlibet/browsers/albums/prefs.py:74 #: ../quodlibet/browsers/covergrid/prefs.py:123 msgid "Album Display" msgstr "Zobrazenie albumov" #: ../quodlibet/browsers/albums/prefs.py:78 #: ../quodlibet/browsers/covergrid/prefs.py:127 #: ../quodlibet/browsers/media.py:39 #: ../quodlibet/browsers/playlists/prefs.py:56 #: ../quodlibet/ext/songsmenu/albumart.py:326 #: ../quodlibet/ext/songsmenu/duplicates.py:350 #: ../quodlibet/ext/songsmenu/filterall.py:48 #: ../quodlibet/qltk/bookmarks.py:101 ../quodlibet/qltk/cbes.py:93 #: ../quodlibet/qltk/data_editors.py:99 ../quodlibet/qltk/data_editors.py:324 #: ../quodlibet/qltk/exfalsowindow.py:297 ../quodlibet/qltk/pluginwin.py:79 #: ../quodlibet/qltk/pluginwin.py:427 ../quodlibet/qltk/prefs.py:707 #: ../quodlibet/qltk/textedit.py:164 ../quodlibet/update.py:148 msgid "_Close" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:55 #: ../quodlibet/browsers/audiofeeds.py:67 #: ../quodlibet/browsers/audiofeeds.py:69 #: ../quodlibet/browsers/audiofeeds.py:159 #: ../quodlibet/browsers/paned/models.py:86 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:46 #: ../quodlibet/formats/_audio.py:495 ../quodlibet/order/__init__.py:27 #: ../quodlibet/qltk/information.py:240 ../quodlibet/qltk/information.py:247 #: ../quodlibet/qltk/information.py:273 ../quodlibet/qltk/wlw.py:70 msgid "Unknown" msgstr "Neznáme" #: ../quodlibet/browsers/audiofeeds.py:246 msgid "New Feed" msgstr "Pridať kanál" #: ../quodlibet/browsers/audiofeeds.py:247 msgid "Enter the location of an audio feed:" msgstr "Vložte umiestnenie audio kanálu:" #: ../quodlibet/browsers/audiofeeds.py:248 #: ../quodlibet/browsers/collection/prefs.py:90 #: ../quodlibet/browsers/iradio.py:341 ../quodlibet/browsers/paned/prefs.py:78 #: ../quodlibet/browsers/playlists/menu.py:96 #: ../quodlibet/browsers/playlists/util.py:52 ../quodlibet/qltk/bookmarks.py:62 #: ../quodlibet/qltk/cbes.py:55 ../quodlibet/qltk/data_editors.py:311 #: ../quodlibet/qltk/edittags.py:288 ../quodlibet/qltk/edittags.py:488 #: ../quodlibet/qltk/quodlibetwindow.py:1354 ../quodlibet/qltk/scanbox.py:61 msgid "_Add" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:265 msgid "Audio Feeds" msgstr "Audio kanály" #: ../quodlibet/browsers/audiofeeds.py:266 msgid "_Audio Feeds" msgstr "_Audio kanály" #: ../quodlibet/browsers/audiofeeds.py:345 #: ../quodlibet/browsers/audiofeeds.py:350 #, fuzzy msgid "_Download…" msgstr "_Sťahovanie" #: ../quodlibet/browsers/audiofeeds.py:359 msgid "Download Files" msgstr "Sťiahnuť súbory" #. Save button #: ../quodlibet/browsers/audiofeeds.py:359 #: ../quodlibet/browsers/audiofeeds.py:371 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:81 #: ../quodlibet/ext/songsmenu/albumart.py:322 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:355 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:278 #: ../quodlibet/ext/songsmenu/html.py:76 #: ../quodlibet/ext/songsmenu/lastfmsync.py:216 #: ../quodlibet/ext/songsmenu/playlist.py:51 #: ../quodlibet/ext/songsmenu/replaygain.py:365 #: ../quodlibet/ext/songsmenu/tapbpm.py:182 ../quodlibet/qltk/_editutils.py:39 #: ../quodlibet/qltk/lyrics.py:38 ../quodlibet/qltk/msg.py:52 #: ../quodlibet/qltk/renamefiles.py:168 ../quodlibet/qltk/tracknumbers.py:113 msgid "_Save" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:371 msgid "Download File" msgstr "Sťiahnuť súbor" #: ../quodlibet/browsers/audiofeeds.py:394 #: ../quodlibet/browsers/playlists/main.py:213 #: ../quodlibet/qltk/data_editors.py:96 msgid "_New" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:454 #: ../quodlibet/browsers/audiofeeds.py:513 msgid "Unable to add feed" msgstr "Nepodarilo sa pridať kanál" #: ../quodlibet/browsers/audiofeeds.py:455 #: ../quodlibet/browsers/audiofeeds.py:514 #, fuzzy, python-format msgid "" "%s could not be added. The server may be down, or the location may not be an " "audio feed." msgstr "" "<b>%s</b> nemôže byť pridané. The server may be down, or the location may " "not be an audio feed." #. refresh button #: ../quodlibet/browsers/audiofeeds.py:462 ../quodlibet/browsers/media.py:217 #: ../quodlibet/browsers/media.py:386 ../quodlibet/qltk/filesel.py:259 #: ../quodlibet/qltk/pluginwin.py:413 #, fuzzy msgid "_Refresh" msgstr "O_bnoviť knižnicu" #: ../quodlibet/browsers/audiofeeds.py:463 #: ../quodlibet/browsers/playlists/main.py:457 #: ../quodlibet/browsers/playlists/util.py:43 ../quodlibet/qltk/delete.py:143 #: ../quodlibet/qltk/filesel.py:256 ../quodlibet/qltk/lyrics.py:39 #: ../quodlibet/qltk/maskedbox.py:28 ../quodlibet/qltk/songsmenu.py:392 #, fuzzy msgid "_Delete" msgstr "Odstrániť súbory" #: ../quodlibet/browsers/audiofeeds.py:530 msgid "" "The current audio backend does not support URLs, Audio Feeds browser " "disabled." msgstr "" #: ../quodlibet/browsers/_base.py:147 ../quodlibet/browsers/_base.py:150 msgid "Library Browser" msgstr "Prehliadať knižnice" #: ../quodlibet/browsers/_base.py:274 ../quodlibet/ext/songsmenu/refresh.py:30 #: ../quodlibet/qltk/exfalsowindow.py:241 ../quodlibet/qltk/information.py:542 #: ../quodlibet/qltk/maskedbox.py:68 ../quodlibet/util/collection.py:527 #, 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:402 ../quodlibet/browsers/_base.py:407 #: ../quodlibet/qltk/tagsfrompath.py:194 ../quodlibet/qltk/textedit.py:141 #: ../quodlibet/util/__init__.py:622 msgid "Invalid pattern" msgstr "Neplatná vzorka" #: ../quodlibet/browsers/collection/main.py:78 msgid "Album Collection" msgstr "" #: ../quodlibet/browsers/collection/main.py:79 msgid "Album _Collection" msgstr "" #: ../quodlibet/browsers/collection/models.py:24 #, fuzzy, python-format msgid "Unknown %s" msgstr "Neznáme" #: ../quodlibet/browsers/collection/models.py:25 #, fuzzy, python-format msgid "Multiple %s Values" msgstr "Rozdeliť na _viacero hodnôt" #: ../quodlibet/browsers/collection/prefs.py:66 #: ../quodlibet/browsers/paned/prefs.py:51 msgid "_Custom" msgstr "_Vlastné" #. Remove button #: ../quodlibet/browsers/collection/prefs.py:94 #: ../quodlibet/browsers/paned/prefs.py:82 #: ../quodlibet/browsers/playlists/menu.py:97 #: ../quodlibet/ext/playlist/remove_duplicates.py:60 #: ../quodlibet/qltk/bookmarks.py:97 ../quodlibet/qltk/bookmarks.py:127 #: ../quodlibet/qltk/cbes.py:82 ../quodlibet/qltk/cbes.py:89 #: ../quodlibet/qltk/data_editors.py:81 ../quodlibet/qltk/data_editors.py:94 #: ../quodlibet/qltk/data_editors.py:301 ../quodlibet/qltk/data_editors.py:314 #: ../quodlibet/qltk/data_editors.py:322 ../quodlibet/qltk/edittags.py:494 #: ../quodlibet/qltk/edittags.py:634 ../quodlibet/qltk/maskedbox.py:48 #: ../quodlibet/qltk/maskedbox.py:88 ../quodlibet/qltk/queue.py:350 #: ../quodlibet/qltk/scanbox.py:36 ../quodlibet/qltk/scanbox.py:63 #, fuzzy msgid "_Remove" msgstr "_Hodnotenie" #: ../quodlibet/browsers/collection/prefs.py:122 #: ../quodlibet/ext/songsmenu/filterall.py:34 #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:92 #: ../quodlibet/qltk/edittags.py:431 msgid "Tag" msgstr "Tag" #: ../quodlibet/browsers/collection/prefs.py:128 msgid "Merge" msgstr "" #: ../quodlibet/browsers/collection/prefs.py:188 #, fuzzy msgid "Album Collection Preferences" msgstr "Nastavenie zoznamu albumov" #: ../quodlibet/browsers/collection/prefs.py:195 #: ../quodlibet/browsers/paned/prefs.py:209 #: ../quodlibet/ext/songsmenu/editplaycount.py:45 #: ../quodlibet/ext/songsmenu/exact_rating.py:38 #: ../quodlibet/player/gstbe/prefs.py:40 ../quodlibet/qltk/prefs.py:127 #: ../quodlibet/qltk/textedit.py:65 msgid "_Apply" msgstr "" #: ../quodlibet/browsers/collection/prefs.py:198 #: ../quodlibet/browsers/paned/prefs.py:213 #: ../quodlibet/browsers/playlists/menu.py:95 #: ../quodlibet/browsers/playlists/util.py:42 #: ../quodlibet/errorreport/ui.py:108 #: ../quodlibet/ext/playlist/export_to_folder.py:37 #: ../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:44 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:281 #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:88 #: ../quodlibet/ext/songsmenu/importexport.py:35 #: ../quodlibet/ext/songsmenu/lastfmsync.py:215 #: ../quodlibet/ext/songsmenu/playlist.py:50 #: ../quodlibet/ext/songsmenu/replaygain.py:364 #: ../quodlibet/ext/songsmenu/tapbpm.py:181 ../quodlibet/plugins/playlist.py:39 #: ../quodlibet/qltk/chooser.py:184 ../quodlibet/qltk/chooser.py:205 #: ../quodlibet/qltk/chooser.py:229 ../quodlibet/qltk/chooser.py:253 #: ../quodlibet/qltk/delete.py:90 ../quodlibet/qltk/delete.py:133 #: ../quodlibet/qltk/edittags.py:287 ../quodlibet/qltk/_editutils.py:38 #: ../quodlibet/qltk/getstring.py:28 ../quodlibet/qltk/maskedbox.py:27 #: ../quodlibet/qltk/msg.py:54 ../quodlibet/qltk/msg.py:93 #: ../quodlibet/qltk/ratingsmenu.py:33 ../quodlibet/qltk/songsmenu.py:45 #: ../quodlibet/qltk/songsmenu.py:73 ../quodlibet/update.py:94 msgid "_Cancel" msgstr "" #: ../quodlibet/browsers/covergrid/main.py:125 #, fuzzy msgid "Cover Grid" msgstr "Celková veľkosť:" #: ../quodlibet/browsers/covergrid/main.py:126 #, fuzzy msgid "_Cover Grid" msgstr "Celková veľkosť:" #: ../quodlibet/browsers/covergrid/prefs.py:54 #, fuzzy msgid "Cover Grid Preferences" msgstr "Nastavenie prehliadača" #: ../quodlibet/browsers/covergrid/prefs.py:64 #, fuzzy msgid "Show album _text" msgstr "Zobraziť _obaly albumov" #: ../quodlibet/browsers/covergrid/prefs.py:71 #, fuzzy msgid "Show \"All Albums\" Item" msgstr "Všetky albumy" #: ../quodlibet/browsers/covergrid/prefs.py:78 msgid "Vertical Split" msgstr "" #: ../quodlibet/browsers/covergrid/prefs.py:110 #: ../quodlibet/browsers/covergrid/prefs.py:111 #, fuzzy msgid "Cover Magnification" msgstr "organizácia" #: ../quodlibet/browsers/filesystem.py:40 msgid "File System" msgstr "Súborový systém" #: ../quodlibet/browsers/filesystem.py:41 msgid "_File System" msgstr "_Súborový systém" #: ../quodlibet/browsers/filesystem.py:113 ../quodlibet/browsers/media.py:491 #: ../quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "Nepodarilo sa skopírovať skladby" #: ../quodlibet/browsers/filesystem.py:114 ../quodlibet/qltk/songlist.py:268 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "" "Vybrané súbory nemôžu byť kopírované do iného zoznamu skladieb alebo fronty." #: ../quodlibet/browsers/filesystem.py:189 msgid "_Add to Library" msgstr "_Pridať do knižnice" #: ../quodlibet/browsers/iradio.py:178 msgid "Unsupported file type" msgstr "Nepodporovaný typ súboru" #: ../quodlibet/browsers/iradio.py:179 #, 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:219 ../quodlibet/browsers/iradio.py:232 #: ../quodlibet/browsers/iradio.py:810 msgid "Unable to add station" msgstr "Nepodarilo sa pridať stanicu" #: ../quodlibet/browsers/iradio.py:243 ../quodlibet/browsers/iradio.py:471 msgid "Internet Radio" msgstr "Internetové rádio" #: ../quodlibet/browsers/iradio.py:243 #, fuzzy msgid "Downloading station list" msgstr "Sťiahnuť súbory" #: ../quodlibet/browsers/iradio.py:339 msgid "New Station" msgstr "Nová stanica" #: ../quodlibet/browsers/iradio.py:340 msgid "Enter the location of an Internet radio station:" msgstr "Vložte umiestnenie Internetovej rádio stanice:" #: ../quodlibet/browsers/iradio.py:358 msgid "Electronic" msgstr "" #: ../quodlibet/browsers/iradio.py:361 msgid "Hip Hop / Rap" msgstr "" #: ../quodlibet/browsers/iradio.py:362 msgid "Oldies" msgstr "" #: ../quodlibet/browsers/iradio.py:363 msgid "R&B" msgstr "" #: ../quodlibet/browsers/iradio.py:364 msgid "Japanese" msgstr "" #: ../quodlibet/browsers/iradio.py:365 msgid "Indian" msgstr "" #: ../quodlibet/browsers/iradio.py:367 msgid "Religious" msgstr "" #: ../quodlibet/browsers/iradio.py:369 msgid "Charts" msgstr "" #: ../quodlibet/browsers/iradio.py:370 msgid "Turkish" msgstr "" #: ../quodlibet/browsers/iradio.py:371 msgid "Reggae / Dancehall" msgstr "" #: ../quodlibet/browsers/iradio.py:372 #, fuzzy msgid "Latin" msgstr "hodnotenie" #: ../quodlibet/browsers/iradio.py:373 msgid "College Radio" msgstr "" #: ../quodlibet/browsers/iradio.py:374 msgid "Talk / News" msgstr "" #: ../quodlibet/browsers/iradio.py:375 msgid "Ambient" msgstr "" #: ../quodlibet/browsers/iradio.py:376 msgid "Jazz" msgstr "" #: ../quodlibet/browsers/iradio.py:377 ../quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "" #: ../quodlibet/browsers/iradio.py:378 ../quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "" #: ../quodlibet/browsers/iradio.py:379 msgid "Alternative" msgstr "" #: ../quodlibet/browsers/iradio.py:380 msgid "Metal" msgstr "" #: ../quodlibet/browsers/iradio.py:381 msgid "Country" msgstr "" #: ../quodlibet/browsers/iradio.py:382 msgid "News" msgstr "" #: ../quodlibet/browsers/iradio.py:383 msgid "Schlager" msgstr "" #: ../quodlibet/browsers/iradio.py:384 msgid "Funk" msgstr "" #: ../quodlibet/browsers/iradio.py:385 msgid "Indie" msgstr "" #: ../quodlibet/browsers/iradio.py:386 msgid "Blues" msgstr "" #: ../quodlibet/browsers/iradio.py:387 msgid "Soul" msgstr "" #: ../quodlibet/browsers/iradio.py:388 msgid "Lounge" msgstr "" #: ../quodlibet/browsers/iradio.py:389 msgid "Punk" msgstr "" #: ../quodlibet/browsers/iradio.py:390 msgid "Reggaeton" msgstr "" #: ../quodlibet/browsers/iradio.py:392 msgid "Slavic" msgstr "" #: ../quodlibet/browsers/iradio.py:394 msgid "Greek" msgstr "" #: ../quodlibet/browsers/iradio.py:395 msgid "Gothic" msgstr "" #: ../quodlibet/browsers/iradio.py:396 ../quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "" #: ../quodlibet/browsers/iradio.py:449 msgid "Would you like to load a list of popular radio stations?" msgstr "" #: ../quodlibet/browsers/iradio.py:455 #, fuzzy msgid "_Load Stations" msgstr "_Nová stanica" #: ../quodlibet/browsers/iradio.py:472 msgid "_Internet Radio" msgstr "_Internetové rádio" #: ../quodlibet/browsers/iradio.py:538 #, fuzzy msgid "_New Station…" msgstr "Nová stanica" #: ../quodlibet/browsers/iradio.py:541 #, fuzzy msgid "_Update Stations" msgstr "_Nová stanica" #: ../quodlibet/browsers/iradio.py:568 #, fuzzy msgid "All Stations" msgstr "Nová stanica" #. TODO: support for ~#rating=!None etc (#1940) #: ../quodlibet/browsers/iradio.py:572 #: ../quodlibet/browsers/soundcloud/main.py:64 msgid "Favorites" msgstr "" #: ../quodlibet/browsers/iradio.py:580 msgid "No Category" msgstr "" #: ../quodlibet/browsers/iradio.py:802 msgid "No stations found" msgstr "Nenájdené žiadne stanice." #: ../quodlibet/browsers/iradio.py:803 #, python-format msgid "No Internet radio stations were found at %s." msgstr "Na %s nebola nájdená žiadna Internetová rádio stanica." #: ../quodlibet/browsers/iradio.py:811 msgid "All stations listed are already in your library." msgstr "Všetky stanice už sú v knižnici." #: ../quodlibet/browsers/iradio.py:828 #, fuzzy msgid "Add to Favorites" msgstr "_Pridať do playlistu" #: ../quodlibet/browsers/iradio.py:832 #, fuzzy msgid "Remove from Favorites" msgstr "_Odstrániť z playlistu" #: ../quodlibet/browsers/iradio.py:932 #, 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/media.py:36 msgid "Device Properties" msgstr "Vlastnosti zariadenia" #: ../quodlibet/browsers/media.py:52 msgid "Device:" msgstr "Zariadenie:" #: ../quodlibet/browsers/media.py:54 msgid "Not mounted" msgstr "Nepripojené" #: ../quodlibet/browsers/media.py:55 #, fuzzy msgid "Mount point:" msgstr "Prípojný bod:" #: ../quodlibet/browsers/media.py:61 ../quodlibet/qltk/cbes.py:40 msgid "_Name:" msgstr "_Názov:" #: ../quodlibet/browsers/media.py:135 msgid "Media Devices" msgstr "Média zariadenia" #: ../quodlibet/browsers/media.py:136 msgid "_Media Devices" msgstr "_Média zariadenia" #. eject button #: ../quodlibet/browsers/media.py:224 ../quodlibet/browsers/media.py:378 msgid "_Eject" msgstr "_Vysunúť" #: ../quodlibet/browsers/media.py:360 #, fuzzy msgid "_Properties" msgstr "Vlastnosti" #: ../quodlibet/browsers/media.py:365 #: ../quodlibet/browsers/playlists/main.py:464 msgid "_Rename" msgstr "_Premenovať" #: ../quodlibet/browsers/media.py:461 #, fuzzy, python-format msgid "%(used-size)s used, %(free-size)s available" msgstr "<b>%s</b> použité, <b>%s</b> dostupné" #: ../quodlibet/browsers/media.py:479 #, fuzzy, python-format msgid "%s is not connected." msgstr "<b>%s</b> nie je pripojené." #: ../quodlibet/browsers/media.py:499 #, fuzzy, python-format msgid "Copying %(song)s" msgstr "Kopírovanie <b>%s</b>" #: ../quodlibet/browsers/media.py:513 ../quodlibet/browsers/media.py:529 msgid "Unable to copy song" msgstr "Neporadilo sa kopírovať skladbu" #: ../quodlibet/browsers/media.py:514 msgid "There is not enough free space for this song." msgstr "Na túto skladbu nie je dost voľného miesta" #: ../quodlibet/browsers/media.py:526 #, fuzzy, python-format msgid "%s could not be copied." msgstr "<b>%s</b> nemôže byť skopírované." #: ../quodlibet/browsers/media.py:545 msgid "Unable to delete songs" msgstr "Nepodarilo sa vymazať skladby" #: ../quodlibet/browsers/media.py:557 #, fuzzy, python-format msgid "Deleting %(song)s" msgstr "Odstraňovanie <b>%s</b>" #: ../quodlibet/browsers/media.py:575 #, fuzzy, python-format msgid "%s could not be deleted." msgstr "<b>%s</b> nemôže byť odstránené." #: ../quodlibet/browsers/media.py:579 msgid "Unable to delete song" msgstr "Nedá sa odstrániť skladba" #: ../quodlibet/browsers/media.py:594 #, fuzzy, python-format msgid "Ejecting %s failed." msgstr "Vysúvanie <b>%s</b> zlyhalo." #: ../quodlibet/browsers/media.py:597 msgid "Unable to eject device" msgstr "Neporadilo sa vysunúť zariadenie" #: ../quodlibet/browsers/media.py:603 msgid "No device backend, Media Devices browser disabled." msgstr "" #: ../quodlibet/browsers/paned/main.py:40 ../quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "Prehliadač" #: ../quodlibet/browsers/paned/main.py:41 msgid "_Paned Browser" msgstr "_Prehliadač" #: ../quodlibet/browsers/paned/main.py:90 msgid "Select _All" msgstr "Označiť _všetko:" #: ../quodlibet/browsers/paned/models.py:104 ../quodlibet/qltk/pluginwin.py:122 #: ../quodlibet/qltk/pluginwin.py:164 msgid "All" msgstr "Všetko" #: ../quodlibet/browsers/paned/prefs.py:67 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "<tt>%s</tt>" msgstr "" #: ../quodlibet/browsers/paned/prefs.py:162 msgid "_Wide Mode" msgstr "" #: ../quodlibet/browsers/paned/prefs.py:197 msgid "Paned Browser Preferences" msgstr "Nastavenie prehliadača" #: ../quodlibet/browsers/paned/prefs.py:204 msgid "Equal pane width" msgstr "" #: ../quodlibet/browsers/playlists/main.py:48 #: ../quodlibet/browsers/playlists/main.py:575 #: ../quodlibet/qltk/pluginwin.py:168 msgid "Playlists" msgstr "Playlisty" #: ../quodlibet/browsers/playlists/main.py:49 msgid "_Playlists" msgstr "_Playlisty" #: ../quodlibet/browsers/playlists/main.py:152 msgid "_Remove from Playlist" msgstr "_Odstrániť z playlistu" #: ../quodlibet/browsers/playlists/main.py:215 #: ../quodlibet/browsers/playlists/main.py:576 msgid "_Import" msgstr "_Import" #: ../quodlibet/browsers/playlists/main.py:391 #: ../quodlibet/browsers/playlists/util.py:50 #: ../quodlibet/util/collection.py:570 msgid "New Playlist" msgstr "Nový playlist" #: ../quodlibet/browsers/playlists/main.py:413 msgid "Unable to import playlist" msgstr "Nepodarilo sa importovať playlist" #: ../quodlibet/browsers/playlists/main.py:414 msgid "Quod Libet can only import playlists in the M3U and PLS formats." msgstr "Quod Libet môže importovať iba playlist vo formáte M3U alebo PLS." #: ../quodlibet/browsers/playlists/main.py:565 msgid "Unable to rename playlist" msgstr "Neporadilo sa premenovať playlist" #: ../quodlibet/browsers/playlists/main.py:576 msgid "Import Playlist" msgstr "Importovať playlist" #: ../quodlibet/browsers/playlists/menu.py:25 #, fuzzy msgid "_New Playlist…" msgstr "_Nový playlist" #: ../quodlibet/browsers/playlists/menu.py:86 #, 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:90 #, 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 "Nový playlist" #: ../quodlibet/browsers/playlists/prefs.py:47 #, fuzzy msgid "Playlist Browser Preferences" msgstr "Nastavenie prehliadača" #: ../quodlibet/browsers/playlists/prefs.py:52 #, fuzzy msgid "Playlist display" msgstr "Playlisty" #: ../quodlibet/browsers/playlists/util.py:33 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "" #: ../quodlibet/browsers/playlists/util.py:35 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" #: ../quodlibet/browsers/playlists/util.py:51 #, fuzzy msgid "Enter a name for the new playlist:" msgstr "Vložte názov novej zložky:" #: ../quodlibet/browsers/playlists/util.py:102 #, fuzzy, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" "Importovanie playlistu.\n" "\n" "%d/%d skladieb pridaných." #: ../quodlibet/browsers/search.py:33 msgid "_Limit Results" msgstr "_Obmedziť výsledky" #: ../quodlibet/browsers/search.py:48 msgid "Search Library" msgstr "Vyhľadávať v knižnici" #: ../quodlibet/browsers/search.py:49 msgid "_Search Library" msgstr "_Vyhľadávať v knižnici" #: ../quodlibet/browsers/soundcloud/main.py:38 #, fuzzy msgid "Soundcloud Browser" msgstr "Prehliadač" #: ../quodlibet/browsers/soundcloud/main.py:39 msgid "Sound_cloud" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:59 #: ../quodlibet/qltk/searchbar.py:73 msgid "Search" msgstr "Vyhľadávať" #: ../quodlibet/browsers/soundcloud/main.py:136 #, python-format msgid "Go to %s" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:380 #, fuzzy msgid "Connected" msgstr "miesto" #: ../quodlibet/browsers/soundcloud/main.py:381 #, python-format msgid "Quod Libet is now connected, <b>%s</b>!" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:393 #, python-format msgid "Log out of %s" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:395 msgid "Enter code…" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:396 #, python-format msgid "Log in to %s" msgstr "" #: ../quodlibet/browsers/soundcloud/util.py:86 msgid "Soundcloud authorisation" msgstr "" #: ../quodlibet/browsers/soundcloud/util.py:87 msgid "Enter Soundcloud auth code:" msgstr "" #: ../quodlibet/cli.py:50 #, fuzzy msgid "Quod Libet is not running (add '--run' to start it)" msgstr "Quod Libet nie je spustený." #: ../quodlibet/cli.py:85 msgid "a music library and player" msgstr "hudobný prehrávač" #: ../quodlibet/cli.py:86 #, fuzzy msgid "[option]" msgstr "[možnosti]" #: ../quodlibet/cli.py:88 msgid "Print the playing song and exit" msgstr "Vypíše hrajúcu skladbu a skončí" #: ../quodlibet/cli.py:89 msgid "Begin playing immediately" msgstr "Začať prehrávanie okamžite" #: ../quodlibet/cli.py:90 msgid "Don't show any windows on start" msgstr "" #: ../quodlibet/cli.py:93 msgid "Jump to next song" msgstr "Preskočiť na nasledujúcu skladbu" #: ../quodlibet/cli.py:95 msgid "Jump to previous song or restart if near the beginning" msgstr "" #: ../quodlibet/cli.py:96 msgid "Jump to previous song" msgstr "Preskočiť na predchádzajúcu skladbu" #: ../quodlibet/cli.py:97 msgid "Start playback" msgstr "Spustiť prehrávanie" #: ../quodlibet/cli.py:98 msgid "Pause playback" msgstr "Pozastaviť prehrávanie" #: ../quodlibet/cli.py:99 msgid "Toggle play/pause mode" msgstr "Prepnúť mód prehrávania/pauzy" #: ../quodlibet/cli.py:100 #, fuzzy msgid "Stop playback" msgstr "Spustiť prehrávanie" #: ../quodlibet/cli.py:101 msgid "Turn up volume" msgstr "Zvýšiť hlasitosť" #: ../quodlibet/cli.py:102 msgid "Turn down volume" msgstr "Znižiť hlasitosť" #: ../quodlibet/cli.py:103 msgid "Print player status" msgstr "Vypísať stav prehrávača" #: ../quodlibet/cli.py:104 msgid "Hide main window" msgstr "Schovať hlavné okno" #: ../quodlibet/cli.py:105 msgid "Show main window" msgstr "Zobraziť hlavné okno" #: ../quodlibet/cli.py:106 msgid "Toggle main window visibility" msgstr "Prepnúť viditelnosť hlavného okna" #: ../quodlibet/cli.py:107 msgid "Focus the running player" msgstr "" #: ../quodlibet/cli.py:108 msgid "Remove active browser filters" msgstr "" #: ../quodlibet/cli.py:109 #, fuzzy msgid "Refresh and rescan library" msgstr "O_bnoviť knižnicu" #: ../quodlibet/cli.py:110 #, fuzzy msgid "List available browsers" msgstr "Vypnúť prehliadač" #: ../quodlibet/cli.py:111 msgid "Print the current playlist" msgstr "Vypísať aktuálny playlist" #: ../quodlibet/cli.py:112 msgid "Print the contents of the queue" msgstr "Vypísať obsah fronty" #: ../quodlibet/cli.py:113 #, fuzzy msgid "Print the active text query" msgstr "Vypísať obsah fronty" #: ../quodlibet/cli.py:114 msgid "Start without plugins" msgstr "" #: ../quodlibet/cli.py:115 #, fuzzy msgid "Start Quod Libet if it isn't running" msgstr "Quod Libet nie je spustený." #: ../quodlibet/cli.py:116 msgid "Exit Quod Libet" msgstr "Ukončiť Quod Libet" #: ../quodlibet/cli.py:121 msgid "Seek within the playing song" msgstr "Presunúť pozíciu hrajúcej skladby" #: ../quodlibet/cli.py:121 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: ../quodlibet/cli.py:122 #, fuzzy msgid "Set or toggle shuffle mode" msgstr "Prepnúť mód prehrávania/pauzy" #: ../quodlibet/cli.py:123 msgid "Turn repeat off, on, or toggle it" msgstr "Zapnúť alebo vypnúť opakovanie" #: ../quodlibet/cli.py:124 msgid "Set the volume" msgstr "Nastaviť hlasitosť" #: ../quodlibet/cli.py:125 msgid "Search your audio library" msgstr "Vyhľadávať v hudobnej knižnici" #: ../quodlibet/cli.py:125 ../quodlibet/cli.py:137 ../quodlibet/cli.py:141 #: ../quodlibet/cli.py:143 msgid "query" msgstr "dotaz" #: ../quodlibet/cli.py:126 msgid "Play a file" msgstr "Prehrať súbor" #: ../quodlibet/cli.py:126 ../quodlibet/cli.py:137 ../quodlibet/cli.py:143 #, fuzzy msgctxt "command" msgid "filename" msgstr "názov súboru" #: ../quodlibet/cli.py:127 msgid "Rate the playing song" msgstr "Ohodnotiť hrajúcu skladbu" #: ../quodlibet/cli.py:128 msgid "Set the current browser" msgstr "Nastaviť aktuálny prehliadač" #: ../quodlibet/cli.py:129 #, fuzzy msgid "Stop after the playing song" msgstr "Ohodnotiť hrajúcu skladbu" #: ../quodlibet/cli.py:130 msgid "Open a new browser" msgstr "Otvoriť nový prehrávač" #: ../quodlibet/cli.py:131 msgid "Show or hide the queue" msgstr "Zobraziť alebo skryť frontu" #: ../quodlibet/cli.py:133 #, fuzzy msgid "Show or hide the main song list (deprecated)" msgstr "Zobraziť alebo skryť hlavný zoznam skladieb" #: ../quodlibet/cli.py:134 msgid "Filter on a random value" msgstr "Filter na náhodnej hodnote" #: ../quodlibet/cli.py:134 #, fuzzy msgctxt "command" msgid "tag" msgstr "Tag" #: ../quodlibet/cli.py:135 msgid "Filter on a tag value" msgstr "Filter na hodnote tagu" #: ../quodlibet/cli.py:135 msgid "tag=value" msgstr "tag=hodnota" #: ../quodlibet/cli.py:136 msgid "Enqueue a file or query" msgstr "Pridať do fronty" #: ../quodlibet/cli.py:138 msgid "Enqueue comma-separated files" msgstr "" #: ../quodlibet/cli.py:139 ../quodlibet/util/tags.py:147 msgid "filename" msgstr "názov súboru" #: ../quodlibet/cli.py:140 msgid "Print filenames of results of query to stdout" msgstr "" #: ../quodlibet/cli.py:142 #, fuzzy msgid "Unqueue a file or query" msgstr "Pridať do fronty" #: ../quodlibet/cli.py:203 #, fuzzy, python-format msgid "Invalid argument for '%s'." msgstr "E: Neplatný argument pre '%s'." #: ../quodlibet/cli.py:204 ../quodlibet/util/__init__.py:190 #, fuzzy, python-format msgid "Try %s --help." msgstr "E: Skúste %s --help." #: ../quodlibet/devices/_base.py:65 msgid "Unknown Device" msgstr "Neznáme zariadenie" #: ../quodlibet/devices/__init__.py:32 #, python-format msgid "Could not import %s, which is needed for device support." msgstr "" #: ../quodlibet/devices/__init__.py:153 #, fuzzy, python-format msgid "%r is not a supported device." msgstr "E: '%s' nie je unikátny prefix." #: ../quodlibet/devices/__init__.py:245 ../quodlibet/devices/__init__.py:251 #, python-format msgid "Could not find '%s'." msgstr "" #: ../quodlibet/devices/__init__.py:450 #, fuzzy msgid "Initializing device backend." msgstr "Neplatná hodnota" #: ../quodlibet/devices/__init__.py:451 #, python-format msgid "Trying '%s'" msgstr "" #: ../quodlibet/devices/__init__.py:461 msgid "Couldn't connect to a device backend." msgstr "" #: ../quodlibet/devices/__init__.py:463 msgid "Device backend initialized." msgstr "" #: ../quodlibet/devices/storage.py:57 #, fuzzy msgid "_Filename pattern:" msgstr "_Formát názvu súboru:" #: ../quodlibet/devices/storage.py:61 msgid "Copy _album covers" msgstr "Kopírovať obaly _albumov" #: ../quodlibet/devices/storage.py:65 msgid "_Remove unused covers and directories" msgstr "_Odstrániť nepoužívané obaly a adresáre" #: ../quodlibet/errorreport/ui.py:60 msgid "An Error Occurred" msgstr "" #: ../quodlibet/errorreport/ui.py:62 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:72 msgid "File Bug Report" msgstr "" #: ../quodlibet/errorreport/ui.py:74 ../quodlibet/errorreport/ui.py:90 msgid "Submit Error Report" msgstr "" #: ../quodlibet/errorreport/ui.py:75 msgid "Quit Program" msgstr "" #: ../quodlibet/errorreport/ui.py:76 #, fuzzy msgid "Ignore Error" msgstr "Zobraziť _chyby" #: ../quodlibet/errorreport/ui.py:80 msgid "Error details:" msgstr "" #: ../quodlibet/errorreport/ui.py:92 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:100 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "" #: ../quodlibet/errorreport/ui.py:109 msgid "_Send" msgstr "" #: ../quodlibet/errorreport/ui.py:115 #, fuzzy msgid "Short description…" msgstr "popis" #: ../quodlibet/errorreport/ui.py:118 msgid "Data to be sent:" msgstr "" #: ../quodlibet/exfalso.py:34 msgid "an audio tag editor" msgstr "editor audio tagov" #: ../quodlibet/exfalso.py:34 ../quodlibet/util/tags.py:148 msgid "directory" msgstr "adresár" #: ../quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "" #: ../quodlibet/ext/covers/artwork_url.py:20 msgid "" "Downloads covers linked to by the artwork_url tag.This works with the " "Soundcloud browser." msgstr "" #: ../quodlibet/ext/covers/discogs.py:25 #, fuzzy msgid "Discogs Cover Source" msgstr "MusicBrainz ID skladby" #: ../quodlibet/ext/covers/discogs.py:26 msgid "Downloads covers from Discogs." msgstr "" #: ../quodlibet/ext/covers/lastfm.py:22 msgid "Last.fm Cover Source" msgstr "" #: ../quodlibet/ext/covers/lastfm.py:23 msgid "Downloads covers from Last.fm's cover art archive." msgstr "" #: ../quodlibet/ext/covers/musicbrainz.py:19 #, fuzzy msgid "MusicBrainz Cover Source" msgstr "MusicBrainz ID skladby" #: ../quodlibet/ext/covers/musicbrainz.py:20 msgid "Downloads covers from MusicBrainz's cover art archive." msgstr "" #: ../quodlibet/ext/editing/iconv.py:26 #, fuzzy msgid "Convert Encodings" msgstr "[Neplatné kódovanie]" #: ../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:25 msgid "Kana/Kanji Simple Inverter" msgstr "" #: ../quodlibet/ext/editing/kakasi.py:26 msgid "Converts kana/kanji to romaji before renaming." msgstr "" #: ../quodlibet/ext/editing/kakasi.py:35 msgid "Romanize _Japanese text" msgstr "" #: ../quodlibet/ext/editing/kakasi.py:63 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:19 msgid "" "Allows arbitrary regex substitutions (s///) when tagging or renaming files." msgstr "" #: ../quodlibet/ext/editing/titlecase.py:20 #, fuzzy msgid "Title Case" msgstr "Názov" #: ../quodlibet/ext/editing/titlecase.py:21 #, fuzzy msgid "Title-cases tag values in the tag editor." msgstr "Editor audio tagov" #: ../quodlibet/ext/editing/titlecase.py:40 #, fuzzy msgid "Title-_case Value" msgstr "_Každé slovo začína veľkým písmenom" #: ../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:69 #, fuzzy msgid "Advanced Preferences" msgstr "Nastavenie prehliadača" #: ../quodlibet/ext/events/advanced_preferences.py:70 msgid "Allow editing of advanced config settings." msgstr "" #: ../quodlibet/ext/events/advanced_preferences.py:162 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:153 msgid "Top of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:154 msgid "Middle of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:155 msgid "Bottom of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:158 msgid "_Position:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:171 #, fuzzy msgid "_Cover size:" msgstr "Celková veľkosť:" #: ../quodlibet/ext/events/animosd/prefs.py:177 #: ../quodlibet/ext/events/lyricswindow.py:334 ../quodlibet/qltk/prefs.py:266 #, fuzzy msgid "Display" msgstr "Upraviť zobrazenie" #: ../quodlibet/ext/events/animosd/prefs.py:190 msgid "_Font:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:195 msgid "Left" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:196 msgid "Center" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:197 #, fuzzy msgid "Right" msgstr "_Váha" #: ../quodlibet/ext/events/animosd/prefs.py:200 msgid "_Align text:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:206 msgid "Text" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:217 msgid "_Text:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:227 msgid "_Fill:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:232 #: ../quodlibet/ext/events/synchronizedlyrics.py:63 msgid "Colors" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:240 msgid "_Shadows" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:241 msgid "_Outline" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:242 msgid "Rou_nded Corners" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:258 msgid "_Delay:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:264 #: ../quodlibet/qltk/pluginwin.py:172 msgid "Effects" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:270 #, fuzzy msgid "Ed_it Display Pattern…" msgstr "Upraviť zobrazenie" #: ../quodlibet/ext/events/animosd/prefs.py:274 #: ../quodlibet/ext/events/trayicon/prefs.py:78 #, fuzzy msgid "Preview" msgstr "_Náhľad" #: ../quodlibet/ext/events/auto_library_update.py:136 msgid "Automatic Library Update" msgstr "" #: ../quodlibet/ext/events/auto_library_update.py:137 #, python-format msgid "Keeps your library up to date with inotify. Requires %s." 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 by Brian Nelson." 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/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:97 msgid "Equalizer" msgstr "" #: ../quodlibet/ext/events/equalizer.py:98 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:132 msgid "The current backend does not support equalization." msgstr "" #: ../quodlibet/ext/events/equalizer.py:138 #, python-format msgid "%.1f kHz" msgstr "" #: ../quodlibet/ext/events/equalizer.py:139 #: ../quodlibet/ext/gstreamer/crossfeed.py:93 #: ../quodlibet/ext/gstreamer/karaoke.py:95 #, python-format msgid "%d Hz" msgstr "" #: ../quodlibet/ext/events/equalizer.py:173 #: ../quodlibet/ext/gstreamer/crossfeed.py:112 #, fuzzy, python-format msgid "%.1f dB" msgstr "%d sekunda" #: ../quodlibet/ext/events/equalizer.py:192 #: ../quodlibet/ext/gstreamer/crossfeed.py:31 #, fuzzy msgid "Custom" msgstr "_Vlastné" #: ../quodlibet/ext/events/equalizer.py:199 #, fuzzy msgid "_Clear" msgstr "Chyby zásuvných modulov" #. Translators: statuses relating to Instant Messenger apps #: ../quodlibet/ext/events/gajim_status.py:27 msgid "online" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:28 msgid "offline" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:29 msgid "chat" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:30 msgid "away" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:31 msgid "xa" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:32 msgid "invisible" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:37 msgid "Gajim Status Message" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:38 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:45 #: ../quodlibet/ext/events/telepathy_status.py:69 msgid "paused" 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:160 msgid "Add '[paused]'" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:163 msgid "If checked, '[paused]' will be added to status message on pause." msgstr "" #: ../quodlibet/ext/events/gajim_status.py:187 msgid "Statuses for which message will be changed" msgstr "" #: ../quodlibet/ext/events/headphonemon.py:156 msgid "Pause on Headphone Unplug" msgstr "" #: ../quodlibet/ext/events/headphonemon.py:157 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" #: ../quodlibet/ext/events/inhibit.py:41 msgid "Inhibit Screensaver" msgstr "" #: ../quodlibet/ext/events/inhibit.py:42 msgid "Prevents the GNOME screensaver from activating while a song is playing." msgstr "" #: ../quodlibet/ext/events/inhibit.py:51 #, fuzzy msgid "Music is playing" msgstr "Hudobný prehrávač" #: ../quodlibet/ext/events/iradiolog.py:16 #, fuzzy msgid "Internet Radio Log" msgstr "Internetové rádio" #: ../quodlibet/ext/events/iradiolog.py:17 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" #: ../quodlibet/ext/events/jep118.py:29 msgid "JEP-118" msgstr "" #: ../quodlibet/ext/events/jep118.py:30 msgid "Outputs a Jabber User Tunes file to ~/.quodlibet/jabber." msgstr "" #: ../quodlibet/ext/events/language.py:21 #, fuzzy msgid "Change Language" msgstr "_Hodnotenie" #: ../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 msgid "A restart is required for any changes to take effect" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:199 #, fuzzy msgid "No active song" msgstr "Nepodarilo sa uložiť skladbu" #: ../quodlibet/ext/events/lyricswindow.py:215 #, fuzzy msgid "No lyrics found" msgstr "Nenájdené žiadne zásuvné moduly." #: ../quodlibet/ext/events/lyricswindow.py:227 #, fuzzy msgid "Lyrics:" msgstr "Text" #: ../quodlibet/ext/events/lyricswindow.py:284 msgid "_Zoom level:" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:302 msgid "URL:" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:307 msgid "Revert to default" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:322 msgid "Search via above URL if the lyrics couldn't be found in LyricsWikia." msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:339 #, fuzzy msgid "Alternate search" msgstr "Vyčistiť vyhľadávanie" #: ../quodlibet/ext/events/lyricswindow.py:347 #, fuzzy msgid "Lyrics Window" msgstr "Text" #: ../quodlibet/ext/events/lyricswindow.py:348 msgid "Shows a window containing lyrics of the playing song." msgstr "" #: ../quodlibet/ext/events/mediaserver.py:38 msgid "UPnP AV Media Server" msgstr "" #: ../quodlibet/ext/events/mediaserver.py:39 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." 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 "miesto" #: ../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:39 msgid "" "Allows control of Quod Libet using the MPRIS 1.0/2.0 D-Bus Interface " "Specification." msgstr "" #: ../quodlibet/ext/events/mpris/__init__.py:45 #: ../quodlibet/ext/events/trayicon/prefs.py:30 #, fuzzy msgid "Hide main window on close" msgstr "Schovať hlavné okno" #: ../quodlibet/ext/events/mpris/__init__.py:48 #: ../quodlibet/ext/events/themeswitcher.py:84 #: ../quodlibet/ext/gstreamer/compressor.py:99 #: ../quodlibet/ext/gstreamer/crossfeed.py:136 #: ../quodlibet/ext/gstreamer/karaoke.py:99 #: ../quodlibet/ext/gstreamer/pitch.py:83 ../quodlibet/qltk/prefs.py:688 #, fuzzy msgid "Preferences" msgstr "Nastavenie" #: ../quodlibet/ext/events/mqtt.py:50 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/mqtt.py:56 msgid "MQTT Publisher" msgstr "" #: ../quodlibet/ext/events/mqtt.py:57 msgid "Publishes status messages to an MQTT topic." msgstr "" #: ../quodlibet/ext/events/mqtt.py:122 msgid "Broker hostname" msgstr "" #: ../quodlibet/ext/events/mqtt.py:122 msgid "broker hostname / IP" msgstr "" #: ../quodlibet/ext/events/mqtt.py:124 msgid "Broker port" msgstr "" #: ../quodlibet/ext/events/mqtt.py:124 msgid "broker port" msgstr "" #: ../quodlibet/ext/events/mqtt.py:126 msgid "Topic" msgstr "" #: ../quodlibet/ext/events/mqtt.py:128 #, fuzzy msgid "Playing Pattern" msgstr "vzorka" #: ../quodlibet/ext/events/mqtt.py:130 msgid "Status text when a song is started." msgstr "" #: ../quodlibet/ext/events/mqtt.py:132 #, fuzzy msgid "Paused Pattern" msgstr "vzorka" #: ../quodlibet/ext/events/mqtt.py:134 msgid "Text when a song is paused." msgstr "" #: ../quodlibet/ext/events/mqtt.py:136 #, fuzzy msgid "No-song Text" msgstr "%d skladba" #: ../quodlibet/ext/events/mqtt.py:138 msgid "Plain text for when there is no current song" msgstr "" #: ../quodlibet/ext/events/mqtt.py:149 #, fuzzy msgid "MQTT Configuration" msgstr "Informácie" #: ../quodlibet/ext/events/mqtt.py:153 #, fuzzy msgid "Status Text" msgstr "vzorka" #: ../quodlibet/ext/events/mqtt.py:185 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "" #: ../quodlibet/ext/events/mqtt.py:189 #, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s" msgstr "" #: ../quodlibet/ext/events/mqtt.py:192 #, fuzzy msgid "Connection error" msgstr "miesto" #: ../quodlibet/ext/events/notify.py:80 msgid "Notification text" msgstr "" #: ../quodlibet/ext/events/notify.py:88 #, fuzzy msgid "_Title:" msgstr "Názov" #: ../quodlibet/ext/events/notify.py:99 ../quodlibet/ext/events/notify.py:128 msgid "Revert to default pattern" msgstr "" #: ../quodlibet/ext/events/notify.py:118 msgid "_Body:" msgstr "" #: ../quodlibet/ext/events/notify.py:138 msgid "_Show notification" msgstr "" #: ../quodlibet/ext/events/notify.py:156 msgid "Show notifications" msgstr "" #: ../quodlibet/ext/events/notify.py:162 msgid "Only on <i>_manual</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:170 msgid "Only on <i>_automatic</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:178 msgid "On <i>a_ll</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:196 msgid "Only when the main window is not _focused" msgstr "" #: ../quodlibet/ext/events/notify.py:204 msgid "Show \"_Next\" button" msgstr "" #: ../quodlibet/ext/events/notify.py:236 msgid "Connection Error" msgstr "" #: ../quodlibet/ext/events/notify.py:237 ../quodlibet/ext/events/notify.py:391 #: ../quodlibet/ext/events/notify.py:433 msgid "Couldn't connect to notification daemon." msgstr "" #: ../quodlibet/ext/events/notify.py:251 msgid "Song Notifications" msgstr "" #: ../quodlibet/ext/events/notify.py:252 msgid "Displays a notification when the song changes." msgstr "" #: ../quodlibet/ext/events/notify.py:415 ../quodlibet/qltk/unity.py:65 msgid "Next" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:178 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:254 #, python-format msgid "Could not contact service '%s'." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:260 msgid "Authentication failed: invalid URL." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:277 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:282 msgid "Client is banned. Contact the author." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:286 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:351 msgid "AudioScrobbler Submission" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:352 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:450 msgid "Authentication successful." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:462 #, fuzzy msgid "_Service:" msgstr "Zariadenie:" #: ../quodlibet/ext/events/qlscrobbler.py:462 msgid "_URL:" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:462 #, fuzzy msgid "User_name:" msgstr "_Názov:" #: ../quodlibet/ext/events/qlscrobbler.py:463 msgid "_Password:" msgstr "" #. Translators: Other service #: ../quodlibet/ext/events/qlscrobbler.py:479 #, fuzzy msgid "Other…" msgstr "_Ostatné:" #. verify data #: ../quodlibet/ext/events/qlscrobbler.py:517 msgid "_Verify account data" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:522 #: ../quodlibet/ext/songsmenu/lastfmsync.py:304 msgid "Account" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:530 #, fuzzy msgid "_Artist pattern:" msgstr "_Interpret" #: ../quodlibet/ext/events/qlscrobbler.py:530 #, fuzzy msgid "_Title pattern:" msgstr "_Formát názvu súboru:" #: ../quodlibet/ext/events/qlscrobbler.py:531 msgid "Exclude _filter:" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:549 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:559 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:568 msgid "Songs matching this filter will not be submitted." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:576 msgid "_Offline mode (don't submit anything)" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:580 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:27 #, fuzzy msgid "Random Album Playback" msgstr "Náhodný al_bum" #: ../quodlibet/ext/events/randomalbum.py:28 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:38 msgid "Rated higher" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:39 msgid "Played more often" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:40 msgid "Skipped more often" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:41 msgid "Played more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:42 msgid "Started more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:43 msgid "Added more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:44 #, fuzzy msgid "Longer albums" msgstr "albumy" #: ../quodlibet/ext/events/randomalbum.py:83 msgid "seconds before starting next album" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:87 #, fuzzy msgid "Weights" msgstr "_Váha" #: ../quodlibet/ext/events/randomalbum.py:89 msgid "Play some albums more than others" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:103 msgid "avoid" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:114 msgid "prefer" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:201 #, fuzzy msgid "Random Album" msgstr "Náhodný al_bum" #: ../quodlibet/ext/events/randomalbum.py:202 #, python-format msgid "Waiting to start %s" msgstr "" #: ../quodlibet/ext/events/rbimport.py:114 #, fuzzy msgid "Import Failed" msgstr "Importovať playlist" #: ../quodlibet/ext/events/rbimport.py:119 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "" #: ../quodlibet/ext/events/rbimport.py:127 msgid "Rhythmbox Import" msgstr "" #: ../quodlibet/ext/events/rbimport.py:128 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "" #: ../quodlibet/ext/events/rbimport.py:132 #, fuzzy msgid "Start Import" msgstr "_Import" #: ../quodlibet/ext/events/screensaver.py:25 msgid "Screensaver Pause" msgstr "" #: ../quodlibet/ext/events/screensaver.py:26 msgid "Pauses playback while the GNOME screensaver is active." msgstr "" #: ../quodlibet/ext/events/searchprovider.py:73 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "" #: ../quodlibet/ext/events/searchprovider.py:79 msgid "GNOME Search Provider" msgstr "" #: ../quodlibet/ext/events/searchprovider.py:80 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/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:29 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:57 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:58 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:34 #, fuzzy msgid "Synchronized Lyrics" msgstr "Text" #: ../quodlibet/ext/events/synchronizedlyrics.py:35 msgid "Shows synchronized lyrics from .lrc file with same name as the track." msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:66 msgid "Text:" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:76 msgid "Background:" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:87 msgid "Font" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:90 msgid "Size (px):" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:62 msgid "Telepathy Status Messages" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:63 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:122 #, fuzzy msgid "Playing:" msgstr "Nehrá" #: ../quodlibet/ext/events/telepathy_status.py:123 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:139 msgid "Paused:" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:140 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:156 msgid "Plain text for status when there is no current song" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:157 #, fuzzy msgid "No song:" msgstr "%d skladba" #. Frame #: ../quodlibet/ext/events/telepathy_status.py:164 #, fuzzy msgid "Status Patterns" msgstr "vzorka" #: ../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/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:77 #: ../quodlibet/ext/events/trayicon/prefs.py:98 #: ../quodlibet/ext/events/trayicon/systemtray.py:177 #: ../quodlibet/qltk/info.py:47 msgid "Not playing" msgstr "Nehrá" #: ../quodlibet/ext/events/trayicon/__init__.py:53 msgid "Tray Icon" msgstr "" #: ../quodlibet/ext/events/trayicon/__init__.py:54 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:183 #: ../quodlibet/qltk/quodlibetwindow.py:1046 #: ../quodlibet/qltk/quodlibetwindow.py:1238 #, fuzzy msgid "_Play" msgstr "_Playlisty" #: ../quodlibet/ext/events/trayicon/menu.py:63 #: ../quodlibet/qltk/quodlibetwindow.py:185 #: ../quodlibet/qltk/quodlibetwindow.py:1240 ../quodlibet/qltk/wlw.py:51 #, fuzzy msgid "P_ause" msgstr "Prehrávač" #: ../quodlibet/ext/events/trayicon/menu.py:68 #: ../quodlibet/qltk/quodlibetwindow.py:190 #: ../quodlibet/qltk/quodlibetwindow.py:1041 #, fuzzy msgid "Pre_vious" msgstr "_Náhľad" #: ../quodlibet/ext/events/trayicon/menu.py:71 #: ../quodlibet/qltk/quodlibetwindow.py:194 #: ../quodlibet/qltk/quodlibetwindow.py:1051 msgid "_Next" msgstr "" #: ../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 #, fuzzy msgid "Stop _After This Song" msgstr "Skončiť po tejto skladbe" #: ../quodlibet/ext/events/trayicon/menu.py:92 #: ../quodlibet/qltk/quodlibetwindow.py:1012 #, fuzzy msgid "Open _Browser" msgstr "Otvoriť nový prehrávač" #: ../quodlibet/ext/events/trayicon/menu.py:103 #: ../quodlibet/qltk/quodlibetwindow.py:1031 ../quodlibet/qltk/songsmenu.py:411 msgid "Edit _Tags" msgstr "Upraviť _tagy" #: ../quodlibet/ext/events/trayicon/menu.py:112 #: ../quodlibet/qltk/quodlibetwindow.py:975 ../quodlibet/qltk/songsmenu.py:424 msgid "_Information" msgstr "_Informácie" #: ../quodlibet/ext/events/trayicon/menu.py:114 #: ../quodlibet/qltk/songsmenu.py:340 #, fuzzy msgid "Play_lists" msgstr "Playlisty" #: ../quodlibet/ext/events/trayicon/menu.py:132 #: ../quodlibet/qltk/quodlibetwindow.py:1026 msgid "_Quit" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:32 ../quodlibet/qltk/prefs.py:69 msgid "Behavior" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:42 msgid "Scroll wheel adjusts volume" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel changes song" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll _Wheel" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:84 #, fuzzy msgid "Tooltip Display" msgstr "Upraviť zobrazenie" #: ../quodlibet/ext/events/viewlyrics.py:23 #, fuzzy msgid "View Lyrics" msgstr "Text" #: ../quodlibet/ext/events/viewlyrics.py:24 msgid "Automatically displays lyrics beneath the song list in the main window." msgstr "" #: ../quodlibet/ext/events/viewlyrics.py:29 #, fuzzy msgid "_Lyrics" msgstr "Text" #: ../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 "Zobraziť _chyby" #: ../quodlibet/ext/events/visualisations.py:76 msgid "Visualiser executable:" msgstr "" #: ../quodlibet/ext/events/visualisations.py:91 msgid "Reload" msgstr "" #: ../quodlibet/ext/events/waveformseekbar.py:406 msgid "Waveform Seek Bar" msgstr "" #: ../quodlibet/ext/events/waveformseekbar.py:410 msgid "A seekbar in the shape of the waveform of the current song." msgstr "" #: ../quodlibet/ext/events/waveformseekbar.py:443 msgid "Override foreground color:" msgstr "" #: ../quodlibet/ext/events/write_cover.py:32 msgid "Picture Saver" msgstr "" #: ../quodlibet/ext/events/write_cover.py:33 msgid "Saves the cover image of the current song to a file." msgstr "" #: ../quodlibet/ext/events/write_cover.py:66 #, fuzzy msgid "File:" msgstr "Súbory" #: ../quodlibet/ext/gstreamer/compressor.py:20 msgid "_Threshold:" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:21 msgid "Threshold until the filter is activated" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:22 msgid "R_atio:" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:22 msgid "Compression ratio" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:74 #: ../quodlibet/ext/gstreamer/karaoke.py:91 #, python-format msgid "%d %%" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:105 msgid "Audio Compressor" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:106 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:19 #, fuzzy msgid "_Preset:" msgstr "_Náhľad" #: ../quodlibet/ext/gstreamer/crossfeed.py:19 #, fuzzy msgid "Filter preset" msgstr "Filter na _interpreta" #: ../quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Frequency cut:" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Low-pass filter cut frequency" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed _level:" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed level" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:25 msgid "Default" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Chu Moy" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Jan Meier" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:31 #, fuzzy msgid "Custom settings" msgstr "_Vlastné" #: ../quodlibet/ext/gstreamer/crossfeed.py:152 msgid "Crossfeed" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:153 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:20 #, fuzzy msgid "Filter _band:" msgstr "Filter na žá_ner" #: ../quodlibet/ext/gstreamer/karaoke.py:21 msgid "The Frequency band of the filter" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:22 #, fuzzy msgid "Filter _width:" msgstr "Filter na _interpreta" #: ../quodlibet/ext/gstreamer/karaoke.py:23 msgid "The Frequency width of the filter" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:24 msgid "_Level:" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:24 msgid "Level of the effect" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:105 msgid "Karaoke" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:106 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:20 msgid "R_ate:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:21 msgid "_Tempo:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:22 msgid "_Pitch:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:89 #, fuzzy msgid "Audio Pitch / Speed" msgstr "Audio kanály" #: ../quodlibet/ext/gstreamer/pitch.py:90 #, fuzzy msgid "Controls the pitch of an audio stream." msgstr "Vložte umiestnenie audio kanálu:" #: ../quodlibet/ext/playlist/export_to_folder.py:29 #: ../quodlibet/ext/playlist/export_to_folder.py:97 #: ../quodlibet/ext/playlist/export_to_folder.py:138 #, fuzzy msgid "Export Playlist to Folder" msgstr "Importovať playlist" #: ../quodlibet/ext/playlist/export_to_folder.py:38 #, fuzzy msgid "_Export" msgstr "_Import" #: ../quodlibet/ext/playlist/export_to_folder.py:43 #, fuzzy msgid "Destination folder:" msgstr "Nenájdené žiadne stanice." #: ../quodlibet/ext/playlist/export_to_folder.py:58 #, fuzzy msgid "Filename pattern:" msgstr "_Formát názvu súboru:" #: ../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:156 #, fuzzy msgid "Default filename pattern:" msgstr "_Formát názvu súboru:" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:23 msgid "Export to Squeezebox" msgstr "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:25 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 "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Export playlist to Squeezebox" msgstr "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:80 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 "_Odstrániť z playlistu" #: ../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 "Nový 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 "" "Playback follows your selection, or the next song in the list once exhausted." msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:22 msgid "Playcount Equalizer" msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:23 msgid "Shuffle, preferring songs with fewer total plays." msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:25 #, fuzzy msgid "Prefer less played" msgstr "naposledy prehrané" #: ../quodlibet/ext/playorder/queue.py:19 #, fuzzy msgid "Queue Only" msgstr "_Fronta" #: ../quodlibet/ext/playorder/queue.py:21 msgid "" "Limits playing of songs to the queue. Select this play order in the main " "window, then double-clicking any song will enqueue it instead of playing." msgstr "" #: ../quodlibet/ext/playorder/reverse.py:14 #, fuzzy msgid "Reverse" msgstr "Nikdy" #: ../quodlibet/ext/playorder/reverse.py:16 msgid "Reverses the play order of songs." msgstr "" #: ../quodlibet/ext/playorder/skip_songs.py:25 #, fuzzy msgid "Skip Songs" msgstr "Žiadne skladby" #: ../quodlibet/ext/playorder/skip_songs.py:27 msgid "" "Playback skips over songs with a rating equal or below a given threshold." msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:30 msgid "Repeat Each Track" msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:32 msgid "Shuffle songs, but repeat every track a set number of times." msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:51 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. Syntax is '@(if: " "condition, then, else)'." msgstr "" #: ../quodlibet/ext/query/pythonexpression.py:14 msgid "Python Query" msgstr "" #: ../quodlibet/ext/query/pythonexpression.py:15 msgid "" "Use Python expressions in queries. Syntax is '@(python: expression)'. The " "variable 's' is the song being matched." msgstr "" #: ../quodlibet/ext/query/savedsearch.py:19 #, fuzzy msgid "Include Saved Search" msgstr "Uložené hodnoty" #: ../quodlibet/ext/query/savedsearch.py:20 msgid "" "Include the results of a saved search as part of another query. Syntax is " "'@(saved: search name)'." 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:116 msgid "Port:" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:121 #, fuzzy msgid "Username:" msgstr "_Premenovať" #: ../quodlibet/ext/_shared/squeezebox/base.py:126 msgid "Password:" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:130 msgid "Library directory the server connects to." msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:132 #, fuzzy msgid "Library path:" msgstr "Knižnica" #. Add verify button #: ../quodlibet/ext/_shared/squeezebox/base.py:141 msgid "_Verify settings" msgstr "" #. Server settings Frame #: ../quodlibet/ext/_shared/squeezebox/base.py:147 msgid "Squeezebox Server" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:150 msgid "Debug" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:26 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:28 msgid "unidentified Squeezebox server" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:37 #, 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:20 #: ../quodlibet/ext/songsmenu/importexport.py:34 #: ../quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:329 #, fuzzy msgid "Fit image to _window" msgstr "Schovať hlavné okno" #. Both labels #: ../quodlibet/ext/songsmenu/albumart.py:338 msgid "_Program:" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:343 msgid "_Edit image after saving" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:345 #, fuzzy msgid "File_name:" msgstr "Názov súboru" #: ../quodlibet/ext/songsmenu/albumart.py:457 msgid "Saving failed" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:458 #, fuzzy, python-format msgid "Unable to save \"%s\"." msgstr "Nepodarilo sa uložiť skladbu" #: ../quodlibet/ext/songsmenu/albumart.py:556 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:613 #, fuzzy msgid "Album Art Downloader" msgstr "Zoznam albumov" #: ../quodlibet/ext/songsmenu/albumart.py:666 #, python-format msgid "from %(source)s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:669 #, python-format msgid "Resolution: %s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:672 #, fuzzy, python-format msgid "Size: %s" msgstr "Veľkosť" #: ../quodlibet/ext/songsmenu/albumart.py:690 #, fuzzy msgid "_Search" msgstr "_Vyhľadať:" #: ../quodlibet/ext/songsmenu/albumart.py:741 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:451 #, fuzzy msgid "Searching…" msgstr "Vyhľadávať" #: ../quodlibet/ext/songsmenu/albumart.py:804 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:922 #, fuzzy msgid "Download Album Art" msgstr "Zoznam albumov" #: ../quodlibet/ext/songsmenu/albumart.py:923 msgid "Downloads album covers from various websites." msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:936 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 "_Upraviť záložky..." #: ../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 "_Upraviť záložky..." #: ../quodlibet/ext/songsmenu/bookmarks.py:73 #, fuzzy msgid "No Bookmarks" msgstr "Záložky" #: ../quodlibet/ext/songsmenu/brainz/__init__.py:24 #, fuzzy msgid "MusicBrainz Lookup" msgstr "MusicBrainz typ albumu" #: ../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 #: ../quodlibet/qltk/downloader.py:52 msgid "Filename" msgstr "Názov súboru" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:130 #, fuzzy msgid "Disc" msgstr "_Disk" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:131 #: ../quodlibet/ext/songsmenu/replaygain.py:404 #: ../quodlibet/qltk/tracknumbers.py:92 msgid "Track" msgstr "Skladba" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:132 #, fuzzy msgid "Title" msgstr "Názov" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:133 #, fuzzy msgid "Artist" msgstr "_Interpret" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:352 #, fuzzy msgid "MusicBrainz lookup" msgstr "MusicBrainz typ albumu" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:375 #, fuzzy msgid "_Query:" msgstr "dotaz" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:378 #, fuzzy msgid "S_earch" msgstr "Vyhľadávať" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:391 msgid "Results <i>(drag to reorder)</i>" msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:447 msgid "Please enter a query." msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:465 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:496 msgid "Error encountered. Please retry." msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:472 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:488 msgid "Loading result…" msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:475 #, fuzzy msgid "No results found." msgstr "Nenájdené žiadne zásuvné moduly." #: ../quodlibet/ext/songsmenu/browsefolders.py:159 #, fuzzy msgid "Browse Folders" msgstr "Prehliadače" #: ../quodlibet/ext/songsmenu/browsefolders.py:160 msgid "Opens the songs' folders in a file manager." msgstr "" #: ../quodlibet/ext/songsmenu/browsefolders.py:172 #, fuzzy msgid "Unable to open folders" msgstr "Nepodarilo sa vytvoriť zložku" #: ../quodlibet/ext/songsmenu/browsefolders.py:173 msgid "No program available to open folders." msgstr "" #: ../quodlibet/ext/songsmenu/console.py:40 msgid "Python Console" msgstr "" #: ../quodlibet/ext/songsmenu/console.py:41 msgid "Interactive Python console." msgstr "" #: ../quodlibet/ext/songsmenu/console.py:72 msgid "You can access the following objects by default:" msgstr "" #: ../quodlibet/ext/songsmenu/console.py:82 msgid "Your current working directory is:" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:41 msgid "Command" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:44 #, fuzzy msgid "name" msgstr "_Premenovať" #: ../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:55 #, fuzzy msgid "pattern" msgstr "Neplatná vzorka" #: ../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:91 #, fuzzy msgid "Input value" msgstr "Neplatná hodnota" #: ../quodlibet/ext/songsmenu/custom_commands.py:92 #, python-format msgid "Value for %s?" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:136 #, fuzzy msgid "Custom Commands" msgstr "_Vlastné" #: ../quodlibet/ext/songsmenu/custom_commands.py:137 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:188 #: ../quodlibet/ext/songsmenu/custom_commands.py:198 #: ../quodlibet/ext/songsmenu/custom_commands.py:252 msgid "Edit Custom Commands" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:199 msgid "" "Supports QL patterns\n" "eg <tt><~artist~title></tt>" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:283 #, fuzzy, python-format msgid "Unable to run custom command %s" msgstr "Nepodarilo sa skopírovať skladby" #: ../quodlibet/ext/songsmenu/duplicates.py:290 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: ../quodlibet/ext/songsmenu/duplicates.py:343 msgid "Collapse / Expand all" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:347 #, python-format msgid "Duplicate key expression is '%s'" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:363 #, fuzzy msgid "Duplicates Browser" msgstr "Vypnúť prehliadač" #: ../quodlibet/ext/songsmenu/duplicates.py:364 msgid "Finds and displays similarly tagged versions of songs." msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:407 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:409 msgid "_Group duplicates by:" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:414 msgid "Duplicate Key" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:419 msgid "Remove _Whitespace" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:420 #, fuzzy msgid "Remove _Diacritics" msgstr "_Hodnotenie" #: ../quodlibet/ext/songsmenu/duplicates.py:421 #, fuzzy msgid "Remove _Punctuation" msgstr "_Hodnotenie" #: ../quodlibet/ext/songsmenu/duplicates.py:422 msgid "Case _Insensitive" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:430 msgid "Matching options" msgstr "" #. Create a dialog. #: ../quodlibet/ext/songsmenu/editplaycount.py:19 #: ../quodlibet/ext/songsmenu/editplaycount.py:41 #, fuzzy msgid "Edit Playcount" msgstr "Upraviť zobrazenie" #: ../quodlibet/ext/songsmenu/editplaycount.py:20 msgid "" "Edit a song's ~#playcount and ~#skipcount.\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's ~#playcount to 0, the ~#lastplayed and ~#laststarted " "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:68 msgid "Play Count" msgstr "" #: ../quodlibet/ext/songsmenu/editplaycount.py:69 msgid "Skip Count" msgstr "" #: ../quodlibet/ext/songsmenu/embedded.py:24 msgid "Edit Embedded Images" msgstr "" #: ../quodlibet/ext/songsmenu/embedded.py:25 msgid "Removes or replaces embedded images." msgstr "" #: ../quodlibet/ext/songsmenu/embedded.py:78 #, fuzzy msgid "_Remove all Images" msgstr "_Hodnotenie" #: ../quodlibet/ext/songsmenu/embedded.py:82 msgid "_Embed Current 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 na hodnote tagu" #: ../quodlibet/ext/songsmenu/filterall.py:81 #, fuzzy msgid "Creates a search query based on tags of the selected songs." msgstr "GStreamer nemohol načítať vybranú skladbu." #: ../quodlibet/ext/songsmenu/filterbrowser.py:19 #, fuzzy msgid "Filter on Directory" msgstr "Filter na žá_ner" #: ../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:41 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 #: ../quodlibet/qltk/downloader.py:67 #, fuzzy msgid "Queued" msgstr "_Fronta" #: ../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 "Zapísať" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" 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 ID skladby" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:296 #, fuzzy msgid "Group by directory" msgstr "adresár" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:305 #, fuzzy msgid "Album Mode" msgstr "Hlavičky _albumu" #: ../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:49 msgid "Generating fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:63 msgid "_Details" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:85 msgid "_Submit" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:115 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:118 msgid "Fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Songs with MBIDs:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with sufficient tags:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs to submit:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:162 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:178 msgid "Submitting fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:186 msgid "Submitting…" msgstr "" #: ../quodlibet/ext/songsmenu/forcewrite.py:17 #, fuzzy msgid "Update Tags in Files" msgstr "_Nová stanica" #: ../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/id3tlen.py:21 msgid "Fix MP3 Duration" msgstr "" #: ../quodlibet/ext/songsmenu/id3tlen.py:22 msgid "" "Removes TLEN frames from ID3 tags which can be the cause for invalid song " "durations." msgstr "" #: ../quodlibet/ext/songsmenu/ifp.py:20 msgid "Send to iFP" msgstr "" #: ../quodlibet/ext/songsmenu/ifp.py:21 msgid "Uploads songs to an iRiver iFP device." msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:51 msgid "Export Metadata" msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:52 msgid "Exports metadata of selected songs as a .tags file." msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:92 #, fuzzy msgid "Import Metadata" msgstr "Importovať playlist" #: ../quodlibet/ext/songsmenu/importexport.py:93 msgid "Imports metadata for selected songs from a .tags file." msgstr "" #: ../quodlibet/ext/songsmenu/k3b.py:23 msgid "Burn CD" msgstr "" #: ../quodlibet/ext/songsmenu/k3b.py:24 msgid "Burns CDs with K3b, Brasero or xfburn." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:96 msgid "Updating chart list." msgstr "" #. No charts to fetch, no update scheduled. #: ../quodlibet/ext/songsmenu/lastfmsync.py:114 msgid "Already up-to-date." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:121 #, python-format msgid "Fetching chart for week of %s." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:143 msgid "Sync complete." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:149 msgid "Error during sync" msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:214 #: ../quodlibet/ext/songsmenu/lastfmsync.py:244 msgid "Last.fm Sync" msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:245 msgid "Updates your library's statistics from your Last.fm profile." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:293 #, fuzzy msgid "_Username:" msgstr "_Premenovať" #: ../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 "" #. Create a dialog. #: ../quodlibet/ext/songsmenu/migratemetadata.py:29 #: ../quodlibet/ext/songsmenu/migratemetadata.py:38 #, fuzzy msgid "Migrate Metadata" msgstr "Importovať playlist" #: ../quodlibet/ext/songsmenu/migratemetadata.py:32 msgid "Copies the quodlibet-specific metadata between songs." msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:45 msgid "_Copy" msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:47 msgid "_Paste" msgstr "" #. Create the tag table. #: ../quodlibet/ext/songsmenu/migratemetadata.py:57 #, fuzzy msgid "Information to copy/paste" msgstr "Informácie" #. Create the indexing box. #: ../quodlibet/ext/songsmenu/migratemetadata.py:79 msgid "Map tracks by disc and track number" msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:80 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 "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:96 #, python-format msgid "There is %d stored track." msgid_plural "There are %d stored tracks." msgstr[0] "" msgstr[1] "" msgstr[2] "" #: ../quodlibet/ext/songsmenu/playlist.py:31 #, fuzzy msgid "Export as Playlist" msgstr "Importovať playlist" #: ../quodlibet/ext/songsmenu/playlist.py:32 msgid "Exports songs to an M3U or PLS playlist." msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:77 msgid "Use relative paths" msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:77 msgid "Use absolute paths" msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:132 #, fuzzy msgid "Unable to export playlist" msgstr "Nepodarilo sa importovať playlist" #: ../quodlibet/ext/songsmenu/playlist.py:133 #, fuzzy, python-format msgid "Writing to <b>%s</b> failed." msgstr "Vysúvanie <b>%s</b> zlyhalo." #. Translators: Plugin name #: ../quodlibet/ext/songsmenu/refresh.py:22 #, fuzzy msgid "Rescan Songs" msgstr "O_bnoviť knižnicu" #: ../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 "O_bnoviť knižnicu" #: ../quodlibet/ext/songsmenu/replaygain.py:362 msgid "ReplayGain Analyzer" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:418 msgid "Progress" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:433 msgid "Gain" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:448 msgid "Peak" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:463 #, python-format msgid "There is <b>%(to-process)s</b> album to update (of %(all)s)" msgid_plural "There are <b>%(to-process)s</b> albums to update (of %(all)s)" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: ../quodlibet/ext/songsmenu/replaygain.py:578 msgid "Replay Gain" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:579 msgid "" "Analyzes and updates ReplayGain information, using GStreamer. Results are " "grouped by album." msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:617 msgid "always" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:618 msgid "if <b>any</b> RG tags are missing" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:620 msgid "if <b>album</b> RG tags are missing" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:637 msgid "_Process albums:" msgstr "" #. Server settings Frame #: ../quodlibet/ext/songsmenu/replaygain.py:649 #, fuzzy msgid "Existing Tags" msgstr "Upraviť tagy" #: ../quodlibet/ext/songsmenu/splitting.py:31 #, fuzzy msgid "Split Tags" msgstr "Upraviť 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 "" #: ../quodlibet/ext/songsmenu/splitting.py:56 #, fuzzy msgid "Split Album" msgstr "Všetky albumy" #: ../quodlibet/ext/songsmenu/splitting.py:57 msgid "Split out disc number." msgstr "" #. TRANSLATORS: BPM mean "beats per minute" #: ../quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "" #: ../quodlibet/ext/songsmenu/tapbpm.py:32 #: ../quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" msgstr "" #: ../quodlibet/ext/songsmenu/tapbpm.py:36 #, fuzzy msgid "Reset" msgstr "_Náhľad" #: ../quodlibet/ext/songsmenu/tapbpm.py:42 #, fuzzy msgid "Tap" msgstr "Tag" #: ../quodlibet/ext/songsmenu/tapbpm.py:172 #: ../quodlibet/ext/songsmenu/tapbpm.py:179 msgid "Tap BPM" msgstr "" #: ../quodlibet/ext/songsmenu/tapbpm.py:173 #, fuzzy msgid "Tap BPM for the selected song." msgstr "Nepodarilo sa vymazať skladby" #: ../quodlibet/ext/songsmenu/website_search.py:35 #, fuzzy msgid "Website Search" msgstr "Vyhľadávať" #: ../quodlibet/ext/songsmenu/website_search.py:36 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern-example)s." msgstr "" #: ../quodlibet/ext/songsmenu/website_search.py:78 #, fuzzy msgid "Search URL patterns" msgstr "vzorka" #: ../quodlibet/ext/songsmenu/website_search.py:88 #, fuzzy msgid "Edit search URLs" msgstr "Upraviť uložené hodnoty..." #. Add link to editor #: ../quodlibet/ext/songsmenu/website_search.py:114 #, fuzzy msgid "Configure Searches…" msgstr "Farebne označovať _vyhľadávanie" #: ../quodlibet/ext/songsmenu/wikipedia.py:46 #, python-format msgid "Search at %(website)s" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:63 msgid "Search Artist in Wikipedia" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:64 msgid "" "Opens a browser window with Wikipedia article on the playing song artist." msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:71 msgid "Search Album in Wikipedia" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:72 msgid "" "Opens a browser window with Wikipedia article on the playing song album." msgstr "" #. then (try to) load all new files #: ../quodlibet/library/libraries.py:650 ../quodlibet/library/libraries.py:660 #: ../quodlibet/library/libraries.py:726 ../quodlibet/library/libraries.py:745 #: ../quodlibet/qltk/information.py:268 ../quodlibet/qltk/prefs.py:639 #: ../quodlibet/util/library.py:124 msgid "Library" msgstr "Knižnica" #: ../quodlibet/library/libraries.py:650 msgid "Checking mount points" msgstr "Kontrola prípojných bodov" #: ../quodlibet/library/libraries.py:660 msgid "Scanning library" msgstr "Skenovanie knižnice" #: ../quodlibet/library/libraries.py:725 #, python-format msgid "Scanning %s" msgstr "Skenovanie %s" #: ../quodlibet/library/libraries.py:745 msgid "Loading files" msgstr "" #: ../quodlibet/operon/base.py:70 #, python-format msgid "Failed to load file: %r" msgstr "" #: ../quodlibet/operon/commands.py:37 msgid "List tags" msgstr "" #: ../quodlibet/operon/commands.py:42 ../quodlibet/operon/commands.py:81 #: ../quodlibet/operon/commands.py:461 msgid "Print terse output" msgstr "" #: ../quodlibet/operon/commands.py:44 ../quodlibet/operon/commands.py:83 #: ../quodlibet/operon/commands.py:463 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "" #: ../quodlibet/operon/commands.py:47 ../quodlibet/operon/commands.py:86 #, fuzzy msgid "Also list programmatic tags" msgstr "Zobraziť _programové tagy" #: ../quodlibet/operon/commands.py:51 ../quodlibet/operon/commands.py:129 #: ../quodlibet/operon/commands.py:220 ../quodlibet/operon/commands.py:293 #: ../quodlibet/operon/commands.py:336 ../quodlibet/operon/commands.py:340 #: ../quodlibet/operon/commands.py:391 ../quodlibet/operon/commands.py:394 #: ../quodlibet/operon/commands.py:433 ../quodlibet/operon/commands.py:468 #: ../quodlibet/operon/commands.py:508 ../quodlibet/operon/commands.py:543 #: ../quodlibet/operon/commands.py:585 msgid "Not enough arguments" msgstr "" #: ../quodlibet/operon/commands.py:53 ../quodlibet/operon/commands.py:90 #: ../quodlibet/operon/commands.py:131 ../quodlibet/operon/commands.py:222 #: ../quodlibet/operon/commands.py:470 msgid "Too many arguments" msgstr "" #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:92 #: ../quodlibet/operon/commands.py:475 ../quodlibet/qltk/data_editors.py:363 #, fuzzy msgid "Description" msgstr "popis" #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:475 #: ../quodlibet/qltk/edittags.py:454 msgid "Value" msgstr "Hodnota" #: ../quodlibet/operon/commands.py:76 msgid "List all common tags" msgstr "" #: ../quodlibet/operon/commands.py:118 msgid "Copy tags from one file to another" msgstr "" #: ../quodlibet/operon/commands.py:123 ../quodlibet/operon/commands.py:164 #: ../quodlibet/operon/commands.py:289 ../quodlibet/operon/commands.py:324 #: ../quodlibet/operon/commands.py:384 msgid "Show changes, don't apply them" msgstr "" #: ../quodlibet/operon/commands.py:125 msgid "Skip tags that can't be written" msgstr "" #: ../quodlibet/operon/commands.py:145 #, python-format msgid "Can't copy tag %r to file: %r" msgstr "" #: ../quodlibet/operon/commands.py:157 #, fuzzy msgid "Edit tags in a text editor" msgstr "Editor audio tagov" #: ../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 "Nie sú vybrané žiadne skladby." #: ../quodlibet/operon/commands.py:284 msgid "Set a tag and remove existing values" msgstr "" #: ../quodlibet/operon/commands.py:304 ../quodlibet/operon/commands.py:444 #: ../quodlibet/operon/commands.py:676 #, python-format msgid "Can not set %r" msgstr "" #: ../quodlibet/operon/commands.py:319 msgid "Remove tags" msgstr "" #: ../quodlibet/operon/commands.py:326 ../quodlibet/operon/commands.py:386 msgid "Value is a regular expression" msgstr "" #: ../quodlibet/operon/commands.py:328 msgid "Remove all tags" msgstr "" #: ../quodlibet/operon/commands.py:332 msgid "Can't combine '--all' with '--regexp'" msgstr "" #: ../quodlibet/operon/commands.py:366 #, python-format msgid "Can't remove %r from %r" msgstr "" #: ../quodlibet/operon/commands.py:379 #, fuzzy msgid "Remove a tag value" msgstr "Filter na hodnote tagu" #: ../quodlibet/operon/commands.py:428 #, fuzzy msgid "Add a tag value" msgstr "Filter na hodnote tagu" #: ../quodlibet/operon/commands.py:456 #, fuzzy msgid "List file information" msgstr "Žiadna informácia o čase" #: ../quodlibet/operon/commands.py:502 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" #: ../quodlibet/operon/commands.py:515 #, fuzzy, python-format msgid "Failed to load image file: %r" msgstr "Nepodarilo sa premenovať súbory" #: ../quodlibet/operon/commands.py:522 ../quodlibet/operon/commands.py:551 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" #: ../quodlibet/operon/commands.py:538 msgid "Remove all embedded images" msgstr "" #: ../quodlibet/operon/commands.py:568 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "" #: ../quodlibet/operon/commands.py:580 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" #: ../quodlibet/operon/commands.py:639 msgid "Rename files based on tags" msgstr "" #: ../quodlibet/operon/commands.py:654 msgid "Fill tags based on the file path" msgstr "" #: ../quodlibet/operon/commands.py:704 ../quodlibet/qltk/information.py:305 #: ../quodlibet/qltk/properties.py:84 ../quodlibet/qltk/renamefiles.py:176 #: ../quodlibet/qltk/tagsfrompath.py:229 ../quodlibet/qltk/tracknumbers.py:79 msgid "File" msgstr "Súbor" #: ../quodlibet/operon/commands.py:712 msgid "Fill tracknumbers for all files" msgstr "" #: ../quodlibet/operon/commands.py:731 msgid "Print tags based on the given pattern" msgstr "" #: ../quodlibet/operon/commands.py:768 #, fuzzy msgid "Display help information" msgstr "Zobraziť krátku informáciu o použití" #: ../quodlibet/operon/util.py:40 #, fuzzy, python-format msgid "'%(column-id)s' is not a valid column name (%(all-column-ids)s)." msgstr "<b>%s</b> nie je platné umiestnenie." #: ../quodlibet/order/__init__.py:30 #, fuzzy msgid "_Unknown" msgstr "Neznáme" #: ../quodlibet/order/__init__.py:142 msgid "In Order" msgstr "V poradí" #: ../quodlibet/order/__init__.py:143 msgid "_In Order" msgstr "_V poradí" #: ../quodlibet/order/reorder.py:23 #, fuzzy msgid "Random" msgstr "_Náhodne" #: ../quodlibet/order/reorder.py:24 ../quodlibet/qltk/queue.py:119 msgid "_Random" msgstr "_Náhodne" #: ../quodlibet/order/reorder.py:39 ../quodlibet/order/reorder.py:40 msgid "Prefer higher rated" msgstr "" #: ../quodlibet/order/repeat.py:43 ../quodlibet/order/repeat.py:44 msgid "Repeat this track" msgstr "" #: ../quodlibet/order/repeat.py:57 ../quodlibet/order/repeat.py:58 #, fuzzy msgid "Repeat all" msgstr "_Opakovať" #: ../quodlibet/order/repeat.py:73 ../quodlibet/order/repeat.py:74 msgid "One Song" msgstr "Jedna skladba" #: ../quodlibet/player/gstbe/player.py:98 msgid "Stream" msgstr "" #: ../quodlibet/player/gstbe/player.py:98 msgid "Buffering" msgstr "" #: ../quodlibet/player/gstbe/player.py:319 msgid "Could not create GStreamer pipeline" msgstr "" #: ../quodlibet/player/gstbe/player.py:560 msgid "No GStreamer element found to handle media format" msgstr "" #: ../quodlibet/player/gstbe/player.py:561 #, 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:25 msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. In case the pipeline contains a sink, it will be used instead of " "the default one." msgstr "" #: ../quodlibet/player/gstbe/prefs.py:36 msgid "_Output pipeline:" msgstr "" #: ../quodlibet/player/gstbe/prefs.py:43 #, fuzzy, python-format msgid "%.1f seconds" msgstr "%d sekunda" #: ../quodlibet/player/gstbe/prefs.py:57 msgid "_Buffer duration:" msgstr "" #: ../quodlibet/player/gstbe/prefs.py:66 msgid "Disable _gapless playback" msgstr "" #: ../quodlibet/player/gstbe/prefs.py:70 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions." msgstr "" #: ../quodlibet/player/gstbe/util.py:93 #, fuzzy msgid "No GStreamer audio sink found" msgstr "Nenájdené žiadne stanice." #: ../quodlibet/player/gstbe/util.py:112 msgid "Invalid GStreamer output pipeline" msgstr "" #: ../quodlibet/player/xinebe/player.py:90 #, fuzzy msgid "Unable to create audio output" msgstr "Nepodarilo sa vytvoriť zložku" #: ../quodlibet/player/xinebe/player.py:91 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "" #: ../quodlibet/plugins/__init__.py:62 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" #: ../quodlibet/plugins/__init__.py:71 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "" #: ../quodlibet/plugins/playlist.py:30 #, 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:41 ../quodlibet/qltk/songsmenu.py:46 #: ../quodlibet/qltk/songsmenu.py:74 #, fuzzy msgid "_Run Plugin" msgstr "_Zásuvné moduly" #: ../quodlibet/qltk/about.py:40 #, python-format msgid "Supported formats: %s" msgstr "Podporované formáty: %s" #: ../quodlibet/qltk/about.py:43 #, python-format msgid "Audio device: %s" msgstr "Audio zariadenie: %s" #. 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:207 ../quodlibet/qltk/information.py:131 msgid "Bookmarks" msgstr "Záložky" #: ../quodlibet/qltk/browser.py:56 msgid "_Filters" msgstr "_Filtre" #: ../quodlibet/qltk/browser.py:57 #, fuzzy msgid "Recently _Played" msgstr "_Nehrané nikdy" #: ../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 "Nová stanica" #: ../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 "Náhodný žá_ner" #: ../quodlibet/qltk/browser.py:82 msgid "Random _Artist" msgstr "Náhodný int_erpret" #: ../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 skladieb ktoré ste hrali najviac" #: ../quodlibet/qltk/cbes.py:48 ../quodlibet/qltk/edittags.py:311 msgid "_Value:" msgstr "_Hodnota:" #: ../quodlibet/qltk/cbes.py:262 msgid "Saved Values" msgstr "Uložené hodnoty" #: ../quodlibet/qltk/cbes.py:263 #, fuzzy msgid "Edit saved values…" msgstr "Upraviť uložené hodnoty..." #: ../quodlibet/qltk/controls.py:111 msgid "Auto_matic" msgstr "" #: ../quodlibet/qltk/controls.py:112 #, fuzzy msgid "_Track Mode" msgstr "Hlavičky _skladby" #: ../quodlibet/qltk/controls.py:113 #, fuzzy msgid "_Album Mode" msgstr "Hlavičky _albumu" #. Translators: player state, no action #: ../quodlibet/qltk/controls.py:122 msgid "_Mute" msgstr "" #: ../quodlibet/qltk/controls.py:128 #, fuzzy msgid "_Replay Gain Mode" msgstr "_Prispôsobiť hlasitosť podľa Replay Gain" #. Translators: New Command/Entry/Item/... #: ../quodlibet/qltk/data_editors.py:119 #, python-format msgid "New %s" msgstr "" #: ../quodlibet/qltk/data_editors.py:218 #, fuzzy msgid "(unknown)" msgstr "Neznáme" #: ../quodlibet/qltk/data_editors.py:355 msgid "Tag expression" msgstr "" #: ../quodlibet/qltk/data_editors.py:382 msgid "Tag expression e.g. people:real or ~album~year." msgstr "" #: ../quodlibet/qltk/data_editors.py:383 #, fuzzy msgid "Enter new tag" msgstr "Filter na hodnote tagu" #: ../quodlibet/qltk/delete.py:37 #, fuzzy 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 "" #: ../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 "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 "" #: ../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 "_Presunúť do koša" #: ../quodlibet/qltk/delete.py:152 ../quodlibet/qltk/delete.py:187 #, fuzzy, python-format msgid "Moving %(current)d/%(total)d." msgstr "Presúvanie %d/%d." #: ../quodlibet/qltk/delete.py:173 ../quodlibet/qltk/delete.py:205 #, fuzzy msgid "Unable to move to trash" msgstr "Neporadilo sa uložiť iPod databázu" #: ../quodlibet/qltk/delete.py:174 ../quodlibet/qltk/delete.py:206 #, fuzzy msgid "Moving one or more files to the trash failed." msgstr "Vysúvanie <b>%s</b> zlyhalo." #: ../quodlibet/qltk/delete.py:216 ../quodlibet/qltk/delete.py:250 #, fuzzy, python-format msgid "Deleting %(current)d/%(total)d." msgstr "Odstraňovanie %d/%d." #: ../quodlibet/qltk/delete.py:236 ../quodlibet/qltk/delete.py:269 #, fuzzy msgid "Unable to delete files" msgstr "Nepodarilo sa odstrániť súbor" #: ../quodlibet/qltk/delete.py:237 ../quodlibet/qltk/delete.py:270 #, fuzzy msgid "Deleting one or more files failed." msgstr "Odstraňovanie <b>%s</b> zlyhalo." #: ../quodlibet/qltk/downloader.py:38 msgid "Downloads" msgstr "Sťahovania" #: ../quodlibet/qltk/downloader.py:62 msgid "Size" msgstr "Veľkosť" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: ../quodlibet/qltk/downloader.py:94 ../quodlibet/qltk/renamefiles.py:265 #: ../quodlibet/qltk/wlw.py:50 msgid "_Stop" msgstr "" #: ../quodlibet/qltk/edittags.py:63 ../quodlibet/qltk/edittags.py:74 #, 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:67 ../quodlibet/qltk/edittags.py:71 #, 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:193 msgid "Split into _Multiple Values" msgstr "Rozdeliť na _viacero hodnôt" #: ../quodlibet/qltk/edittags.py:211 msgid "Split Disc out of _Album" msgstr "Oddeliť disk z _albumu" #: ../quodlibet/qltk/edittags.py:228 msgid "Split _Version out of Title" msgstr "Oddeliť _verziu z názvu" #: ../quodlibet/qltk/edittags.py:259 msgid "Split Arranger out of Ar_tist" msgstr "Oddeliť aranžéra z in_terpreta" #: ../quodlibet/qltk/edittags.py:264 msgid "Split _Performer out of Artist" msgstr "Oddeliť _hudobníka z interpreta" #: ../quodlibet/qltk/edittags.py:270 #, fuzzy msgid "Split _Performer out of Title" msgstr "Oddeliť _hudobníka z interpreta" #: ../quodlibet/qltk/edittags.py:276 #, fuzzy msgid "Split _Originalartist out of Title" msgstr "Oddeliť _verziu z názvu" #: ../quodlibet/qltk/edittags.py:283 msgid "Add a Tag" msgstr "Pridať tag" #: ../quodlibet/qltk/edittags.py:302 msgid "_Tag:" msgstr "_Tag:" #: ../quodlibet/qltk/edittags.py:404 msgid "Edit Tags" msgstr "Upraviť tagy" #: ../quodlibet/qltk/edittags.py:477 msgid "Show _programmatic tags" msgstr "Zobraziť _programové tagy" #: ../quodlibet/qltk/edittags.py:478 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" #. Translators: Revert button in the tag editor #: ../quodlibet/qltk/edittags.py:508 #, fuzzy msgctxt "edittags" msgid "_Revert" msgstr "Nikdy" #. Translators: Save button in the tag editor #: ../quodlibet/qltk/edittags.py:513 msgctxt "edittags" msgid "_Save" msgstr "" #: ../quodlibet/qltk/edittags.py:659 msgid "Unable to add tag" msgstr "Nepodarilo sa pridať tag" #: ../quodlibet/qltk/edittags.py:660 #, fuzzy, python-format msgid "Unable to add <b>%s</b>" msgstr "Neporadilo sa pridať skladby" #: ../quodlibet/qltk/edittags.py:662 #, fuzzy, python-format msgid "" "The files currently selected do not support multiple values for <b>%s</b>." msgstr "" "Nepodarilo sa pridať <b>%s</b>\n" "\n" "The files currently selected do not support multiple values." #. Can't add the new tag. #: ../quodlibet/qltk/edittags.py:689 ../quodlibet/qltk/edittags.py:856 #: ../quodlibet/qltk/tagsfrompath.py:212 ../quodlibet/util/__init__.py:554 #: ../quodlibet/util/tags.py:231 msgid "Invalid tag" msgstr "Neplatný tag" #: ../quodlibet/qltk/edittags.py:690 ../quodlibet/qltk/edittags.py:857 #: ../quodlibet/qltk/tagsfrompath.py:213 #, python-format msgid "" "Invalid tag <b>%s</b>\n" "\n" "The files currently selected do not support editing this tag." msgstr "" "Neplatný tag <b>%s</b>\n" "\n" "The files currently selected do not support editing this tag." #: ../quodlibet/qltk/edittags.py:828 ../quodlibet/qltk/edittags.py:868 msgid "Invalid value" msgstr "Neplatná hodnota" #: ../quodlibet/qltk/edittags.py:829 ../quodlibet/qltk/edittags.py:869 #, python-format msgid "" "Invalid value: <b>%(value)s</b>\n" "\n" "%(error)s" msgstr "" "Neplarná hodnota: <b>%(value)s</b>\n" "\n" "%(error)s" #: ../quodlibet/qltk/_editutils.py:28 msgid "Tag may not be accurate" msgstr "Tag môže byť nepresný" #: ../quodlibet/qltk/_editutils.py:31 #, 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> zmenené počas behu programu. Uloženie bez obnovenia knižnice môže " "prepísať zmeny v skladbe.\n" "\n" "Uložiť túto skladba aj tak?" #: ../quodlibet/qltk/_editutils.py:47 msgid "Unable to save song" msgstr "Nepodarilo sa uložiť skladbu" #: ../quodlibet/qltk/_editutils.py:50 #, 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 "" "Ukladanie <b>%s</b> zlyhalo. Súbor je možno len pre čítanie alebo nemáte " "práva na jeho zmenu." #: ../quodlibet/qltk/_editutils.py:142 #, fuzzy msgid "_More options…" msgstr "_Viac možností..." #: ../quodlibet/qltk/entry.py:80 msgid "_Undo" msgstr "" #: ../quodlibet/qltk/entry.py:82 msgid "_Redo" msgstr "" #: ../quodlibet/qltk/exfalsowindow.py:95 #: ../quodlibet/qltk/quodlibetwindow.py:1066 msgid "_About" msgstr "" #: ../quodlibet/qltk/exfalsowindow.py:99 #: ../quodlibet/qltk/quodlibetwindow.py:1088 msgid "_Check for Updates…" msgstr "" #: ../quodlibet/qltk/exfalsowindow.py:105 #: ../quodlibet/qltk/quodlibetwindow.py:1021 ../quodlibet/qltk/songsmenu.py:304 msgid "_Plugins" msgstr "_Zásuvné moduly" #: ../quodlibet/qltk/exfalsowindow.py:267 #, fuzzy, python-format msgid "%(title)s and %(count)s more" msgid_plural "%(title)s and %(count)s 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" #: ../quodlibet/qltk/exfalsowindow.py:279 msgid "Ex Falso Preferences" msgstr "Možnosti Ex Falso" #: ../quodlibet/qltk/exfalsowindow.py:289 ../quodlibet/qltk/prefs.py:598 msgid "Split _on:" msgstr "R_ozdeliť na:" #: ../quodlibet/qltk/exfalsowindow.py:295 ../quodlibet/qltk/prefs.py:613 msgid "Tag Editing" msgstr "Editácia tagov" #: ../quodlibet/qltk/filesel.py:210 msgid "Folders" msgstr "Zložky" #: ../quodlibet/qltk/filesel.py:253 #, fuzzy msgid "_New Folder…" msgstr "Nová zložka" #: ../quodlibet/qltk/filesel.py:262 #, fuzzy msgid "_Select all Sub-Folders" msgstr "_Vybrať všetky podzložky..." #: ../quodlibet/qltk/filesel.py:374 msgid "New Folder" msgstr "Nová zložka" #: ../quodlibet/qltk/filesel.py:374 msgid "Enter a name for the new folder:" msgstr "Vložte názov novej zložky:" #: ../quodlibet/qltk/filesel.py:387 msgid "Unable to create folder" msgstr "Nepodarilo sa vytvoriť zložku" #: ../quodlibet/qltk/filesel.py:404 msgid "Unable to delete folder" msgstr "Nepodarilo sa odstrániť zložku" #: ../quodlibet/qltk/filesel.py:519 ../quodlibet/qltk/pluginwin.py:167 msgid "Songs" msgstr "Skladby" #. Translators: As in "by Artist Name" #: ../quodlibet/qltk/info.py:42 #, python-format msgid "by %s" msgstr "od %s" #: ../quodlibet/qltk/info.py:43 ../quodlibet/qltk/information.py:167 #: ../quodlibet/qltk/information.py:448 #, python-format msgid "Disc %s" msgstr "Disk %s" #: ../quodlibet/qltk/info.py:44 ../quodlibet/qltk/information.py:172 #, python-format msgid "Track %s" msgstr "Skladba %s" #: ../quodlibet/qltk/info.py:108 #, fuzzy msgid "_Edit Display…" msgstr "Upraviť zobrazenie" #: ../quodlibet/qltk/information.py:105 msgid "No songs are selected." msgstr "Nie sú vybrané žiadne skladby." #: ../quodlibet/qltk/information.py:106 msgid "No Songs" msgstr "Žiadne skladby" #: ../quodlibet/qltk/information.py:121 ../quodlibet/qltk/information.py:338 #: ../quodlibet/qltk/information.py:471 ../quodlibet/qltk/information.py:531 msgid "Information" msgstr "Informácie" #: ../quodlibet/qltk/information.py:126 msgid "Lyrics" msgstr "Text" #: ../quodlibet/qltk/information.py:184 ../quodlibet/qltk/information.py:396 #, python-format msgid "Produced by %s" msgstr "Vytvorené v %s" #: ../quodlibet/qltk/information.py:199 ../quodlibet/util/tags.py:76 msgid "artist" msgstr "interpret" #: ../quodlibet/qltk/information.py:200 ../quodlibet/qltk/information.py:561 #: ../quodlibet/util/tags.py:76 msgid "artists" msgstr "interpreti" #. for backwards compat #: ../quodlibet/qltk/information.py:221 ../quodlibet/util/tags.py:86 #: ../quodlibet/util/tags.py:114 msgid "performers" msgstr "hudobníci" #: ../quodlibet/qltk/information.py:235 ../quodlibet/qltk/information.py:248 #: ../quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "Nikdy" #: ../quodlibet/qltk/information.py:236 #, fuzzy, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "%d krát" msgstr[1] "%d krát" msgstr[2] "%d krát" #: ../quodlibet/qltk/information.py:254 ../quodlibet/util/tags.py:139 msgid "added" msgstr "pridané" #: ../quodlibet/qltk/information.py:255 ../quodlibet/util/tags.py:140 msgid "last played" msgstr "naposledy prehrané" #: ../quodlibet/qltk/information.py:256 ../quodlibet/util/tags.py:150 msgid "plays" msgstr "prehraní" #: ../quodlibet/qltk/information.py:257 ../quodlibet/util/tags.py:151 msgid "skips" msgstr "preskočení" #: ../quodlibet/qltk/information.py:258 ../quodlibet/util/tags.py:156 msgid "rating" msgstr "hodnotenie" #: ../quodlibet/qltk/information.py:287 msgid "path" msgstr "" #: ../quodlibet/qltk/information.py:288 ../quodlibet/util/tags.py:154 msgid "length" msgstr "dĺžka" #: ../quodlibet/qltk/information.py:289 #, fuzzy msgid "format" msgstr "Informácie" #: ../quodlibet/qltk/information.py:290 ../quodlibet/util/tags.py:163 msgid "codec" msgstr "" #: ../quodlibet/qltk/information.py:291 ../quodlibet/util/tags.py:164 #, fuzzy msgid "encoding" msgstr "[Neplatné kódovanie]" #: ../quodlibet/qltk/information.py:292 ../quodlibet/util/tags.py:160 msgid "bitrate" msgstr "bitrate" #: ../quodlibet/qltk/information.py:293 ../quodlibet/util/tags.py:161 msgid "file size" msgstr "veľkosť súboru" #: ../quodlibet/qltk/information.py:294 ../quodlibet/util/tags.py:149 msgid "modified" msgstr "upravené" #: ../quodlibet/qltk/information.py:331 msgid "Additional" msgstr "" #: ../quodlibet/qltk/information.py:383 #, 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:458 msgid "Track unavailable" msgstr "Skladba nedostupná" #: ../quodlibet/qltk/information.py:464 msgid "Track List" msgstr "Zoznam skladieb" #: ../quodlibet/qltk/information.py:505 ../quodlibet/qltk/information.py:578 #, 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:508 msgid "Selected Discography" msgstr "Vybraná diskografia" #: ../quodlibet/qltk/information.py:558 #, 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:586 ../quodlibet/util/tags.py:74 msgid "albums" msgstr "albumy" #: ../quodlibet/qltk/information.py:599 msgid "Total length:" msgstr "Celková dľžka:" #: ../quodlibet/qltk/information.py:603 msgid "Total size:" msgstr "Celková veľkosť:" #: ../quodlibet/qltk/information.py:606 msgid "Files" msgstr "Súbory" #: ../quodlibet/qltk/lyrics.py:37 msgid "_Download" msgstr "_Sťahovanie" #: ../quodlibet/qltk/lyrics.py:40 #, fuzzy msgid "_Edit" msgstr "_Upraviť zobrazenie..." #. buffer.set_text(_("No lyrics found.\n\nYou can click the " #. "Download button to have Quod Libet search " #. "for lyrics online. You can also enter them " #. "yourself and click save.")) #: ../quodlibet/qltk/lyrics.py:73 ../quodlibet/qltk/lyrics.py:109 msgid "No lyrics found for this song." msgstr "Nenájdený žiadny text pre túto skladbu." #: ../quodlibet/qltk/lyrics.py:82 #, fuzzy msgid "Searching for lyrics…" msgstr "Vyhľadávanie textov..." #: ../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/msg.py:41 msgid "Discard tag changes?" msgstr "Zahodiť zmeny v tagoch?" #: ../quodlibet/qltk/msg.py:42 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:55 ../quodlibet/qltk/prefs.py:595 #: ../quodlibet/qltk/textedit.py:64 ../quodlibet/qltk/tracknumbers.py:117 #, fuzzy msgid "_Revert" msgstr "Nikdy" #: ../quodlibet/qltk/msg.py:86 msgid "File exists" msgstr "Súbor existuje" #: ../quodlibet/qltk/msg.py:88 #, python-format msgid "Replace %(file-name)s?" msgstr "" #: ../quodlibet/qltk/msg.py:94 #, fuzzy msgid "_Replace File" msgstr "Premenovať súbory" #: ../quodlibet/qltk/notif.py:182 msgid "Active tasks" msgstr "" #: ../quodlibet/qltk/notif.py:188 #, python-format msgid "%d tasks running" msgstr "" #: ../quodlibet/qltk/playorder.py:254 #, fuzzy msgid "Toggle shuffle mode" msgstr "Prepnúť mód prehrávania/pauzy" #: ../quodlibet/qltk/playorder.py:270 #, fuzzy msgid "Toggle repeat mode" msgstr "Prepnúť mód prehrávania/pauzy" #: ../quodlibet/qltk/pluginwin.py:44 msgid "Plugin Errors" msgstr "Chyby zásuvných modulov" #: ../quodlibet/qltk/pluginwin.py:124 msgid "Enabled" msgstr "" #: ../quodlibet/qltk/pluginwin.py:125 #, fuzzy msgid "Disabled" msgstr "Vypnúť prehliadač" #: ../quodlibet/qltk/pluginwin.py:131 msgid "No category" msgstr "" #: ../quodlibet/qltk/pluginwin.py:169 msgid "Events" msgstr "" #: ../quodlibet/qltk/pluginwin.py:170 #, fuzzy msgid "Play Order" msgstr "_Poradie:" #: ../quodlibet/qltk/pluginwin.py:171 #, fuzzy msgid "Editing" msgstr "Editácia tagov" #: ../quodlibet/qltk/pluginwin.py:173 #, fuzzy msgid "Covers" msgstr "Celková veľkosť:" #: ../quodlibet/qltk/pluginwin.py:309 msgid "No plugins found." msgstr "Nenájdené žiadne zásuvné moduly." #: ../quodlibet/qltk/pluginwin.py:358 #, fuzzy msgid "Plugins" msgstr "_Zásuvné moduly" #: ../quodlibet/qltk/pluginwin.py:402 msgid "Show _Errors" msgstr "Zobraziť _chyby" #: ../quodlibet/qltk/prefs.py:45 msgid "_Disc" msgstr "_Disk" #: ../quodlibet/qltk/prefs.py:46 msgid "_Track" msgstr "_Skladba" #: ../quodlibet/qltk/prefs.py:47 #, fuzzy msgid "Grou_ping" msgstr "zoskupenie" #: ../quodlibet/qltk/prefs.py:50 msgid "Al_bum" msgstr "_Album" #: ../quodlibet/qltk/prefs.py:55 msgid "_Filename" msgstr "Názob _súboru" #: ../quodlibet/qltk/prefs.py:57 msgid "_Length" msgstr "_Dľžka" #: ../quodlibet/qltk/prefs.py:64 msgid "_Jump to playing song automatically" msgstr "Automaticky _preskočiť na hrajúcu skladbu" #: ../quodlibet/qltk/prefs.py:66 msgid "When the playing song changes, scroll to it in the song list" msgstr "" #: ../quodlibet/qltk/prefs.py:82 msgid "_Others:" msgstr "_Ostatné:" #: ../quodlibet/qltk/prefs.py:88 #, fuzzy msgid "_Edit…" msgstr "_Upraviť zobrazenie..." #: ../quodlibet/qltk/prefs.py:91 msgid "Add or remove additional column headers" msgstr "" #: ../quodlibet/qltk/prefs.py:101 msgid "Visible Columns" msgstr "Viditeľné stĺpce" #: ../quodlibet/qltk/prefs.py:104 msgid "Title includes _version" msgstr "Názov obsahuje _verziu" #: ../quodlibet/qltk/prefs.py:106 #, fuzzy msgid "Artist includes all _people" msgstr "Názov obsahuje _verziu" #: ../quodlibet/qltk/prefs.py:108 #, fuzzy msgid "Album includes _disc subtitle" msgstr "Album obsahuje ča_sť" #: ../quodlibet/qltk/prefs.py:110 msgid "Filename includes _folder" msgstr "Názov súboru obsahuje _zložku" #: ../quodlibet/qltk/prefs.py:123 #, fuzzy msgid "Column Preferences" msgstr "Nastavenie" #: ../quodlibet/qltk/prefs.py:129 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "" #: ../quodlibet/qltk/prefs.py:142 ../quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Zoznam skladieb" #: ../quodlibet/qltk/prefs.py:222 #, fuzzy msgid "Edit Columns" msgstr "Viditeľné stĺpce" #: ../quodlibet/qltk/prefs.py:259 msgid "Duration totals" msgstr "" #: ../quodlibet/qltk/prefs.py:271 msgid "_Global filter:" msgstr "_Globálny filter:" #: ../quodlibet/qltk/prefs.py:277 msgid "Apply this query in addition to all others" msgstr "" #. Translators: The heading of the preference group, no action #: ../quodlibet/qltk/prefs.py:283 #, fuzzy msgctxt "heading" msgid "Search" msgstr "Vyhľadávať" #: ../quodlibet/qltk/prefs.py:287 ../quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Prehliadače" #: ../quodlibet/qltk/prefs.py:293 msgid "Confirm _multiple ratings" msgstr "" #: ../quodlibet/qltk/prefs.py:295 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "" #: ../quodlibet/qltk/prefs.py:298 msgid "Enable _one-click ratings" msgstr "" #: ../quodlibet/qltk/prefs.py:300 msgid "Enable rating by clicking on the rating column in the song list" msgstr "" #: ../quodlibet/qltk/prefs.py:306 ../quodlibet/qltk/prefs.py:616 #, fuzzy msgid "Ratings" msgstr "_Hodnotenie" #. Filename choice algorithm config #: ../quodlibet/qltk/prefs.py:312 msgid "Prefer _embedded art" msgstr "" #: ../quodlibet/qltk/prefs.py:314 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" #: ../quodlibet/qltk/prefs.py:319 msgid "_Fixed image filename:" msgstr "" #: ../quodlibet/qltk/prefs.py:321 msgid "The single image filename to use if selected" msgstr "" #: ../quodlibet/qltk/prefs.py:327 msgid "The album art image file to use when forced" msgstr "" #: ../quodlibet/qltk/prefs.py:336 #, fuzzy msgid "Album Art" msgstr "Zoznam albumov" #: ../quodlibet/qltk/prefs.py:357 #, fuzzy msgid "Playback" msgstr "Pozastaviť prehrávanie" #: ../quodlibet/qltk/prefs.py:362 msgid "Output Configuration" msgstr "" #: ../quodlibet/qltk/prefs.py:373 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" #: ../quodlibet/qltk/prefs.py:376 #, fuzzy msgid "_Fall-back gain (dB):" msgstr "_Hlasitosť (dB):" #: ../quodlibet/qltk/prefs.py:387 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "" #: ../quodlibet/qltk/prefs.py:390 #, fuzzy msgid "_Pre-amp gain (dB):" msgstr "_Hlasitosť (dB):" #: ../quodlibet/qltk/prefs.py:395 #, fuzzy msgid "_Enable Replay Gain volume adjustment" msgstr "_Prispôsobiť hlasitosť podľa Replay Gain" #: ../quodlibet/qltk/prefs.py:420 #, fuzzy msgid "Replay Gain Volume Adjustment" msgstr "_Prispôsobiť hlasitosť podľa Replay Gain" #: ../quodlibet/qltk/prefs.py:450 msgid "_Default rating:" msgstr "" #: ../quodlibet/qltk/prefs.py:493 #, fuzzy msgid "Rating _scale:" msgstr "_Hodnotenie" #: ../quodlibet/qltk/prefs.py:542 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:547 msgid "_Bayesian averaging amount:" msgstr "" #: ../quodlibet/qltk/prefs.py:556 #, fuzzy msgid "Save ratings and play _counts" msgstr "Ukladať hodnotenia a počty hraní" #: ../quodlibet/qltk/prefs.py:560 msgid "_Email:" msgstr "_Email:" #: ../quodlibet/qltk/prefs.py:562 msgid "Ratings and play counts will be set for this email address" msgstr "Hodnotenia a počty hraní budú nastavené pre túto emailovú adresu" #: ../quodlibet/qltk/prefs.py:577 #, fuzzy msgid "Auto-save tag changes" msgstr "Zahodiť zmeny v tagoch?" #: ../quodlibet/qltk/prefs.py:579 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "" #: ../quodlibet/qltk/prefs.py:587 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:610 #, fuzzy msgid "Tags" msgstr "Upraviť tagy" #: ../quodlibet/qltk/prefs.py:631 #, fuzzy msgid "Updating for new ratings" msgstr "_Nová stanica" #: ../quodlibet/qltk/prefs.py:641 #, fuzzy msgid "Scan library _on start" msgstr "O_bnoviť knižnicu" #: ../quodlibet/qltk/prefs.py:651 ../quodlibet/qltk/quodlibetwindow.py:1100 #, fuzzy msgid "_Scan Library" msgstr "_Vyhľadávať v knižnici" #: ../quodlibet/qltk/prefs.py:653 ../quodlibet/qltk/quodlibetwindow.py:1162 msgid "Check for changes in your library" msgstr "Skontrolovať zmeny v knižnici" #: ../quodlibet/qltk/prefs.py:658 #, fuzzy msgid "Re_build Library" msgstr "Z_novunačítať knižnicu" #: ../quodlibet/qltk/prefs.py:661 #, fuzzy msgid "Reload all songs in your library. This can take a long time." msgstr "Znovunačítať všetky skladby v knižnici (toto môže trvať dlho)" #: ../quodlibet/qltk/prefs.py:671 #, fuzzy msgid "Scan Directories" msgstr "Prehľadávať _adresáre" #: ../quodlibet/qltk/prefs.py:677 #, fuzzy msgid "Hidden Songs" msgstr "Žiadne skladby" #: ../quodlibet/qltk/properties.py:158 ../quodlibet/util/collection.py:398 #, fuzzy, python-format 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" #: ../quodlibet/qltk/properties.py:162 ../quodlibet/qltk/properties.py:164 msgid "Properties" msgstr "Vlastnosti" #: ../quodlibet/qltk/queue.py:101 msgid "_Queue" msgstr "_Fronta" #: ../quodlibet/qltk/queue.py:126 msgid "Stop Once Empty" msgstr "" #: ../quodlibet/qltk/queue.py:130 #, fuzzy msgid "_Clear Queue" msgstr "Chyby zásuvných modulov" #: ../quodlibet/qltk/queue.py:242 #, 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:198 msgid "_Browse Library" msgstr "_Prehliadať knižnicu" #: ../quodlibet/qltk/quodlibetwindow.py:395 #, fuzzy msgid "Toggle queue visibility" msgstr "Prepnúť viditelnosť hlavného okna" #: ../quodlibet/qltk/quodlibetwindow.py:516 #, fuzzy msgid "Playback Error" msgstr "Pozastaviť prehrávanie" #: ../quodlibet/qltk/quodlibetwindow.py:524 #, fuzzy msgid "Set up library directories?" msgstr "Vyberte adresáre" #: ../quodlibet/qltk/quodlibetwindow.py:525 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:531 msgid "_Not Now" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:532 msgid "_Set Up" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:956 msgid "Unable to add songs" msgstr "Neporadilo sa pridať skladby" #: ../quodlibet/qltk/quodlibetwindow.py:957 #: ../quodlibet/qltk/quodlibetwindow.py:1364 #, fuzzy, python-format msgid "%s uses an unsupported protocol." msgstr "<b>%s</b> používa nepodporovaný protokol." #: ../quodlibet/qltk/quodlibetwindow.py:980 msgid "_Jump to Playing Song" msgstr "_Preskočiť na hrajúcu skladbu" #: ../quodlibet/qltk/quodlibetwindow.py:986 #, fuzzy msgid "_File" msgstr "Súbor" #: ../quodlibet/qltk/quodlibetwindow.py:987 #, fuzzy msgid "_Song" msgstr "Skladby" #: ../quodlibet/qltk/quodlibetwindow.py:988 msgid "_View" msgstr "_Zobraziť" #: ../quodlibet/qltk/quodlibetwindow.py:989 #, fuzzy msgid "_Browse" msgstr "Prehliadače" #: ../quodlibet/qltk/quodlibetwindow.py:990 msgid "_Control" msgstr "_Ovládanie" #: ../quodlibet/qltk/quodlibetwindow.py:991 msgid "_Help" msgstr "_Pomocník" #: ../quodlibet/qltk/quodlibetwindow.py:997 #, fuzzy msgid "_Add a Folder…" msgstr "Pridať _zložku..." #: ../quodlibet/qltk/quodlibetwindow.py:1002 #, fuzzy msgid "_Add a File…" msgstr "Pridať _súbor..." #: ../quodlibet/qltk/quodlibetwindow.py:1007 #, fuzzy msgid "_Add a Location…" msgstr "Pridať umiestnenie" #: ../quodlibet/qltk/quodlibetwindow.py:1036 #, fuzzy msgid "Edit Bookmarks…" msgstr "_Upraviť záložky..." #: ../quodlibet/qltk/quodlibetwindow.py:1056 #, fuzzy msgid "Stop After This Song" msgstr "Skončiť po tejto skladbe" #: ../quodlibet/qltk/quodlibetwindow.py:1062 msgid "_Keyboard Shortcuts" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:1071 msgid "Online Help" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:1080 #, fuzzy msgid "Search Help" msgstr "Vyhľadávať" #: ../quodlibet/qltk/quodlibetwindow.py:1352 msgid "Add a Location" msgstr "Pridať umiestnenie" #: ../quodlibet/qltk/quodlibetwindow.py:1353 msgid "Enter the location of an audio file:" msgstr "Vložte umiestnenie audio súboru:" #: ../quodlibet/qltk/quodlibetwindow.py:1358 #: ../quodlibet/qltk/quodlibetwindow.py:1363 msgid "Unable to add location" msgstr "Nepodarilo sa pridať umiestnenie" #: ../quodlibet/qltk/quodlibetwindow.py:1359 #, fuzzy, python-format msgid "%s is not a valid location." msgstr "<b>%s</b> nie je platné umiestnenie." #: ../quodlibet/qltk/quodlibetwindow.py:1372 #: ../quodlibet/qltk/quodlibetwindow.py:1381 msgid "Add Music" msgstr "Pridať hudbu" #: ../quodlibet/qltk/quodlibetwindow.py:1372 ../quodlibet/qltk/scanbox.py:99 #, fuzzy msgid "_Add Folders" msgstr "Pridať _zložku..." #: ../quodlibet/qltk/quodlibetwindow.py:1379 #, fuzzy msgid "Music Files" msgstr "Hudobný prehrávač" #: ../quodlibet/qltk/quodlibetwindow.py:1381 #, fuzzy msgid "_Add Files" msgstr "Pridať _súbor..." #: ../quodlibet/qltk/ratingsmenu.py:24 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "" #: ../quodlibet/qltk/ratingsmenu.py:26 msgid "The saved ratings will be removed" msgstr "" #: ../quodlibet/qltk/ratingsmenu.py:27 #, python-format msgid "The rating of all selected songs will be changed to '%s'" msgstr "" #: ../quodlibet/qltk/ratingsmenu.py:57 ../quodlibet/qltk/ratingsmenu.py:111 #, fuzzy msgid "_Remove Rating" msgstr "_Hodnotenie" #: ../quodlibet/qltk/ratingsmenu.py:98 #, fuzzy msgid "Change _Rating" msgstr "_Hodnotenie" #: ../quodlibet/qltk/renamefiles.py:46 msgid "Replace spaces with _underscores" msgstr "Nahradiť medzery _podtržítkami" #: ../quodlibet/qltk/renamefiles.py:56 msgid "Strip _Windows-incompatible characters" msgstr "Odstrániť znaky nekompatibilné s _Windows" #: ../quodlibet/qltk/renamefiles.py:74 msgid "Strip _diacritical marks" msgstr "Odstrániť _diakritiku" #: ../quodlibet/qltk/renamefiles.py:85 msgid "Strip non-_ASCII characters" msgstr "Odstrániť ne-_ASCII znaky" #: ../quodlibet/qltk/renamefiles.py:95 msgid "Use only _lowercase characters" msgstr "" #: ../quodlibet/qltk/renamefiles.py:123 msgid "Rename Files" msgstr "Premenovať súbory" #: ../quodlibet/qltk/renamefiles.py:139 ../quodlibet/qltk/tagsfrompath.py:116 #, fuzzy msgid "Path Patterns" msgstr "vzorka" #: ../quodlibet/qltk/renamefiles.py:140 ../quodlibet/qltk/tagsfrompath.py:117 #, fuzzy msgid "Edit saved patterns…" msgstr "Upraviť uložené hodnoty..." #: ../quodlibet/qltk/renamefiles.py:143 ../quodlibet/qltk/tagsfrompath.py:120 #: ../quodlibet/qltk/tracknumbers.py:58 msgid "_Preview" msgstr "_Náhľad" #: ../quodlibet/qltk/renamefiles.py:190 msgid "New Name" msgstr "Nový názov" #: ../quodlibet/qltk/renamefiles.py:255 msgid "Unable to rename file" msgstr "Nepodarilo sa premenovať súbory" #: ../quodlibet/qltk/renamefiles.py:256 #, fuzzy, python-format msgid "" "Renaming <b>%(old-name)s</b> to <b>%(new-name)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." msgstr "" "Premenovanie <b>%s</b> do <b>%s</b> zlyhalo. Možno cieľový súbor už existuje " "alebo nemáte právo vytvoriť nový súbor alebo odstrániť starý." #: ../quodlibet/qltk/renamefiles.py:264 #, fuzzy msgid "Ignore _All Errors" msgstr "Zobraziť _chyby" #: ../quodlibet/qltk/renamefiles.py:267 msgid "_Continue" msgstr "_Pokračovať" #: ../quodlibet/qltk/renamefiles.py:296 msgid "Path is not absolute" msgstr "Cesta nie je absolútna" #: ../quodlibet/qltk/renamefiles.py:297 #, python-format msgid "" "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 ~/." 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:47 #, fuzzy msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "" "Skladby uložené v týchto zložkách (oddelené pomocou ':') budú pridané do " "Vašej knižnice" #: ../quodlibet/qltk/scanbox.py:99 msgid "Select Directories" msgstr "Vyberte adresáre" #: ../quodlibet/qltk/searchbar.py:52 #, fuzzy msgid "Saved Searches" msgstr "Uložené hodnoty" #: ../quodlibet/qltk/searchbar.py:53 #, fuzzy msgid "Edit saved searches…" msgstr "Upraviť uložené hodnoty..." #: ../quodlibet/qltk/searchbar.py:74 msgid "Search your library, using free text or QL queries" msgstr "" #: ../quodlibet/qltk/searchbar.py:129 #, fuzzy msgid "Search after _typing" msgstr "Skončiť po tejto skladbe" #: ../quodlibet/qltk/searchbar.py:132 msgid "Show search results after the user stops typing." msgstr "" #: ../quodlibet/qltk/searchbar.py:187 msgid "_Limit:" msgstr "_Limit:" #: ../quodlibet/qltk/searchbar.py:200 msgid "_Weight" msgstr "_Váha" #: ../quodlibet/qltk/seekbutton.py:238 msgid "Display remaining time" msgstr "Zobraziť zostávajúci čas" #: ../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 msgid "Focus the search entry" msgstr "" #: ../quodlibet/qltk/shortcuts.py:22 #, fuzzy msgid "Reset filters and jump to the playing song" msgstr "Presunúť pozíciu hrajúcej skladby" #: ../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 "Nepodarilo sa vymazať skladby" #: ../quodlibet/qltk/shortcuts.py:29 #, fuzzy msgid "Delete the selected songs" msgstr "Nepodarilo sa vymazať skladby" #: ../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 ../quodlibet/qltk/shortcuts.py:41 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: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:377 #, python-format msgid "_Filter on %s" msgstr "_Filter na %s" #: ../quodlibet/qltk/songlist.py:1094 #, fuzzy msgid "All _Headers" msgstr "Hlavičky _albumu" #: ../quodlibet/qltk/songlist.py:1095 msgid "_Track Headers" msgstr "Hlavičky _skladby" #: ../quodlibet/qltk/songlist.py:1096 msgid "_Album Headers" msgstr "Hlavičky _albumu" #: ../quodlibet/qltk/songlist.py:1097 msgid "_People Headers" msgstr "Hlavičky ľ_udí" #: ../quodlibet/qltk/songlist.py:1098 msgid "_Date Headers" msgstr "Hlavičky _dátumu" #: ../quodlibet/qltk/songlist.py:1099 msgid "_File Headers" msgstr "Hlavičky _súboru" #: ../quodlibet/qltk/songlist.py:1100 msgid "_Production Headers" msgstr "Hlavičky _produkcie" #: ../quodlibet/qltk/songlist.py:1115 #, fuzzy msgid "_Customize Headers…" msgstr "_Vlastné hlavičky..." #: ../quodlibet/qltk/songlist.py:1120 msgid "_Expand Column" msgstr "" #: ../quodlibet/qltk/songsmenu.py:36 #, 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:64 #, 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:149 #, fuzzy msgid "Configure Plugins…" msgstr "Farebne označovať _vyhľadávanie" #: ../quodlibet/qltk/songsmenu.py:345 msgid "Add to _Queue" msgstr "Pridať do _fronty" #: ../quodlibet/qltk/songsmenu.py:368 msgid "_Copy to Device" msgstr "_Kopírovať na zariadenie" #: ../quodlibet/qltk/songsmenu.py:379 #, fuzzy msgid "_Remove from Library" msgstr "_Odstrániť z playlistu" #: ../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:101 msgid "Tags From Path" msgstr "Tagy z cesty" #: ../quodlibet/qltk/tagsfrompath.py:138 msgid "Tags replace existing ones" msgstr "Nahradiť pôvodné tagy" #: ../quodlibet/qltk/tagsfrompath.py:139 msgid "Tags are added to existing ones" msgstr "Pridať k pôvodným tagom" #. Save button #: ../quodlibet/qltk/tagsfrompath.py:153 msgid "Save" msgstr "" #: ../quodlibet/qltk/tagsfrompath.py:195 #, python-format msgid "" "The pattern\n" "\t<b>%s</b>\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/tagsfrompath.py:216 msgid "Invalid tags" msgstr "Neplatné tagy" #: ../quodlibet/qltk/tagsfrompath.py:217 #, python-format msgid "" "Invalid tags <b>%s</b>\n" "\n" "The files currently selected do not support editing these tags." msgstr "" #: ../quodlibet/qltk/textedit.py:142 #, 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:158 msgid "Edit Display" msgstr "Upraviť zobrazenie" #: ../quodlibet/qltk/tracknumbers.py:39 msgid "Track Numbers" msgstr "Čísla skladieb" #: ../quodlibet/qltk/tracknumbers.py:42 msgid "Start fro_m:" msgstr "Začať _od:" #: ../quodlibet/qltk/tracknumbers.py:51 msgid "_Total tracks:" msgstr "_Celkový počet:" #: ../quodlibet/qltk/unity.py:52 #, fuzzy msgid "Play/Pause" msgstr "Prehrávač" #: ../quodlibet/qltk/unity.py:75 #, fuzzy msgid "Previous" msgstr "_Náhľad" #: ../quodlibet/qltk/views.py:923 #, fuzzy, 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 "" #: ../quodlibet/qltk/wlw.py:234 #, fuzzy, python-format msgid "%(current)s of %(all)s" msgstr "Presúvanie %d/%d." #: ../quodlibet/update.py:89 #, fuzzy msgid "Checking for Updates" msgstr "Kontrola prípojných bodov" #: ../quodlibet/update.py:124 #, fuzzy msgid "Connection failed" msgstr "miesto" #: ../quodlibet/update.py:133 #, python-format msgid "You are already using the newest version %(version)s" msgstr "" #: ../quodlibet/update.py:136 #, 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:420 msgid "Playlists must have a name" msgstr "" #: ../quodlibet/util/collection.py:603 #, python-format msgid "A playlist named %s already exists." msgstr "Playlist s názvom %s už existuje." #: ../quodlibet/util/cover/built_in.py:26 #, fuzzy msgid "Embedded album covers" msgstr "Zobraziť _obaly albumov" #: ../quodlibet/util/cover/built_in.py:27 msgid "Uses covers embedded into audio files." msgstr "" #: ../quodlibet/util/cover/built_in.py:49 #, fuzzy msgid "Filesystem cover" msgstr "Súborový systém" #: ../quodlibet/util/cover/built_in.py:50 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "" #: ../quodlibet/util/__init__.py:93 msgid "Display brief usage information" msgstr "Zobraziť krátku informáciu o použití" #: ../quodlibet/util/__init__.py:95 msgid "Display version and copyright" msgstr "Zobraziť verziu a copyright" #: ../quodlibet/util/__init__.py:135 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "" #: ../quodlibet/util/__init__.py:137 msgid "[options]" msgstr "[možnosti]" #: ../quodlibet/util/__init__.py:182 #, fuzzy, python-format msgid "Option %r not recognized." msgstr "E: Možnosť '%s' nerospoznaná." #: ../quodlibet/util/__init__.py:185 #, fuzzy, python-format msgid "Option %r requires an argument." msgstr "E: Možnosť '%s' vyžaduje parameter." #: ../quodlibet/util/__init__.py:188 #, fuzzy, python-format msgid "%r is not a unique prefix." msgstr "E: '%s' nie je unikátny prefix." #: ../quodlibet/util/__init__.py:364 #, python-format msgid "%d kbps" msgstr "%d kbps" #: ../quodlibet/util/__init__.py:419 #, fuzzy, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%d sekunda" msgstr[1] "%d sekundy" msgstr[2] "%d sekúnd" #: ../quodlibet/util/__init__.py:432 msgid "No time information" msgstr "Žiadna informácia o čase" #: ../quodlibet/util/__init__.py:435 #, 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:436 #, 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:437 #, 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:438 #, 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:439 #, 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:563 #, fuzzy msgctxt "check" msgid "titlecase?" msgstr "nope" #: ../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 "" #: ../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 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 "" "MusicBrainz status albumu musí byť '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 msgid "Unable to edit song" msgstr "Neporadilo sa editovať skladbu" #: ../quodlibet/util/songwrapper.py:113 #, python-format msgid "" "Saving <b>%s</b> failed. The file may be read-only, corrupted, or you do not " "have permission to edit it." msgstr "" "Ukladanie <b>%s</b> zlyhalo. Súbor je možno len pre čítanie alebo nemáte " "práva na jeho zmenu." #: ../quodlibet/util/string/__init__.py:34 #: ../quodlibet/util/string/__init__.py:44 msgid "[Invalid Encoding]" msgstr "[Neplatné kódovanie]" #: ../quodlibet/util/tags.py:74 msgid "album" msgstr "album" #: ../quodlibet/util/tags.py:75 msgid "arranger" msgstr "aranžér" #: ../quodlibet/util/tags.py:75 msgid "arrangers" msgstr "aranžéri" #: ../quodlibet/util/tags.py:75 #, fuzzy msgid "arrangement" msgstr "aranžér" #: ../quodlibet/util/tags.py:77 msgid "author" msgstr "autor" #: ../quodlibet/util/tags.py:77 msgid "authors" msgstr "autori" #: ../quodlibet/util/tags.py:78 msgid "composer" msgstr "skladateľ" #: ../quodlibet/util/tags.py:78 msgid "composers" msgstr "skladatelia" #: ../quodlibet/util/tags.py:78 #, fuzzy msgid "composition" msgstr "skladateľ" #. Translators: conducting as in conducting a musical performance #: ../quodlibet/util/tags.py:80 msgid "conductor" msgstr "dirigent" #: ../quodlibet/util/tags.py:80 msgid "conductors" msgstr "dirigenti" #: ../quodlibet/util/tags.py:80 #, fuzzy msgid "conducting" msgstr "dirigent" #: ../quodlibet/util/tags.py:81 msgid "contact" msgstr "kontakt" #: ../quodlibet/util/tags.py:82 msgid "copyright" msgstr "copyright" #: ../quodlibet/util/tags.py:83 msgid "date" msgstr "dátum" #: ../quodlibet/util/tags.py:84 msgid "description" msgstr "popis" #: ../quodlibet/util/tags.py:85 msgid "genre" msgstr "žáner" #: ../quodlibet/util/tags.py:85 #, fuzzy msgid "genres" msgstr "žáner" #: ../quodlibet/util/tags.py:86 msgid "performer" msgstr "hudobník" #: ../quodlibet/util/tags.py:87 msgid "grouping" msgstr "zoskupenie" #: ../quodlibet/util/tags.py:88 msgid "language" msgstr "jazyk" #: ../quodlibet/util/tags.py:89 msgid "license" msgstr "licencia" #: ../quodlibet/util/tags.py:90 msgid "location" msgstr "miesto" #: ../quodlibet/util/tags.py:91 msgid "lyricist" msgstr "autor textu" #: ../quodlibet/util/tags.py:91 msgid "lyricists" msgstr "autori textu" #: ../quodlibet/util/tags.py:91 #, fuzzy msgid "lyrics" msgstr "autor textu" #. Translators: Also e.g. "record label", "publisher" #: ../quodlibet/util/tags.py:93 msgid "organization" msgstr "organizácia" #: ../quodlibet/util/tags.py:94 msgid "title" msgstr "názov" #: ../quodlibet/util/tags.py:95 msgid "version" msgstr "verzia" #: ../quodlibet/util/tags.py:96 msgid "website" msgstr "webstránka" #: ../quodlibet/util/tags.py:98 msgid "album artist" msgstr "interpret albumu" #: ../quodlibet/util/tags.py:99 msgid "BPM" msgstr "BPM" #. Translators: This used to be called "part". #: ../quodlibet/util/tags.py:102 ../quodlibet/util/tags.py:103 msgid "disc subtitle" msgstr "" #: ../quodlibet/util/tags.py:104 ../quodlibet/util/tags.py:141 msgid "disc" msgstr "disk" #: ../quodlibet/util/tags.py:105 ../quodlibet/util/tags.py:143 msgid "track" msgstr "skladba" #: ../quodlibet/util/tags.py:106 msgid "label ID" msgstr "katalógové číslo" #: ../quodlibet/util/tags.py:107 msgid "original release date" msgstr "originálny dátum vydania" #: ../quodlibet/util/tags.py:108 msgid "original album" msgstr "pôvodný album" #: ../quodlibet/util/tags.py:109 msgid "original artist" msgstr "pôvodný interpret" #: ../quodlibet/util/tags.py:110 msgid "recording date" msgstr "dátum nahrania" #: ../quodlibet/util/tags.py:111 msgid "release country" msgstr "krajina vydania" #. 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:120 #, fuzzy msgid "MusicBrainz recording ID" msgstr "MusicBrainz ID skladby" #: ../quodlibet/util/tags.py:121 #, fuzzy msgid "MusicBrainz release track ID" msgstr "MusicBrainz ID skladby" #: ../quodlibet/util/tags.py:122 #, fuzzy msgid "MusicBrainz release ID" msgstr "MusicBrainz ID skladby" #: ../quodlibet/util/tags.py:123 #, fuzzy msgid "MusicBrainz artist ID" msgstr "MusicBrainz artist ID" #: ../quodlibet/util/tags.py:124 #, fuzzy msgid "MusicBrainz release artist ID" msgstr "MusicBrainz ID skladby" #: ../quodlibet/util/tags.py:125 msgid "MusicBrainz TRM ID" msgstr "MusicBrainz TRM ID" #: ../quodlibet/util/tags.py:126 msgid "MusicIP PUID" msgstr "MusicIP PUID" #: ../quodlibet/util/tags.py:127 msgid "MusicBrainz album status" msgstr "MusicBrainz status albumu" #: ../quodlibet/util/tags.py:128 msgid "MusicBrainz album type" msgstr "MusicBrainz typ albumu" #: ../quodlibet/util/tags.py:129 #, fuzzy msgid "MusicBrainz release group ID" msgstr "MusicBrainz ID skladby" #. Translators: "gain" means a volume adjustment, not "to acquire". #: ../quodlibet/util/tags.py:132 msgid "track gain" msgstr "" #: ../quodlibet/util/tags.py:133 msgid "track peak" msgstr "" #. Translators: "gain" means a volume adjustment, not "to acquire". #: ../quodlibet/util/tags.py:135 msgid "album gain" msgstr "" #: ../quodlibet/util/tags.py:136 msgid "album peak" msgstr "" #: ../quodlibet/util/tags.py:137 #, fuzzy msgid "reference loudness" msgstr "Nastavenie" #: ../quodlibet/util/tags.py:142 msgid "discs" msgstr "disky" #: ../quodlibet/util/tags.py:144 msgid "tracks" msgstr "skladby" #: ../quodlibet/util/tags.py:145 msgid "last started" msgstr "naposledy spustené" #: ../quodlibet/util/tags.py:146 msgid "full name" msgstr "celý názov" #: ../quodlibet/util/tags.py:153 msgid "mount point" msgstr "prípojný bod" #: ../quodlibet/util/tags.py:155 msgid "people" msgstr "ľudia" #: ../quodlibet/util/tags.py:157 msgid "year" msgstr "rok" #: ../quodlibet/util/tags.py:158 #, fuzzy msgid "original release year" msgstr "originálny dátum vydania" #: ../quodlibet/util/tags.py:159 #, fuzzy msgid "bookmark" msgstr "Záložky" #: ../quodlibet/util/tags.py:162 #, fuzzy msgid "file format" msgstr "formát" #: ../quodlibet/util/tags.py:165 #, fuzzy msgid "playlists" msgstr "Playlisty" #: ../quodlibet/util/tags.py:166 msgid "channel count" msgstr "" #. Translators: e.g. "artist (sort)" #: ../quodlibet/util/tags.py:256 msgid "sort" msgstr "" #. Translators: e.g. "performer (roles)" #: ../quodlibet/util/tags.py:264 msgid "roles" msgstr "" #, fuzzy #~ msgid "browsers" #~ msgstr "Prehliadače" #~ msgid "Unable to download lyrics." #~ msgstr "Neporadilo sa stiahnuť text." #~ msgid "Remove all songs from the queue" #~ msgstr "Odstrániť všetky skladby z fronty" #~ msgid "Watch this folder for new songs" #~ msgstr "Sledovať túto zložku pre nové skladby" #~ 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 "Model:" #~ msgstr "Model:" #~ msgid "Capacity:" #~ msgstr "Kapacita:" #~ msgid "Firmware:" #~ msgstr "Firmware:" #, fuzzy #~ msgid "Removing orphaned iPod track" #~ msgstr "W: odstraňovanie ositorené iPod skladby" #, 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 "Unable to open input files" #~ msgstr "Neporadilo sa otvoriť súbory" #, 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 "_Select" #~ msgstr "_Výber" #~ 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 "Choose New Stations" #~ msgstr "Zvoľte nové stanice" #~ msgid "Add" #~ msgstr "Pridať" #, fuzzy #~ msgid "Bitrate" #~ msgstr "bitrate" #~ msgid "_Stations..." #~ msgstr "_Stanice:" #, fuzzy #~ msgid "Quod Libet" #~ msgstr "Ukončiť Quod Libet" #~ 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9751859 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/po/sr_RS.po�������������������������������������������������������������������������0000644�0001750�0001750�00000655072�00000000000�014523� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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: 2019-08-13 06:59+0200\n" "PO-Revision-Date: 2019-08-17 06:05+0200\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" "Language: sr\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: Poedit 2.2.1\n" #: quodlibet/browsers/albums/main.py:206 #: quodlibet/browsers/covergrid/main.py:54 msgid "_Title" msgstr "_Назив" #: quodlibet/browsers/albums/main.py:207 #: quodlibet/browsers/covergrid/main.py:55 quodlibet/qltk/prefs.py:49 msgid "_Artist" msgstr "_Уметник" #: quodlibet/browsers/albums/main.py:208 #: quodlibet/browsers/covergrid/main.py:56 quodlibet/qltk/prefs.py:54 msgid "_Date" msgstr "_Датум" #: quodlibet/browsers/albums/main.py:209 msgid "_Original Date" msgstr "_Изворни датум" #: quodlibet/browsers/albums/main.py:210 #: quodlibet/browsers/covergrid/main.py:57 quodlibet/qltk/prefs.py:53 msgid "_Genre" msgstr "_Жанр" #: quodlibet/browsers/albums/main.py:211 #: quodlibet/browsers/covergrid/main.py:58 quodlibet/qltk/prefs.py:58 #: quodlibet/qltk/ratingsmenu.py:39 msgid "_Rating" msgstr "_Оцена" #: quodlibet/browsers/albums/main.py:212 msgid "_Playcount" msgstr "_Број пуштања" #: quodlibet/browsers/albums/main.py:218 #: quodlibet/browsers/covergrid/main.py:64 msgid "Sort _by…" msgstr "Разврстај _по…" #: quodlibet/browsers/albums/main.py:239 #: quodlibet/browsers/covergrid/main.py:85 #: quodlibet/browsers/paned/prefs.py:203 #: quodlibet/browsers/playlists/main.py:667 quodlibet/qltk/exfalsowindow.py:108 #: quodlibet/qltk/pluginwin.py:341 quodlibet/qltk/quodlibetwindow.py:906 msgid "_Preferences" msgstr "_Поставке" #: quodlibet/browsers/albums/main.py:409 msgid "Album List" msgstr "Листа албума" #: quodlibet/browsers/albums/main.py:410 msgid "_Album List" msgstr "_Листа албума" #: quodlibet/browsers/albums/main.py:524 #: quodlibet/browsers/covergrid/main.py:285 #: quodlibet/browsers/covergrid/main.py:501 msgid "All Albums" msgstr "Сви албуми" #: quodlibet/browsers/albums/main.py:525 #: quodlibet/browsers/covergrid/main.py:286 #: quodlibet/browsers/covergrid/main.py:502 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d албум" msgstr[1] "%d албума" msgstr[2] "%d албума" #: quodlibet/browsers/albums/main.py:706 #: quodlibet/browsers/covergrid/main.py:480 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:16 #: 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:385 quodlibet/util/collection.py:247 #, 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:383 quodlibet/util/collection.py:251 #, 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:124 #: quodlibet/ext/songsmenu/cover_download.py:243 msgid "Options" msgstr "Опције" #: quodlibet/browsers/albums/prefs.py:74 #: quodlibet/browsers/covergrid/prefs.py:127 msgid "Album Display" msgstr "Приказ албума" #: quodlibet/browsers/albums/prefs.py:78 #: quodlibet/browsers/covergrid/prefs.py:131 #: quodlibet/browsers/playlists/prefs.py:56 #: quodlibet/ext/songsmenu/albumart.py:328 #: quodlibet/ext/songsmenu/duplicates.py:345 #: quodlibet/ext/songsmenu/filterall.py:48 quodlibet/qltk/bookmarks.py:101 #: quodlibet/qltk/cbes.py:93 quodlibet/qltk/data_editors.py:96 #: quodlibet/qltk/data_editors.py:321 quodlibet/qltk/exfalsowindow.py:286 #: quodlibet/qltk/pluginwin.py:79 quodlibet/qltk/pluginwin.py:428 #: quodlibet/qltk/prefs.py:764 quodlibet/qltk/textedit.py:163 #: quodlibet/update.py:149 msgid "_Close" msgstr "_Затвори" #: quodlibet/browsers/audiofeeds.py:52 quodlibet/browsers/audiofeeds.py:64 #: quodlibet/browsers/audiofeeds.py:66 quodlibet/browsers/audiofeeds.py:156 #: quodlibet/browsers/paned/models.py:85 #: quodlibet/ext/songsmenu/fingerprint/search.py:46 #: quodlibet/formats/_audio.py:488 quodlibet/order/__init__.py:27 #: quodlibet/qltk/information.py:244 quodlibet/qltk/information.py:251 #: quodlibet/qltk/information.py:277 quodlibet/qltk/wlw.py:69 msgid "Unknown" msgstr "Непознато" #: quodlibet/browsers/audiofeeds.py:247 msgid "New Feed" msgstr "Нови извор" #: quodlibet/browsers/audiofeeds.py:248 msgid "Enter the location of an audio feed:" msgstr "Унесите локацију аудио извора:" #: quodlibet/browsers/audiofeeds.py:249 #: quodlibet/browsers/collection/prefs.py:89 quodlibet/browsers/iradio.py:357 #: quodlibet/browsers/paned/prefs.py:120 #: quodlibet/browsers/playlists/menu.py:96 #: quodlibet/browsers/playlists/util.py:52 quodlibet/qltk/bookmarks.py:62 #: quodlibet/qltk/cbes.py:55 quodlibet/qltk/data_editors.py:308 #: quodlibet/qltk/edittags.py:327 quodlibet/qltk/edittags.py:527 #: quodlibet/qltk/quodlibetwindow.py:1276 quodlibet/qltk/scanbox.py:61 msgid "_Add" msgstr "_Додај" #: quodlibet/browsers/audiofeeds.py:303 msgid "Audio Feeds" msgstr "Аудио извори" #: quodlibet/browsers/audiofeeds.py:304 msgid "_Audio Feeds" msgstr "_Аудио извори" #: quodlibet/browsers/audiofeeds.py:407 quodlibet/qltk/data_editors.py:93 msgid "_New" msgstr "_Ново" #: quodlibet/browsers/audiofeeds.py:467 quodlibet/browsers/audiofeeds.py:526 msgid "Unable to add feed" msgstr "Не могу додати извор" #: quodlibet/browsers/audiofeeds.py:468 quodlibet/browsers/audiofeeds.py:527 #, python-format msgid "" "%s could not be added. The server may be down, or the location may not be an " "audio feed." msgstr "" "%s не може бити додат. Можда је сервер недоступан или извор није аудио запис." #: quodlibet/browsers/audiofeeds.py:475 quodlibet/qltk/filesel.py:260 #: quodlibet/qltk/pluginwin.py:414 msgid "_Refresh" msgstr "_Освежи" #: quodlibet/browsers/audiofeeds.py:476 #: quodlibet/browsers/playlists/main.py:487 #: quodlibet/browsers/playlists/util.py:43 quodlibet/qltk/delete.py:143 #: quodlibet/qltk/filesel.py:257 quodlibet/qltk/lyrics.py:35 #: quodlibet/qltk/maskedbox.py:28 quodlibet/qltk/songsmenu.py:364 msgid "_Delete" msgstr "_Обриши" #: quodlibet/browsers/audiofeeds.py:543 msgid "" "The current audio backend does not support URLs, Audio Feeds browser " "disabled." msgstr "" "Тренутна аудио подршка не подржава URL, претраживач аудио извора је " "онемогућен." #: quodlibet/browsers/_base.py:146 quodlibet/browsers/_base.py:149 msgid "Library Browser" msgstr "Претраживач библиотеке" #: quodlibet/browsers/_base.py:273 quodlibet/ext/songsmenu/console.py:45 #: quodlibet/ext/songsmenu/refresh.py:30 quodlibet/qltk/exfalsowindow.py:240 #: quodlibet/qltk/information.py:554 quodlibet/qltk/maskedbox.py:68 #: quodlibet/util/collection.py:532 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d песма" msgstr[1] "%d песме" msgstr[2] "%d песама" #: quodlibet/browsers/_base.py:401 quodlibet/browsers/_base.py:406 #: quodlibet/qltk/tagsfrompath.py:193 quodlibet/qltk/textedit.py:140 #: quodlibet/util/__init__.py:573 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:23 #, python-format msgid "Unknown %s" msgstr "Непознат %s" #: quodlibet/browsers/collection/models.py:24 #, python-format msgid "Multiple %s Values" msgstr "Више %s вредности" #: quodlibet/browsers/collection/prefs.py:65 #: quodlibet/browsers/paned/prefs.py:93 msgid "_Custom" msgstr "_Прилагођено" #. Remove button #: quodlibet/browsers/collection/prefs.py:93 #: quodlibet/browsers/paned/prefs.py:124 #: quodlibet/browsers/playlists/menu.py:97 #: quodlibet/ext/playlist/remove_duplicates.py:60 #: quodlibet/qltk/bookmarks.py:97 quodlibet/qltk/bookmarks.py:127 #: quodlibet/qltk/cbes.py:82 quodlibet/qltk/cbes.py:89 #: quodlibet/qltk/data_editors.py:78 quodlibet/qltk/data_editors.py:91 #: quodlibet/qltk/data_editors.py:298 quodlibet/qltk/data_editors.py:311 #: quodlibet/qltk/data_editors.py:319 quodlibet/qltk/edittags.py:533 #: quodlibet/qltk/edittags.py:710 quodlibet/qltk/maskedbox.py:48 #: quodlibet/qltk/maskedbox.py:88 quodlibet/qltk/queue.py:427 #: quodlibet/qltk/scanbox.py:36 quodlibet/qltk/scanbox.py:63 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:470 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:247 #: quodlibet/ext/songsmenu/editplaycount.py:45 #: quodlibet/ext/songsmenu/exact_rating.py:38 #: quodlibet/player/gstbe/prefs.py:40 quodlibet/qltk/prefs.py:127 #: quodlibet/qltk/textedit.py:64 msgid "_Apply" msgstr "_Примени" #: quodlibet/browsers/collection/prefs.py:197 #: quodlibet/browsers/paned/prefs.py:251 #: quodlibet/browsers/playlists/menu.py:95 #: quodlibet/browsers/playlists/util.py:42 quodlibet/errorreport/ui.py:103 #: quodlibet/ext/playlist/export_to_folder.py:38 #: 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:44 #: quodlibet/ext/songsmenu/fingerprint/search.py:281 #: quodlibet/ext/songsmenu/fingerprint/submit.py:90 #: quodlibet/ext/songsmenu/importexport.py:40 #: quodlibet/ext/songsmenu/lastfmsync.py:218 #: quodlibet/ext/songsmenu/playlist.py:50 #: 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:326 #: quodlibet/qltk/_editutils.py:39 quodlibet/qltk/getstring.py:28 #: quodlibet/qltk/maskedbox.py:27 quodlibet/qltk/msg.py:54 #: quodlibet/qltk/msg.py:93 quodlibet/qltk/msg.py:111 #: quodlibet/qltk/ratingsmenu.py:33 quodlibet/update.py:95 msgid "_Cancel" msgstr "_Откажи" #: quodlibet/browsers/covergrid/main.py:126 msgid "Cover Grid" msgstr "Мрежа омота" #: quodlibet/browsers/covergrid/main.py:127 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:71 msgid "Show \"All Albums\" Item" msgstr "Прикажи ставку \"Сви албуми\"" #: quodlibet/browsers/covergrid/prefs.py:82 msgid "Wide Mode" msgstr "Широк режим" #: quodlibet/browsers/covergrid/prefs.py:114 #: quodlibet/browsers/covergrid/prefs.py:115 msgid "Cover Magnification" msgstr "Увеличавање омота" #: quodlibet/browsers/filesystem.py:39 msgid "File System" msgstr "Систем датотека" #: quodlibet/browsers/filesystem.py:40 msgid "_File System" msgstr "_Систем датотека" #: quodlibet/browsers/filesystem.py:124 quodlibet/qltk/songlist.py:255 msgid "Unable to copy songs" msgstr "Не могу да умножим песме" #: quodlibet/browsers/filesystem.py:125 quodlibet/qltk/songlist.py:256 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "Одабране ставке не могу бити умножене у други низ или листу песама." #: quodlibet/browsers/filesystem.py:197 msgid "_Add to Library" msgstr "_Додај у библиотеку" #: quodlibet/browsers/iradio.py:182 msgid "Unsupported file type" msgstr "Неподржан тип датотеке" #: quodlibet/browsers/iradio.py:183 #, 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:230 quodlibet/browsers/iradio.py:243 #: quodlibet/browsers/iradio.py:836 msgid "Unable to add station" msgstr "Не могу да додам страницу" #: quodlibet/browsers/iradio.py:254 quodlibet/browsers/iradio.py:487 msgid "Internet Radio" msgstr "Интернет радио" #: quodlibet/browsers/iradio.py:254 msgid "Downloading station list" msgstr "Преузимам листу станица" #: quodlibet/browsers/iradio.py:355 msgid "New Station" msgstr "Нова станица" #: quodlibet/browsers/iradio.py:356 msgid "Enter the location of an Internet radio station:" msgstr "Унесите локацију интернет радио станице:" #: quodlibet/browsers/iradio.py:374 msgid "Electronic" msgstr "Електронска" #: quodlibet/browsers/iradio.py:377 msgid "Hip Hop / Rap" msgstr "Хип Хоп / Реп" #: quodlibet/browsers/iradio.py:378 msgid "Oldies" msgstr "Стара" #: quodlibet/browsers/iradio.py:379 msgid "R&B" msgstr "R&B" #: quodlibet/browsers/iradio.py:380 msgid "Japanese" msgstr "Јапанска" #: quodlibet/browsers/iradio.py:381 msgid "Indian" msgstr "Индијска" #: quodlibet/browsers/iradio.py:383 msgid "Religious" msgstr "Духовна" #: quodlibet/browsers/iradio.py:385 msgid "Charts" msgstr "Табеле" #: quodlibet/browsers/iradio.py:386 msgid "Turkish" msgstr "Турска" #: quodlibet/browsers/iradio.py:387 msgid "Reggae / Dancehall" msgstr "Реге / За плес" #: quodlibet/browsers/iradio.py:388 msgid "Latin" msgstr "Латино" #: quodlibet/browsers/iradio.py:389 msgid "College Radio" msgstr "Факултетски радио" #: quodlibet/browsers/iradio.py:390 msgid "Talk / News" msgstr "Разговор / Вести" #: quodlibet/browsers/iradio.py:391 msgid "Ambient" msgstr "Амбиентална" #: quodlibet/browsers/iradio.py:392 msgid "Jazz" msgstr "Џез" #: quodlibet/browsers/iradio.py:393 quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "Класична" #: quodlibet/browsers/iradio.py:394 quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "Поп" #: quodlibet/browsers/iradio.py:395 msgid "Alternative" msgstr "Алтернативна" #: quodlibet/browsers/iradio.py:396 msgid "Metal" msgstr "Метал" #: quodlibet/browsers/iradio.py:397 msgid "Country" msgstr "Кантри" #: quodlibet/browsers/iradio.py:398 msgid "News" msgstr "Вести" #: quodlibet/browsers/iradio.py:399 msgid "Schlager" msgstr "Шлагери" #: quodlibet/browsers/iradio.py:400 msgid "Funk" msgstr "Фанк" #: quodlibet/browsers/iradio.py:401 msgid "Indie" msgstr "Инди" #: quodlibet/browsers/iradio.py:402 msgid "Blues" msgstr "Блуз" #: quodlibet/browsers/iradio.py:403 msgid "Soul" msgstr "Соул" #: quodlibet/browsers/iradio.py:404 msgid "Lounge" msgstr "За одмарање" #: quodlibet/browsers/iradio.py:405 msgid "Punk" msgstr "Панк" #: quodlibet/browsers/iradio.py:406 msgid "Reggaeton" msgstr "Регетон" #: quodlibet/browsers/iradio.py:408 msgid "Slavic" msgstr "Словенска" #: quodlibet/browsers/iradio.py:410 msgid "Greek" msgstr "Грчка" #: quodlibet/browsers/iradio.py:411 msgid "Gothic" msgstr "Готика" #: quodlibet/browsers/iradio.py:412 quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "Рок" #: quodlibet/browsers/iradio.py:465 msgid "Would you like to load a list of popular radio stations?" msgstr "Да ли желите да учитате листу популарних радио станица?" #: quodlibet/browsers/iradio.py:471 msgid "_Load Stations" msgstr "_Учитај станице" #: quodlibet/browsers/iradio.py:488 msgid "_Internet Radio" msgstr "_Интернет радио" #: quodlibet/browsers/iradio.py:561 msgid "_New Station…" msgstr "_Нова станица…" #: quodlibet/browsers/iradio.py:564 msgid "_Update Stations" msgstr "_Ажурирај станице" #: quodlibet/browsers/iradio.py:591 msgid "All Stations" msgstr "Све станице" #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:595 quodlibet/browsers/soundcloud/main.py:65 msgid "Favorites" msgstr "Омиљено" #: quodlibet/browsers/iradio.py:603 msgid "No Category" msgstr "Без категорије" #: quodlibet/browsers/iradio.py:828 msgid "No stations found" msgstr "Нису пронађене станице" #: quodlibet/browsers/iradio.py:829 #, python-format msgid "No Internet radio stations were found at %s." msgstr "Интернет радио станица није нађена на %s." #: quodlibet/browsers/iradio.py:837 msgid "All stations listed are already in your library." msgstr "Излистане станице су већ у вашој библиотеци." #: quodlibet/browsers/iradio.py:854 msgid "Add to Favorites" msgstr "Додај у омиљене" #: quodlibet/browsers/iradio.py:858 msgid "Remove from Favorites" msgstr "Уклони из омиљених" #: quodlibet/browsers/iradio.py:958 #, 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:103 quodlibet/qltk/pluginwin.py:122 #: quodlibet/qltk/pluginwin.py:164 msgid "All" msgstr "Све" #: quodlibet/browsers/paned/prefs.py:41 #: quodlibet/ext/songsmenu/cover_download.py:118 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" "<tt>%s</tt>" msgstr "" "Означи шаблон опционим обележјима нпр. <tt>kompozitor</tt> или\n" "<tt>%s</tt>" #: quodlibet/browsers/paned/prefs.py:231 msgid "Paned Browser Preferences" msgstr "Postavke pano pretraživača" #: quodlibet/browsers/paned/prefs.py:236 msgid "Column layout" msgstr "Изглед колона" #: quodlibet/browsers/paned/prefs.py:240 msgid "Column content" msgstr "Садржај колона" #: quodlibet/browsers/paned/prefs.py:242 msgid "Equal pane width" msgstr "Једнака ширина паноа" #: quodlibet/browsers/playlists/main.py:48 #: quodlibet/browsers/playlists/main.py:603 quodlibet/qltk/pluginwin.py:168 msgid "Playlists" msgstr "Листа извођења" #: quodlibet/browsers/playlists/main.py:49 msgid "_Playlists" msgstr "_Листа извођења" #: quodlibet/browsers/playlists/main.py:152 msgid "_Remove from Playlist" msgstr "_Уклони са листе извођења" #: quodlibet/browsers/playlists/main.py:217 msgid "New" msgstr "Ново" #: quodlibet/browsers/playlists/main.py:221 msgid "Import" msgstr "Увези" #: quodlibet/browsers/playlists/main.py:443 msgid "Unable to import playlist" msgstr "Не могу да увезем листу извођења" #: quodlibet/browsers/playlists/main.py:444 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:494 msgid "_Rename" msgstr "_Преименуј" #: quodlibet/browsers/playlists/main.py:592 msgid "Unable to rename playlist" msgstr "Не могу да преименујем листу пуштања" #: quodlibet/browsers/playlists/main.py:604 msgid "Import Playlist" msgstr "Увези листу извођења" #: quodlibet/browsers/playlists/main.py:604 msgid "_Import" msgstr "_Увези" #: quodlibet/browsers/playlists/menu.py:25 msgid "_New Playlist…" msgstr "_Нова листа извођења…" #: quodlibet/browsers/playlists/menu.py:86 #, 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:90 #, 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:33 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "Да ли сте сигурни да желите да избришете листу извођења '%s'?" #: quodlibet/browsers/playlists/util.py:35 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" "Све информације о одабраној листи извођења ће бити неповратно избрисане." #: quodlibet/browsers/playlists/util.py:50 #: quodlibet/browsers/playlists/util.py:125 quodlibet/util/collection.py:575 msgid "New Playlist" msgstr "Нова листа извођења" #: quodlibet/browsers/playlists/util.py:51 msgid "Enter a name for the new playlist:" msgstr "Унесите име за нову листу извођења:" #: quodlibet/browsers/playlists/util.py:89 #, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" "Увозим листу извођења.\n" "\n" "%(current)d/%(total)d додато песама." #: quodlibet/browsers/search.py:32 msgid "_Limit Results" msgstr "_Ограничи резултате" #: quodlibet/browsers/search.py:37 msgid "_Allow multiple queries" msgstr "_Дозволи више претрага" #: quodlibet/browsers/search.py:53 msgid "Search Library" msgstr "Претражи библиотеку" #: quodlibet/browsers/search.py:54 msgid "_Search Library" msgstr "_Претражи библиотеку" #: quodlibet/browsers/soundcloud/main.py:39 msgid "Soundcloud Browser" msgstr "Soundcloud претраживач" #: quodlibet/browsers/soundcloud/main.py:40 msgid "Sound_cloud" msgstr "Sound_cloud" #: quodlibet/browsers/soundcloud/main.py:60 quodlibet/qltk/searchbar.py:81 msgid "Search" msgstr "Претрага" #: quodlibet/browsers/soundcloud/main.py:69 msgid "My tracks" msgstr "Моји записи" #: quodlibet/browsers/soundcloud/main.py:141 #, python-format msgid "Go to %s" msgstr "Иди на %s" #: quodlibet/browsers/soundcloud/main.py:443 msgid "Connected" msgstr "Повезан" #: quodlibet/browsers/soundcloud/main.py:444 #, python-format msgid "Quod Libet is now connected, <b>%s</b>!" msgstr "Quod Libet је повезан, <b>%s</b>!" #: quodlibet/browsers/soundcloud/main.py:456 #, python-format msgid "Log out of %s" msgstr "Одјави се са %s" #: quodlibet/browsers/soundcloud/main.py:458 msgid "Enter code…" msgstr "Унеси код…" #: quodlibet/browsers/soundcloud/main.py:459 #, python-format msgid "Log in to %s" msgstr "Пријави се на %s" #: quodlibet/browsers/soundcloud/util.py:86 msgid "Soundcloud authorisation" msgstr "Soundcloud аутентификација" #: quodlibet/browsers/soundcloud/util.py:87 msgid "Enter Soundcloud auth code:" msgstr "Унесите Soundcloud аутентификациони код:" #: quodlibet/cli.py:50 msgid "Quod Libet is not running (add '--run' to start it)" msgstr "Quod Libet није покренут (додај '--run' за покретање)" #: quodlibet/cli.py:86 msgid "a music library and player" msgstr "музичка библиотека и плејер" #: quodlibet/cli.py:87 msgid "[option]" msgstr "[опција]" #: quodlibet/cli.py:89 msgid "Print the playing song and exit" msgstr "Одштампај пуштену песму и изађи" #: quodlibet/cli.py:90 msgid "Begin playing immediately" msgstr "Одмах почни извођење" #: quodlibet/cli.py:91 msgid "Don't show any windows on start" msgstr "Не приказуј прозоре при покретању" #: quodlibet/cli.py:94 msgid "Jump to next song" msgstr "Скочи на следећу песму" #: quodlibet/cli.py:96 msgid "Jump to previous song or restart if near the beginning" msgstr "Скочи на претходну песму или пусти поново ако је при почетку" #: quodlibet/cli.py:97 msgid "Jump to previous song" msgstr "Скочи на претходну песму" #: quodlibet/cli.py:98 msgid "Start playback" msgstr "Покрени извођење" #: quodlibet/cli.py:99 msgid "Pause playback" msgstr "Паузирај извођење" #: quodlibet/cli.py:100 msgid "Toggle play/pause mode" msgstr "Мењај пусти/паузирај режим" #: quodlibet/cli.py:101 msgid "Stop playback" msgstr "Заустави извођење" #: quodlibet/cli.py:102 msgid "Turn up volume" msgstr "Појачај" #: quodlibet/cli.py:103 msgid "Turn down volume" msgstr "Смањи" #: quodlibet/cli.py:104 msgid "Increase rating of playing song by one star" msgstr "Повећај оцену тренутне песме за једну звездицу" #: quodlibet/cli.py:105 msgid "Decrease rating of playing song by one star" msgstr "Умањи оцену тренутне песме за једну звездицу" #: quodlibet/cli.py:106 msgid "Print player status" msgstr "Одштампај стање плејера" #: quodlibet/cli.py:107 msgid "Hide main window" msgstr "Сакриј главни прозор" #: quodlibet/cli.py:108 msgid "Show main window" msgstr "Прикажи главни прозор" #: quodlibet/cli.py:109 msgid "Toggle main window visibility" msgstr "Промени видљивост главног прозора" #: quodlibet/cli.py:110 msgid "Focus the running player" msgstr "Фокусирај покренути плејер" #: quodlibet/cli.py:111 msgid "Remove active browser filters" msgstr "Уклони филтере активног претраживача" #: quodlibet/cli.py:112 msgid "Refresh and rescan library" msgstr "Освежи и претражи библиотеку" #: quodlibet/cli.py:113 msgid "List available browsers" msgstr "Излистај доступне претраживаче" #: quodlibet/cli.py:114 msgid "Print the current playlist" msgstr "Одштампај тренутну листу извођења" #: quodlibet/cli.py:115 msgid "Print the contents of the queue" msgstr "Одштампај садржај низа" #: quodlibet/cli.py:116 msgid "Print the active text query" msgstr "Одштампај упит активног текста" #: quodlibet/cli.py:117 msgid "Start without plugins" msgstr "Покрени без прикључака" #: quodlibet/cli.py:118 msgid "Start Quod Libet if it isn't running" msgstr "Покрени Quod Libet ако није покренут" #: quodlibet/cli.py:119 msgid "Exit Quod Libet" msgstr "Напусти Quod Libet" #: quodlibet/cli.py:124 msgid "Seek within the playing song" msgstr "Премотај тренутну песму" #: quodlibet/cli.py:124 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: quodlibet/cli.py:125 msgid "Set or toggle shuffle mode" msgstr "Постави или промени режим мешања" #: quodlibet/cli.py:126 msgid "Set shuffle mode type" msgstr "Постави тип режима мешања" #: quodlibet/cli.py:127 msgid "Turn repeat off, on, or toggle it" msgstr "Укључи или искључи понављање" #: quodlibet/cli.py:128 msgid "Set repeat mode type" msgstr "Промени тип понављања" #: quodlibet/cli.py:129 msgid "Set the volume" msgstr "Подеси јачину" #: quodlibet/cli.py:130 msgid "Search your audio library" msgstr "Претражи своју аудио библиотеку" #: quodlibet/cli.py:130 quodlibet/cli.py:140 quodlibet/cli.py:144 #: quodlibet/cli.py:146 msgid "query" msgstr "упит" #: quodlibet/cli.py:131 msgid "Play a file" msgstr "Репродукуј датотеку" #: quodlibet/cli.py:131 quodlibet/cli.py:140 quodlibet/cli.py:146 msgctxt "command" msgid "filename" msgstr "име дадотеке" #: quodlibet/cli.py:132 msgid "Set rating of playing song" msgstr "Оцени тренутну песму" #: quodlibet/cli.py:133 msgid "Set the current browser" msgstr "Постави тренутни претраживач" #: quodlibet/cli.py:134 msgid "Stop after the playing song" msgstr "Заустави након завршетка песме" #: quodlibet/cli.py:135 msgid "Open a new browser" msgstr "Отвори нов претраживач" #: quodlibet/cli.py:136 msgid "Show or hide the queue" msgstr "Прикажи или сакриј захтеве" #: quodlibet/cli.py:137 msgid "Filter on a random value" msgstr "Филтрирај по насумичној вредности" #: quodlibet/cli.py:137 msgctxt "command" msgid "tag" msgstr "ознака" #: quodlibet/cli.py:138 msgid "Filter on a tag value" msgstr "Филтрирај по вредношћу ознаке" #: quodlibet/cli.py:138 msgid "tag=value" msgstr "ознака=вредност" #: quodlibet/cli.py:139 msgid "Enqueue a file or query" msgstr "Нанизати датотеку или захтев" #: quodlibet/cli.py:141 msgid "Enqueue comma-separated files" msgstr "Нанизати зарезом раздвојене датотеке" #: quodlibet/cli.py:142 quodlibet/util/tags.py:157 msgid "filename" msgstr "име датотеке" #: quodlibet/cli.py:143 msgid "Print filenames of results of query to stdout" msgstr "Штампај имена датотека резултата захтева на стдоут" #: quodlibet/cli.py:145 msgid "Unqueue a file or query" msgstr "Избаци из низа датотеку или захтев" #: quodlibet/cli.py:147 msgid "Add a file or directory to the library" msgstr "Додај датотеку или директоријум у библиотеку" #: quodlibet/cli.py:148 quodlibet/util/tags.py:100 msgid "location" msgstr "локација" #: quodlibet/cli.py:213 #, python-format msgid "Invalid argument for '%s'." msgstr "Неважећи аргумент за '%s'." #: quodlibet/cli.py:214 quodlibet/util/__init__.py:173 #, 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 "Quit Program" 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:34 msgid "an audio tag editor" msgstr "уређивач аудио ознака" #: quodlibet/exfalso.py:34 quodlibet/util/tags.py:158 msgid "directory" msgstr "директоријум" #: quodlibet/exfalso.py:41 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:20 msgid "" "Downloads covers linked to by the artwork_url tag. This works with the " "Soundcloud browser." 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:20 msgid "MusicBrainz Cover Source" msgstr "MusicBrainz извор омота" #: quodlibet/ext/covers/musicbrainz.py:21 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:19 msgid "" "Allows arbitrary regex substitutions (s///) 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:68 msgid "Advanced Preferences" msgstr "Напредне поставке" #: quodlibet/ext/events/advanced_preferences.py:69 msgid "Allow editing of advanced config settings." msgstr "Дозволи мењање напредних подешавања конфигурације." #: quodlibet/ext/events/advanced_preferences.py:187 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/ext/events/weblyrics.py:318 quodlibet/qltk/prefs.py:266 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:66 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:172 msgid "Effects" msgstr "Ефекти" #: quodlibet/ext/events/animosd/prefs.py:288 msgid "Ed_it Display Pattern…" msgstr "Ур_еди шаблон приказа…" #: quodlibet/ext/events/animosd/prefs.py:292 #: 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_library_update.py:138 msgid "Automatic Library Update" msgstr "Аутоматско ажурирање билбиотеке" #: quodlibet/ext/events/auto_library_update.py:139 #, python-format msgid "Keeps your library up to date with inotify. Requires %s." msgstr "Држи вашу библиотеку ажурном користећи inotify. Захтева %s." #: 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 by Brian Nelson." msgstr "" "Аутоматски оцењује песме када су пуштене или рпескочене. Ово користи " "\"убрзани\" алгоритам са вукс од Брајана Нелсона." #: quodlibet/ext/events/bansheeimport.py:106 msgid "Specified Banshee database is malformed or missing" msgstr "" "Оређује да ли је Banshee база података недоступна или је лоше формирана" #: quodlibet/ext/events/bansheeimport.py:111 #: quodlibet/ext/events/rbimport.py:114 msgid "Import Failed" msgstr "Увоз неуспешан" #: quodlibet/ext/events/bansheeimport.py:117 #, 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:126 msgid "Banshee Import" msgstr "Banshee увоз" #: quodlibet/ext/events/bansheeimport.py:127 msgid "Imports ratings and song statistics from Banshee." msgstr "Увози оцене и статистику песме из Banshee." #: quodlibet/ext/events/bansheeimport.py:136 msgid "_Database path:" msgstr "_База података:" #: quodlibet/ext/events/bansheeimport.py:164 #: quodlibet/ext/events/rbimport.py:132 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/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:93 #: quodlibet/ext/gstreamer/karaoke.py:95 #, python-format msgid "%d Hz" msgstr "%d Hz" #: quodlibet/ext/events/equalizer.py:198 #: quodlibet/ext/gstreamer/crossfeed.py:112 #, 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/playlist/export_to_squeezebox.py:80 #: quodlibet/ext/songsmenu/albumart.py:324 #: quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/cover_download.py:309 #: quodlibet/ext/songsmenu/fingerprint/search.py:278 #: quodlibet/ext/songsmenu/html.py:75 quodlibet/ext/songsmenu/lastfmsync.py:219 #: quodlibet/ext/songsmenu/playlist.py:51 #: quodlibet/ext/songsmenu/replaygain.py:354 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/_editutils.py:40 #: quodlibet/qltk/lyrics.py:34 quodlibet/qltk/msg.py:52 #: quodlibet/qltk/renamefiles.py:216 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:42 msgid "Inhibit Screensaver" msgstr "Онемогући чувара екрана" #: quodlibet/ext/events/inhibit.py:43 msgid "Prevents the GNOME screensaver from activating while a song is playing." msgstr "" "Спречава GNOM чувара екрана да се активира када је у току репродукција песме." #: quodlibet/ext/events/inhibit.py:52 msgid "Music is playing" msgstr "Музика свира" #: quodlibet/ext/events/iradiolog.py:16 msgid "Internet Radio Log" msgstr "Интернет радио дневник" #: quodlibet/ext/events/iradiolog.py:17 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:31 msgid "Outputs a Jabber User Tunes file to ~/.quodlibet/jabber." 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 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:37 msgid "MPRIS D-Bus Support" msgstr "MPRIS D-Bus подршка" #: quodlibet/ext/events/mpris/__init__.py:38 msgid "" "Allows control of Quod Libet using the MPRIS 2 D-Bus Interface Specification." msgstr "" "Омогућава контролу Quod Libet-а користећи MPRIS 2 D-Bus спецификацију сучеља." #: quodlibet/ext/events/mpris/__init__.py:44 #: quodlibet/ext/events/trayicon/prefs.py:36 msgid "Hide main window on close" msgstr "Сакриј главни прозор при затварању" #: quodlibet/ext/events/mpris/__init__.py:47 #: quodlibet/ext/events/themeswitcher.py:84 #: quodlibet/ext/gstreamer/compressor.py:99 #: quodlibet/ext/gstreamer/crossfeed.py:136 #: quodlibet/ext/gstreamer/karaoke.py:99 quodlibet/ext/gstreamer/pitch.py:89 #: quodlibet/qltk/prefs.py:741 msgid "Preferences" msgstr "Поставке" #: quodlibet/ext/events/mqtt.py:54 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "Прихвата QL шаблоне нпр. %s" #: quodlibet/ext/events/mqtt.py:60 msgid "MQTT Publisher" msgstr "MQTT објављивач" #: quodlibet/ext/events/mqtt.py:61 msgid "Publishes status messages to an MQTT topic." msgstr "Објављује статусне поруке на MQTT тему." #: quodlibet/ext/events/mqtt.py:128 msgid "Broker hostname" msgstr "Име домаћина посредника" #: quodlibet/ext/events/mqtt.py:129 msgid "broker hostname / IP (defaults to localhost)" msgstr "име домаћина посредника / IP (подразумевано на localhost)" #: quodlibet/ext/events/mqtt.py:131 msgid "Broker port" msgstr "Порт посредника" #: quodlibet/ext/events/mqtt.py:131 msgid "broker port (defaults to 1883)" msgstr "порт посредника (подразумевано на 1883)" #: quodlibet/ext/events/mqtt.py:133 msgid "Topic" msgstr "Тема" #: quodlibet/ext/events/mqtt.py:135 msgid "Playing Pattern" msgstr "Образац репродукције" #: quodlibet/ext/events/mqtt.py:137 msgid "Status text when a song is started." msgstr "Статус текст када је песма пуштена." #: quodlibet/ext/events/mqtt.py:139 msgid "Paused Pattern" msgstr "Образац паузе" #: quodlibet/ext/events/mqtt.py:141 msgid "Text when a song is paused." msgstr "Текст када је песма паузирана." #: quodlibet/ext/events/mqtt.py:143 msgid "No-song Text" msgstr "Текст без песме" #: quodlibet/ext/events/mqtt.py:145 msgid "Plain text for when there is no current song" msgstr "Празан текст када нема пуштене песме" #: quodlibet/ext/events/mqtt.py:156 msgid "MQTT Configuration" msgstr "MQTT конфигурација" #: quodlibet/ext/events/mqtt.py:160 msgid "Status Text" msgstr "Статус текст" #: quodlibet/ext/events/mqtt.py:192 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "Повезан ка посреднику на %(host)s:%(port)d" #: quodlibet/ext/events/mqtt.py:196 #, 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:199 msgid "Connection error" 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/qlscrobbler.py:175 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" "Молимо посетите прозор додатака да подесите QLScrobbler. До тада, песме неће " "бити приложене." #: quodlibet/ext/events/qlscrobbler.py:252 #, python-format msgid "Could not contact service '%s'." msgstr "Не могу контактирати сервис '%s'." #: quodlibet/ext/events/qlscrobbler.py:258 msgid "Authentication failed: invalid URL." msgstr "Аутентификација неуспела: неважећи URL." #: quodlibet/ext/events/qlscrobbler.py:275 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "" "Аутентификација неуспела: Неважеће корисничко име '%s' или погрешна лозинка." #: quodlibet/ext/events/qlscrobbler.py:280 msgid "Client is banned. Contact the author." msgstr "Забрањен приступ. Контактирајте аутора." #: quodlibet/ext/events/qlscrobbler.py:284 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" "Погрешно системско време. Достава можда неће успети док се то не исправи." #: quodlibet/ext/events/qlscrobbler.py:349 msgid "AudioScrobbler Submission" msgstr "AudioScrobbler достава" #: quodlibet/ext/events/qlscrobbler.py:350 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" "Audioscrobbler клијент за Last.fm, Libre.fm и друге Audioscrobbler сервисе." #: quodlibet/ext/events/qlscrobbler.py:455 msgid "Authentication successful." msgstr "Аутентификација успешна." #: quodlibet/ext/events/qlscrobbler.py:467 msgid "_Service:" msgstr "_Сервис:" #: quodlibet/ext/events/qlscrobbler.py:467 msgid "_URL:" msgstr "_URL:" #: quodlibet/ext/events/qlscrobbler.py:467 msgid "User_name:" msgstr "Корисничко_име:" #: quodlibet/ext/events/qlscrobbler.py:468 msgid "_Password:" msgstr "_Лозинка:" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:484 msgid "Other…" msgstr "Друго…" #. verify data #: quodlibet/ext/events/qlscrobbler.py:522 msgid "_Verify account data" msgstr "_Провери податке налога" #: quodlibet/ext/events/qlscrobbler.py:527 #: quodlibet/ext/songsmenu/lastfmsync.py:312 msgid "Account" msgstr "Налог" #: quodlibet/ext/events/qlscrobbler.py:535 msgid "_Artist pattern:" msgstr "_Уметник шаблон:" #: quodlibet/ext/events/qlscrobbler.py:535 msgid "_Title pattern:" msgstr "_Наслов шаблон:" #: quodlibet/ext/events/qlscrobbler.py:536 msgid "Exclude _filter:" msgstr "Изузми _филтер:" #: quodlibet/ext/events/qlscrobbler.py:554 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" "Шаблон за форматирање имена уметника за доставу. Оставите празно за " "подразумевано." #: quodlibet/ext/events/qlscrobbler.py:564 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" "Шаблон за форматирање имена наслова за доставу. Оставите празно за " "подразумевано." #: quodlibet/ext/events/qlscrobbler.py:573 msgid "Songs matching this filter will not be submitted" msgstr "Песме које се подударају овим филтером неће бити достављене" #: quodlibet/ext/events/qlscrobbler.py:581 msgid "_Offline mode (don't submit anything)" msgstr "_Режим ван мреже (не достављај ништа)" #: quodlibet/ext/events/qlscrobbler.py:585 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:28 msgid "Random Album Playback" msgstr "Насумично извођење албума" #: quodlibet/ext/events/randomalbum.py:29 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:39 msgid "Rated higher" msgstr "Боље оцењено" #: quodlibet/ext/events/randomalbum.py:40 msgid "Played more often" msgstr "Чешће пуштано" #: quodlibet/ext/events/randomalbum.py:41 msgid "Skipped more often" msgstr "Чешће прескакано" #: quodlibet/ext/events/randomalbum.py:42 msgid "Played more recently" msgstr "Скоро пуштано" #: quodlibet/ext/events/randomalbum.py:43 msgid "Started more recently" msgstr "Скоро покретано" #: quodlibet/ext/events/randomalbum.py:44 msgid "Added more recently" msgstr "Скоро додато" #: quodlibet/ext/events/randomalbum.py:45 msgid "Longer albums" msgstr "Дужи албуми" #: quodlibet/ext/events/randomalbum.py:84 msgid "seconds before starting next album" msgstr "секунди пре почетка следећег албума" #: quodlibet/ext/events/randomalbum.py:88 msgid "Weights" msgstr "Значај" #: quodlibet/ext/events/randomalbum.py:90 msgid "Play some albums more than others" msgstr "Пуштај неке албуме чешће од других" #: quodlibet/ext/events/randomalbum.py:104 msgid "avoid" msgstr "избегни" #: quodlibet/ext/events/randomalbum.py:115 msgid "prefer" msgstr "преферирај" #: quodlibet/ext/events/randomalbum.py:219 msgid "Random Album" msgstr "Насумичан албум" #: quodlibet/ext/events/randomalbum.py:220 #, python-format msgid "Waiting to start %s" msgstr "Чекам да почне %s" #: quodlibet/ext/events/rbimport.py:119 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "Успешно увезене оцене и статистика за %d песама" #: quodlibet/ext/events/rbimport.py:127 msgid "Rhythmbox Import" msgstr "Rhythmbox увоз" #: quodlibet/ext/events/rbimport.py:128 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:73 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "GNOME Shell претраживач Quod Libet није инсталиран." #: quodlibet/ext/events/searchprovider.py:79 msgid "GNOME Search Provider" msgstr "GNOME претраживач" #: quodlibet/ext/events/searchprovider.py:80 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" "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:29 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:57 #: quodlibet/ext/playlist/export_to_squeezebox.py:89 msgid "Error finding Squeezebox server" msgstr "Грешка у проналажењу Squeezebox сервера" #: quodlibet/ext/events/squeezebox_sync.py:58 #: quodlibet/ext/playlist/export_to_squeezebox.py:90 #, python-format msgid "Error finding %s. Please check settings" msgstr "Грешка проналажења %s. Молимо проверите подешавања" #: quodlibet/ext/events/synchronizedlyrics.py:34 msgid "Synchronized Lyrics" msgstr "Синхронизовани текст" #: quodlibet/ext/events/synchronizedlyrics.py:35 msgid "Shows synchronized lyrics from .lrc file with same name as the track." msgstr "" "Показује синхронизовани текст песме из .lrc датотеке са истим именом као " "запис." #: quodlibet/ext/events/synchronizedlyrics.py:69 msgid "Text:" msgstr "Текст:" #: quodlibet/ext/events/synchronizedlyrics.py:79 msgid "Background:" msgstr "Позадина:" #: quodlibet/ext/events/synchronizedlyrics.py:90 msgid "Font" msgstr "Фонт" #: quodlibet/ext/events/synchronizedlyrics.py:93 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:145 msgid "Paused:" msgstr "Паузирано:" #: quodlibet/ext/events/telepathy_status.py:146 #, 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:162 msgid "Plain text for status when there is no current song" msgstr "Празан текст за статус када ништа није пуштено" #: quodlibet/ext/events/telepathy_status.py:163 msgid "No song:" msgstr "Нема песме:" #. Frame #: quodlibet/ext/events/telepathy_status.py:170 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:91 msgid "Thumb Rating" msgstr "Палац оцена" #: quodlibet/ext/events/thumbrating.py:92 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 '~#score'." 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:47 msgid "Not playing" msgstr "Не свира" #: quodlibet/ext/events/trayicon/__init__.py:53 msgid "Tray Icon" msgstr "Трака задатака" #: quodlibet/ext/events/trayicon/__init__.py:54 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:183 quodlibet/qltk/quodlibetwindow.py:936 #: quodlibet/qltk/quodlibetwindow.py:1142 msgid "_Play" msgstr "_Пусти" #: quodlibet/ext/events/trayicon/menu.py:63 #: quodlibet/qltk/quodlibetwindow.py:185 quodlibet/qltk/quodlibetwindow.py:1144 #: quodlibet/qltk/wlw.py:50 msgid "P_ause" msgstr "П_аузирај" #: quodlibet/ext/events/trayicon/menu.py:68 #: quodlibet/qltk/quodlibetwindow.py:190 quodlibet/qltk/quodlibetwindow.py:931 msgid "Pre_vious" msgstr "Пре_тходно" #: quodlibet/ext/events/trayicon/menu.py:71 #: quodlibet/qltk/quodlibetwindow.py:194 quodlibet/qltk/quodlibetwindow.py:941 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:902 msgid "Open _Browser" msgstr "Отвори _претраживач" #: quodlibet/ext/events/trayicon/menu.py:103 #: quodlibet/qltk/quodlibetwindow.py:921 quodlibet/qltk/songsmenu.py:383 msgid "Edit _Tags" msgstr "Измени _ознаке" #: quodlibet/ext/events/trayicon/menu.py:112 #: quodlibet/qltk/quodlibetwindow.py:864 quodlibet/qltk/songsmenu.py:396 msgid "_Information" msgstr "_Информације" #: quodlibet/ext/events/trayicon/menu.py:114 quodlibet/qltk/songsmenu.py:324 msgid "Play_lists" msgstr "Листа _извођења" #: quodlibet/ext/events/trayicon/menu.py:132 #: quodlibet/qltk/quodlibetwindow.py:916 msgid "_Quit" msgstr "_Одустани" #: quodlibet/ext/events/trayicon/prefs.py:38 quodlibet/qltk/prefs.py:69 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 quodlibet/ext/events/weblyrics.py:193 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:603 msgid "Waveform Seek Bar" msgstr "Таласна трака мотања" #: quodlibet/ext/events/waveformseekbar.py:607 msgid "A seekbar in the shape of the waveform of the current song." msgstr "Трака мотања у облику таласа тренутне песме." #: quodlibet/ext/events/waveformseekbar.py:676 msgid "Override foreground color:" msgstr "Користи боју предњег дела:" #: quodlibet/ext/events/waveformseekbar.py:680 msgid "Override hover color:" msgstr "Користи боју плутања:" #: quodlibet/ext/events/waveformseekbar.py:684 msgid "Override remaining color:" msgstr "Користи за остале боје:" #: quodlibet/ext/events/waveformseekbar.py:688 msgid "Show current position" msgstr "Прикажи тренутну позицију" #: quodlibet/ext/events/waveformseekbar.py:693 msgid "Show time labels" msgstr "Прикажи имена времена" #: quodlibet/ext/events/waveformseekbar.py:701 msgid "Seek amount when scrolling (milliseconds):" msgstr "Корак мотања приликом скроловања (милисекунде):" #: quodlibet/ext/events/weblyrics.py:208 msgid "No lyrics found" msgstr "Нема нађеног текста" #: quodlibet/ext/events/weblyrics.py:268 msgid "_Zoom level:" msgstr "_Увеличавање ниво:" #: quodlibet/ext/events/weblyrics.py:286 msgid "URL:" msgstr "URL:" #: quodlibet/ext/events/weblyrics.py:291 msgid "Revert to default" msgstr "Врати на подразумевано" #: quodlibet/ext/events/weblyrics.py:306 msgid "Search via above URL if the lyrics couldn't be found in LyricsWikia." msgstr "" "Тражи преко горњег URL-а ако текст не може бити пронађен на LyricsWikia." #: quodlibet/ext/events/weblyrics.py:323 msgid "Alternate search" msgstr "Алтернативна претрага" #: quodlibet/ext/events/weblyrics.py:332 msgid "Web Lyrics" msgstr "Веб текст" #: quodlibet/ext/events/weblyrics.py:333 msgid "Shows a sidebar containing online lyrics of the playing song." 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:20 msgid "_Threshold:" msgstr "_Праг:" #: quodlibet/ext/gstreamer/compressor.py:21 msgid "Threshold until the filter is activated" msgstr "Праг док филтер не буде активиран" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "R_atio:" msgstr "О_днос:" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "Compression ratio" msgstr "Однос компресије" #: quodlibet/ext/gstreamer/compressor.py:74 #: quodlibet/ext/gstreamer/karaoke.py:91 #, python-format msgid "%d %%" msgstr "%d %%" #: quodlibet/ext/gstreamer/compressor.py:105 msgid "Audio Compressor" msgstr "Аудио компресор" #: quodlibet/ext/gstreamer/compressor.py:106 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "Мења опсег свих узорака изнад одређеног прага са одређеним односом." #: quodlibet/ext/gstreamer/crossfeed.py:19 msgid "_Preset:" msgstr "_Одабир:" #: quodlibet/ext/gstreamer/crossfeed.py:19 msgid "Filter preset" msgstr "Филтрирај одабир" #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Frequency cut:" msgstr "_Фреквенција одсецање:" #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Low-pass filter cut frequency" msgstr "Ниски-пролаз филтер фреквенција одсецања" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed _level:" msgstr "Извор _ниво:" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed level" msgstr "Извор ниво" #: quodlibet/ext/gstreamer/crossfeed.py:25 msgid "Default" msgstr "Подразумевано" #: quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "Најближе позицији виртуелног звучника (30°, 3 метра)" #: quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Chu Moy" msgstr "Chu Moy" #: quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "Близу Chu Moy укрштеног извора (популарно)" #: quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Jan Meier" msgstr "Jan Meier" #: quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "БлизуJan Meier's CORDA појачалима (мала промена)" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Custom" msgstr "Прилагођено" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Custom settings" msgstr "Прилагођена подешавања" #: quodlibet/ext/gstreamer/crossfeed.py:152 msgid "Crossfeed" msgstr "Укрштен извор" #: quodlibet/ext/gstreamer/crossfeed.py:153 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:20 msgid "Filter _band:" msgstr "Филтер _појас:" #: quodlibet/ext/gstreamer/karaoke.py:21 msgid "The Frequency band of the filter" msgstr "Фреквентни појас филтера" #: quodlibet/ext/gstreamer/karaoke.py:22 msgid "Filter _width:" msgstr "Филтер _ширина:" #: quodlibet/ext/gstreamer/karaoke.py:23 msgid "The Frequency width of the filter" msgstr "Фреквентни опсег филтера" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "_Level:" msgstr "_Ниво:" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "Level of the effect" msgstr "Ниво ефеката" #: quodlibet/ext/gstreamer/karaoke.py:105 msgid "Karaoke" msgstr "Караоке" #: quodlibet/ext/gstreamer/karaoke.py:106 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:21 msgid "R_ate:" msgstr "У_честалост:" #: quodlibet/ext/gstreamer/pitch.py:22 msgid "_Tempo:" msgstr "_Темпо:" #: quodlibet/ext/gstreamer/pitch.py:23 msgid "_Pitch:" msgstr "_Степен:" #: quodlibet/ext/gstreamer/pitch.py:95 msgid "Audio Pitch / Speed" msgstr "Аудио степен / брзина" #: quodlibet/ext/gstreamer/pitch.py:96 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:147 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:100 msgid "Exports a playlist by copying files to a folder." msgstr "Извози листу извођења копирајући датотеке у фасцикле." #: quodlibet/ext/playlist/export_to_folder.py:121 #: quodlibet/ext/songsmenu/playlist.py:132 msgid "Unable to export playlist" msgstr "Не могу да извезем листу извођења" #: quodlibet/ext/playlist/export_to_folder.py:122 msgid "Ensure you have write access to the destination." msgstr "Уверите се да имате приступ записивању на одредиште." #: quodlibet/ext/playlist/export_to_folder.py:165 msgid "Default filename pattern:" 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. Shares configuration with <a href=" "\"quodlibet:///prefs/plugins/Squeezebox Output\">Squeezebox Sync plugin</a>." msgstr "" "Динамички извози листу извођења у Logitech Squeezebox листу, уколико деле " "структуру директоријума. Дели конфигурацију са <a href=\"quodlibet:///prefs/" "plugins/Squeezebox Output\">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:96 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 "" "Playback follows your selection, or the next song in the list once exhausted." msgstr "" "Репродукција прати ваш одабир, или следећу песму уколико је листа исцрпљена." #: quodlibet/ext/playorder/playcounteq.py:21 msgid "Playcount Equalizer" msgstr "Уједначивач броја пуштања" #: quodlibet/ext/playorder/playcounteq.py:22 msgid "Shuffle, preferring songs with fewer total plays." msgstr "Меша и даје предност песмама које су ређе пуштане." #: quodlibet/ext/playorder/playcounteq.py:24 msgid "Prefer less played" msgstr "Пожели мање пуштане" #: quodlibet/ext/playorder/queue.py:19 msgid "Queue Only" msgstr "Само низ" #: quodlibet/ext/playorder/queue.py:21 msgid "" "Limits playing of songs to the queue. Select this play order in the main " "window, then double-clicking any song will enqueue it instead of playing." msgstr "" "Ограничава пуштање песама на низ. Ако је овај поредак одабран, дупли-клик ће " "додати песму у низ уместо да је пусти." #: quodlibet/ext/playorder/reverse.py:14 msgid "Reverse" msgstr "Окренут" #: quodlibet/ext/playorder/reverse.py:16 msgid "Reverses the play order of songs." msgstr "Окреће редослед пуштања песама." #: quodlibet/ext/playorder/shufflebygrouping.py:31 #: quodlibet/ext/playorder/shufflebygrouping.py:93 msgid "Shuffle by Grouping" msgstr "Мешај по групама" #: quodlibet/ext/playorder/shufflebygrouping.py:32 msgid "" "Shuffles by a grouping of songs defined by a common tag instead of by track, " "similar to album shuffle. This is useful for shuffling multi-movement " "classical works while making sure all movements play in order before " "shuffling to the next piece." msgstr "" "Меша тако што групише песме дефинисане ознакама уместо записа, слично мешању " "албума." #: quodlibet/ext/playorder/shufflebygrouping.py:38 msgid "Shuffle by grouping" msgstr "Мешај по групама" #: quodlibet/ext/playorder/shufflebygrouping.py:94 msgid "Waiting to start new group…" msgstr "Чекам да започнем нову групу…" #: quodlibet/ext/playorder/shufflebygrouping.py:144 msgid "Grouping tag:" msgstr "Груписане ознаке:" #: quodlibet/ext/playorder/shufflebygrouping.py:148 msgid "Tag to group songs by" msgstr "Ознаке за груписање песама" #: quodlibet/ext/playorder/shufflebygrouping.py:150 msgid "Filter tag:" msgstr "Филтер ознака:" #: quodlibet/ext/playorder/shufflebygrouping.py:155 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:160 msgid "Delay:" msgstr "_Кашњење:" #: quodlibet/ext/playorder/shufflebygrouping.py:166 msgid "Time delay in seconds before starting next group" msgstr "Временско закашњење у секундама пре почетка следеће групе" #: quodlibet/ext/playorder/shufflebygrouping.py:182 msgid "Reset to defaults" msgstr "Поништи на подразумевано" #: quodlibet/ext/playorder/skip_songs.py:25 msgid "Skip Songs" msgstr "Прескочи песме" #: quodlibet/ext/playorder/skip_songs.py:27 msgid "" "Playback skips over songs with a rating equal or below a given threshold." msgstr "Прескаче песме са оценом једнаком или испод задатог прага." #: quodlibet/ext/playorder/track_repeat.py:30 msgid "Repeat Each Track" msgstr "Понављај сваки запис" #: quodlibet/ext/playorder/track_repeat.py:32 msgid "Shuffle songs, but repeat every track a set number of times." msgstr "Меша песме, али понавља сваки запис постављеним бројем пута." #: quodlibet/ext/playorder/track_repeat.py:51 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. Syntax is '@(if: " "condition, then, else)'." msgstr "" "Бира упит који се подудара са ситуационим упитом. синтакса је '@(if: " "condition, then, else)'." #: quodlibet/ext/query/missing.py:15 msgid "Missing Query" msgstr "Недостајући упит" #: quodlibet/ext/query/missing.py:16 msgid "Matches songs without the given tag." msgstr "Упарује песме без додељене ознаке." #: quodlibet/ext/query/missing.py:27 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. Syntax is '@(python: expression)'. The " "variable 's' (or 'a') is the song / album being matched. '_ts' is a (real " "number) timestamp at start of query. Modules 'time' and 'random' are also " "available, and the class 'Random' (==random.Random) too." msgstr "" "Користи Python израз у упитима. Синтакса је \"@(python: expression)\". " "Променљива \"s\" (или \"a\") је подударна песма / албум. \"_ts\" је " "временска ознака на почетку упита. Модули \"време\" и \"насумично\" су " "доступни, и класа \"Насумично\" (==random.Random) такође." #: quodlibet/ext/query/savedsearch.py:19 msgid "Include Saved Search" msgstr "Укључи сачувану претрагу" #: quodlibet/ext/query/savedsearch.py:20 msgid "" "Include the results of a saved search as part of another query. Syntax is " "'@(saved: search name)'." msgstr "" "Укључује резултате сачуваних претрага као део другог упита. Синтакса је " "'@(saved: search name)'." #: 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:116 msgid "Port:" msgstr "Порт:" #: quodlibet/ext/_shared/squeezebox/base.py:121 msgid "Username:" msgstr "Корисничко име:" #: quodlibet/ext/_shared/squeezebox/base.py:126 msgid "Password:" msgstr "Лозинка:" #: quodlibet/ext/_shared/squeezebox/base.py:130 msgid "Library directory the server connects to" msgstr "Директоријум библиотеке повезивања сервера" #: quodlibet/ext/_shared/squeezebox/base.py:132 msgid "Library path:" msgstr "Путања библиотеке:" #. Add verify button #: quodlibet/ext/_shared/squeezebox/base.py:141 msgid "_Verify settings" msgstr "_Провери поставке" #. Server settings Frame #: quodlibet/ext/_shared/squeezebox/base.py:147 msgid "Squeezebox Server" msgstr "Squeezebox сервер" #: quodlibet/ext/_shared/squeezebox/base.py:150 msgid "Debug" msgstr "Испитај" #: quodlibet/ext/_shared/squeezebox/server.py:26 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "Squeezebox сервер на {hostname}:{port}" #: quodlibet/ext/_shared/squeezebox/server.py:28 msgid "unidentified Squeezebox server" msgstr "неидентификовани Squeezebox сервер" #: quodlibet/ext/_shared/squeezebox/server.py:37 #, 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:20 #: quodlibet/ext/songsmenu/importexport.py:39 quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "_У реду" #: quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" "Пронађен Squeezebox сервер.\n" "Молимо одаберите плејер" #: quodlibet/ext/songsmenu/albumart.py:331 msgid "Fit image to _window" msgstr "Уклопи слику у _прозор" #: quodlibet/ext/songsmenu/albumart.py:337 msgid "See '[plugins] cover_filenames' config entry for image filename strings" msgstr "Види '[plugins] cover_filenames' конфигурацију за име слике" #. Both labels #: quodlibet/ext/songsmenu/albumart.py:343 msgid "_Program:" msgstr "_Програм:" #: quodlibet/ext/songsmenu/albumart.py:348 msgid "_Edit image after saving" msgstr "_Уреди слику након чувања" #: quodlibet/ext/songsmenu/albumart.py:350 msgid "File_name:" msgstr "Име _датотеке:" #: quodlibet/ext/songsmenu/albumart.py:466 msgid "Saving failed" msgstr "Неуспешно чување" #: quodlibet/ext/songsmenu/albumart.py:467 #, python-format msgid "Unable to save \"%s\"." msgstr "Не могу да сачувам \"%s\"." #: quodlibet/ext/songsmenu/albumart.py:565 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "[albumart] HTTP грешка: %s" #: quodlibet/ext/songsmenu/albumart.py:622 msgid "Album Art Downloader" msgstr "Преузимач омота" #: quodlibet/ext/songsmenu/albumart.py:675 #, python-format msgid "from %(source)s" msgstr "из %(source)s" #: quodlibet/ext/songsmenu/albumart.py:678 #, python-format msgid "Resolution: %s" msgstr "Резолуција: %s" #: quodlibet/ext/songsmenu/albumart.py:681 #, python-format msgid "Size: %s" msgstr "Величина: %s" #: quodlibet/ext/songsmenu/albumart.py:727 msgid "Per engine 'at best' results limit" msgstr "По покретачу \"најбољи\" резултат ограничење" #: quodlibet/ext/songsmenu/albumart.py:737 msgid "_Search" msgstr "_Претрага" #: quodlibet/ext/songsmenu/albumart.py:819 #: quodlibet/ext/songsmenu/brainz/widgets.py:451 msgid "Searching…" msgstr "Тражим…" #: quodlibet/ext/songsmenu/albumart.py:884 #: quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "Завршено" #: quodlibet/ext/songsmenu/albumart.py:1006 msgid "Download Album Art" msgstr "Преузми омот албума" #: quodlibet/ext/songsmenu/albumart.py:1007 msgid "Downloads album covers from various websites." msgstr "Преузима омоте албума са различитих интернет адреса." #: quodlibet/ext/songsmenu/albumart.py:1020 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 msgid "Disc" msgstr "Диск" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 #: quodlibet/ext/songsmenu/replaygain.py:393 quodlibet/qltk/tracknumbers.py:91 msgid "Track" msgstr "Запис" #: quodlibet/ext/songsmenu/brainz/widgets.py:132 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:447 msgid "Please enter a query." msgstr "Молимо упишите упит." #: quodlibet/ext/songsmenu/brainz/widgets.py:465 #: quodlibet/ext/songsmenu/brainz/widgets.py:496 msgid "Error encountered. Please retry." msgstr "Дошло је до грешке. Покушајте поново." #: quodlibet/ext/songsmenu/brainz/widgets.py:472 #: quodlibet/ext/songsmenu/brainz/widgets.py:488 msgid "Loading result…" msgstr "Учитавам резултате…" #: quodlibet/ext/songsmenu/brainz/widgets.py:475 msgid "No results found." msgstr "Нема резултата." #: quodlibet/ext/songsmenu/console.py:40 msgid "Python Console" msgstr "Python конзола" #: quodlibet/ext/songsmenu/console.py:41 msgid "Interactive Python console. Opens a new window." msgstr "Интерактивна Python конзола. Отвара нови прозор." #: quodlibet/ext/songsmenu/console.py:48 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "{plugin_name} за {songs} ({app})" #: quodlibet/ext/songsmenu/console.py:55 msgid "Python Console Sidebar" msgstr "Python конзола бочна страница" #: quodlibet/ext/songsmenu/console.py:56 msgid "" "Interactive Python console sidebar, that follows the selected songs in the " "main window." msgstr "" "Бочна страна за интерактивну Python конзолу која прати одабране песме у " "главном прозору." #: quodlibet/ext/songsmenu/console.py:75 msgid "You can access the following objects by default:" msgstr "Можете приступити следећим подразумеваним објектима:" #: quodlibet/ext/songsmenu/console.py:85 msgid "Your current working directory is:" msgstr "Ваш тренутни радни директоријум је:" #: quodlibet/ext/songsmenu/cover_download.py:119 msgid "Classic" msgstr "Класично" #: quodlibet/ext/songsmenu/cover_download.py:120 msgid "Large" msgstr "Велико" #: quodlibet/ext/songsmenu/cover_download.py:121 msgid "HD" msgstr "HD" #: quodlibet/ext/songsmenu/cover_download.py:122 msgid "Full HD" msgstr "Full HD" #: quodlibet/ext/songsmenu/cover_download.py:123 msgid "WQXGA" msgstr "WQXGA" #: quodlibet/ext/songsmenu/cover_download.py:124 msgid "4K UHD" msgstr "4K UHD" #: quodlibet/ext/songsmenu/cover_download.py:129 msgid "Cover Art Download" msgstr "Омот преузимање" #: quodlibet/ext/songsmenu/cover_download.py:180 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "Учитавам %(source)s - %(dimensions)s…" #: quodlibet/ext/songsmenu/cover_download.py:231 #, python-format msgid "" "Nothing found for albums:\n" "<i>%(albums)s</i>.\n" "\n" "Providers used:\n" "<tt>%(providers)s</tt>" msgstr "" "Ништа није пронађено за албуме:\n" "<i>%(albums)s</i>.\n" "\n" "Коришћени извори:\n" "<tt>%(providers)s</tt>" #: quodlibet/ext/songsmenu/cover_download.py:234 msgid "No covers found" msgstr "Нема пронађених омота" #: quodlibet/ext/songsmenu/cover_download.py:254 #, python-format msgid "%(size)d ✕ %(size)d px" msgstr "%(size)d ✕ %(size)d px" #: quodlibet/ext/songsmenu/cover_download.py:267 msgid "Preview size" msgstr "Величина прегледа" #: quodlibet/ext/songsmenu/cover_download.py:276 msgid "Save destination" msgstr "Одредиште чувања" #: quodlibet/ext/songsmenu/cover_download.py:336 msgid "Download Cover Art" msgstr "Преузимање омота" #: quodlibet/ext/songsmenu/cover_download.py:337 msgid "Downloads high-quality album covers using cover plugins." 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:55 msgid "pattern" 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 "" "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:91 msgid "Input value" msgstr "Вредност излаза" #: quodlibet/ext/songsmenu/custom_commands.py:92 #, python-format msgid "Value for %s?" msgstr "Вредност за %s?" #: quodlibet/ext/songsmenu/custom_commands.py:137 msgid "Custom Commands" msgstr "Прилагођене команде" #: quodlibet/ext/songsmenu/custom_commands.py:138 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" "Покреће прилагођене команде (у гомили ако је потребно) за песме користећи " "било које ознаке." #: quodlibet/ext/songsmenu/custom_commands.py:197 #: quodlibet/ext/songsmenu/custom_commands.py:207 #: quodlibet/ext/songsmenu/custom_commands.py:259 msgid "Edit Custom Commands" msgstr "Уреди прилагођене команде" #: quodlibet/ext/songsmenu/custom_commands.py:290 #, 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:397 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:399 msgid "_Group duplicates by:" msgstr "_Групише дупликате по:" #: quodlibet/ext/songsmenu/duplicates.py:404 msgid "Duplicate Key" msgstr "Дупликат кључ" #: quodlibet/ext/songsmenu/duplicates.py:409 msgid "Remove _Whitespace" msgstr "Уклони _бео простор" #: quodlibet/ext/songsmenu/duplicates.py:410 msgid "Remove _Diacritics" msgstr "Уклони _дијакритике" #: quodlibet/ext/songsmenu/duplicates.py:411 msgid "Remove _Punctuation" msgstr "Уклони _интерпукције" #: quodlibet/ext/songsmenu/duplicates.py:412 msgid "Case _Insensitive" msgstr "Слово _неосетљиво" #: quodlibet/ext/songsmenu/duplicates.py:420 msgid "Matching options" msgstr "Опције подударања" #. Create a dialog. #: quodlibet/ext/songsmenu/editplaycount.py:19 #: quodlibet/ext/songsmenu/editplaycount.py:41 msgid "Edit Playcount" msgstr "Уреди број пуштања" #: quodlibet/ext/songsmenu/editplaycount.py:20 msgid "" "Edit a song's ~#playcount and ~#skipcount.\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's ~#playcount to 0, the ~#lastplayed and ~#laststarted " "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:68 msgid "Play Count" msgstr "Број пуштања" #: quodlibet/ext/songsmenu/editplaycount.py:69 msgid "Skip Count" msgstr "Број прескакања" #: quodlibet/ext/songsmenu/embedded.py:25 msgid "Edit Embedded Images" msgstr "Уреди уграђене слике" #: quodlibet/ext/songsmenu/embedded.py:26 msgid "Removes or replaces embedded images." msgstr "Уклапа или замењује уграђене слике." #: quodlibet/ext/songsmenu/embedded.py:81 msgid "_Remove all Images" msgstr "_Уклони све слике" #: quodlibet/ext/songsmenu/embedded.py:85 msgid "_Embed Current 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/exact_rating.py:54 quodlibet/qltk/ratingsmenu.py:98 msgid "Change _Rating" 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 "" "Генерише звучни отисак користећи 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 "Пиши" #: quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" 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:65 quodlibet/ext/songsmenu/html.py:75 msgid "Export to HTML" msgstr "Извези у HTML" #: quodlibet/ext/songsmenu/html.py:66 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:62 msgid "Error uploading" msgstr "Грешка при слању" #: quodlibet/ext/songsmenu/ifp.py:63 #, python-format msgid "" "Unable to upload <b>%s</b>. The device may be out of space, or turned off." msgstr "" "Не могу да пошаљем <b>%s</b>. Уређај можда нема довољно простора или је " "искључен." #: quodlibet/ext/songsmenu/importexport.py:60 msgid "Export Metadata" msgstr "Извези метаподатке" #: quodlibet/ext/songsmenu/importexport.py:61 msgid "Exports metadata of selected songs as a .tags file." msgstr "Извози метаподатке одабраних песама као .tags датотеку." #: quodlibet/ext/songsmenu/importexport.py:105 msgid "Import Metadata" msgstr "Увези метаподатке" #: quodlibet/ext/songsmenu/importexport.py:106 msgid "Imports metadata for selected songs from a .tags file." msgstr "Увози метаподатке одабраних песма из .tags датотеке." #: quodlibet/ext/songsmenu/k3b.py:23 msgid "Burn CD" msgstr "Нарежи ЦД" #: quodlibet/ext/songsmenu/k3b.py:24 msgid "Burns CDs with K3b, Brasero or xfburn." msgstr "Уписује на ЦД користећи k3b, Brasero ili xfburn." #: quodlibet/ext/songsmenu/lastfmsync.py:97 msgid "Updating chart list." msgstr "Ажурирам листу образаца." #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:116 msgid "Already up-to-date." msgstr "Већ је ажурирано." #: quodlibet/ext/songsmenu/lastfmsync.py:124 #, python-format msgid "Fetching chart for week of %s." msgstr "Скупљам обрасце за недељу %s." #: quodlibet/ext/songsmenu/lastfmsync.py:146 msgid "Sync complete." msgstr "Синхронизација завршена." #: quodlibet/ext/songsmenu/lastfmsync.py:152 msgid "Error during sync" msgstr "Грешка при синхронизацији" #: quodlibet/ext/songsmenu/lastfmsync.py:217 #: quodlibet/ext/songsmenu/lastfmsync.py:247 msgid "Last.fm Sync" msgstr "Last.fm Синхронизација" #: quodlibet/ext/songsmenu/lastfmsync.py:248 msgid "Updates your library's statistics from your Last.fm profile." msgstr "Ажурира статистику ваше библиотеке са Last.fm профила." #: quodlibet/ext/songsmenu/lastfmsync.py:301 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 "Претвара имена албума и уметника да сортира имена, лоше." #. Create a dialog. #: quodlibet/ext/songsmenu/migratemetadata.py:36 #: quodlibet/ext/songsmenu/migratemetadata.py:45 msgid "Migrate Metadata" msgstr "Премести метаподатке" #: quodlibet/ext/songsmenu/migratemetadata.py:39 msgid "Copies the quodlibet-specific metadata between songs." msgstr "Копира quodlibet метаподатке између песама." #: quodlibet/ext/songsmenu/migratemetadata.py:52 msgid "_Copy" msgstr "_Умножи" #: quodlibet/ext/songsmenu/migratemetadata.py:54 msgid "_Paste" msgstr "_Убаци" #. Create the tag table. #: quodlibet/ext/songsmenu/migratemetadata.py:64 msgid "Information to copy/paste" msgstr "Информација за умножавање/убацивање" #. Create the indexing box. #: quodlibet/ext/songsmenu/migratemetadata.py:86 msgid "Map tracks by disc and track number" msgstr "Мапира записе по диску и броју записа" #: quodlibet/ext/songsmenu/migratemetadata.py:87 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> ово мора бити омогућено када су метаподаци умножени да би " "информација записа била сачувана." #: quodlibet/ext/songsmenu/migratemetadata.py:103 #, python-format msgid "There is %d stored track." msgid_plural "There are %d stored tracks." msgstr[0] "Има %d сачуван запис." msgstr[1] "Има %d сачувана записа." msgstr[2] "Има %d сачуваних записа." #: quodlibet/ext/songsmenu/playlist.py:31 msgid "Export as Playlist" msgstr "Извези као листу извођења" #: quodlibet/ext/songsmenu/playlist.py:32 msgid "Exports songs to an M3U or PLS playlist." msgstr "Извози песме у M3U или PLS листу извођења." #: quodlibet/ext/songsmenu/playlist.py:77 msgid "Use relative paths" msgstr "Користи релативне путање" #: quodlibet/ext/songsmenu/playlist.py:77 msgid "Use absolute paths" msgstr "Користи апсолутне путање" #: quodlibet/ext/songsmenu/playlist.py:133 #, python-format msgid "Writing to <b>%s</b> 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 испитивач" #: quodlibet/ext/songsmenu/replaygain.py:407 msgid "Progress" msgstr "Напредак" #: quodlibet/ext/songsmenu/replaygain.py:422 msgid "Gain" msgstr "Gain" #: quodlibet/ext/songsmenu/replaygain.py:437 msgid "Peak" msgstr "Peak" #: quodlibet/ext/songsmenu/replaygain.py:452 #, python-format msgid "There is <b>%(to-process)s</b> album to update (of %(all)s)" msgid_plural "There are <b>%(to-process)s</b> 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:568 msgid "Replay Gain" msgstr "Replay Gain" #: quodlibet/ext/songsmenu/replaygain.py:569 msgid "" "Analyzes and updates ReplayGain information, using GStreamer. Results are " "grouped by album." msgstr "" "Испитује и ажурира ReplayGain информације користећи GStreamer. Резултати су " "груписани по албуму." #: quodlibet/ext/songsmenu/replaygain.py:607 msgid "always" msgstr "увек" #: quodlibet/ext/songsmenu/replaygain.py:608 msgid "if <b>any</b> RG tags are missing" msgstr "ако недостају <b>any</b> RG ознаке" #: quodlibet/ext/songsmenu/replaygain.py:610 msgid "if <b>album</b> RG tags are missing" msgstr "ако недостају <b>album</b> RG ознаке" #: quodlibet/ext/songsmenu/replaygain.py:627 msgid "_Process albums:" msgstr "_OОбрада албума:" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:639 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 msgid "Tap BPM for the selected song." msgstr "Tap BPM за одабрану песму." #: quodlibet/ext/songsmenu/website_search.py:37 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-example)s." msgstr "" "Претражује ваш избор странице користећи било које ознаке.\n" "Подржава шаблоне нпр. %(pattern-example)s." #: quodlibet/ext/songsmenu/website_search.py:80 msgid "Search URL patterns" msgstr "Претрага URL шаблона" #: quodlibet/ext/songsmenu/website_search.py:90 msgid "Edit search URLs" msgstr "Уреди претрагу URL-а" #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:116 msgid "Configure Searches…" msgstr "Конфигуриши претрагу…" #: quodlibet/ext/songsmenu/wikipedia.py:35 msgid "Search Tag in Wikipedia" msgstr "Претражи ознаку у Википедији" #: quodlibet/ext/songsmenu/wikipedia.py:36 msgid "" "Opens a browser window with the Wikipedia article on the selected song's " "corresponding tag." msgstr "" "Отвара прозор у прегледачу са страницом чланка Википедија за одабрану ознаку " "песме." #: quodlibet/ext/songsmenu/wikipedia.py:56 #, python-format msgid "Search at %(website)s" msgstr "Потражи на %(website)s" #: quodlibet/ext/songsmenu/wikipedia.py:70 #: quodlibet/ext/songsmenu/wikipedia.py:76 quodlibet/qltk/edittags.py:443 msgid "Edit Tags" msgstr "Уреди ознаке" #: quodlibet/ext/songsmenu/wikipedia.py:111 msgid "Search failed" msgstr "Претрага није успела" #: quodlibet/ext/songsmenu/wikipedia.py:112 #, python-format msgid "Tag \"%s\" not found." msgstr "Ознака \"%s\" није нађена." #. then (try to) load all new files #: quodlibet/library/libraries.py:651 quodlibet/library/libraries.py:661 #: quodlibet/library/libraries.py:727 quodlibet/library/libraries.py:746 #: quodlibet/qltk/information.py:272 quodlibet/qltk/prefs.py:692 #: quodlibet/util/library.py:123 msgid "Library" msgstr "Библиотека" #: quodlibet/library/libraries.py:651 msgid "Checking mount points" msgstr "Проверавам прикључне тачке" #: quodlibet/library/libraries.py:661 msgid "Scanning library" msgstr "Претрага библиотеке" #: quodlibet/library/libraries.py:726 #, python-format msgid "Scanning %s" msgstr "Претрага %s" #: quodlibet/library/libraries.py:746 msgid "Loading files" msgstr "Учитавам датотеке" #: quodlibet/main.py:50 msgid "Music player and music library manager" msgstr "Музички плејер и организатор билбиотеке" #: quodlibet/operon/base.py:70 #, 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:462 msgid "Print terse output" msgstr "Штампај сажет излаз" #: quodlibet/operon/commands.py:43 quodlibet/operon/commands.py:82 #: quodlibet/operon/commands.py:464 #, 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:336 quodlibet/operon/commands.py:340 #: quodlibet/operon/commands.py:392 quodlibet/operon/commands.py:395 #: quodlibet/operon/commands.py:434 quodlibet/operon/commands.py:469 #: quodlibet/operon/commands.py:509 quodlibet/operon/commands.py:544 #: quodlibet/operon/commands.py:586 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:471 msgid "Too many arguments" msgstr "Превише аргумената" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:91 #: quodlibet/operon/commands.py:476 quodlibet/qltk/data_editors.py:352 msgid "Description" msgstr "Опис" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:476 #: quodlibet/qltk/edittags.py:493 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:324 #: quodlibet/operon/commands.py:385 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:304 quodlibet/operon/commands.py:445 #: quodlibet/operon/commands.py:677 #, python-format msgid "Can not set %r" msgstr "Не могу пставити %r" #: quodlibet/operon/commands.py:319 msgid "Remove tags" msgstr "Уклони ознаке" #: quodlibet/operon/commands.py:326 quodlibet/operon/commands.py:387 msgid "Value is a regular expression" msgstr "Вредност је обичан израз" #: quodlibet/operon/commands.py:328 msgid "Remove all tags" msgstr "Уклони све ознаке" #: quodlibet/operon/commands.py:332 msgid "Can't combine '--all' with '--regexp'" msgstr "Не могу да комбинујем'--all' са '--regexp'" #: quodlibet/operon/commands.py:366 #, python-brace-format msgid "Can't remove {tagname} from {filename}" msgstr "Не могу уклонити {tagname} из {filename}" #: quodlibet/operon/commands.py:380 msgid "Remove a tag value" msgstr "Уклони вредност ознаке" #: quodlibet/operon/commands.py:429 msgid "Add a tag value" msgstr "Додај вредност ознаке" #: quodlibet/operon/commands.py:457 msgid "List file information" msgstr "Излистај информације о датотеци" #: quodlibet/operon/commands.py:503 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" "Постави понуђену слику као примарну уграђену слику и уклони све остале " "уграђене слике" #: quodlibet/operon/commands.py:516 #, python-format msgid "Failed to load image file: %r" msgstr "Неуспешно учитавање слике: %r" #: quodlibet/operon/commands.py:523 quodlibet/operon/commands.py:552 #, 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:539 msgid "Remove all embedded images" msgstr "Уклони све уграђене слике" #: quodlibet/operon/commands.py:569 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "Извези уграђене слике на %(filepath)s" #: quodlibet/operon/commands.py:581 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" "Путања где ће слике бити сачуване (подразумевано је радни директоријум)" #: quodlibet/operon/commands.py:640 msgid "Rename files based on tags" msgstr "Преименуј датотеке користећи ознаке" #: quodlibet/operon/commands.py:655 msgid "Fill tags based on the file path" msgstr "Испуни ознаке користећи путању датотеке" #: quodlibet/operon/commands.py:705 quodlibet/qltk/information.py:309 #: quodlibet/qltk/properties.py:83 quodlibet/qltk/renamefiles.py:224 #: quodlibet/qltk/tagsfrompath.py:228 quodlibet/qltk/tracknumbers.py:78 msgid "File" msgstr "Датотека" #: quodlibet/operon/commands.py:713 msgid "Fill tracknumbers for all files" msgstr "Испуни број песме за све датотеке" #: quodlibet/operon/commands.py:732 msgid "Print tags based on the given pattern" msgstr "Штампај ознаке по одређеном шаблону" #: quodlibet/operon/commands.py:769 msgid "Display help information" msgstr "Прикажи помоћне информације" #: quodlibet/operon/util.py:43 #, 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:30 msgid "_Unknown" msgstr "_Непознато" #: quodlibet/order/__init__.py:142 msgid "In Order" msgstr "По реду" #: quodlibet/order/__init__.py:143 msgid "_In Order" msgstr "_По реду" #: quodlibet/order/reorder.py:22 msgid "Random" msgstr "Насумично" #: quodlibet/order/reorder.py:23 quodlibet/qltk/queue.py:147 msgid "_Random" msgstr "_Насумично" #: quodlibet/order/reorder.py:40 quodlibet/order/reorder.py:41 msgid "Prefer higher rated" msgstr "Преферирај боље оцењене" #: quodlibet/order/repeat.py:43 quodlibet/order/repeat.py:44 msgid "Repeat this track" msgstr "Понови овај запис" #: quodlibet/order/repeat.py:57 quodlibet/order/repeat.py:58 msgid "Repeat all" msgstr "Понови све" #: quodlibet/order/repeat.py:73 quodlibet/order/repeat.py:74 msgid "One Song" msgstr "Једна песма" #: quodlibet/player/gstbe/player.py:98 msgid "Stream" msgstr "Стрим" #: quodlibet/player/gstbe/player.py:98 msgid "Buffering" msgstr "Пуњење меморије" #: quodlibet/player/gstbe/player.py:452 msgid "Could not create GStreamer pipeline" msgstr "Не могу створити GStreamer pipeline" #: quodlibet/player/gstbe/player.py:651 msgid "No GStreamer element found to handle media format" msgstr "Није пронађен ни један GStreamer елемент за обраду формата" #: quodlibet/player/gstbe/player.py:652 #, 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:25 msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. In case the pipeline contains a sink, it will be used instead of " "the default one." msgstr "" "GStreamer output pipeline коришћен за репродукцију. Оставите празно за " "подразумевани. У неким другим случајевима, користиће се подразумевани." #: quodlibet/player/gstbe/prefs.py:36 msgid "_Output pipeline:" msgstr "_Output pipeline:" #: quodlibet/player/gstbe/prefs.py:43 #, python-format msgid "%.1f seconds" msgstr "%.1f секунди" #: quodlibet/player/gstbe/prefs.py:57 msgid "_Buffer duration:" msgstr "_Buffer duration:" #: quodlibet/player/gstbe/prefs.py:66 msgid "Disable _gapless playback" msgstr "Онемогући _gapless репродукцију" #: quodlibet/player/gstbe/prefs.py:70 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions" msgstr "" "Онемогућавање gapless репродукције може избећи проблеме при мењању песама са " "неким верзијама GStreamer-а" #: quodlibet/player/gstbe/util.py:101 msgid "No GStreamer audio sink found" msgstr "Нема нађеног GStreamer audio sink" #: quodlibet/player/gstbe/util.py:120 msgid "Invalid GStreamer output pipeline" msgstr "Неважећа GStreamer излазна pipeline" #: quodlibet/player/xinebe/player.py:90 msgid "Unable to create audio output" msgstr "Не могу да креирам аудио излаз" #: quodlibet/player/xinebe/player.py:91 #, 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:61 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" "Не могу да пронађем модул '{module}'. Можда је потребно да инсталирате пакет?" #: quodlibet/plugins/__init__.py:70 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "Не могу пронаћи GStreamer елемент '{element}'." #: 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:55 #: quodlibet/qltk/songsmenu.py:66 msgid "_Run Plugin" 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:40 msgid "_Name:" msgstr "_Име:" #: quodlibet/qltk/cbes.py:48 quodlibet/qltk/edittags.py:350 msgid "_Value:" msgstr "Вредност:" #: quodlibet/qltk/cbes.py:263 msgid "Saved Values" msgstr "Сачуване вредности" #: quodlibet/qltk/cbes.py:264 msgid "Edit saved values…" msgstr "Уреди сачуване вредности…" #: quodlibet/qltk/controls.py:111 msgid "Auto_matic" msgstr "Ауто_матски" #: quodlibet/qltk/controls.py:112 msgid "_Track Mode" msgstr "_Режим записа" #: quodlibet/qltk/controls.py:113 msgid "_Album Mode" msgstr "_Режим албума" #. Translators: player state, no action #: quodlibet/qltk/controls.py:122 msgid "_Mute" msgstr "_Утишај" #: quodlibet/qltk/controls.py:128 msgid "_Replay Gain Mode" msgstr "_Replay Gain Режим" #. Translators: New Command/Entry/Item/... #: quodlibet/qltk/data_editors.py:116 #, python-format msgid "New %s" msgstr "Нов %s" #: quodlibet/qltk/data_editors.py:215 msgid "(unknown)" msgstr "непознато)" #: quodlibet/qltk/data_editors.py:344 msgid "Tag expression" msgstr "Израз ознаке" #: quodlibet/qltk/data_editors.py:371 msgid "Tag expression e.g. people:real or ~album~year" msgstr "Израз ознаке нпр. people:real ili ~album~year" #: quodlibet/qltk/data_editors.py:372 msgid "Enter new tag" 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/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:197 msgid "Split into _Multiple Values" msgstr "Одвоју у _вишеструке вредности" #: quodlibet/qltk/edittags.py:219 msgid "Split Disc out of _Album" msgstr "Одвоји диск од _албума" #: quodlibet/qltk/edittags.py:243 msgid "Split _Version out of Title" msgstr "Одвоји _верзију од назива" #: quodlibet/qltk/edittags.py:298 msgid "Split Arranger out of Ar_tist" msgstr "Одвоји аранжера од Ум_етника" #: quodlibet/qltk/edittags.py:303 msgid "Split _Performer out of Artist" msgstr "Одвоји _извођача од уметника" #: quodlibet/qltk/edittags.py:309 msgid "Split _Performer out of Title" msgstr "Одвоји _извођача од назива" #: quodlibet/qltk/edittags.py:315 msgid "Split _Originalartist out of Title" msgstr "Одвоји _изворног уметника од назива" #: quodlibet/qltk/edittags.py:322 msgid "Add a Tag" msgstr "Додај ознаку" #: quodlibet/qltk/edittags.py:341 msgid "_Tag:" msgstr "_Ознака:" #: quodlibet/qltk/edittags.py:516 msgid "Show _programmatic tags" msgstr "Прикажи _прагматичне ознаке" #: quodlibet/qltk/edittags.py:517 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" "Приступи свим ознакама, укључујући машински произведене нпр. MusicBrainz или " "Replay Gain ознаке" #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:547 msgctxt "edittags" msgid "_Revert" msgstr "_Врати" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:552 msgctxt "edittags" msgid "_Save" msgstr "_Сачувај" #: quodlibet/qltk/edittags.py:681 msgid "_Configure" msgstr "_Подеси" #: quodlibet/qltk/edittags.py:696 msgid "_Split Tag" msgstr "_Раздвоји ознаке" #: quodlibet/qltk/edittags.py:705 msgid "_Copy Value(s)" msgstr "_Умножи вредност(и)" #: quodlibet/qltk/edittags.py:736 msgid "Unable to add tag" msgstr "Не могу додати ознаку" #: quodlibet/qltk/edittags.py:737 #, python-format msgid "Unable to add <b>%s</b>" msgstr "Не могу додати <b>%s</b>" #: quodlibet/qltk/edittags.py:739 #, python-format msgid "" "The files currently selected do not support multiple values for <b>%s</b>." msgstr "" "Тренутно одабране датотеке не подржавају вишеструке вредности за <b>%s</b>." #. Can't add the new tag. #: quodlibet/qltk/edittags.py:766 quodlibet/qltk/edittags.py:947 #: quodlibet/qltk/tagsfrompath.py:211 quodlibet/util/__init__.py:505 #: quodlibet/util/tags.py:243 msgid "Invalid tag" msgstr "Неважећа ознака" #: quodlibet/qltk/edittags.py:767 quodlibet/qltk/edittags.py:948 #: quodlibet/qltk/tagsfrompath.py:212 #, python-format msgid "" "Invalid tag <b>%s</b>\n" "\n" "The files currently selected do not support editing this tag." msgstr "" "Неважећа ознака <b>%s</b>\n" "\n" "Тренутно одабрана датотека не подржава ову ознаку." #: quodlibet/qltk/edittags.py:918 quodlibet/qltk/edittags.py:959 msgid "Invalid value" msgstr "Неважећа вредност" #: quodlibet/qltk/edittags.py:919 quodlibet/qltk/edittags.py:960 #, python-format msgid "" "Invalid value: <b>%(value)s</b>\n" "\n" "%(error)s" msgstr "" "Неважећа вредност: <b>%(value)s</b>\n" "\n" "%(error)s" #: quodlibet/qltk/_editutils.py:29 msgid "Tag may not be accurate" msgstr "Ознака може бити непрецизна" #: quodlibet/qltk/_editutils.py:32 #, 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:48 msgid "Unable to save song" msgstr "Не могу да сачувам песму" #: quodlibet/qltk/_editutils.py:51 #, 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:143 msgid "_More options…" msgstr "_Више опција…" #: quodlibet/qltk/entry.py:78 msgid "_Undo" msgstr "_Опозови" #: quodlibet/qltk/entry.py:80 msgid "_Redo" msgstr "_Понови" #: quodlibet/qltk/exfalsowindow.py:94 quodlibet/qltk/quodlibetwindow.py:956 msgid "_About" msgstr "_О апликацији" #: quodlibet/qltk/exfalsowindow.py:98 quodlibet/qltk/quodlibetwindow.py:978 msgid "_Check for Updates…" msgstr "_Провери доступна ажурирања…" #: quodlibet/qltk/exfalsowindow.py:104 quodlibet/qltk/quodlibetwindow.py:911 #: quodlibet/qltk/songsmenu.py:289 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:278 msgid "Ex Falso Preferences" msgstr "Ex Falso Поставке" #: quodlibet/qltk/exfalsowindow.py:284 quodlibet/qltk/prefs.py:666 msgid "Tag Editing" 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:386 msgid "Unable to create folder" msgstr "Не могу да створим фасциклу" #: quodlibet/qltk/filesel.py:403 msgid "Unable to delete folder" msgstr "Не могу да обришем фасциклу" #: quodlibet/qltk/filesel.py:519 quodlibet/qltk/pluginwin.py:167 msgid "Songs" msgstr "Песме" #. Translators: As in "by Artist Name" #: quodlibet/qltk/info.py:42 #, python-format msgid "by %s" msgstr "од %s" #: quodlibet/qltk/info.py:43 quodlibet/qltk/information.py:171 #: quodlibet/qltk/information.py:452 #, python-format msgid "Disc %s" msgstr "Диск %s" #: quodlibet/qltk/info.py:44 quodlibet/qltk/information.py:176 #, python-format msgid "Track %s" msgstr "Запис %s" #: quodlibet/qltk/info.py:108 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:342 #: quodlibet/qltk/information.py:475 quodlibet/qltk/information.py:543 msgid "Information" msgstr "Информације" #: quodlibet/qltk/information.py:127 msgid "Lyrics" msgstr "Текст речи" #: quodlibet/qltk/information.py:188 quodlibet/qltk/information.py:400 #, python-format msgid "Produced by %s" msgstr "Издато од %s" #: quodlibet/qltk/information.py:203 quodlibet/util/tags.py:85 msgid "artist" msgstr "уметник" #: quodlibet/qltk/information.py:204 quodlibet/qltk/information.py:573 #: quodlibet/util/tags.py:85 msgid "artists" msgstr "уметници" #. for backwards compat #: quodlibet/qltk/information.py:225 quodlibet/util/tags.py:96 #: quodlibet/util/tags.py:124 msgid "performers" msgstr "извођачи" #: quodlibet/qltk/information.py:239 quodlibet/qltk/information.py:252 #: quodlibet/qltk/songlistcolumns.py:276 msgid "Never" msgstr "Никад" #: quodlibet/qltk/information.py:240 #, 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:258 quodlibet/util/tags.py:149 msgid "added" msgstr "додато" #: quodlibet/qltk/information.py:259 quodlibet/util/tags.py:150 msgid "last played" msgstr "задње пуштано" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:160 msgid "plays" msgstr "свира" #: quodlibet/qltk/information.py:261 quodlibet/util/tags.py:161 msgid "skips" msgstr "прескаче" #: quodlibet/qltk/information.py:262 quodlibet/util/tags.py:166 msgid "rating" msgstr "оцена" #: quodlibet/qltk/information.py:291 msgid "path" msgstr "путања" #: quodlibet/qltk/information.py:292 quodlibet/util/tags.py:164 msgid "length" msgstr "дужина" #: quodlibet/qltk/information.py:293 msgid "format" msgstr "формат" #: quodlibet/qltk/information.py:294 quodlibet/util/tags.py:174 msgid "codec" msgstr "кодек" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:175 msgid "encoding" msgstr "енкодирање" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:171 msgid "bitrate" msgstr "учесталост битова" #: quodlibet/qltk/information.py:297 quodlibet/util/tags.py:172 msgid "file size" msgstr "величина датотеке" #: quodlibet/qltk/information.py:298 quodlibet/util/tags.py:159 msgid "modified" msgstr "измењено" #: quodlibet/qltk/information.py:335 msgid "Additional" msgstr "Додатно" #: quodlibet/qltk/information.py:387 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d одабран" msgstr[1] "%d одабрана" msgstr[2] "%d одабраних" #: quodlibet/qltk/information.py:462 msgid "Track unavailable" msgstr "Запис недоступан" #: quodlibet/qltk/information.py:468 msgid "Track List" msgstr "Листа записа" #: quodlibet/qltk/information.py:500 quodlibet/qltk/information.py:590 #, 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:503 msgid "Selected Discography" msgstr "Одабрана дискографија" #: quodlibet/qltk/information.py:570 #, 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:598 quodlibet/util/tags.py:83 msgid "albums" msgstr "албуми" #: quodlibet/qltk/information.py:611 msgid "Total length:" msgstr "Укупна дужина:" #: quodlibet/qltk/information.py:615 msgid "Total size:" msgstr "Укупна величина:" #: quodlibet/qltk/information.py:618 msgid "Files" msgstr "Датотеке" #: quodlibet/qltk/lyrics.py:36 msgid "_View online" msgstr "_Погледај на интернету" #: quodlibet/qltk/lyrics.py:64 msgid "No lyrics found for this song." msgstr "Нема понуђеног текста за ову песму." #: quodlibet/qltk/lyrics.py:75 msgid "Searching for lyrics…" 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/msg.py:41 msgid "Discard tag changes?" msgstr "Занемари промене ознака?" #: quodlibet/qltk/msg.py:42 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "" "Ознаке су измењене али нису сачуване. сачувај датотеке или опозови и " "занемари измене?" #: quodlibet/qltk/msg.py:55 quodlibet/qltk/prefs.py:628 #: quodlibet/qltk/prefs.py:635 quodlibet/qltk/textedit.py:63 #: quodlibet/qltk/tracknumbers.py:116 msgid "_Revert" msgstr "_Опозови" #: quodlibet/qltk/msg.py:104 msgid "File exists" msgstr "Датотека постоји" #: quodlibet/qltk/msg.py:106 #, python-format msgid "Replace %(file-name)s?" msgstr "Замени %(file-name)s?" #: quodlibet/qltk/msg.py:112 msgid "_Replace File" msgstr "_Замени датотеку" #: quodlibet/qltk/notif.py:182 msgid "Active tasks" msgstr "Активни задаци" #: quodlibet/qltk/notif.py:188 #, python-format msgid "%d tasks running" msgstr "%d покренутих задатака" #: quodlibet/qltk/playorder.py:256 msgid "Toggle shuffle mode" msgstr "Мењај режим мешања" #: quodlibet/qltk/playorder.py:272 msgid "Toggle repeat mode" msgstr "Мењај режим понављања" #: quodlibet/qltk/pluginwin.py:44 msgid "Plugin Errors" msgstr "Грешке додатка" #: quodlibet/qltk/pluginwin.py:124 msgid "Enabled" msgstr "Омогућено" #: quodlibet/qltk/pluginwin.py:125 msgid "Disabled" msgstr "Онемогућено" #: quodlibet/qltk/pluginwin.py:131 msgid "No category" msgstr "Без категорије" #: quodlibet/qltk/pluginwin.py:169 msgid "Events" msgstr "Догађаји" #: quodlibet/qltk/pluginwin.py:170 msgid "Play Order" msgstr "Редослед извођења" #: quodlibet/qltk/pluginwin.py:171 msgid "Editing" msgstr "Уређивање" #: quodlibet/qltk/pluginwin.py:173 msgid "Covers" msgstr "Омоти" #: quodlibet/qltk/pluginwin.py:309 msgid "No plugins found." msgstr "Додаци нису нађени." #: quodlibet/qltk/pluginwin.py:358 msgid "Plugins" msgstr "Додаци" #: quodlibet/qltk/pluginwin.py:382 msgid "Filter by plugin state / tag" msgstr "Филтрирај по стању додатка" #: quodlibet/qltk/pluginwin.py:388 msgid "Filter by plugin type" msgstr "Филтрирај по типу додатка" #: quodlibet/qltk/pluginwin.py:394 msgid "Filter by plugin name or description" msgstr "Филтрирај по имену или опису додатка" #: quodlibet/qltk/pluginwin.py:403 msgid "Show _Errors" msgstr "Прикажи _грешке" #: quodlibet/qltk/prefs.py:45 msgid "_Disc" msgstr "_Диск" #: quodlibet/qltk/prefs.py:46 msgid "_Track" msgstr "_Запис" #: quodlibet/qltk/prefs.py:47 msgid "Grou_ping" msgstr "Гру_писање" #: quodlibet/qltk/prefs.py:50 msgid "Al_bum" msgstr "Ал_бум" #: quodlibet/qltk/prefs.py:55 msgid "_Filename" msgstr "_Име датотеке" #: quodlibet/qltk/prefs.py:57 msgid "_Length" msgstr "_Дужина" #: quodlibet/qltk/prefs.py:64 msgid "_Jump to playing song automatically" msgstr "_Аутоматски скочи на пуштену песму" #: quodlibet/qltk/prefs.py:66 msgid "When the playing song changes, scroll to it in the song list" msgstr "Када се промени пуштена песма, премотај до ње у листи песама" #: quodlibet/qltk/prefs.py:82 msgid "_Others:" msgstr "_Други:" #: quodlibet/qltk/prefs.py:88 msgid "_Edit…" msgstr "_Уреди…" #: quodlibet/qltk/prefs.py:91 msgid "Add or remove additional column headers" msgstr "Додај или уклони додатна заглавља колона" #: quodlibet/qltk/prefs.py:101 msgid "Visible Columns" msgstr "Видљиве колоне" #: quodlibet/qltk/prefs.py:104 msgid "Title includes _version" msgstr "Име укључује _верзију" #: quodlibet/qltk/prefs.py:106 msgid "Artist includes all _people" msgstr "Уметник укључује све _људе" #: quodlibet/qltk/prefs.py:108 msgid "Album includes _disc subtitle" msgstr "Албум укључује _диск поднатпис" #: quodlibet/qltk/prefs.py:110 msgid "Filename includes _folder" msgstr "Име датотеке укључује _фасциклу" #: quodlibet/qltk/prefs.py:123 msgid "Column Preferences" msgstr "Поставке колоне" #: quodlibet/qltk/prefs.py:129 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "" "Примени тренутну конфигурацију на листу песама, додај нову колону на крају" #: quodlibet/qltk/prefs.py:142 quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Листа песама" #: quodlibet/qltk/prefs.py:222 msgid "Edit Columns" msgstr "Уреди колоне" #: quodlibet/qltk/prefs.py:259 msgid "Duration totals" msgstr "Укупно трајање" #: quodlibet/qltk/prefs.py:271 msgid "_Global filter:" msgstr "_Глобални филтер:" #: quodlibet/qltk/prefs.py:277 msgid "Apply this query in addition to all others" msgstr "Примени овај упит уз све друге" #. Translators: The heading of the preference group, no action #: quodlibet/qltk/prefs.py:283 msgctxt "heading" msgid "Search" msgstr "Претрага" #: quodlibet/qltk/prefs.py:287 quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Претраживачи" #: quodlibet/qltk/prefs.py:293 msgid "Confirm _multiple ratings" msgstr "Потврди _више оцена" #: quodlibet/qltk/prefs.py:295 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "Питај за потврду пре него што променим оцене за више песама одједном" #: quodlibet/qltk/prefs.py:298 msgid "Enable _one-click ratings" msgstr "Омогући _један-клик оцене" #: quodlibet/qltk/prefs.py:300 msgid "Enable rating by clicking on the rating column in the song list" msgstr "Омогућава оцењивање кликом на колону оцене у листи песама" #: quodlibet/qltk/prefs.py:306 quodlibet/qltk/prefs.py:669 msgid "Ratings" msgstr "Оцене" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:312 msgid "Prefer _embedded art" msgstr "Преферирај _уграђени омот" #: quodlibet/qltk/prefs.py:314 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" "Одаберите за коришћење омота уграђеног у аудио запис (када је доступно) пре " "других извора" #: quodlibet/qltk/prefs.py:319 msgid "_Fixed image filename:" msgstr "_Фиксирано име слике:" #: quodlibet/qltk/prefs.py:321 msgid "The single image filename to use if selected" msgstr "Једиснтвено име слике за коришћење ако је одабрано" #: quodlibet/qltk/prefs.py:327 msgid "The album art image file to use when forced (supports wildcards)" msgstr "Слика омота за коришћење када је присиљено" #: quodlibet/qltk/prefs.py:337 msgid "Album Art" msgstr "Омот албума" #: quodlibet/qltk/prefs.py:358 msgid "Playback" msgstr "Репродукција" #: quodlibet/qltk/prefs.py:363 msgid "Output Configuration" msgstr "Конфигурација излаза" #: quodlibet/qltk/prefs.py:374 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" "Ако нема Replay Gain информација за песму, постави јачину по овој вредности" #: quodlibet/qltk/prefs.py:377 msgid "_Fall-back gain (dB):" msgstr "_Fall-back gain (dB):" #: quodlibet/qltk/prefs.py:388 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "Постави јачину за све песме по задатој вредности" #: quodlibet/qltk/prefs.py:391 msgid "_Pre-amp gain (dB):" msgstr "_Pre-amp gain (dB):" #: quodlibet/qltk/prefs.py:396 msgid "_Enable Replay Gain volume adjustment" msgstr "_Omogući Replay Gain промену јачине" #: quodlibet/qltk/prefs.py:421 msgid "Replay Gain Volume Adjustment" msgstr "Replay Gain промена јачине" #: quodlibet/qltk/prefs.py:428 msgid "_Continue playback on startup" msgstr "_Настави репродукцију при покретању" #: quodlibet/qltk/prefs.py:430 msgid "" "If music is playing on shutdown, automatically start playing on next startup" msgstr "" "Ако је музика свирала при гашењу, аутоматски настави репродукцију при " "следећем покретању" #: quodlibet/qltk/prefs.py:434 msgid "Startup" msgstr "Покретање" #: quodlibet/qltk/prefs.py:461 msgid "_Default rating:" msgstr "_Подразумевана оцена:" #: quodlibet/qltk/prefs.py:504 msgid "Rating _scale:" msgstr "Скала _оцена:" #: quodlibet/qltk/prefs.py:553 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:558 msgid "_Bayesian averaging amount:" msgstr "_Bayesian просечна количина:" #: quodlibet/qltk/prefs.py:567 msgid "Save ratings and play _counts in tags" msgstr "Сачувај оцене и _број пуштања у ознакама" #: quodlibet/qltk/prefs.py:575 msgid "_Email:" msgstr "_Имејл:" #: quodlibet/qltk/prefs.py:577 msgid "Ratings and play counts will be saved in tags for this email address" msgstr "" "Оцене и број пуштања ће бити сачуване у ознакама за ову адресу електронске " "поште" #: quodlibet/qltk/prefs.py:597 msgid "Auto-save tag changes" msgstr "Аутоматски сачувај промену оцена" #: quodlibet/qltk/prefs.py:599 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "Сачувај промене у ознакама без потврде при уређивању више датотека" #: quodlibet/qltk/prefs.py:608 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:618 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:631 msgid "Split _tag on:" msgstr "Подели _ознаке на:" #: quodlibet/qltk/prefs.py:638 msgid "Split _subtag on:" msgstr "Подели _подознаке на:" #: quodlibet/qltk/prefs.py:663 msgid "Tags" msgstr "Ознаке" #: quodlibet/qltk/prefs.py:684 msgid "Updating for new ratings" msgstr "Ажурирам за нове оцене" #: quodlibet/qltk/prefs.py:694 msgid "Scan library _on start" msgstr "Скенирај библиотеку _при покретању" #: quodlibet/qltk/prefs.py:704 quodlibet/qltk/quodlibetwindow.py:990 msgid "_Scan Library" msgstr "_Скенирај библиотеку" #: quodlibet/qltk/prefs.py:706 quodlibet/qltk/quodlibetwindow.py:1052 msgid "Check for changes in your library" msgstr "Провери промене у библиотеци" #: quodlibet/qltk/prefs.py:711 msgid "Re_build Library" msgstr "Поново _изгради библиотеку" #: quodlibet/qltk/prefs.py:714 msgid "Reload all songs in your library. This can take a long time." msgstr "Поново учитај све песме у библиотеку. Ово може потрајати веома дуго." #: quodlibet/qltk/prefs.py:724 msgid "Scan Directories" msgstr "Skeniraj direktorijume" #: quodlibet/qltk/prefs.py:730 msgid "Hidden Songs" msgstr "Скривене песме" #: quodlibet/qltk/properties.py:157 quodlibet/util/collection.py:403 #, 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:104 msgid "_Queue" msgstr "_Низ" #: quodlibet/qltk/queue.py:124 msgid "Ephemeral" msgstr "Пролазан" #: quodlibet/qltk/queue.py:125 msgid "Remove songs from the queue after playing them" msgstr "Уклони песме из низа после репродукције" #: quodlibet/qltk/queue.py:133 msgid "Persistent" msgstr "Непрестано" #: quodlibet/qltk/queue.py:134 msgid "Keep songs in the queue after playing them" msgstr "Задржи песме у низу након репродукције" #: quodlibet/qltk/queue.py:142 msgid "Mode" msgstr "Режим" #: quodlibet/qltk/queue.py:153 msgid "Stop at End" msgstr "Заустави на крају" #: quodlibet/qltk/queue.py:157 msgid "_Clear Queue" msgstr "_Очисти низ" #: quodlibet/qltk/queue.py:178 msgid "Disable queue - the queue will be ignored when playing" msgstr "Онемогући низ - низ ће бити занемарен приликом репродукције" #: quodlibet/qltk/queue.py:290 #, 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:198 msgid "_Browse Library" msgstr "_Прегледај библиотеку" #: quodlibet/qltk/quodlibetwindow.py:348 msgid "Toggle queue visibility" msgstr "Мења видљивост низа" #: quodlibet/qltk/quodlibetwindow.py:376 msgid "Playback Error" msgstr "Грешка при репродукцији" #: quodlibet/qltk/quodlibetwindow.py:384 msgid "Set up library directories?" msgstr "Додај директоријум библиотеке?" #: quodlibet/qltk/quodlibetwindow.py:385 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "Немате музику додату у библиотеку. Да ли желите сада да додате?" #: quodlibet/qltk/quodlibetwindow.py:391 msgid "_Not Now" msgstr "_Не сад" #: quodlibet/qltk/quodlibetwindow.py:392 msgid "_Set Up" msgstr "_Додај" #: quodlibet/qltk/quodlibetwindow.py:845 msgid "Unable to add songs" msgstr "Не могу да додам песме" #: quodlibet/qltk/quodlibetwindow.py:846 quodlibet/qltk/quodlibetwindow.py:1286 #, python-format msgid "%s uses an unsupported protocol." msgstr "%s користи неподржан протокол." #: quodlibet/qltk/quodlibetwindow.py:869 msgid "_Jump to Playing Song" msgstr "_Скочи на пуштену песму" #: quodlibet/qltk/quodlibetwindow.py:876 msgid "_File" msgstr "_Датотека" #: quodlibet/qltk/quodlibetwindow.py:877 msgid "_Song" msgstr "_Песма" #: quodlibet/qltk/quodlibetwindow.py:878 msgid "_View" msgstr "_Преглед" #: quodlibet/qltk/quodlibetwindow.py:879 msgid "_Browse" msgstr "_Истражи" #: quodlibet/qltk/quodlibetwindow.py:880 msgid "_Control" msgstr "_Управљај" #: quodlibet/qltk/quodlibetwindow.py:881 msgid "_Help" msgstr "_Помоћ" #: quodlibet/qltk/quodlibetwindow.py:887 msgid "_Add a Folder…" msgstr "_Додај фасциклу…" #: quodlibet/qltk/quodlibetwindow.py:892 msgid "_Add a File…" msgstr "_Додај датотеку…" #: quodlibet/qltk/quodlibetwindow.py:897 msgid "_Add a Location…" msgstr "_Додај локацију…" #: quodlibet/qltk/quodlibetwindow.py:926 msgid "Edit Bookmarks…" msgstr "Уреди обележиваче…" #: quodlibet/qltk/quodlibetwindow.py:946 msgid "Stop After This Song" msgstr "Заустави после ове песме" #: quodlibet/qltk/quodlibetwindow.py:952 msgid "_Keyboard Shortcuts" msgstr "_Пречице тастатуре" #: quodlibet/qltk/quodlibetwindow.py:961 msgid "Online Help" msgstr "Помоћ на мрежи" #: quodlibet/qltk/quodlibetwindow.py:970 msgid "Search Help" msgstr "Потражи помоћ" #: quodlibet/qltk/quodlibetwindow.py:1274 msgid "Add a Location" msgstr "Додај локацију" #: quodlibet/qltk/quodlibetwindow.py:1275 msgid "Enter the location of an audio file:" msgstr "Унеси локацију аудио датотеке:" #: quodlibet/qltk/quodlibetwindow.py:1280 #: quodlibet/qltk/quodlibetwindow.py:1285 msgid "Unable to add location" msgstr "Не могу да додам локацију" #: quodlibet/qltk/quodlibetwindow.py:1281 #, python-format msgid "%s is not a valid location." msgstr "%s није исправна локација." #: quodlibet/qltk/quodlibetwindow.py:1294 #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "Add Music" msgstr "Додај музику" #: quodlibet/qltk/quodlibetwindow.py:1294 quodlibet/qltk/scanbox.py:99 msgid "_Add Folders" msgstr "_Додај фасцикле" #: quodlibet/qltk/quodlibetwindow.py:1301 msgid "Music Files" msgstr "Музичке датотеке" #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "_Add Files" msgstr "_Додај датотеке" #: quodlibet/qltk/ratingsmenu.py:24 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "Да ли сте сигурни да желите да измените оцену свих %d песама?" #: quodlibet/qltk/ratingsmenu.py:26 msgid "The saved ratings will be removed" msgstr "Сачуване оцене ће бити уклоњене" #: quodlibet/qltk/ratingsmenu.py:27 #, python-format msgid "The rating of all selected songs will be changed to '%s'" msgstr "Оцене свих одабраних песама ће бити промењене на '%s'" #: quodlibet/qltk/ratingsmenu.py:57 quodlibet/qltk/ratingsmenu.py:111 msgid "_Remove Rating" msgstr "_Уклони оцене" #: quodlibet/qltk/renamefiles.py:51 msgid "Replace spaces with _underscores" msgstr "Замени празан простор са _доњим цртама" #: quodlibet/qltk/renamefiles.py:61 msgid "Strip _Windows-incompatible characters" msgstr "Уклони _Виндоуз некомпатибилне карактере" #: quodlibet/qltk/renamefiles.py:79 msgid "Strip _diacritical marks" msgstr "Уклони _дијакритичке ознаке" #: quodlibet/qltk/renamefiles.py:90 msgid "Strip non-_ASCII characters" msgstr "Укони не-_ASCII карактере" #: quodlibet/qltk/renamefiles.py:100 msgid "Use only _lowercase characters" msgstr "Користи само _мала слова" #: quodlibet/qltk/renamefiles.py:128 msgid "Rename Files" msgstr "Преименуј датотеке" #: quodlibet/qltk/renamefiles.py:146 quodlibet/qltk/tagsfrompath.py:115 msgid "Path Patterns" msgstr "Шаблон путање" #: quodlibet/qltk/renamefiles.py:147 quodlibet/qltk/tagsfrompath.py:116 msgid "Edit saved patterns…" msgstr "Уреди сачуване шаблоне…" #: quodlibet/qltk/renamefiles.py:150 quodlibet/qltk/tagsfrompath.py:119 #: quodlibet/qltk/tracknumbers.py:57 msgid "_Preview" msgstr "_Преглед" #: quodlibet/qltk/renamefiles.py:177 msgid "File names" msgstr "Имена датотека" #: quodlibet/qltk/renamefiles.py:187 msgid "_Move album art" msgstr "_Помери омот албума" #: quodlibet/qltk/renamefiles.py:190 msgid "See '[albumart] filenames' config entry for image search strings" msgstr "Видите '[albumart] filenames' унос конфигурације за претрагу слика" #: quodlibet/qltk/renamefiles.py:195 msgid "_Overwrite album art at target" msgstr "_Препиши омот албума по циљу" #: quodlibet/qltk/renamefiles.py:203 msgid "_Remove empty directories" msgstr "_Уклони празне директоријуме" #: quodlibet/qltk/renamefiles.py:209 msgid "Album art" msgstr "Омот албума" #: quodlibet/qltk/renamefiles.py:238 msgid "New Name" msgstr "Ново име" #: quodlibet/qltk/renamefiles.py:315 msgid "Unable to rename file" msgstr "Не могу да преименујем датотеку" #: quodlibet/qltk/renamefiles.py:316 #, python-format msgid "" "Renaming <b>%(old-name)s</b> to <b>%(new-name)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." msgstr "" "Преименовање <b>%(old-name)s</b> у <b>%(new-name)s</b> неуспешно. Могуће да " "циљана датотека већ постоји, или немате дозволу да направите нову датотеку " "или уклоните стару." #: quodlibet/qltk/renamefiles.py:324 msgid "Ignore _All Errors" msgstr "Занемари _све грешке" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: quodlibet/qltk/renamefiles.py:325 quodlibet/qltk/wlw.py:49 msgid "_Stop" msgstr "_Заустави" #: quodlibet/qltk/renamefiles.py:327 msgid "_Continue" msgstr "_Настави" #: quodlibet/qltk/renamefiles.py:440 msgid "Path is not absolute" msgstr "Путања није апсолутна" #: quodlibet/qltk/renamefiles.py:441 #, python-format msgid "" "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 ~/." msgstr "" "Шаблон\n" "\t<b>%s</b>\n" "садржи / али не почиње од корена. Да би избегли погрешно именоване фасцикле, " "коренујте свој шаблон почетком са / или ~/." #: quodlibet/qltk/scanbox.py:47 msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "" "Песме у излистаним фасциклама ће бити додате у библиотеку када се листа " "освежи" #: quodlibet/qltk/scanbox.py:99 msgid "Select Directories" msgstr "Одабери директоријуме" #: quodlibet/qltk/searchbar.py:57 msgid "Saved Searches" msgstr "Сачувана претрага" #: quodlibet/qltk/searchbar.py:58 msgid "Edit saved searches…" msgstr "Уреди сачуване претраге…" #: quodlibet/qltk/searchbar.py:82 msgid "Search your library, using free text or QL queries" msgstr "Претрага ваше библиотеке користећи слободан текст или QL упите" #: quodlibet/qltk/searchbar.py:144 msgid "Search after _typing" msgstr "Тражи након _куцања" #: quodlibet/qltk/searchbar.py:147 msgid "Show search results after the user stops typing" msgstr "Показује резултате претраге након што корисник заврши са куцањем" #: quodlibet/qltk/searchbar.py:215 msgid "_Limit:" msgstr "_Ограничење:" #: quodlibet/qltk/searchbar.py:228 msgid "_Weight" msgstr "_Значај" #: quodlibet/qltk/searchbar.py:355 msgid "Add query" msgstr "Додај питање" #: quodlibet/qltk/searchbar.py:356 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:375 #, python-format msgid "_Filter on %s" msgstr "_Филтрирај по %s" #: quodlibet/qltk/songlist.py:1093 msgid "All _Headers" msgstr "Сва _заглавља" #: quodlibet/qltk/songlist.py:1094 msgid "_Track Headers" msgstr "_Запис заглавље" #: quodlibet/qltk/songlist.py:1095 msgid "_Album Headers" msgstr "_Албум заглавље" #: quodlibet/qltk/songlist.py:1096 msgid "_People Headers" msgstr "_Људи заглавље" #: quodlibet/qltk/songlist.py:1097 msgid "_Date Headers" msgstr "_Датум заглавље" #: quodlibet/qltk/songlist.py:1098 msgid "_File Headers" msgstr "_Датотека заглавље" #: quodlibet/qltk/songlist.py:1099 msgid "_Production Headers" msgstr "_Продукција заглавље" #: quodlibet/qltk/songlist.py:1114 msgid "_Customize Headers…" msgstr "_Прилагоди заглавље…" #: quodlibet/qltk/songlist.py:1119 msgid "_Expand Column" msgstr "_Прошири колону" #: quodlibet/qltk/songsmenu.py:40 #, python-format msgid "Remove track: \"%%(title)s\" from library?" msgid_plural "Remove %(count)d tracks from library?" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/qltk/songsmenu.py:46 msgid "Remove from Library" msgstr "Уклони из библиотеке" #: quodlibet/qltk/songsmenu.py:51 #, 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:62 #, 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:134 msgid "Configure Plugins…" msgstr "Подеси додатке…" #: quodlibet/qltk/songsmenu.py:329 msgid "Add to _Queue" msgstr "Додај у _Низ" #: quodlibet/qltk/songsmenu.py:349 msgid "_Remove from Library…" msgstr "_Уклони из библиотеке…" #: quodlibet/qltk/songsmenu.py:414 msgid "Unable to show files" msgstr "Не могу да прикажем датотеке" #: quodlibet/qltk/songsmenu.py:415 msgid "Error showing files, or no program available to show them." msgstr "" "Грешка при приказивању датотеке, или нема програма који би је приказали." #: quodlibet/qltk/songsmenu.py:422 #, python-format msgid "_Show in File Manager" msgid_plural "_Show %(total)d Files in File Manager" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/qltk/tagsfrompath.py:46 msgid "Replace _underscores with spaces" msgstr "Замени _доње црте са празним простором" #: quodlibet/qltk/tagsfrompath.py:56 msgid "_Title-case tags" msgstr "_Велико-слово ознаке" #: quodlibet/qltk/tagsfrompath.py:66 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<b>%s</b>\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" "Шаблон\n" "\t<b>%s</b>\n" "је неисраван. Могуће да садржи исту ознаку два пута или има небалансиране " "заграде (< / >)." #: quodlibet/qltk/tagsfrompath.py:215 msgid "Invalid tags" msgstr "Неважеће ознаке" #: quodlibet/qltk/tagsfrompath.py:216 #, 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" "Тренутно одабрана датотека не подржава уређивање ових ознака." #: 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:923 #, python-format msgid "and %d more…" msgstr "и %d још…" #: quodlibet/qltk/wlw.py:199 msgid "Saving the songs you changed." msgstr "Чувам измењене песме." #: quodlibet/qltk/wlw.py:200 #, 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:233 #, 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:425 msgid "Playlists must have a name" msgstr "Листа извођења мора имати име" #: quodlibet/util/collection.py:608 #, python-format msgid "A playlist named %s already exists." msgstr "Листа извођења %s већ постоји." #: quodlibet/util/cover/built_in.py:32 msgid "Embedded album covers" msgstr "Уграђени омоти албума" #: quodlibet/util/cover/built_in.py:33 msgid "Uses covers embedded into audio files." msgstr "Користи омоте уграђене у аудио датотеке." #: quodlibet/util/cover/built_in.py:55 msgid "Filesystem cover" msgstr "Омоти фасцикле" #: quodlibet/util/cover/built_in.py:56 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:76 msgid "Display brief usage information" msgstr "Прикажи укратке информације коришћења" #: quodlibet/util/__init__.py:78 msgid "Display version and copyright" msgstr "Прикажи верзију и ауторска права" #: quodlibet/util/__init__.py:79 msgid "Print debugging information" msgstr "Одштампај информације исправљања грешака" #: quodlibet/util/__init__.py:118 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "Коришћење: %(program)s %(usage)s" #: quodlibet/util/__init__.py:120 msgid "[options]" msgstr "[опције]" #: quodlibet/util/__init__.py:165 #, python-format msgid "Option %r not recognized." msgstr "Опција %r није позната." #: quodlibet/util/__init__.py:168 #, python-format msgid "Option %r requires an argument." msgstr "Опција %r захтева аргумент." #: quodlibet/util/__init__.py:171 #, python-format msgid "%r is not a unique prefix." msgstr "%r није јединствен префикс." #: quodlibet/util/__init__.py:347 #, python-format msgid "%d kbps" msgstr "%d kbps" #: quodlibet/util/__init__.py:402 #, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%s секунда" msgstr[1] "%s секунде" msgstr[2] "%s секунди" #: quodlibet/util/__init__.py:415 msgid "No time information" msgstr "Нема информација о трајању" #: quodlibet/util/__init__.py:418 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d секунда" msgstr[1] "%d секунде" msgstr[2] "%d секунди" #: quodlibet/util/__init__.py:419 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d минут" msgstr[1] "%d минута" msgstr[2] "%d минута" #: quodlibet/util/__init__.py:420 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d сат" msgstr[1] "%d сата" msgstr[2] "%d сати" #: quodlibet/util/__init__.py:421 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d дан" msgstr[1] "%d дана" msgstr[2] "%d дана" #: quodlibet/util/__init__.py:422 #, 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:514 msgctxt "check" msgid "titlecase?" msgstr "не" #: quodlibet/util/massagers.py:114 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:129 msgid "Replay Gain gains must be entered in 'x.yy dB' format." msgstr "Replay Gain повећања морају бити унета у 'x.yy dB' формату." #: quodlibet/util/massagers.py:150 msgid "Replay Gain peaks must be entered in 'x.yy' format." msgstr "Replay Gain peaks морају бити унети у 'x.yy' формату." #: quodlibet/util/massagers.py:172 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:194 msgid "" "MusicBrainz release status must be 'official', 'promotional', or 'bootleg'." msgstr "" "MusicBrainz статус издања мора бити 'official', 'promotional', или 'bootleg'." #: quodlibet/util/massagers.py:207 msgid "Language must be an ISO 639-2 three-letter code" msgstr "Језик мора бити ISO 639-2 три-слова стандард" #: quodlibet/util/songwrapper.py:116 msgid "Unable to edit song" msgstr "Не могу уредити песму" #: quodlibet/util/songwrapper.py:117 #, python-format msgid "" "Saving <b>%s</b> 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:151 msgid "disc" msgstr "диск" #: quodlibet/util/tags.py:115 quodlibet/util/tags.py:153 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 "земља издања" #. 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:130 msgid "MusicBrainz recording ID" msgstr "MusicBrainz ID снимања" #: quodlibet/util/tags.py:131 msgid "MusicBrainz release track ID" msgstr "MusicBrainz ID издања записа" #: quodlibet/util/tags.py:132 msgid "MusicBrainz release ID" msgstr "MusicBrainz ID издања" #: quodlibet/util/tags.py:133 msgid "MusicBrainz artist ID" msgstr "MusicBrainz ID уметника" #: quodlibet/util/tags.py:134 msgid "MusicBrainz release artist ID" msgstr "MusicBrainz ID издања уметника" #: quodlibet/util/tags.py:135 msgid "MusicBrainz TRM ID" msgstr "MusicBrainz TRM ID" #: quodlibet/util/tags.py:136 msgid "MusicIP PUID" msgstr "MusicIP PUID" #: quodlibet/util/tags.py:137 msgid "MusicBrainz album status" msgstr "MusicBrainz статус албума" #: quodlibet/util/tags.py:138 msgid "MusicBrainz album type" msgstr "MusicBrainz тип албума" #: quodlibet/util/tags.py:139 msgid "MusicBrainz release group ID" msgstr "MusicBrainz ID издања групе" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:142 msgid "track gain" msgstr "track gain" #: quodlibet/util/tags.py:143 msgid "track peak" msgstr "track peak" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:145 msgid "album gain" msgstr "album gain" #: quodlibet/util/tags.py:146 msgid "album peak" msgstr "album peak" #: quodlibet/util/tags.py:147 msgid "reference loudness" msgstr "референца јачине звука" #: quodlibet/util/tags.py:152 msgid "discs" msgstr "дискови" #: quodlibet/util/tags.py:154 msgid "tracks" msgstr "записи" #: quodlibet/util/tags.py:155 msgid "last started" msgstr "задње покретано" #: quodlibet/util/tags.py:156 msgid "full name" msgstr "пуно име" #: quodlibet/util/tags.py:163 msgid "mount point" msgstr "тачка качења" #: quodlibet/util/tags.py:165 msgid "people" msgstr "људи" #: quodlibet/util/tags.py:167 msgid "year" msgstr "година" #: quodlibet/util/tags.py:168 msgid "original release year" msgstr "оригинална година издања" #: quodlibet/util/tags.py:169 msgid "bookmark" msgstr "обележивач" #: quodlibet/util/tags.py:170 msgid "bitdepth" msgstr "дубина бита" #: quodlibet/util/tags.py:173 msgid "file format" msgstr "формат датотеке" #: quodlibet/util/tags.py:176 msgid "playlists" msgstr "листе пуштања" #: quodlibet/util/tags.py:177 msgid "sample rate" msgstr "брзина узорка" #: quodlibet/util/tags.py:178 msgid "channel count" msgstr "број канала" #. Translators: e.g. "artist (sort)" #: quodlibet/util/tags.py:268 msgid "sort" msgstr "разврстај" #. Translators: e.g. "performer (roles)" #: quodlibet/util/tags.py:276 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 је програм за организацију музике. Пружа више различитих начина " "да прегледате вашу аудио збирку/библиотеку, а такође поседује и подршку за " "интернет радио и аудио изворе. Има јако флексибилне способности уређивања " "метаподатака ознака и претраге." ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9751859 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/po/sr_RS@latin.po�������������������������������������������������������������������0000644�0001750�0001750�00000564125�00000000000�015651� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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: 2019-08-13 06:59+0200\n" "PO-Revision-Date: 2019-08-17 06:09+0200\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" "Language: sr\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: Poedit 2.2.1\n" #: quodlibet/browsers/albums/main.py:206 #: quodlibet/browsers/covergrid/main.py:54 msgid "_Title" msgstr "_Naziv" #: quodlibet/browsers/albums/main.py:207 #: quodlibet/browsers/covergrid/main.py:55 quodlibet/qltk/prefs.py:49 msgid "_Artist" msgstr "_Umetnik" #: quodlibet/browsers/albums/main.py:208 #: quodlibet/browsers/covergrid/main.py:56 quodlibet/qltk/prefs.py:54 msgid "_Date" msgstr "_Datum" #: quodlibet/browsers/albums/main.py:209 msgid "_Original Date" msgstr "_Izvorni datum" #: quodlibet/browsers/albums/main.py:210 #: quodlibet/browsers/covergrid/main.py:57 quodlibet/qltk/prefs.py:53 msgid "_Genre" msgstr "_Žanr" #: quodlibet/browsers/albums/main.py:211 #: quodlibet/browsers/covergrid/main.py:58 quodlibet/qltk/prefs.py:58 #: quodlibet/qltk/ratingsmenu.py:39 msgid "_Rating" msgstr "_Ocena" #: quodlibet/browsers/albums/main.py:212 msgid "_Playcount" msgstr "_Broj puštanja" #: quodlibet/browsers/albums/main.py:218 #: quodlibet/browsers/covergrid/main.py:64 msgid "Sort _by…" msgstr "Razvrstaj _po…" #: quodlibet/browsers/albums/main.py:239 #: quodlibet/browsers/covergrid/main.py:85 #: quodlibet/browsers/paned/prefs.py:203 #: quodlibet/browsers/playlists/main.py:667 quodlibet/qltk/exfalsowindow.py:108 #: quodlibet/qltk/pluginwin.py:341 quodlibet/qltk/quodlibetwindow.py:906 msgid "_Preferences" msgstr "_Postavke" #: quodlibet/browsers/albums/main.py:409 msgid "Album List" msgstr "Lista albuma" #: quodlibet/browsers/albums/main.py:410 msgid "_Album List" msgstr "_Lista albuma" #: quodlibet/browsers/albums/main.py:524 #: quodlibet/browsers/covergrid/main.py:285 #: quodlibet/browsers/covergrid/main.py:501 msgid "All Albums" msgstr "Svi albumi" #: quodlibet/browsers/albums/main.py:525 #: quodlibet/browsers/covergrid/main.py:286 #: quodlibet/browsers/covergrid/main.py:502 #, 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:706 #: quodlibet/browsers/covergrid/main.py:480 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:16 #: 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:385 quodlibet/util/collection.py:247 #, 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:383 quodlibet/util/collection.py:251 #, 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:124 #: quodlibet/ext/songsmenu/cover_download.py:243 msgid "Options" msgstr "Opcije" #: quodlibet/browsers/albums/prefs.py:74 #: quodlibet/browsers/covergrid/prefs.py:127 msgid "Album Display" msgstr "Prikaz Albuma" #: quodlibet/browsers/albums/prefs.py:78 #: quodlibet/browsers/covergrid/prefs.py:131 #: quodlibet/browsers/playlists/prefs.py:56 #: quodlibet/ext/songsmenu/albumart.py:328 #: quodlibet/ext/songsmenu/duplicates.py:345 #: quodlibet/ext/songsmenu/filterall.py:48 quodlibet/qltk/bookmarks.py:101 #: quodlibet/qltk/cbes.py:93 quodlibet/qltk/data_editors.py:96 #: quodlibet/qltk/data_editors.py:321 quodlibet/qltk/exfalsowindow.py:286 #: quodlibet/qltk/pluginwin.py:79 quodlibet/qltk/pluginwin.py:428 #: quodlibet/qltk/prefs.py:764 quodlibet/qltk/textedit.py:163 #: quodlibet/update.py:149 msgid "_Close" msgstr "_Zatvori" #: quodlibet/browsers/audiofeeds.py:52 quodlibet/browsers/audiofeeds.py:64 #: quodlibet/browsers/audiofeeds.py:66 quodlibet/browsers/audiofeeds.py:156 #: quodlibet/browsers/paned/models.py:85 #: quodlibet/ext/songsmenu/fingerprint/search.py:46 #: quodlibet/formats/_audio.py:488 quodlibet/order/__init__.py:27 #: quodlibet/qltk/information.py:244 quodlibet/qltk/information.py:251 #: quodlibet/qltk/information.py:277 quodlibet/qltk/wlw.py:69 msgid "Unknown" msgstr "Nepoznato" #: quodlibet/browsers/audiofeeds.py:247 msgid "New Feed" msgstr "Novi izvor" #: quodlibet/browsers/audiofeeds.py:248 msgid "Enter the location of an audio feed:" msgstr "Unesi lokaciju audio izvora:" #: quodlibet/browsers/audiofeeds.py:249 #: quodlibet/browsers/collection/prefs.py:89 quodlibet/browsers/iradio.py:357 #: quodlibet/browsers/paned/prefs.py:120 #: quodlibet/browsers/playlists/menu.py:96 #: quodlibet/browsers/playlists/util.py:52 quodlibet/qltk/bookmarks.py:62 #: quodlibet/qltk/cbes.py:55 quodlibet/qltk/data_editors.py:308 #: quodlibet/qltk/edittags.py:327 quodlibet/qltk/edittags.py:527 #: quodlibet/qltk/quodlibetwindow.py:1276 quodlibet/qltk/scanbox.py:61 msgid "_Add" msgstr "_Dodaj" #: quodlibet/browsers/audiofeeds.py:303 msgid "Audio Feeds" msgstr "Audio izvori" #: quodlibet/browsers/audiofeeds.py:304 msgid "_Audio Feeds" msgstr "_Audio izvori" #: quodlibet/browsers/audiofeeds.py:407 quodlibet/qltk/data_editors.py:93 msgid "_New" msgstr "_Novo" #: quodlibet/browsers/audiofeeds.py:467 quodlibet/browsers/audiofeeds.py:526 msgid "Unable to add feed" msgstr "Ne mogu dodati izvor" #: quodlibet/browsers/audiofeeds.py:468 quodlibet/browsers/audiofeeds.py:527 #, python-format msgid "" "%s could not be added. The server may be down, or the location may not be an " "audio feed." msgstr "" "%s ne može biti dodat. Možda je server nedostupan ili izvor nije audio zapis." #: quodlibet/browsers/audiofeeds.py:475 quodlibet/qltk/filesel.py:260 #: quodlibet/qltk/pluginwin.py:414 msgid "_Refresh" msgstr "_Osveži" #: quodlibet/browsers/audiofeeds.py:476 #: quodlibet/browsers/playlists/main.py:487 #: quodlibet/browsers/playlists/util.py:43 quodlibet/qltk/delete.py:143 #: quodlibet/qltk/filesel.py:257 quodlibet/qltk/lyrics.py:35 #: quodlibet/qltk/maskedbox.py:28 quodlibet/qltk/songsmenu.py:364 msgid "_Delete" msgstr "_Obriši" #: quodlibet/browsers/audiofeeds.py:543 msgid "" "The current audio backend does not support URLs, Audio Feeds browser " "disabled." msgstr "" "Trenutna audio podrška ne podržava URL, pretraživač audio izvora je " "onemogućen." #: quodlibet/browsers/_base.py:146 quodlibet/browsers/_base.py:149 msgid "Library Browser" msgstr "Pretraživač biblioteke" #: quodlibet/browsers/_base.py:273 quodlibet/ext/songsmenu/console.py:45 #: quodlibet/ext/songsmenu/refresh.py:30 quodlibet/qltk/exfalsowindow.py:240 #: quodlibet/qltk/information.py:554 quodlibet/qltk/maskedbox.py:68 #: quodlibet/util/collection.py:532 #, 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:401 quodlibet/browsers/_base.py:406 #: quodlibet/qltk/tagsfrompath.py:193 quodlibet/qltk/textedit.py:140 #: quodlibet/util/__init__.py:573 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:23 #, python-format msgid "Unknown %s" msgstr "Nepoznat %s" #: quodlibet/browsers/collection/models.py:24 #, 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" #. Remove button #: quodlibet/browsers/collection/prefs.py:93 #: quodlibet/browsers/paned/prefs.py:124 #: quodlibet/browsers/playlists/menu.py:97 #: quodlibet/ext/playlist/remove_duplicates.py:60 #: quodlibet/qltk/bookmarks.py:97 quodlibet/qltk/bookmarks.py:127 #: quodlibet/qltk/cbes.py:82 quodlibet/qltk/cbes.py:89 #: quodlibet/qltk/data_editors.py:78 quodlibet/qltk/data_editors.py:91 #: quodlibet/qltk/data_editors.py:298 quodlibet/qltk/data_editors.py:311 #: quodlibet/qltk/data_editors.py:319 quodlibet/qltk/edittags.py:533 #: quodlibet/qltk/edittags.py:710 quodlibet/qltk/maskedbox.py:48 #: quodlibet/qltk/maskedbox.py:88 quodlibet/qltk/queue.py:427 #: quodlibet/qltk/scanbox.py:36 quodlibet/qltk/scanbox.py:63 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:470 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:247 #: quodlibet/ext/songsmenu/editplaycount.py:45 #: quodlibet/ext/songsmenu/exact_rating.py:38 #: quodlibet/player/gstbe/prefs.py:40 quodlibet/qltk/prefs.py:127 #: quodlibet/qltk/textedit.py:64 msgid "_Apply" msgstr "_Primeni" #: quodlibet/browsers/collection/prefs.py:197 #: quodlibet/browsers/paned/prefs.py:251 #: quodlibet/browsers/playlists/menu.py:95 #: quodlibet/browsers/playlists/util.py:42 quodlibet/errorreport/ui.py:103 #: quodlibet/ext/playlist/export_to_folder.py:38 #: 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:44 #: quodlibet/ext/songsmenu/fingerprint/search.py:281 #: quodlibet/ext/songsmenu/fingerprint/submit.py:90 #: quodlibet/ext/songsmenu/importexport.py:40 #: quodlibet/ext/songsmenu/lastfmsync.py:218 #: quodlibet/ext/songsmenu/playlist.py:50 #: 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:326 #: quodlibet/qltk/_editutils.py:39 quodlibet/qltk/getstring.py:28 #: quodlibet/qltk/maskedbox.py:27 quodlibet/qltk/msg.py:54 #: quodlibet/qltk/msg.py:93 quodlibet/qltk/msg.py:111 #: quodlibet/qltk/ratingsmenu.py:33 quodlibet/update.py:95 msgid "_Cancel" msgstr "_Otkaži" #: quodlibet/browsers/covergrid/main.py:126 msgid "Cover Grid" msgstr "Mreža omota" #: quodlibet/browsers/covergrid/main.py:127 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:71 msgid "Show \"All Albums\" Item" msgstr "Prikaži stavku \"Svi albumi\"" #: quodlibet/browsers/covergrid/prefs.py:82 msgid "Wide Mode" msgstr "Širok režim" #: quodlibet/browsers/covergrid/prefs.py:114 #: quodlibet/browsers/covergrid/prefs.py:115 msgid "Cover Magnification" msgstr "Uveličavanje omota" #: quodlibet/browsers/filesystem.py:39 msgid "File System" msgstr "Sistem datoteka" #: quodlibet/browsers/filesystem.py:40 msgid "_File System" msgstr "_Sistem datoteka" #: quodlibet/browsers/filesystem.py:124 quodlibet/qltk/songlist.py:255 msgid "Unable to copy songs" msgstr "Ne mogu da umnožim pesme" #: quodlibet/browsers/filesystem.py:125 quodlibet/qltk/songlist.py:256 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:197 msgid "_Add to Library" msgstr "_Dodaj u biblioteku" #: quodlibet/browsers/iradio.py:182 msgid "Unsupported file type" msgstr "Nepodržan tip datoteke" #: quodlibet/browsers/iradio.py:183 #, 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:230 quodlibet/browsers/iradio.py:243 #: quodlibet/browsers/iradio.py:836 msgid "Unable to add station" msgstr "Ne mogu da dodam stanicu" #: quodlibet/browsers/iradio.py:254 quodlibet/browsers/iradio.py:487 msgid "Internet Radio" msgstr "Internet radio" #: quodlibet/browsers/iradio.py:254 msgid "Downloading station list" msgstr "Preuzimam listu stanica" #: quodlibet/browsers/iradio.py:355 msgid "New Station" msgstr "Nova stanica" #: quodlibet/browsers/iradio.py:356 msgid "Enter the location of an Internet radio station:" msgstr "Unesite lokaciju internet radio stanice:" #: quodlibet/browsers/iradio.py:374 msgid "Electronic" msgstr "Elektronska" #: quodlibet/browsers/iradio.py:377 msgid "Hip Hop / Rap" msgstr "Hip hop / Rep" #: quodlibet/browsers/iradio.py:378 msgid "Oldies" msgstr "Stara" #: quodlibet/browsers/iradio.py:379 msgid "R&B" msgstr "R&B" #: quodlibet/browsers/iradio.py:380 msgid "Japanese" msgstr "Japanska" #: quodlibet/browsers/iradio.py:381 msgid "Indian" msgstr "Indijska" #: quodlibet/browsers/iradio.py:383 msgid "Religious" msgstr "Duhovna" #: quodlibet/browsers/iradio.py:385 msgid "Charts" msgstr "Tabele" #: quodlibet/browsers/iradio.py:386 msgid "Turkish" msgstr "Turska" #: quodlibet/browsers/iradio.py:387 msgid "Reggae / Dancehall" msgstr "Rege / Za ples" #: quodlibet/browsers/iradio.py:388 msgid "Latin" msgstr "Latino" #: quodlibet/browsers/iradio.py:389 msgid "College Radio" msgstr "Fakultetski radio" #: quodlibet/browsers/iradio.py:390 msgid "Talk / News" msgstr "Razgovor / Vesti" #: quodlibet/browsers/iradio.py:391 msgid "Ambient" msgstr "Ambientalna" #: quodlibet/browsers/iradio.py:392 msgid "Jazz" msgstr "Džez" #: quodlibet/browsers/iradio.py:393 quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "Klasična" #: quodlibet/browsers/iradio.py:394 quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "Pop" #: quodlibet/browsers/iradio.py:395 msgid "Alternative" msgstr "Alternativna" #: quodlibet/browsers/iradio.py:396 msgid "Metal" msgstr "Metal" #: quodlibet/browsers/iradio.py:397 msgid "Country" msgstr "Kantri" #: quodlibet/browsers/iradio.py:398 msgid "News" msgstr "Vesti" #: quodlibet/browsers/iradio.py:399 msgid "Schlager" msgstr "Šlageri" #: quodlibet/browsers/iradio.py:400 msgid "Funk" msgstr "Fank" #: quodlibet/browsers/iradio.py:401 msgid "Indie" msgstr "Indi" #: quodlibet/browsers/iradio.py:402 msgid "Blues" msgstr "Bluz" #: quodlibet/browsers/iradio.py:403 msgid "Soul" msgstr "Soul" #: quodlibet/browsers/iradio.py:404 msgid "Lounge" msgstr "Za odmaranje" #: quodlibet/browsers/iradio.py:405 msgid "Punk" msgstr "Pank" #: quodlibet/browsers/iradio.py:406 msgid "Reggaeton" msgstr "Regeton" #: quodlibet/browsers/iradio.py:408 msgid "Slavic" msgstr "Slovenska" #: quodlibet/browsers/iradio.py:410 msgid "Greek" msgstr "Grčka" #: quodlibet/browsers/iradio.py:411 msgid "Gothic" msgstr "Gotika" #: quodlibet/browsers/iradio.py:412 quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "Rok" #: quodlibet/browsers/iradio.py:465 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:471 msgid "_Load Stations" msgstr "_Učitaj stanice" #: quodlibet/browsers/iradio.py:488 msgid "_Internet Radio" msgstr "_Internet radio" #: quodlibet/browsers/iradio.py:561 msgid "_New Station…" msgstr "_Nova stanica…" #: quodlibet/browsers/iradio.py:564 msgid "_Update Stations" msgstr "_Ažuriraj stanice" #: quodlibet/browsers/iradio.py:591 msgid "All Stations" msgstr "Sve stanice" #. TODO: support for ~#rating=!None etc (#1940) #: quodlibet/browsers/iradio.py:595 quodlibet/browsers/soundcloud/main.py:65 msgid "Favorites" msgstr "Omiljeno" #: quodlibet/browsers/iradio.py:603 msgid "No Category" msgstr "Nema kategorije" #: quodlibet/browsers/iradio.py:828 msgid "No stations found" msgstr "Nisu pronađene stanice" #: quodlibet/browsers/iradio.py:829 #, python-format msgid "No Internet radio stations were found at %s." msgstr "Internet stanica nije nađena na %s." #: quodlibet/browsers/iradio.py:837 msgid "All stations listed are already in your library." msgstr "Izlistane stanice su već u vašoj biblioteci." #: quodlibet/browsers/iradio.py:854 msgid "Add to Favorites" msgstr "Dodaj u omiljene" #: quodlibet/browsers/iradio.py:858 msgid "Remove from Favorites" msgstr "Ukloni iz omiljenih" #: quodlibet/browsers/iradio.py:958 #, 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:103 quodlibet/qltk/pluginwin.py:122 #: quodlibet/qltk/pluginwin.py:164 msgid "All" msgstr "Sve" #: quodlibet/browsers/paned/prefs.py:41 #: quodlibet/ext/songsmenu/cover_download.py:118 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 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "<tt>%s</tt>" msgstr "" "Označi šablon opcionim obeležjima npr. <tt>kompozitor</tt> ili\n" "<tt>%s</tt>" #: quodlibet/browsers/paned/prefs.py:231 msgid "Paned Browser Preferences" msgstr "Postavke pano pretraživača" #: quodlibet/browsers/paned/prefs.py:236 msgid "Column layout" msgstr "Izgled kolona" #: quodlibet/browsers/paned/prefs.py:240 msgid "Column content" msgstr "Sadržaj kolona" #: quodlibet/browsers/paned/prefs.py:242 msgid "Equal pane width" msgstr "Jednaka širina panoa" #: quodlibet/browsers/playlists/main.py:48 #: quodlibet/browsers/playlists/main.py:603 quodlibet/qltk/pluginwin.py:168 msgid "Playlists" msgstr "Lista izvođenja" #: quodlibet/browsers/playlists/main.py:49 msgid "_Playlists" msgstr "_Lista izvođenja" #: quodlibet/browsers/playlists/main.py:152 msgid "_Remove from Playlist" msgstr "_Ukloni sa liste izvođenja" #: quodlibet/browsers/playlists/main.py:217 msgid "New" msgstr "Novo" #: quodlibet/browsers/playlists/main.py:221 msgid "Import" msgstr "Uvezi" #: quodlibet/browsers/playlists/main.py:443 msgid "Unable to import playlist" msgstr "Ne mogu da uvezem listu izvođenja" #: quodlibet/browsers/playlists/main.py:444 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:494 msgid "_Rename" msgstr "_Preimenuj" #: quodlibet/browsers/playlists/main.py:592 msgid "Unable to rename playlist" msgstr "Ne mogu da preimenujem listu puštanja" #: quodlibet/browsers/playlists/main.py:604 msgid "Import Playlist" msgstr "Uvezi listu izvođenja" #: quodlibet/browsers/playlists/main.py:604 msgid "_Import" msgstr "_Uvezi" #: quodlibet/browsers/playlists/menu.py:25 msgid "_New Playlist…" msgstr "_Nova lista izvođenja…" #: quodlibet/browsers/playlists/menu.py:86 #, 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:90 #, 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:33 #, 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:35 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:50 #: quodlibet/browsers/playlists/util.py:125 quodlibet/util/collection.py:575 msgid "New Playlist" msgstr "Nova lista izvođenja" #: quodlibet/browsers/playlists/util.py:51 msgid "Enter a name for the new playlist:" msgstr "Unesite ime za novu listu izvođenja:" #: quodlibet/browsers/playlists/util.py:89 #, 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/search.py:32 msgid "_Limit Results" msgstr "_Ograniči rezultate" #: quodlibet/browsers/search.py:37 msgid "_Allow multiple queries" msgstr "_Dozvoli više pretraga" #: quodlibet/browsers/search.py:53 msgid "Search Library" msgstr "Pretraži biblioteku" #: quodlibet/browsers/search.py:54 msgid "_Search Library" msgstr "_Pretraži biblioteku" #: quodlibet/browsers/soundcloud/main.py:39 msgid "Soundcloud Browser" msgstr "Soundcloud pretraživač" #: quodlibet/browsers/soundcloud/main.py:40 msgid "Sound_cloud" msgstr "Sound_cloud" #: quodlibet/browsers/soundcloud/main.py:60 quodlibet/qltk/searchbar.py:81 msgid "Search" msgstr "Pretraga" #: quodlibet/browsers/soundcloud/main.py:69 msgid "My tracks" msgstr "Moji zapisi" #: quodlibet/browsers/soundcloud/main.py:141 #, python-format msgid "Go to %s" msgstr "Idi na %s" #: quodlibet/browsers/soundcloud/main.py:443 msgid "Connected" msgstr "Povezan" #: quodlibet/browsers/soundcloud/main.py:444 #, python-format msgid "Quod Libet is now connected, <b>%s</b>!" msgstr "Quod Libet je povezan, <b>%s</b>!" #: quodlibet/browsers/soundcloud/main.py:456 #, python-format msgid "Log out of %s" msgstr "Odjavi se sa %s" #: quodlibet/browsers/soundcloud/main.py:458 msgid "Enter code…" msgstr "Unesi kod…" #: quodlibet/browsers/soundcloud/main.py:459 #, python-format msgid "Log in to %s" msgstr "Prijavi se na %s" #: quodlibet/browsers/soundcloud/util.py:86 msgid "Soundcloud authorisation" msgstr "Soundcloud autentifikacija" #: quodlibet/browsers/soundcloud/util.py:87 msgid "Enter Soundcloud auth code:" msgstr "Unesite Soundcloud autentifikacioni kod:" #: quodlibet/cli.py:50 msgid "Quod Libet is not running (add '--run' to start it)" msgstr "Quod Libet nije pokrenut (dodaj '--run' za pokretanje)" #: quodlibet/cli.py:86 msgid "a music library and player" msgstr "muzička biblioteka i plejer" #: quodlibet/cli.py:87 msgid "[option]" msgstr "[opcija]" #: quodlibet/cli.py:89 msgid "Print the playing song and exit" msgstr "Odštampaj puštenu pesmu i izađi" #: quodlibet/cli.py:90 msgid "Begin playing immediately" msgstr "Odmah počni izvođenje" #: quodlibet/cli.py:91 msgid "Don't show any windows on start" msgstr "Ne prikazuj prozore pri pokretanju" #: quodlibet/cli.py:94 msgid "Jump to next song" msgstr "Skoči na sledeću pesmu" #: quodlibet/cli.py:96 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:97 msgid "Jump to previous song" msgstr "Skoči na prethodnu pesmu" #: quodlibet/cli.py:98 msgid "Start playback" msgstr "Pokreni izvođenje" #: quodlibet/cli.py:99 msgid "Pause playback" msgstr "Pauziraj izvođenje" #: quodlibet/cli.py:100 msgid "Toggle play/pause mode" msgstr "Menjaj pusti/pauziraj režim" #: quodlibet/cli.py:101 msgid "Stop playback" msgstr "Zaustavi izvođenje" #: quodlibet/cli.py:102 msgid "Turn up volume" msgstr "Pojačaj" #: quodlibet/cli.py:103 msgid "Turn down volume" msgstr "Smanji" #: quodlibet/cli.py:104 msgid "Increase rating of playing song by one star" msgstr "Povećaj ocenu trenutne pesme za jednu zvezdicu" #: quodlibet/cli.py:105 msgid "Decrease rating of playing song by one star" msgstr "Umanji ocenu trenutne pesme za jednu zvezdicu" #: quodlibet/cli.py:106 msgid "Print player status" msgstr "Odštampaj stanje plejera" #: quodlibet/cli.py:107 msgid "Hide main window" msgstr "Sakrij glavnu prozor" #: quodlibet/cli.py:108 msgid "Show main window" msgstr "Prikaži glavni prozor" #: quodlibet/cli.py:109 msgid "Toggle main window visibility" msgstr "Promeni vidljivost glavnog prozora" #: quodlibet/cli.py:110 msgid "Focus the running player" msgstr "Fokusiraj pokrenuti plejer" #: quodlibet/cli.py:111 msgid "Remove active browser filters" msgstr "Ukloni filtere aktivnog pretraživača" #: quodlibet/cli.py:112 msgid "Refresh and rescan library" msgstr "Osveži i pretraži biblioteku" #: quodlibet/cli.py:113 msgid "List available browsers" msgstr "Izlistaj dostupne pretraživače" #: quodlibet/cli.py:114 msgid "Print the current playlist" msgstr "Odštampaj trenutnu listu izvođenja" #: quodlibet/cli.py:115 msgid "Print the contents of the queue" msgstr "Odštampaj sadržaj niza" #: quodlibet/cli.py:116 msgid "Print the active text query" msgstr "Odštampaj upit aktivnog teksta" #: quodlibet/cli.py:117 msgid "Start without plugins" msgstr "Pokreni bez priključaka" #: quodlibet/cli.py:118 msgid "Start Quod Libet if it isn't running" msgstr "Pokreni Quod Libet ako nije pokrenut" #: quodlibet/cli.py:119 msgid "Exit Quod Libet" msgstr "Napusti Quod Libet" #: quodlibet/cli.py:124 msgid "Seek within the playing song" msgstr "Premotaj trenutnu pesmu" #: quodlibet/cli.py:124 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: quodlibet/cli.py:125 msgid "Set or toggle shuffle mode" msgstr "Postavi ili promeni režim mešanja" #: quodlibet/cli.py:126 msgid "Set shuffle mode type" msgstr "Postavi tip režima mešanja" #: quodlibet/cli.py:127 msgid "Turn repeat off, on, or toggle it" msgstr "Uključi ili isključi ponavljanje" #: quodlibet/cli.py:128 msgid "Set repeat mode type" msgstr "Promeni tip ponavljanja" #: quodlibet/cli.py:129 msgid "Set the volume" msgstr "Podesi jačinu" #: quodlibet/cli.py:130 msgid "Search your audio library" msgstr "Pretraži svoju audio biblioteku" #: quodlibet/cli.py:130 quodlibet/cli.py:140 quodlibet/cli.py:144 #: quodlibet/cli.py:146 msgid "query" msgstr "upit" #: quodlibet/cli.py:131 msgid "Play a file" msgstr "Reprodukuj datoteku" #: quodlibet/cli.py:131 quodlibet/cli.py:140 quodlibet/cli.py:146 msgctxt "command" msgid "filename" msgstr "ime datoteke" #: quodlibet/cli.py:132 msgid "Set rating of playing song" msgstr "Oceni trenutnu pesmu" #: quodlibet/cli.py:133 msgid "Set the current browser" msgstr "Postavi trenutni pretraživač" #: quodlibet/cli.py:134 msgid "Stop after the playing song" msgstr "Zaustavi nakon završetka pesme" #: quodlibet/cli.py:135 msgid "Open a new browser" msgstr "Otvori nov pretraživač" #: quodlibet/cli.py:136 msgid "Show or hide the queue" msgstr "Prikaži ili sakrij zahteve" #: quodlibet/cli.py:137 msgid "Filter on a random value" msgstr "Filtriraj po nasumičnoj vrednosti" #: quodlibet/cli.py:137 msgctxt "command" msgid "tag" msgstr "oznaka" #: quodlibet/cli.py:138 msgid "Filter on a tag value" msgstr "Filitriraj po vrednošću oznake" #: quodlibet/cli.py:138 msgid "tag=value" msgstr "oznaka=vrednost" #: quodlibet/cli.py:139 msgid "Enqueue a file or query" msgstr "Nanizati datoteku ili zahtev" #: quodlibet/cli.py:141 msgid "Enqueue comma-separated files" msgstr "Nanizati zarezom razdvojene datoteke" #: quodlibet/cli.py:142 quodlibet/util/tags.py:157 msgid "filename" msgstr "ime datoteke" #: quodlibet/cli.py:143 msgid "Print filenames of results of query to stdout" msgstr "Štampaj imena datoteka rezultata zahteva na stdout" #: quodlibet/cli.py:145 msgid "Unqueue a file or query" msgstr "Izbaci iz niza datoteku ili zahtev" #: quodlibet/cli.py:147 msgid "Add a file or directory to the library" msgstr "Dodaj datoteku ili direktorijum u biblioteku" #: quodlibet/cli.py:148 quodlibet/util/tags.py:100 msgid "location" msgstr "lokacija" #: quodlibet/cli.py:213 #, python-format msgid "Invalid argument for '%s'." msgstr "Nevažeći argument za '%s'." #: quodlibet/cli.py:214 quodlibet/util/__init__.py:173 #, 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 "Quit Program" msgstr "Izađi iz programa" #: 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:34 msgid "an audio tag editor" msgstr "uređivač audio oznaka" #: quodlibet/exfalso.py:34 quodlibet/util/tags.py:158 msgid "directory" msgstr "direktorijum" #: quodlibet/exfalso.py:41 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:20 msgid "" "Downloads covers linked to by the artwork_url tag. This works with the " "Soundcloud browser." 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:20 msgid "MusicBrainz Cover Source" msgstr "MusicBrainz izvor omota" #: quodlibet/ext/covers/musicbrainz.py:21 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:19 msgid "" "Allows arbitrary regex substitutions (s///) 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:68 msgid "Advanced Preferences" msgstr "Napredne postavke" #: quodlibet/ext/events/advanced_preferences.py:69 msgid "Allow editing of advanced config settings." msgstr "Dozvoli menjanje naprednih podešavanja konfiguracije." #: quodlibet/ext/events/advanced_preferences.py:187 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/ext/events/weblyrics.py:318 quodlibet/qltk/prefs.py:266 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:66 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:172 msgid "Effects" msgstr "Efekti" #: quodlibet/ext/events/animosd/prefs.py:288 msgid "Ed_it Display Pattern…" msgstr "Ur_edi šablon prikaza…" #: quodlibet/ext/events/animosd/prefs.py:292 #: 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_library_update.py:138 msgid "Automatic Library Update" msgstr "Automatsko ažuriranje bibilioteke" #: quodlibet/ext/events/auto_library_update.py:139 #, 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." #: 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 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." #: quodlibet/ext/events/bansheeimport.py:106 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:111 #: quodlibet/ext/events/rbimport.py:114 msgid "Import Failed" msgstr "Uvoz neuspešan" #: quodlibet/ext/events/bansheeimport.py:117 #, 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:126 msgid "Banshee Import" msgstr "Banshee uvoz" #: quodlibet/ext/events/bansheeimport.py:127 msgid "Imports ratings and song statistics from Banshee." msgstr "Uvozi ocene i statistiku pesme iz Banshee." #: quodlibet/ext/events/bansheeimport.py:136 msgid "_Database path:" msgstr "_Baza podataka:" #: quodlibet/ext/events/bansheeimport.py:164 #: quodlibet/ext/events/rbimport.py:132 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/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:93 #: quodlibet/ext/gstreamer/karaoke.py:95 #, python-format msgid "%d Hz" msgstr "%d Hz" #: quodlibet/ext/events/equalizer.py:198 #: quodlibet/ext/gstreamer/crossfeed.py:112 #, 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/playlist/export_to_squeezebox.py:80 #: quodlibet/ext/songsmenu/albumart.py:324 #: quodlibet/ext/songsmenu/brainz/widgets.py:355 #: quodlibet/ext/songsmenu/cover_download.py:309 #: quodlibet/ext/songsmenu/fingerprint/search.py:278 #: quodlibet/ext/songsmenu/html.py:75 quodlibet/ext/songsmenu/lastfmsync.py:219 #: quodlibet/ext/songsmenu/playlist.py:51 #: quodlibet/ext/songsmenu/replaygain.py:354 #: quodlibet/ext/songsmenu/tapbpm.py:187 quodlibet/qltk/_editutils.py:40 #: quodlibet/qltk/lyrics.py:34 quodlibet/qltk/msg.py:52 #: quodlibet/qltk/renamefiles.py:216 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:42 msgid "Inhibit Screensaver" msgstr "Onemogući čuvara ekrana" #: quodlibet/ext/events/inhibit.py:43 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." #: quodlibet/ext/events/inhibit.py:52 msgid "Music is playing" msgstr "Muzika svira" #: quodlibet/ext/events/iradiolog.py:16 msgid "Internet Radio Log" msgstr "Internet radio dnevnik" #: quodlibet/ext/events/iradiolog.py:17 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:31 msgid "Outputs a Jabber User Tunes file to ~/.quodlibet/jabber." 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 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:37 msgid "MPRIS D-Bus Support" msgstr "MPRIS D-Bus podrška" #: quodlibet/ext/events/mpris/__init__.py:38 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." #: quodlibet/ext/events/mpris/__init__.py:44 #: quodlibet/ext/events/trayicon/prefs.py:36 msgid "Hide main window on close" msgstr "Sakrij glavni prozor pri zatvaranju" #: quodlibet/ext/events/mpris/__init__.py:47 #: quodlibet/ext/events/themeswitcher.py:84 #: quodlibet/ext/gstreamer/compressor.py:99 #: quodlibet/ext/gstreamer/crossfeed.py:136 #: quodlibet/ext/gstreamer/karaoke.py:99 quodlibet/ext/gstreamer/pitch.py:89 #: quodlibet/qltk/prefs.py:741 msgid "Preferences" msgstr "Postavke" #: quodlibet/ext/events/mqtt.py:54 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "Prihvata QL šablone npr. %s" #: quodlibet/ext/events/mqtt.py:60 msgid "MQTT Publisher" msgstr "MQTT objavljivač" #: quodlibet/ext/events/mqtt.py:61 msgid "Publishes status messages to an MQTT topic." msgstr "Objavljuje statusne poruke na MQTT temu." #: quodlibet/ext/events/mqtt.py:128 msgid "Broker hostname" msgstr "Ime domaćina posrednika" #: quodlibet/ext/events/mqtt.py:129 msgid "broker hostname / IP (defaults to localhost)" msgstr "ime domaćina posrednika / IP (podrazumevano na localhost)" #: quodlibet/ext/events/mqtt.py:131 msgid "Broker port" msgstr "Port posrednika" #: quodlibet/ext/events/mqtt.py:131 msgid "broker port (defaults to 1883)" msgstr "port posrednika (podrazumevano na 1883)" #: quodlibet/ext/events/mqtt.py:133 msgid "Topic" msgstr "Tema" #: quodlibet/ext/events/mqtt.py:135 msgid "Playing Pattern" msgstr "Obrazac reprodukcije" #: quodlibet/ext/events/mqtt.py:137 msgid "Status text when a song is started." msgstr "Status tekst kada je pesma puštena." #: quodlibet/ext/events/mqtt.py:139 msgid "Paused Pattern" msgstr "Obrazac pauze" #: quodlibet/ext/events/mqtt.py:141 msgid "Text when a song is paused." msgstr "Tekst kada je pesma pauzirana." #: quodlibet/ext/events/mqtt.py:143 msgid "No-song Text" msgstr "Tekst bez pesme" #: quodlibet/ext/events/mqtt.py:145 msgid "Plain text for when there is no current song" msgstr "Prazan tekst kada nema puštene pesme" #: quodlibet/ext/events/mqtt.py:156 msgid "MQTT Configuration" msgstr "MQTT konfiguracija" #: quodlibet/ext/events/mqtt.py:160 msgid "Status Text" msgstr "Status tekst" #: quodlibet/ext/events/mqtt.py:192 #, 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:196 #, 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:199 msgid "Connection error" msgstr "Greška pri povezivanju" #: 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/qlscrobbler.py:175 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:252 #, python-format msgid "Could not contact service '%s'." msgstr "Ne mogu kontaktirati servis '%s'." #: quodlibet/ext/events/qlscrobbler.py:258 msgid "Authentication failed: invalid URL." msgstr "Autentifikacija neuspela: nevažeći URL." #: quodlibet/ext/events/qlscrobbler.py:275 #, 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:280 msgid "Client is banned. Contact the author." msgstr "Zabranjen pristup. Kontaktirajte autora." #: quodlibet/ext/events/qlscrobbler.py:284 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:349 msgid "AudioScrobbler Submission" msgstr "AudioScrobbler dostava" #: quodlibet/ext/events/qlscrobbler.py:350 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:455 msgid "Authentication successful." msgstr "Autentifikacija uspešna." #: quodlibet/ext/events/qlscrobbler.py:467 msgid "_Service:" msgstr "_Servis:" #: quodlibet/ext/events/qlscrobbler.py:467 msgid "_URL:" msgstr "_URL:" #: quodlibet/ext/events/qlscrobbler.py:467 msgid "User_name:" msgstr "Korisničko_ime:" #: quodlibet/ext/events/qlscrobbler.py:468 msgid "_Password:" msgstr "_Lozinka:" #. Translators: Other service #: quodlibet/ext/events/qlscrobbler.py:484 msgid "Other…" msgstr "Drugo…" #. verify data #: quodlibet/ext/events/qlscrobbler.py:522 msgid "_Verify account data" msgstr "_Proveri podatke naloga" #: quodlibet/ext/events/qlscrobbler.py:527 #: quodlibet/ext/songsmenu/lastfmsync.py:312 msgid "Account" msgstr "Nalog" #: quodlibet/ext/events/qlscrobbler.py:535 msgid "_Artist pattern:" msgstr "_Umetnik šablon:" #: quodlibet/ext/events/qlscrobbler.py:535 msgid "_Title pattern:" msgstr "_Naslov šablon:" #: quodlibet/ext/events/qlscrobbler.py:536 msgid "Exclude _filter:" msgstr "Izuzmi _filter:" #: quodlibet/ext/events/qlscrobbler.py:554 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:564 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:573 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:581 msgid "_Offline mode (don't submit anything)" msgstr "_Režim van mreže (ne dostavljaj ništa)" #: quodlibet/ext/events/qlscrobbler.py:585 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:28 msgid "Random Album Playback" msgstr "Nasumično izvođenje albuma" #: quodlibet/ext/events/randomalbum.py:29 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:39 msgid "Rated higher" msgstr "Bolje ocenjeno" #: quodlibet/ext/events/randomalbum.py:40 msgid "Played more often" msgstr "Češće puštano" #: quodlibet/ext/events/randomalbum.py:41 msgid "Skipped more often" msgstr "Češće preskakano" #: quodlibet/ext/events/randomalbum.py:42 msgid "Played more recently" msgstr "Skoro puštano" #: quodlibet/ext/events/randomalbum.py:43 msgid "Started more recently" msgstr "Skoro pokretano" #: quodlibet/ext/events/randomalbum.py:44 msgid "Added more recently" msgstr "Skoro dodato" #: quodlibet/ext/events/randomalbum.py:45 msgid "Longer albums" msgstr "Duži albumi" #: quodlibet/ext/events/randomalbum.py:84 msgid "seconds before starting next album" msgstr "sekundi pre početka sledećeg albuma" #: quodlibet/ext/events/randomalbum.py:88 msgid "Weights" msgstr "Značaj" #: quodlibet/ext/events/randomalbum.py:90 msgid "Play some albums more than others" msgstr "Puštaj neke albume češće od drugih" #: quodlibet/ext/events/randomalbum.py:104 msgid "avoid" msgstr "izbegni" #: quodlibet/ext/events/randomalbum.py:115 msgid "prefer" msgstr "preferiraj" #: quodlibet/ext/events/randomalbum.py:219 msgid "Random Album" msgstr "Nasumičan album" #: quodlibet/ext/events/randomalbum.py:220 #, python-format msgid "Waiting to start %s" msgstr "Čekam da počne %s" #: quodlibet/ext/events/rbimport.py:119 #, 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:127 msgid "Rhythmbox Import" msgstr "Rhythmbox uvoz" #: quodlibet/ext/events/rbimport.py:128 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:73 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:79 msgid "GNOME Search Provider" msgstr "GNOME pretraživač" #: quodlibet/ext/events/searchprovider.py:80 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 msgid "" "Store Seekpoints A and/or B for tracks. Skip to time A and stop after time B " "when track is played.\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:29 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:57 #: quodlibet/ext/playlist/export_to_squeezebox.py:89 msgid "Error finding Squeezebox server" msgstr "Greška u pronalaženju Squeezebox servera" #: quodlibet/ext/events/squeezebox_sync.py:58 #: quodlibet/ext/playlist/export_to_squeezebox.py:90 #, python-format msgid "Error finding %s. Please check settings" msgstr "Greška pronalaženja %s. Molimo proverite podešavanja" #: quodlibet/ext/events/synchronizedlyrics.py:34 msgid "Synchronized Lyrics" msgstr "Sinhronizovani tekst" #: quodlibet/ext/events/synchronizedlyrics.py:35 msgid "Shows synchronized lyrics from .lrc file with same name as the track." msgstr "" "Pokazuje sinhronizovani tekst pesme iz .lrc datoteke sa istim imenom kao i " "zapis." #: quodlibet/ext/events/synchronizedlyrics.py:69 msgid "Text:" msgstr "Tekst:" #: quodlibet/ext/events/synchronizedlyrics.py:79 msgid "Background:" msgstr "Pozadina:" #: quodlibet/ext/events/synchronizedlyrics.py:90 msgid "Font" msgstr "Font" #: quodlibet/ext/events/synchronizedlyrics.py:93 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:145 msgid "Paused:" msgstr "Pauzirano:" #: quodlibet/ext/events/telepathy_status.py:146 #, 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:162 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:163 msgid "No song:" msgstr "Nema pesme:" #. Frame #: quodlibet/ext/events/telepathy_status.py:170 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:91 msgid "Thumb Rating" msgstr "Palac ocena" #: quodlibet/ext/events/thumbrating.py:92 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 '~#score'." 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:47 msgid "Not playing" msgstr "Ne svira" #: quodlibet/ext/events/trayicon/__init__.py:53 msgid "Tray Icon" msgstr "Traka zadataka" #: quodlibet/ext/events/trayicon/__init__.py:54 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:183 quodlibet/qltk/quodlibetwindow.py:936 #: quodlibet/qltk/quodlibetwindow.py:1142 msgid "_Play" msgstr "_Pusti" #: quodlibet/ext/events/trayicon/menu.py:63 #: quodlibet/qltk/quodlibetwindow.py:185 quodlibet/qltk/quodlibetwindow.py:1144 #: quodlibet/qltk/wlw.py:50 msgid "P_ause" msgstr "P_auziraj" #: quodlibet/ext/events/trayicon/menu.py:68 #: quodlibet/qltk/quodlibetwindow.py:190 quodlibet/qltk/quodlibetwindow.py:931 msgid "Pre_vious" msgstr "Pre_thodno" #: quodlibet/ext/events/trayicon/menu.py:71 #: quodlibet/qltk/quodlibetwindow.py:194 quodlibet/qltk/quodlibetwindow.py:941 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:902 msgid "Open _Browser" msgstr "Otvori _pretraživač" #: quodlibet/ext/events/trayicon/menu.py:103 #: quodlibet/qltk/quodlibetwindow.py:921 quodlibet/qltk/songsmenu.py:383 msgid "Edit _Tags" msgstr "Izmeni _oznake" #: quodlibet/ext/events/trayicon/menu.py:112 #: quodlibet/qltk/quodlibetwindow.py:864 quodlibet/qltk/songsmenu.py:396 msgid "_Information" msgstr "_Informacije" #: quodlibet/ext/events/trayicon/menu.py:114 quodlibet/qltk/songsmenu.py:324 msgid "Play_lists" msgstr "Lista _izvođenja" #: quodlibet/ext/events/trayicon/menu.py:132 #: quodlibet/qltk/quodlibetwindow.py:916 msgid "_Quit" msgstr "_Odustani" #: quodlibet/ext/events/trayicon/prefs.py:38 quodlibet/qltk/prefs.py:69 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 quodlibet/ext/events/weblyrics.py:193 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:603 msgid "Waveform Seek Bar" msgstr "Talasna traka motanja" #: quodlibet/ext/events/waveformseekbar.py:607 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:676 msgid "Override foreground color:" msgstr "Koristi boju prednjeg dela:" #: quodlibet/ext/events/waveformseekbar.py:680 msgid "Override hover color:" msgstr "Koristi boju plutanja:" #: quodlibet/ext/events/waveformseekbar.py:684 msgid "Override remaining color:" msgstr "Koristi za ostale boje:" #: quodlibet/ext/events/waveformseekbar.py:688 msgid "Show current position" msgstr "Prikaži trenutnu poziciju" #: quodlibet/ext/events/waveformseekbar.py:693 msgid "Show time labels" msgstr "Prikaži imena vremena" #: quodlibet/ext/events/waveformseekbar.py:701 msgid "Seek amount when scrolling (milliseconds):" msgstr "Korak motanja prilikom skrolovanja (milisekunde):" #: quodlibet/ext/events/weblyrics.py:208 msgid "No lyrics found" msgstr "Nema nađenog teksta" #: quodlibet/ext/events/weblyrics.py:268 msgid "_Zoom level:" msgstr "_Uveličavanje nivo:" #: quodlibet/ext/events/weblyrics.py:286 msgid "URL:" msgstr "URL:" #: quodlibet/ext/events/weblyrics.py:291 msgid "Revert to default" msgstr "Vrati na podrazumevano" #: quodlibet/ext/events/weblyrics.py:306 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." #: quodlibet/ext/events/weblyrics.py:323 msgid "Alternate search" msgstr "Alternativna pretraga" #: quodlibet/ext/events/weblyrics.py:332 msgid "Web Lyrics" msgstr "Veb tekst" #: quodlibet/ext/events/weblyrics.py:333 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." #: 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:20 msgid "_Threshold:" msgstr "_Prag:" #: quodlibet/ext/gstreamer/compressor.py:21 msgid "Threshold until the filter is activated" msgstr "Prag dok filter ne bude aktiviran" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "R_atio:" msgstr "O_dnos:" #: quodlibet/ext/gstreamer/compressor.py:22 msgid "Compression ratio" msgstr "Odnos kompresije" #: quodlibet/ext/gstreamer/compressor.py:74 #: quodlibet/ext/gstreamer/karaoke.py:91 #, python-format msgid "%d %%" msgstr "%d %%" #: quodlibet/ext/gstreamer/compressor.py:105 msgid "Audio Compressor" msgstr "Audio kompresor" #: quodlibet/ext/gstreamer/compressor.py:106 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:19 msgid "_Preset:" msgstr "_Odabir:" #: quodlibet/ext/gstreamer/crossfeed.py:19 msgid "Filter preset" msgstr "Filtriraj odabir" #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Frequency cut:" msgstr "_Frekvencija odsecanje:" #: quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Low-pass filter cut frequency" msgstr "Niski-prolaz filter frekvencija odsecanja" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed _level:" msgstr "Izvor _nivo:" #: quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed level" msgstr "Izvor nivo" #: quodlibet/ext/gstreamer/crossfeed.py:25 msgid "Default" msgstr "Podrazumevano" #: quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "Najbliže poziciji virtuelnog zvučnika (30°, 3 metra)" #: quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Chu Moy" msgstr "Chu Moy" #: quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "Blizu Chu Moy ukrštenog izvora (popularno)" #: quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Jan Meier" msgstr "Jan Meier" #: quodlibet/ext/gstreamer/crossfeed.py:30 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:31 msgid "Custom" msgstr "Prilagođeno" #: quodlibet/ext/gstreamer/crossfeed.py:31 msgid "Custom settings" msgstr "Prilagođena podešavanja" #: quodlibet/ext/gstreamer/crossfeed.py:152 msgid "Crossfeed" msgstr "Ukršten izvor" #: quodlibet/ext/gstreamer/crossfeed.py:153 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:20 msgid "Filter _band:" msgstr "Filter _pojas:" #: quodlibet/ext/gstreamer/karaoke.py:21 msgid "The Frequency band of the filter" msgstr "Frekventni pojas filtera" #: quodlibet/ext/gstreamer/karaoke.py:22 msgid "Filter _width:" msgstr "Filter _širina:" #: quodlibet/ext/gstreamer/karaoke.py:23 msgid "The Frequency width of the filter" msgstr "Frekventni opseg filtera" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "_Level:" msgstr "_Nivo:" #: quodlibet/ext/gstreamer/karaoke.py:24 msgid "Level of the effect" msgstr "Nivo efekata" #: quodlibet/ext/gstreamer/karaoke.py:105 msgid "Karaoke" msgstr "Karaoke" #: quodlibet/ext/gstreamer/karaoke.py:106 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:21 msgid "R_ate:" msgstr "U_čestalost:" #: quodlibet/ext/gstreamer/pitch.py:22 msgid "_Tempo:" msgstr "_Tempo:" #: quodlibet/ext/gstreamer/pitch.py:23 msgid "_Pitch:" msgstr "_Stepen:" #: quodlibet/ext/gstreamer/pitch.py:95 msgid "Audio Pitch / Speed" msgstr "Audio stepen / brzina" #: quodlibet/ext/gstreamer/pitch.py:96 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:147 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:100 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:121 #: quodlibet/ext/songsmenu/playlist.py:132 msgid "Unable to export playlist" msgstr "Ne mogu da izvezem listu izvođenja" #: quodlibet/ext/playlist/export_to_folder.py:122 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:165 msgid "Default filename pattern:" msgstr "Podrazumevan šablon imena datoteka:" #: quodlibet/ext/playlist/export_to_squeezebox.py:22 msgid "Export to Squeezebox" msgstr "Izvezi u Squeezebox" #: quodlibet/ext/playlist/export_to_squeezebox.py:24 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 "" "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: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:96 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 msgid "" "Playback 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/playcounteq.py:21 msgid "Playcount Equalizer" msgstr "Ujednačivač broja puštanja" #: quodlibet/ext/playorder/playcounteq.py:22 msgid "Shuffle, preferring songs with fewer total plays." msgstr "Meša i daje prednost pesmama koje su ređe puštane." #: quodlibet/ext/playorder/playcounteq.py:24 msgid "Prefer less played" msgstr "Poželi manje puštane" #: quodlibet/ext/playorder/queue.py:19 msgid "Queue Only" msgstr "Samo Niz" #: quodlibet/ext/playorder/queue.py:21 msgid "" "Limits playing of songs to the queue. 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/reverse.py:14 msgid "Reverse" msgstr "Okrenut" #: quodlibet/ext/playorder/reverse.py:16 msgid "Reverses the play order of songs." msgstr "Okreće redoslet puštanja pesama." #: quodlibet/ext/playorder/shufflebygrouping.py:31 #: quodlibet/ext/playorder/shufflebygrouping.py:93 msgid "Shuffle by Grouping" msgstr "Mešaj po grupama" #: quodlibet/ext/playorder/shufflebygrouping.py:32 msgid "" "Shuffles by a grouping of songs defined by a common tag instead of by track, " "similar to album shuffle. This is useful for shuffling multi-movement " "classical works while 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:38 msgid "Shuffle by grouping" msgstr "Mešaj po grupama" #: quodlibet/ext/playorder/shufflebygrouping.py:94 msgid "Waiting to start new group…" msgstr "Čekam da započnem novu grupu…" #: quodlibet/ext/playorder/shufflebygrouping.py:144 msgid "Grouping tag:" msgstr "Grupisane oznake:" #: quodlibet/ext/playorder/shufflebygrouping.py:148 msgid "Tag to group songs by" msgstr "Oznake za grupisanje pesama" #: quodlibet/ext/playorder/shufflebygrouping.py:150 msgid "Filter tag:" msgstr "Filter oznaka:" #: quodlibet/ext/playorder/shufflebygrouping.py:155 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:160 msgid "Delay:" msgstr "_Kašnjenje:" #: quodlibet/ext/playorder/shufflebygrouping.py:166 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:182 msgid "Reset to defaults" msgstr "Poništi na podrazumevano" #: quodlibet/ext/playorder/skip_songs.py:25 msgid "Skip Songs" msgstr "Preskoči pesme" #: quodlibet/ext/playorder/skip_songs.py:27 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." #: quodlibet/ext/playorder/track_repeat.py:30 msgid "Repeat Each Track" msgstr "Ponavljaj svaki zapis" #: quodlibet/ext/playorder/track_repeat.py:32 msgid "Shuffle songs, but repeat every track a set number of times." msgstr "Meša pesme, ali ponavlja svaki zapis postavljenim brojem puta." #: quodlibet/ext/playorder/track_repeat.py:51 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 msgid "" "Chooses the query to match based on a condition query. Syntax is '@(if: " "condition, then, else)'." msgstr "" "Bira upit koji se podudara sa situacionim upitom. Sintaksa je '@(if: " "condition, then, else)'." #: quodlibet/ext/query/missing.py:15 msgid "Missing Query" msgstr "Nedostajući upit" #: quodlibet/ext/query/missing.py:16 msgid "Matches songs without the given tag." msgstr "Uparuje pesme bez dodeljene oznake." #: quodlibet/ext/query/missing.py:27 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. Syntax is '@(python: expression)'. The " "variable 's' (or 'a') is the song / album being matched. '_ts' is a (real " "number) timestamp at start of query. Modules 'time' and 'random' are also " "available, and the class 'Random' (==random.Random) 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:19 msgid "Include Saved Search" msgstr "Uključi sačuvanu pretragu" #: quodlibet/ext/query/savedsearch.py:20 msgid "" "Include the results of a saved search as part of another query. Syntax is " "'@(saved: search name)'." msgstr "" "Uključuje rezultate sačuvanih pretraga kao deo drugog upita. Sintaksa je " "'@(saved: search name)'." #: 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:116 msgid "Port:" msgstr "Port:" #: quodlibet/ext/_shared/squeezebox/base.py:121 msgid "Username:" msgstr "Korisničko ime:" #: quodlibet/ext/_shared/squeezebox/base.py:126 msgid "Password:" msgstr "Lozinka:" #: quodlibet/ext/_shared/squeezebox/base.py:130 msgid "Library directory the server connects to" msgstr "Direktorijum biblioteke povezivanja servera" #: quodlibet/ext/_shared/squeezebox/base.py:132 msgid "Library path:" msgstr "Putanja biblioteke:" #. Add verify button #: quodlibet/ext/_shared/squeezebox/base.py:141 msgid "_Verify settings" msgstr "_Proveri postavke" #. Server settings Frame #: quodlibet/ext/_shared/squeezebox/base.py:147 msgid "Squeezebox Server" msgstr "Squeezebox server" #: quodlibet/ext/_shared/squeezebox/base.py:150 msgid "Debug" msgstr "Ispitaj" #: quodlibet/ext/_shared/squeezebox/server.py:26 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "Squeezebox server na {hostname}:{port}" #: quodlibet/ext/_shared/squeezebox/server.py:28 msgid "unidentified Squeezebox server" msgstr "neidentifikovani Squeezebox server" #: quodlibet/ext/_shared/squeezebox/server.py:37 #, 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:20 #: quodlibet/ext/songsmenu/importexport.py:39 quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "_U redu" #: 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:331 msgid "Fit image to _window" msgstr "Uklopi sliku u _prozor" #: quodlibet/ext/songsmenu/albumart.py:337 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:343 msgid "_Program:" msgstr "_Program:" #: quodlibet/ext/songsmenu/albumart.py:348 msgid "_Edit image after saving" msgstr "_Uredi sliku nakon čuvanja" #: quodlibet/ext/songsmenu/albumart.py:350 msgid "File_name:" msgstr "Ime _datoteke:" #: quodlibet/ext/songsmenu/albumart.py:466 msgid "Saving failed" msgstr "Neuspešno čuvanje" #: quodlibet/ext/songsmenu/albumart.py:467 #, python-format msgid "Unable to save \"%s\"." msgstr "Ne mogu da sačuvam \"%s\"." #: quodlibet/ext/songsmenu/albumart.py:565 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "[albumart] HTTP greška: %s" #: quodlibet/ext/songsmenu/albumart.py:622 msgid "Album Art Downloader" msgstr "Preuzimač omota" #: quodlibet/ext/songsmenu/albumart.py:675 #, python-format msgid "from %(source)s" msgstr "iz %(source)s" #: quodlibet/ext/songsmenu/albumart.py:678 #, python-format msgid "Resolution: %s" msgstr "Rezolucija: %s" #: quodlibet/ext/songsmenu/albumart.py:681 #, python-format msgid "Size: %s" msgstr "Veličina: %s" #: quodlibet/ext/songsmenu/albumart.py:727 msgid "Per engine 'at best' results limit" msgstr "Po pokretaču \"najbolji\" rezultat ograničenje" #: quodlibet/ext/songsmenu/albumart.py:737 msgid "_Search" msgstr "_Pretraga" #: quodlibet/ext/songsmenu/albumart.py:819 #: quodlibet/ext/songsmenu/brainz/widgets.py:451 msgid "Searching…" msgstr "Tražim…" #: quodlibet/ext/songsmenu/albumart.py:884 #: quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "Završeno" #: quodlibet/ext/songsmenu/albumart.py:1006 msgid "Download Album Art" msgstr "Preuzmi omot albuma" #: quodlibet/ext/songsmenu/albumart.py:1007 msgid "Downloads album covers from various websites." msgstr "Preuzima omote albuma sa različitih internet adresa." #: quodlibet/ext/songsmenu/albumart.py:1020 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 msgid "Disc" msgstr "Disk" #: quodlibet/ext/songsmenu/brainz/widgets.py:131 #: quodlibet/ext/songsmenu/replaygain.py:393 quodlibet/qltk/tracknumbers.py:91 msgid "Track" msgstr "Zapis" #: quodlibet/ext/songsmenu/brainz/widgets.py:132 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:447 msgid "Please enter a query." msgstr "Molimo upišite upit." #: quodlibet/ext/songsmenu/brainz/widgets.py:465 #: quodlibet/ext/songsmenu/brainz/widgets.py:496 msgid "Error encountered. Please retry." msgstr "Došlo je do greške. Pokušajte ponovo." #: quodlibet/ext/songsmenu/brainz/widgets.py:472 #: quodlibet/ext/songsmenu/brainz/widgets.py:488 msgid "Loading result…" msgstr "Učitavam rezultate…" #: quodlibet/ext/songsmenu/brainz/widgets.py:475 msgid "No results found." msgstr "Nema rezultata." #: quodlibet/ext/songsmenu/console.py:40 msgid "Python Console" msgstr "Python konzola" #: quodlibet/ext/songsmenu/console.py:41 msgid "Interactive Python console. Opens a new window." msgstr "Interaktivna Python konzola. Otvara novi prozor." #: quodlibet/ext/songsmenu/console.py:48 #, python-brace-format msgid "{plugin_name} for {songs} ({app})" msgstr "{plugin_name} za {songs} ({app})" #: quodlibet/ext/songsmenu/console.py:55 msgid "Python Console Sidebar" msgstr "Python konzola bočna stranica" #: quodlibet/ext/songsmenu/console.py:56 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:75 msgid "You can access the following objects by default:" msgstr "Možete pristupiti sledećim podrazumevanim objektima:" #: quodlibet/ext/songsmenu/console.py:85 msgid "Your current working directory is:" msgstr "Vaš trenutni radni direktorijum je:" #: quodlibet/ext/songsmenu/cover_download.py:119 msgid "Classic" msgstr "Klasično" #: quodlibet/ext/songsmenu/cover_download.py:120 msgid "Large" msgstr "Veliko" #: quodlibet/ext/songsmenu/cover_download.py:121 msgid "HD" msgstr "HD" #: quodlibet/ext/songsmenu/cover_download.py:122 msgid "Full HD" msgstr "Full HD" #: quodlibet/ext/songsmenu/cover_download.py:123 msgid "WQXGA" msgstr "WQXGA" #: quodlibet/ext/songsmenu/cover_download.py:124 msgid "4K UHD" msgstr "4K UHD" #: quodlibet/ext/songsmenu/cover_download.py:129 msgid "Cover Art Download" msgstr "Omot preuzimanje" #: quodlibet/ext/songsmenu/cover_download.py:180 #, python-format msgid "Loading %(source)s - %(dimensions)s…" msgstr "Učitavam %(source)s - %(dimensions)s…" #: quodlibet/ext/songsmenu/cover_download.py:231 #, python-format msgid "" "Nothing found for albums:\n" "<i>%(albums)s</i>.\n" "\n" "Providers used:\n" "<tt>%(providers)s</tt>" 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:234 msgid "No covers found" msgstr "Nema pronađenih omota" #: quodlibet/ext/songsmenu/cover_download.py:254 #, python-format msgid "%(size)d ✕ %(size)d px" msgstr "%(size)d ✕ %(size)d px" #: quodlibet/ext/songsmenu/cover_download.py:267 msgid "Preview size" msgstr "Veličina pregleda" #: quodlibet/ext/songsmenu/cover_download.py:276 msgid "Save destination" msgstr "Odredište čuvanja" #: quodlibet/ext/songsmenu/cover_download.py:336 msgid "Download Cover Art" msgstr "Preuzimanje omota" #: quodlibet/ext/songsmenu/cover_download.py:337 msgid "Downloads high-quality album covers using cover plugins." msgstr "Preuzima omote visokog kvaliteta koristeći dodatak omota." #: 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:55 msgid "pattern" msgstr "šablon" #: 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:91 msgid "Input value" msgstr "Vrednost ulaza" #: quodlibet/ext/songsmenu/custom_commands.py:92 #, python-format msgid "Value for %s?" msgstr "Vrednost za %s?" #: quodlibet/ext/songsmenu/custom_commands.py:137 msgid "Custom Commands" msgstr "Prilagođene komande" #: quodlibet/ext/songsmenu/custom_commands.py:138 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:197 #: quodlibet/ext/songsmenu/custom_commands.py:207 #: quodlibet/ext/songsmenu/custom_commands.py:259 msgid "Edit Custom Commands" msgstr "Uredi prilagođene komande" #: quodlibet/ext/songsmenu/custom_commands.py:290 #, 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:397 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:399 msgid "_Group duplicates by:" msgstr "_Grupiše duplikate po:" #: quodlibet/ext/songsmenu/duplicates.py:404 msgid "Duplicate Key" msgstr "Duplikat ključ" #: quodlibet/ext/songsmenu/duplicates.py:409 msgid "Remove _Whitespace" msgstr "Ukloni _beo prostor" #: quodlibet/ext/songsmenu/duplicates.py:410 msgid "Remove _Diacritics" msgstr "Ukoni _dijakritike" #: quodlibet/ext/songsmenu/duplicates.py:411 msgid "Remove _Punctuation" msgstr "Ukoni _interpunkcije" #: quodlibet/ext/songsmenu/duplicates.py:412 msgid "Case _Insensitive" msgstr "Slovo _neosetljivo" #: quodlibet/ext/songsmenu/duplicates.py:420 msgid "Matching options" msgstr "Opcije podudaranja" #. Create a dialog. #: quodlibet/ext/songsmenu/editplaycount.py:19 #: quodlibet/ext/songsmenu/editplaycount.py:41 msgid "Edit Playcount" msgstr "Uredi broj puštanja" #: quodlibet/ext/songsmenu/editplaycount.py:20 msgid "" "Edit a song's ~#playcount and ~#skipcount.\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's ~#playcount to 0, the ~#lastplayed and ~#laststarted " "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:68 msgid "Play Count" msgstr "Broj puštanja" #: quodlibet/ext/songsmenu/editplaycount.py:69 msgid "Skip Count" msgstr "Broj preskakanja" #: quodlibet/ext/songsmenu/embedded.py:25 msgid "Edit Embedded Images" msgstr "Uredi ugrađene slike" #: quodlibet/ext/songsmenu/embedded.py:26 msgid "Removes or replaces embedded images." msgstr "Uklanja ili zamenjuje ugrađene slike." #: quodlibet/ext/songsmenu/embedded.py:81 msgid "_Remove all Images" msgstr "_Ukloni sve slike" #: quodlibet/ext/songsmenu/embedded.py:85 msgid "_Embed Current Image" msgstr "_Ugradi trenutnu sliku" #: 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/exact_rating.py:54 quodlibet/qltk/ratingsmenu.py:98 msgid "Change _Rating" msgstr "Promeni _ocenu" #: 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" #: quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" msgstr "Status" #. 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:65 quodlibet/ext/songsmenu/html.py:75 msgid "Export to HTML" msgstr "Izvezi u HTML" #: quodlibet/ext/songsmenu/html.py:66 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:62 msgid "Error uploading" msgstr "Greška pri slanju" #: quodlibet/ext/songsmenu/ifp.py:63 #, python-format msgid "" "Unable to upload <b>%s</b>. 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/importexport.py:60 msgid "Export Metadata" msgstr "Izvezi metapodatke" #: quodlibet/ext/songsmenu/importexport.py:61 msgid "Exports metadata of selected songs as a .tags file." msgstr "Izvozi metapodatke odabranih pesama kao .tags datoteku." #: quodlibet/ext/songsmenu/importexport.py:105 msgid "Import Metadata" msgstr "Uvezi metapodatke" #: quodlibet/ext/songsmenu/importexport.py:106 msgid "Imports metadata for selected songs from a .tags file." msgstr "Uvozi metapodatke odabranih pesama iz .tags datoteke." #: quodlibet/ext/songsmenu/k3b.py:23 msgid "Burn CD" msgstr "Nareži CD" #: quodlibet/ext/songsmenu/k3b.py:24 msgid "Burns CDs with K3b, Brasero or xfburn." msgstr "Upisuje na CD koristeći k3b, Brasero ili xfburn." #: quodlibet/ext/songsmenu/lastfmsync.py:97 msgid "Updating chart list." msgstr "Ažuriram listu obrazaca." #. No charts to fetch, no update scheduled. #: quodlibet/ext/songsmenu/lastfmsync.py:116 msgid "Already up-to-date." msgstr "Već je ažurirano." #: quodlibet/ext/songsmenu/lastfmsync.py:124 #, python-format msgid "Fetching chart for week of %s." msgstr "Skupljam obrasce za nedelju %s." #: quodlibet/ext/songsmenu/lastfmsync.py:146 msgid "Sync complete." msgstr "Sinhrnoizacija završena." #: quodlibet/ext/songsmenu/lastfmsync.py:152 msgid "Error during sync" msgstr "Greška pri sinhronizaciji" #: quodlibet/ext/songsmenu/lastfmsync.py:217 #: quodlibet/ext/songsmenu/lastfmsync.py:247 msgid "Last.fm Sync" msgstr "Last.fm Sinhronizacija" #: quodlibet/ext/songsmenu/lastfmsync.py:248 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:301 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." #. Create a dialog. #: quodlibet/ext/songsmenu/migratemetadata.py:36 #: quodlibet/ext/songsmenu/migratemetadata.py:45 msgid "Migrate Metadata" msgstr "Premesti metapodatke" #: quodlibet/ext/songsmenu/migratemetadata.py:39 msgid "Copies the quodlibet-specific metadata between songs." msgstr "Kopira quodlibet metapodatke između pesama." #: quodlibet/ext/songsmenu/migratemetadata.py:52 msgid "_Copy" msgstr "_Umnoži" #: quodlibet/ext/songsmenu/migratemetadata.py:54 msgid "_Paste" msgstr "_Ubaci" #. Create the tag table. #: quodlibet/ext/songsmenu/migratemetadata.py:64 msgid "Information to copy/paste" msgstr "Informacija za umnožavanje/ubacivanje" #. Create the indexing box. #: quodlibet/ext/songsmenu/migratemetadata.py:86 msgid "Map tracks by disc and track number" msgstr "Mapira zapise po disku i broju zapisa" #: quodlibet/ext/songsmenu/migratemetadata.py:87 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." #: quodlibet/ext/songsmenu/migratemetadata.py:103 #, python-format 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." #: quodlibet/ext/songsmenu/playlist.py:31 msgid "Export as Playlist" msgstr "Izvezi kao listu izvođenja" #: quodlibet/ext/songsmenu/playlist.py:32 msgid "Exports songs to an M3U or PLS playlist." msgstr "Izvozi pesme u M3U ili PLS listu izvođenja." #: quodlibet/ext/songsmenu/playlist.py:77 msgid "Use relative paths" msgstr "Koristi relativne putanje" #: quodlibet/ext/songsmenu/playlist.py:77 msgid "Use absolute paths" msgstr "Koristi apsolutne putanje" #: quodlibet/ext/songsmenu/playlist.py:133 #, python-format msgid "Writing to <b>%s</b> 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č" #: quodlibet/ext/songsmenu/replaygain.py:407 msgid "Progress" msgstr "Napredak" #: quodlibet/ext/songsmenu/replaygain.py:422 msgid "Gain" msgstr "Gain" #: quodlibet/ext/songsmenu/replaygain.py:437 msgid "Peak" msgstr "Peak" #: quodlibet/ext/songsmenu/replaygain.py:452 #, python-format msgid "There is <b>%(to-process)s</b> album to update (of %(all)s)" msgid_plural "There are <b>%(to-process)s</b> 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:568 msgid "Replay Gain" msgstr "Replay Gain" #: quodlibet/ext/songsmenu/replaygain.py:569 msgid "" "Analyzes and updates ReplayGain information, using GStreamer. Results are " "grouped by album." msgstr "" "Ispituje i ažurira ReplayGain informacije koristeći GStreamer. Rezultati su " "grupisani po albumu." #: quodlibet/ext/songsmenu/replaygain.py:607 msgid "always" msgstr "uvek" #: quodlibet/ext/songsmenu/replaygain.py:608 msgid "if <b>any</b> RG tags are missing" msgstr "ako nedostaju <b>any</b> RG oznake" #: quodlibet/ext/songsmenu/replaygain.py:610 msgid "if <b>album</b> RG tags are missing" msgstr "ako nedostaju <b>album</b> RG oznake" #: quodlibet/ext/songsmenu/replaygain.py:627 msgid "_Process albums:" msgstr "_Obrada albuma:" #. Server settings Frame #: quodlibet/ext/songsmenu/replaygain.py:639 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 msgid "Tap BPM for the selected song." msgstr "Tap BPM za odabranu pesmu." #: quodlibet/ext/songsmenu/website_search.py:37 msgid "Website Search" msgstr "Pretraži veb" #: 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-example)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:80 msgid "Search URL patterns" msgstr "Pretraga URL šablona" #: quodlibet/ext/songsmenu/website_search.py:90 msgid "Edit search URLs" msgstr "Uredi pretragu URL-a" #. Add link to editor #: quodlibet/ext/songsmenu/website_search.py:116 msgid "Configure Searches…" msgstr "Konfiguriši pretragu…" #: quodlibet/ext/songsmenu/wikipedia.py:35 msgid "Search Tag in Wikipedia" msgstr "Pretraži oznaku u Vikipediji" #: quodlibet/ext/songsmenu/wikipedia.py:36 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:56 #, python-format msgid "Search at %(website)s" msgstr "Potraži na %(website)s" #: quodlibet/ext/songsmenu/wikipedia.py:70 #: quodlibet/ext/songsmenu/wikipedia.py:76 quodlibet/qltk/edittags.py:443 msgid "Edit Tags" msgstr "Uredi oznake" #: quodlibet/ext/songsmenu/wikipedia.py:111 msgid "Search failed" msgstr "Pretraga nije uspela" #: quodlibet/ext/songsmenu/wikipedia.py:112 #, python-format msgid "Tag \"%s\" not found." msgstr "Oznaka \"%s\" nije nađena." #. then (try to) load all new files #: quodlibet/library/libraries.py:651 quodlibet/library/libraries.py:661 #: quodlibet/library/libraries.py:727 quodlibet/library/libraries.py:746 #: quodlibet/qltk/information.py:272 quodlibet/qltk/prefs.py:692 #: quodlibet/util/library.py:123 msgid "Library" msgstr "Biblioteka" #: quodlibet/library/libraries.py:651 msgid "Checking mount points" msgstr "Proveravam priključne tačke" #: quodlibet/library/libraries.py:661 msgid "Scanning library" msgstr "Pretraga biblioteke" #: quodlibet/library/libraries.py:726 #, python-format msgid "Scanning %s" msgstr "Pretraga %s" #: quodlibet/library/libraries.py:746 msgid "Loading files" msgstr "Učitavam datoteke" #: quodlibet/main.py:50 msgid "Music player and music library manager" msgstr "Muzički plejer i organizator biblioteke" #: quodlibet/operon/base.py:70 #, 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:462 msgid "Print terse output" msgstr "Štampaj sažet izlaz" #: quodlibet/operon/commands.py:43 quodlibet/operon/commands.py:82 #: quodlibet/operon/commands.py:464 #, 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:336 quodlibet/operon/commands.py:340 #: quodlibet/operon/commands.py:392 quodlibet/operon/commands.py:395 #: quodlibet/operon/commands.py:434 quodlibet/operon/commands.py:469 #: quodlibet/operon/commands.py:509 quodlibet/operon/commands.py:544 #: quodlibet/operon/commands.py:586 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:471 msgid "Too many arguments" msgstr "Previše argumenata" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:91 #: quodlibet/operon/commands.py:476 quodlibet/qltk/data_editors.py:352 msgid "Description" msgstr "Opis" #: quodlibet/operon/commands.py:55 quodlibet/operon/commands.py:476 #: quodlibet/qltk/edittags.py:493 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:324 #: quodlibet/operon/commands.py:385 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:304 quodlibet/operon/commands.py:445 #: quodlibet/operon/commands.py:677 #, python-format msgid "Can not set %r" msgstr "Ne mogu postaviti %r" #: quodlibet/operon/commands.py:319 msgid "Remove tags" msgstr "Ukloni oznake" #: quodlibet/operon/commands.py:326 quodlibet/operon/commands.py:387 msgid "Value is a regular expression" msgstr "Vrednost je običan izraz" #: quodlibet/operon/commands.py:328 msgid "Remove all tags" msgstr "Ukoni sve oznake" #: quodlibet/operon/commands.py:332 msgid "Can't combine '--all' with '--regexp'" msgstr "Ne mogu da kombinujem '--all' sa '--regexp'" #: quodlibet/operon/commands.py:366 #, python-brace-format msgid "Can't remove {tagname} from {filename}" msgstr "Ne mogu ukloniti {tagname} iz {filename}" #: quodlibet/operon/commands.py:380 msgid "Remove a tag value" msgstr "Ukloni vrednost oznake" #: quodlibet/operon/commands.py:429 msgid "Add a tag value" msgstr "Dodaj vrednost oznake" #: quodlibet/operon/commands.py:457 msgid "List file information" msgstr "Izlistaj informacije o datoteci" #: quodlibet/operon/commands.py:503 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:516 #, python-format msgid "Failed to load image file: %r" msgstr "Neuspešno učitavanje slike: %r" #: quodlibet/operon/commands.py:523 quodlibet/operon/commands.py:552 #, 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:539 msgid "Remove all embedded images" msgstr "Ukoni sve ugrađene slike" #: quodlibet/operon/commands.py:569 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "Izvezi ugrađene slike na %(filepath)s" #: quodlibet/operon/commands.py:581 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:640 msgid "Rename files based on tags" msgstr "Preimenuj datoteke koristeći oznake" #: quodlibet/operon/commands.py:655 msgid "Fill tags based on the file path" msgstr "Ispuni oznake koristeći putanju datoteke" #: quodlibet/operon/commands.py:705 quodlibet/qltk/information.py:309 #: quodlibet/qltk/properties.py:83 quodlibet/qltk/renamefiles.py:224 #: quodlibet/qltk/tagsfrompath.py:228 quodlibet/qltk/tracknumbers.py:78 msgid "File" msgstr "Datoteka" #: quodlibet/operon/commands.py:713 msgid "Fill tracknumbers for all files" msgstr "Ispuni broj pesme za sve datoteke" #: quodlibet/operon/commands.py:732 msgid "Print tags based on the given pattern" msgstr "Štampaj oznake po određenom šablonu" #: quodlibet/operon/commands.py:769 msgid "Display help information" msgstr "Prikaži pomoćne informacije" #: quodlibet/operon/util.py:43 #, 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:30 msgid "_Unknown" msgstr "_Nepoznato" #: quodlibet/order/__init__.py:142 msgid "In Order" msgstr "Po redu" #: quodlibet/order/__init__.py:143 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:147 msgid "_Random" msgstr "_Nasumično" #: quodlibet/order/reorder.py:40 quodlibet/order/reorder.py:41 msgid "Prefer higher rated" msgstr "Preferiraj bolje ocenjene" #: quodlibet/order/repeat.py:43 quodlibet/order/repeat.py:44 msgid "Repeat this track" msgstr "Ponovi ovaj zapis" #: quodlibet/order/repeat.py:57 quodlibet/order/repeat.py:58 msgid "Repeat all" msgstr "Ponovi sve" #: quodlibet/order/repeat.py:73 quodlibet/order/repeat.py:74 msgid "One Song" msgstr "Jedna pesma" #: quodlibet/player/gstbe/player.py:98 msgid "Stream" msgstr "Strim" #: quodlibet/player/gstbe/player.py:98 msgid "Buffering" msgstr "Punjenje memorije" #: quodlibet/player/gstbe/player.py:452 msgid "Could not create GStreamer pipeline" msgstr "Ne mogu stvoriti GStreamer pipeline" #: quodlibet/player/gstbe/player.py:651 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:652 #, 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:25 msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. In case 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:36 msgid "_Output pipeline:" msgstr "_Output pipeline:" #: quodlibet/player/gstbe/prefs.py:43 #, python-format msgid "%.1f seconds" msgstr "%.1f sekundi" #: quodlibet/player/gstbe/prefs.py:57 msgid "_Buffer duration:" msgstr "_Buffer duration:" #: quodlibet/player/gstbe/prefs.py:66 msgid "Disable _gapless playback" msgstr "Onemogući _gapless reprodukciju" #: quodlibet/player/gstbe/prefs.py:70 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/util.py:101 msgid "No GStreamer audio sink found" msgstr "Nema nađenog GStreamer audio sink" #: quodlibet/player/gstbe/util.py:120 msgid "Invalid GStreamer output pipeline" msgstr "Nevažeća GStreamer izlazna pipeline" #: quodlibet/player/xinebe/player.py:90 msgid "Unable to create audio output" msgstr "Ne mogu da kreiram audio izlaz" #: quodlibet/player/xinebe/player.py:91 #, 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:61 #, 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:70 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "Ne mogu pronaći GStreamer element '{element}'." #: 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:55 #: quodlibet/qltk/songsmenu.py:66 msgid "_Run Plugin" msgstr "_Pokreni dodatak" #. 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:40 msgid "_Name:" msgstr "_Ime:" #: quodlibet/qltk/cbes.py:48 quodlibet/qltk/edittags.py:350 msgid "_Value:" msgstr "Vrednost:" #: quodlibet/qltk/cbes.py:263 msgid "Saved Values" msgstr "Sačuvane vrednosti" #: quodlibet/qltk/cbes.py:264 msgid "Edit saved values…" msgstr "Uredi sačuvane vrednosti…" #: quodlibet/qltk/controls.py:111 msgid "Auto_matic" msgstr "Auto_matski" #: quodlibet/qltk/controls.py:112 msgid "_Track Mode" msgstr "_Režim zapisa" #: quodlibet/qltk/controls.py:113 msgid "_Album Mode" msgstr "_Režim albuma" #. Translators: player state, no action #: quodlibet/qltk/controls.py:122 msgid "_Mute" msgstr "_Utišaj" #: quodlibet/qltk/controls.py:128 msgid "_Replay Gain Mode" msgstr "_Replay Gain Režim" #. Translators: New Command/Entry/Item/... #: quodlibet/qltk/data_editors.py:116 #, python-format msgid "New %s" msgstr "Nov %s" #: quodlibet/qltk/data_editors.py:215 msgid "(unknown)" msgstr "(nepoznato)" #: quodlibet/qltk/data_editors.py:344 msgid "Tag expression" msgstr "Izraz oznake" #: quodlibet/qltk/data_editors.py:371 msgid "Tag expression e.g. people:real or ~album~year" msgstr "Izraz oznake npr. people:real ili ~album~year" #: quodlibet/qltk/data_editors.py:372 msgid "Enter new tag" msgstr "Upiši novu oznaku" #: 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/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:197 msgid "Split into _Multiple Values" msgstr "Odvoji u _višestruke vrednosti" #: quodlibet/qltk/edittags.py:219 msgid "Split Disc out of _Album" msgstr "Odvoji disk od _albuma" #: quodlibet/qltk/edittags.py:243 msgid "Split _Version out of Title" msgstr "Odvoji _verziju od naziva" #: quodlibet/qltk/edittags.py:298 msgid "Split Arranger out of Ar_tist" msgstr "Odvoji aranžera od Um_etnika" #: quodlibet/qltk/edittags.py:303 msgid "Split _Performer out of Artist" msgstr "Odvoji _izvođača od umetnika" #: quodlibet/qltk/edittags.py:309 msgid "Split _Performer out of Title" msgstr "Odvoji _izvođača od naziva" #: quodlibet/qltk/edittags.py:315 msgid "Split _Originalartist out of Title" msgstr "Odvoji _izvornog umetnika od naziva" #: quodlibet/qltk/edittags.py:322 msgid "Add a Tag" msgstr "Dodaj oznaku" #: quodlibet/qltk/edittags.py:341 msgid "_Tag:" msgstr "_Oznaka:" #: quodlibet/qltk/edittags.py:516 msgid "Show _programmatic tags" msgstr "Prikaži _pragmatične oznake" #: quodlibet/qltk/edittags.py:517 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" #. Translators: Revert button in the tag editor #: quodlibet/qltk/edittags.py:547 msgctxt "edittags" msgid "_Revert" msgstr "_Vrati" #. Translators: Save button in the tag editor #: quodlibet/qltk/edittags.py:552 msgctxt "edittags" msgid "_Save" msgstr "_Sačuvaj" #: quodlibet/qltk/edittags.py:681 msgid "_Configure" msgstr "_Podesi" #: quodlibet/qltk/edittags.py:696 msgid "_Split Tag" msgstr "_Razdvoji oznake" #: quodlibet/qltk/edittags.py:705 msgid "_Copy Value(s)" msgstr "_Umnoži vrednost(i)" #: quodlibet/qltk/edittags.py:736 msgid "Unable to add tag" msgstr "Ne mogu dodati oznaku" #: quodlibet/qltk/edittags.py:737 #, python-format msgid "Unable to add <b>%s</b>" msgstr "Ne mogu dodati <b>%s</b>" #: quodlibet/qltk/edittags.py:739 #, python-format msgid "" "The files currently selected do not support multiple values for <b>%s</b>." msgstr "" "Trenutno odabrane datoteke ne podržavaju višestruke vrednosti za <b>%s</b>." #. Can't add the new tag. #: quodlibet/qltk/edittags.py:766 quodlibet/qltk/edittags.py:947 #: quodlibet/qltk/tagsfrompath.py:211 quodlibet/util/__init__.py:505 #: quodlibet/util/tags.py:243 msgid "Invalid tag" msgstr "Nevažeća oznaka" #: quodlibet/qltk/edittags.py:767 quodlibet/qltk/edittags.py:948 #: quodlibet/qltk/tagsfrompath.py:212 #, python-format msgid "" "Invalid tag <b>%s</b>\n" "\n" "The files currently selected do not support editing this tag." msgstr "" "Nevažeća oznaka <b>%s</b>\n" "\n" "Trenutno odabrana datoteka ne podržava ovu oznaku." #: quodlibet/qltk/edittags.py:918 quodlibet/qltk/edittags.py:959 msgid "Invalid value" msgstr "Nevažeća vrednost" #: quodlibet/qltk/edittags.py:919 quodlibet/qltk/edittags.py:960 #, python-format msgid "" "Invalid value: <b>%(value)s</b>\n" "\n" "%(error)s" msgstr "" "Nevažeća vrednost: <b>%(value)s</b>\n" "\n" "%(error)s" #: quodlibet/qltk/_editutils.py:29 msgid "Tag may not be accurate" msgstr "Oznaka može biti neprecizna" #: quodlibet/qltk/_editutils.py:32 #, 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:48 msgid "Unable to save song" msgstr "Ne mogu da sačuvam pesmu" #: quodlibet/qltk/_editutils.py:51 #, 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:143 msgid "_More options…" msgstr "_Više opcija…" #: quodlibet/qltk/entry.py:78 msgid "_Undo" msgstr "_Opozovi" #: quodlibet/qltk/entry.py:80 msgid "_Redo" msgstr "_Ponovi" #: quodlibet/qltk/exfalsowindow.py:94 quodlibet/qltk/quodlibetwindow.py:956 msgid "_About" msgstr "_O aplikaciji" #: quodlibet/qltk/exfalsowindow.py:98 quodlibet/qltk/quodlibetwindow.py:978 msgid "_Check for Updates…" msgstr "_Proveri dostupna ažuriranja…" #: quodlibet/qltk/exfalsowindow.py:104 quodlibet/qltk/quodlibetwindow.py:911 #: quodlibet/qltk/songsmenu.py:289 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:278 msgid "Ex Falso Preferences" msgstr "Ex Falso Postavke" #: quodlibet/qltk/exfalsowindow.py:284 quodlibet/qltk/prefs.py:666 msgid "Tag Editing" msgstr "Uređivanje oznaka" #: 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:386 msgid "Unable to create folder" msgstr "Ne mogu da stvorim fasciklu" #: quodlibet/qltk/filesel.py:403 msgid "Unable to delete folder" msgstr "Ne mogu da obrišem fasciklu" #: quodlibet/qltk/filesel.py:519 quodlibet/qltk/pluginwin.py:167 msgid "Songs" msgstr "Pesme" #. Translators: As in "by Artist Name" #: quodlibet/qltk/info.py:42 #, python-format msgid "by %s" msgstr "od %s" #: quodlibet/qltk/info.py:43 quodlibet/qltk/information.py:171 #: quodlibet/qltk/information.py:452 #, python-format msgid "Disc %s" msgstr "Disk %s" #: quodlibet/qltk/info.py:44 quodlibet/qltk/information.py:176 #, python-format msgid "Track %s" msgstr "Zapis %s" #: quodlibet/qltk/info.py:108 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:342 #: quodlibet/qltk/information.py:475 quodlibet/qltk/information.py:543 msgid "Information" msgstr "Informacije" #: quodlibet/qltk/information.py:127 msgid "Lyrics" msgstr "Tekst reči" #: quodlibet/qltk/information.py:188 quodlibet/qltk/information.py:400 #, python-format msgid "Produced by %s" msgstr "Izdato od %s" #: quodlibet/qltk/information.py:203 quodlibet/util/tags.py:85 msgid "artist" msgstr "umetnik" #: quodlibet/qltk/information.py:204 quodlibet/qltk/information.py:573 #: quodlibet/util/tags.py:85 msgid "artists" msgstr "umetnici" #. for backwards compat #: quodlibet/qltk/information.py:225 quodlibet/util/tags.py:96 #: quodlibet/util/tags.py:124 msgid "performers" msgstr "izvođači" #: quodlibet/qltk/information.py:239 quodlibet/qltk/information.py:252 #: quodlibet/qltk/songlistcolumns.py:276 msgid "Never" msgstr "Nikad" #: quodlibet/qltk/information.py:240 #, 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:258 quodlibet/util/tags.py:149 msgid "added" msgstr "dodato" #: quodlibet/qltk/information.py:259 quodlibet/util/tags.py:150 msgid "last played" msgstr "zadnje puštano" #: quodlibet/qltk/information.py:260 quodlibet/util/tags.py:160 msgid "plays" msgstr "svira" #: quodlibet/qltk/information.py:261 quodlibet/util/tags.py:161 msgid "skips" msgstr "preskače" #: quodlibet/qltk/information.py:262 quodlibet/util/tags.py:166 msgid "rating" msgstr "ocena" #: quodlibet/qltk/information.py:291 msgid "path" msgstr "putanja" #: quodlibet/qltk/information.py:292 quodlibet/util/tags.py:164 msgid "length" msgstr "dužina" #: quodlibet/qltk/information.py:293 msgid "format" msgstr "format" #: quodlibet/qltk/information.py:294 quodlibet/util/tags.py:174 msgid "codec" msgstr "kodek" #: quodlibet/qltk/information.py:295 quodlibet/util/tags.py:175 msgid "encoding" msgstr "enkodiranje" #: quodlibet/qltk/information.py:296 quodlibet/util/tags.py:171 msgid "bitrate" msgstr "učestalost bitova" #: quodlibet/qltk/information.py:297 quodlibet/util/tags.py:172 msgid "file size" msgstr "veličina datoteke" #: quodlibet/qltk/information.py:298 quodlibet/util/tags.py:159 msgid "modified" msgstr "izmenjeno" #: quodlibet/qltk/information.py:335 msgid "Additional" msgstr "Dodatno" #: quodlibet/qltk/information.py:387 #, 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:462 msgid "Track unavailable" msgstr "Zapis nedostupan" #: quodlibet/qltk/information.py:468 msgid "Track List" msgstr "Lista zapisa" #: quodlibet/qltk/information.py:500 quodlibet/qltk/information.py:590 #, 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:503 msgid "Selected Discography" msgstr "Odabrana doskografija" #: quodlibet/qltk/information.py:570 #, 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:598 quodlibet/util/tags.py:83 msgid "albums" msgstr "albumi" #: quodlibet/qltk/information.py:611 msgid "Total length:" msgstr "Ukupna dužina:" #: quodlibet/qltk/information.py:615 msgid "Total size:" msgstr "Ukupna veličina:" #: quodlibet/qltk/information.py:618 msgid "Files" msgstr "Datoteke" #: quodlibet/qltk/lyrics.py:36 msgid "_View online" msgstr "_Pregledaj na internetu" #: quodlibet/qltk/lyrics.py:64 msgid "No lyrics found for this song." msgstr "Nema pronađenog teksta za ovu pesmu." #: quodlibet/qltk/lyrics.py:75 msgid "Searching for lyrics…" msgstr "Tražim tekst…" #: 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/msg.py:41 msgid "Discard tag changes?" msgstr "Zanemari promene oznaka?" #: quodlibet/qltk/msg.py:42 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:55 quodlibet/qltk/prefs.py:628 #: quodlibet/qltk/prefs.py:635 quodlibet/qltk/textedit.py:63 #: quodlibet/qltk/tracknumbers.py:116 msgid "_Revert" msgstr "_Opozovi" #: quodlibet/qltk/msg.py:104 msgid "File exists" msgstr "Datoteka postoji" #: quodlibet/qltk/msg.py:106 #, python-format msgid "Replace %(file-name)s?" msgstr "Zameni %(file-name)s?" #: quodlibet/qltk/msg.py:112 msgid "_Replace File" msgstr "_Zameni datoteku" #: quodlibet/qltk/notif.py:182 msgid "Active tasks" msgstr "Aktivni zadaci" #: quodlibet/qltk/notif.py:188 #, python-format msgid "%d tasks running" msgstr "%d pokrenutih zadataka" #: quodlibet/qltk/playorder.py:256 msgid "Toggle shuffle mode" msgstr "Menjaj režim mešanja" #: quodlibet/qltk/playorder.py:272 msgid "Toggle repeat mode" msgstr "Menjaj režim ponavljanja" #: quodlibet/qltk/pluginwin.py:44 msgid "Plugin Errors" msgstr "Greške dodatka" #: quodlibet/qltk/pluginwin.py:124 msgid "Enabled" msgstr "Omogućeno" #: quodlibet/qltk/pluginwin.py:125 msgid "Disabled" msgstr "Onemogućeno" #: quodlibet/qltk/pluginwin.py:131 msgid "No category" msgstr "Bez kategorije" #: quodlibet/qltk/pluginwin.py:169 msgid "Events" msgstr "Događaji" #: quodlibet/qltk/pluginwin.py:170 msgid "Play Order" msgstr "Redosled izvođenja" #: quodlibet/qltk/pluginwin.py:171 msgid "Editing" msgstr "Uređivanje" #: quodlibet/qltk/pluginwin.py:173 msgid "Covers" msgstr "Omoti" #: quodlibet/qltk/pluginwin.py:309 msgid "No plugins found." msgstr "Dodaci nisu nađeni." #: quodlibet/qltk/pluginwin.py:358 msgid "Plugins" msgstr "Dodaci" #: quodlibet/qltk/pluginwin.py:382 msgid "Filter by plugin state / tag" msgstr "Filtriraj po stanju dodatka" #: quodlibet/qltk/pluginwin.py:388 msgid "Filter by plugin type" msgstr "Filtriraj po tipu dodatka" #: quodlibet/qltk/pluginwin.py:394 msgid "Filter by plugin name or description" msgstr "Filtriraj po imenu ili opisu dodatka" #: quodlibet/qltk/pluginwin.py:403 msgid "Show _Errors" msgstr "Prikaži _greške" #: quodlibet/qltk/prefs.py:45 msgid "_Disc" msgstr "_Disk" #: quodlibet/qltk/prefs.py:46 msgid "_Track" msgstr "_Zapis" #: quodlibet/qltk/prefs.py:47 msgid "Grou_ping" msgstr "Gru_pisanje" #: quodlibet/qltk/prefs.py:50 msgid "Al_bum" msgstr "Al_bum" #: quodlibet/qltk/prefs.py:55 msgid "_Filename" msgstr "_ime datoteke" #: quodlibet/qltk/prefs.py:57 msgid "_Length" msgstr "_Dužina" #: quodlibet/qltk/prefs.py:64 msgid "_Jump to playing song automatically" msgstr "_Automatski skoči na puštenu pesmu" #: quodlibet/qltk/prefs.py:66 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:82 msgid "_Others:" msgstr "_Drugi:" #: quodlibet/qltk/prefs.py:88 msgid "_Edit…" msgstr "_Uredi…" #: quodlibet/qltk/prefs.py:91 msgid "Add or remove additional column headers" msgstr "Dodaj ili ukloni dodatna zaglavlja kolona" #: quodlibet/qltk/prefs.py:101 msgid "Visible Columns" msgstr "Vidljive kolone" #: quodlibet/qltk/prefs.py:104 msgid "Title includes _version" msgstr "Ime uključuje _verziju" #: quodlibet/qltk/prefs.py:106 msgid "Artist includes all _people" msgstr "Umetnik uključuje sve _ljude" #: quodlibet/qltk/prefs.py:108 msgid "Album includes _disc subtitle" msgstr "Album uključuje _disk podnatpis" #: quodlibet/qltk/prefs.py:110 msgid "Filename includes _folder" msgstr "Ime datoteke uključjue _fasciklu" #: quodlibet/qltk/prefs.py:123 msgid "Column Preferences" msgstr "Postavke kolone" #: quodlibet/qltk/prefs.py:129 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:142 quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Lista pesama" #: quodlibet/qltk/prefs.py:222 msgid "Edit Columns" msgstr "Uredi kolone" #: quodlibet/qltk/prefs.py:259 msgid "Duration totals" msgstr "Ukupno trajanje" #: quodlibet/qltk/prefs.py:271 msgid "_Global filter:" msgstr "_Globalni filter:" #: quodlibet/qltk/prefs.py:277 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:283 msgctxt "heading" msgid "Search" msgstr "Pretraga" #: quodlibet/qltk/prefs.py:287 quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Pretraživači" #: quodlibet/qltk/prefs.py:293 msgid "Confirm _multiple ratings" msgstr "Potvrdi _više ocena" #: quodlibet/qltk/prefs.py:295 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:298 msgid "Enable _one-click ratings" msgstr "Omogući _jedan-klik ocene" #: quodlibet/qltk/prefs.py:300 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:306 quodlibet/qltk/prefs.py:669 msgid "Ratings" msgstr "Ocene" #. Filename choice algorithm config #: quodlibet/qltk/prefs.py:312 msgid "Prefer _embedded art" msgstr "Preferiraj _ugrađeni omot" #: quodlibet/qltk/prefs.py:314 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:319 msgid "_Fixed image filename:" msgstr "_Fiksirano ime slike:" #: quodlibet/qltk/prefs.py:321 msgid "The single image filename to use if selected" msgstr "Jedinstveno ime slike za korišćenje ako je odabrano" #: quodlibet/qltk/prefs.py:327 msgid "The album art image file to use when forced (supports wildcards)" msgstr "Slika omota za korišćenje kada je prisiljeno" #: quodlibet/qltk/prefs.py:337 msgid "Album Art" msgstr "Omot albuma" #: quodlibet/qltk/prefs.py:358 msgid "Playback" msgstr "Reprodukcija" #: quodlibet/qltk/prefs.py:363 msgid "Output Configuration" msgstr "Konfiguracija izlaza" #: quodlibet/qltk/prefs.py:374 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:377 msgid "_Fall-back gain (dB):" msgstr "_Fall-back gain (dB):" #: quodlibet/qltk/prefs.py:388 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:391 msgid "_Pre-amp gain (dB):" msgstr "_Pre-amp gain (dB):" #: quodlibet/qltk/prefs.py:396 msgid "_Enable Replay Gain volume adjustment" msgstr "_Omogući Replay Gain promenu jačine" #: quodlibet/qltk/prefs.py:421 msgid "Replay Gain Volume Adjustment" msgstr "Replay Gain promena jačine" #: quodlibet/qltk/prefs.py:428 msgid "_Continue playback on startup" msgstr "_Nastavi reprodukciju pri pokretanju" #: quodlibet/qltk/prefs.py:430 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:434 msgid "Startup" msgstr "Pokretanje" #: quodlibet/qltk/prefs.py:461 msgid "_Default rating:" msgstr "_Podrazumevana ocena:" #: quodlibet/qltk/prefs.py:504 msgid "Rating _scale:" msgstr "Skala _ocena:" #: quodlibet/qltk/prefs.py:553 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:558 msgid "_Bayesian averaging amount:" msgstr "_Bayesian prosečna količina:" #: quodlibet/qltk/prefs.py:567 msgid "Save ratings and play _counts in tags" msgstr "Sačuvaj ocene i _broj puštanja u oznakama" #: quodlibet/qltk/prefs.py:575 msgid "_Email:" msgstr "_Imejl:" #: quodlibet/qltk/prefs.py:577 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:597 msgid "Auto-save tag changes" msgstr "Automatski sačuvaj promene ocena" #: quodlibet/qltk/prefs.py:599 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:608 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:618 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:631 msgid "Split _tag on:" msgstr "Podeli _oznake na:" #: quodlibet/qltk/prefs.py:638 msgid "Split _subtag on:" msgstr "Podeli _podoznake na:" #: quodlibet/qltk/prefs.py:663 msgid "Tags" msgstr "Oznake" #: quodlibet/qltk/prefs.py:684 msgid "Updating for new ratings" msgstr "Ažuriram za nove ocene" #: quodlibet/qltk/prefs.py:694 msgid "Scan library _on start" msgstr "Skeniraj biblioteku _pri pokretanju" #: quodlibet/qltk/prefs.py:704 quodlibet/qltk/quodlibetwindow.py:990 msgid "_Scan Library" msgstr "_Skeniraj biblioteku" #: quodlibet/qltk/prefs.py:706 quodlibet/qltk/quodlibetwindow.py:1052 msgid "Check for changes in your library" msgstr "Proveri promene u biblioteci" #: quodlibet/qltk/prefs.py:711 msgid "Re_build Library" msgstr "Ponovo _izgradi biblioteku" #: quodlibet/qltk/prefs.py:714 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:724 msgid "Scan Directories" msgstr "Skeniraj direktorijume" #: quodlibet/qltk/prefs.py:730 msgid "Hidden Songs" msgstr "Skrivene pesme" #: quodlibet/qltk/properties.py:157 quodlibet/util/collection.py:403 #, 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:104 msgid "_Queue" msgstr "_Niz" #: quodlibet/qltk/queue.py:124 msgid "Ephemeral" msgstr "Prolazan" #: quodlibet/qltk/queue.py:125 msgid "Remove songs from the queue after playing them" msgstr "Ukloni pesme iz niza posle reprodukcije" #: quodlibet/qltk/queue.py:133 msgid "Persistent" msgstr "Neprestano" #: quodlibet/qltk/queue.py:134 msgid "Keep songs in the queue after playing them" msgstr "Zadrži pesme u nizu nakon reprodukcije" #: quodlibet/qltk/queue.py:142 msgid "Mode" msgstr "Režim" #: quodlibet/qltk/queue.py:153 msgid "Stop at End" msgstr "Zaustavi na kraju" #: quodlibet/qltk/queue.py:157 msgid "_Clear Queue" msgstr "_Očisti niz" #: quodlibet/qltk/queue.py:178 msgid "Disable queue - the queue will be ignored when playing" msgstr "Onemogući niz - niz će biti zanemaren prilikom reprodukcije" #: quodlibet/qltk/queue.py:290 #, 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:198 msgid "_Browse Library" msgstr "_Pregledaj bibilioteku" #: quodlibet/qltk/quodlibetwindow.py:348 msgid "Toggle queue visibility" msgstr "Menja vidljivost niza" #: quodlibet/qltk/quodlibetwindow.py:376 msgid "Playback Error" msgstr "Greška pri reprodukciji" #: quodlibet/qltk/quodlibetwindow.py:384 msgid "Set up library directories?" msgstr "Dodaj direktorijum bibilioteke?" #: quodlibet/qltk/quodlibetwindow.py:385 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:391 msgid "_Not Now" msgstr "_Ne sad" #: quodlibet/qltk/quodlibetwindow.py:392 msgid "_Set Up" msgstr "_Dodaj" #: quodlibet/qltk/quodlibetwindow.py:845 msgid "Unable to add songs" msgstr "Ne mogu da dodam pesme" #: quodlibet/qltk/quodlibetwindow.py:846 quodlibet/qltk/quodlibetwindow.py:1286 #, python-format msgid "%s uses an unsupported protocol." msgstr "%s koristi nepodržan protokol." #: quodlibet/qltk/quodlibetwindow.py:869 msgid "_Jump to Playing Song" msgstr "_Skoči na puštenu pesmu" #: quodlibet/qltk/quodlibetwindow.py:876 msgid "_File" msgstr "_Datoteka" #: quodlibet/qltk/quodlibetwindow.py:877 msgid "_Song" msgstr "_Pesma" #: quodlibet/qltk/quodlibetwindow.py:878 msgid "_View" msgstr "_Pregled" #: quodlibet/qltk/quodlibetwindow.py:879 msgid "_Browse" msgstr "_Istraži" #: quodlibet/qltk/quodlibetwindow.py:880 msgid "_Control" msgstr "_Upravljaj" #: quodlibet/qltk/quodlibetwindow.py:881 msgid "_Help" msgstr "_Pomoć" #: quodlibet/qltk/quodlibetwindow.py:887 msgid "_Add a Folder…" msgstr "_Dodaj u fasciklu…" #: quodlibet/qltk/quodlibetwindow.py:892 msgid "_Add a File…" msgstr "_Dodaj datoteku…" #: quodlibet/qltk/quodlibetwindow.py:897 msgid "_Add a Location…" msgstr "_Dodaj lokaciju…" #: quodlibet/qltk/quodlibetwindow.py:926 msgid "Edit Bookmarks…" msgstr "Uredi obeleživače…" #: quodlibet/qltk/quodlibetwindow.py:946 msgid "Stop After This Song" msgstr "Zaustavi posle ove pesme" #: quodlibet/qltk/quodlibetwindow.py:952 msgid "_Keyboard Shortcuts" msgstr "_Prečice tastature" #: quodlibet/qltk/quodlibetwindow.py:961 msgid "Online Help" msgstr "Pomoć na mreži" #: quodlibet/qltk/quodlibetwindow.py:970 msgid "Search Help" msgstr "Potraži pomoć" #: quodlibet/qltk/quodlibetwindow.py:1274 msgid "Add a Location" msgstr "Dodaj lokaciju" #: quodlibet/qltk/quodlibetwindow.py:1275 msgid "Enter the location of an audio file:" msgstr "Unesi lokaciju audio datoteke:" #: quodlibet/qltk/quodlibetwindow.py:1280 #: quodlibet/qltk/quodlibetwindow.py:1285 msgid "Unable to add location" msgstr "Ne mogu da dodam lokaciju" #: quodlibet/qltk/quodlibetwindow.py:1281 #, python-format msgid "%s is not a valid location." msgstr "%s nije ispravna lokacija." #: quodlibet/qltk/quodlibetwindow.py:1294 #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "Add Music" msgstr "Dodaj muziku" #: quodlibet/qltk/quodlibetwindow.py:1294 quodlibet/qltk/scanbox.py:99 msgid "_Add Folders" msgstr "_Dodaj fascikle" #: quodlibet/qltk/quodlibetwindow.py:1301 msgid "Music Files" msgstr "Muzičke datoteke" #: quodlibet/qltk/quodlibetwindow.py:1303 msgid "_Add Files" msgstr "_Dodaj datoteke" #: quodlibet/qltk/ratingsmenu.py:24 #, 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:26 msgid "The saved ratings will be removed" msgstr "Sačuvane ocene će biti uklonjene" #: quodlibet/qltk/ratingsmenu.py:27 #, 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:57 quodlibet/qltk/ratingsmenu.py:111 msgid "_Remove Rating" msgstr "_Ukloni ocene" #: quodlibet/qltk/renamefiles.py:51 msgid "Replace spaces with _underscores" msgstr "Zameni prazan prostor sa _donjim crtama" #: quodlibet/qltk/renamefiles.py:61 msgid "Strip _Windows-incompatible characters" msgstr "Ukloni _Vindouz nekompatibilne karaktere" #: quodlibet/qltk/renamefiles.py:79 msgid "Strip _diacritical marks" msgstr "Ukoni _dijakritičke oznake" #: quodlibet/qltk/renamefiles.py:90 msgid "Strip non-_ASCII characters" msgstr "Ukloni ne-_ASCII karaktere" #: quodlibet/qltk/renamefiles.py:100 msgid "Use only _lowercase characters" msgstr "Koristi samo _mala slova" #: quodlibet/qltk/renamefiles.py:128 msgid "Rename Files" msgstr "Preimenuj datoteke" #: quodlibet/qltk/renamefiles.py:146 quodlibet/qltk/tagsfrompath.py:115 msgid "Path Patterns" msgstr "Šablon putanje" #: quodlibet/qltk/renamefiles.py:147 quodlibet/qltk/tagsfrompath.py:116 msgid "Edit saved patterns…" msgstr "Uredi saćuvane šablone…" #: quodlibet/qltk/renamefiles.py:150 quodlibet/qltk/tagsfrompath.py:119 #: quodlibet/qltk/tracknumbers.py:57 msgid "_Preview" msgstr "_Pregled" #: quodlibet/qltk/renamefiles.py:177 msgid "File names" msgstr "Imena datoteka" #: quodlibet/qltk/renamefiles.py:187 msgid "_Move album art" msgstr "_Pomeri omot albuma" #: quodlibet/qltk/renamefiles.py:190 msgid "See '[albumart] filenames' config entry for image search strings" msgstr "Vidite '[albumart] filenames' unos konfiguracije za pretragu slika" #: quodlibet/qltk/renamefiles.py:195 msgid "_Overwrite album art at target" msgstr "_Prepiši omot albuma po cilju" #: quodlibet/qltk/renamefiles.py:203 msgid "_Remove empty directories" msgstr "_Ukoni prazne direktorijume" #: quodlibet/qltk/renamefiles.py:209 msgid "Album art" msgstr "Omot albuma" #: quodlibet/qltk/renamefiles.py:238 msgid "New Name" msgstr "Novo ime" #: quodlibet/qltk/renamefiles.py:315 msgid "Unable to rename file" msgstr "Ne mogu da preimenujem datoteku" #: quodlibet/qltk/renamefiles.py:316 #, python-format msgid "" "Renaming <b>%(old-name)s</b> to <b>%(new-name)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." 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:324 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:325 quodlibet/qltk/wlw.py:49 msgid "_Stop" msgstr "_Zaustavi" #: quodlibet/qltk/renamefiles.py:327 msgid "_Continue" msgstr "_Nastavi" #: quodlibet/qltk/renamefiles.py:440 msgid "Path is not absolute" msgstr "Putanja nije apsolutna" #: quodlibet/qltk/renamefiles.py:441 #, python-format msgid "" "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 ~/." 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:47 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:99 msgid "Select Directories" msgstr "Odaberi direktorijume" #: quodlibet/qltk/searchbar.py:57 msgid "Saved Searches" msgstr "Sačuvana pretraga" #: quodlibet/qltk/searchbar.py:58 msgid "Edit saved searches…" msgstr "Uredi sačuvane pretrage…" #: quodlibet/qltk/searchbar.py:82 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:144 msgid "Search after _typing" msgstr "Traži nakon _kucanja" #: quodlibet/qltk/searchbar.py:147 msgid "Show search results after the user stops typing" msgstr "Pokazuje rezultate pretrage nakon što korisnik završi s kucanjem" #: quodlibet/qltk/searchbar.py:215 msgid "_Limit:" msgstr "_Ograničenje:" #: quodlibet/qltk/searchbar.py:228 msgid "_Weight" msgstr "_Značaj" #: quodlibet/qltk/searchbar.py:355 msgid "Add query" msgstr "Dodaj pitanje" #: quodlibet/qltk/searchbar.py:356 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:375 #, python-format msgid "_Filter on %s" msgstr "_Filtriraj po %s" #: quodlibet/qltk/songlist.py:1093 msgid "All _Headers" msgstr "Sva _zaglavlja" #: quodlibet/qltk/songlist.py:1094 msgid "_Track Headers" msgstr "_Zapis zaglavlje" #: quodlibet/qltk/songlist.py:1095 msgid "_Album Headers" msgstr "_Album zaglavlje" #: quodlibet/qltk/songlist.py:1096 msgid "_People Headers" msgstr "_Ljudi zaglavlje" #: quodlibet/qltk/songlist.py:1097 msgid "_Date Headers" msgstr "_Datum zaglavlje" #: quodlibet/qltk/songlist.py:1098 msgid "_File Headers" msgstr "_Datoteka zaglavlje" #: quodlibet/qltk/songlist.py:1099 msgid "_Production Headers" msgstr "_Produkcija zaglavlje" #: quodlibet/qltk/songlist.py:1114 msgid "_Customize Headers…" msgstr "_Prolagodi zaglavlje…" #: quodlibet/qltk/songlist.py:1119 msgid "_Expand Column" msgstr "_Proširi kolonu" #: quodlibet/qltk/songsmenu.py:40 #, python-format msgid "Remove track: \"%%(title)s\" from library?" msgid_plural "Remove %(count)d tracks from library?" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/qltk/songsmenu.py:46 msgid "Remove from Library" msgstr "Ukloni iz biblioteke" #: quodlibet/qltk/songsmenu.py:51 #, 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:62 #, 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:134 msgid "Configure Plugins…" msgstr "Podesi dodatke…" #: quodlibet/qltk/songsmenu.py:329 msgid "Add to _Queue" msgstr "Dodaj u _Niz" #: quodlibet/qltk/songsmenu.py:349 msgid "_Remove from Library…" msgstr "_Ukloni iz biblioteke…" #: quodlibet/qltk/songsmenu.py:414 msgid "Unable to show files" msgstr "Ne mogu da prikažem datoteke" #: quodlibet/qltk/songsmenu.py:415 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:422 #, python-format msgid "_Show in File Manager" msgid_plural "_Show %(total)d Files in File Manager" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: quodlibet/qltk/tagsfrompath.py:46 msgid "Replace _underscores with spaces" msgstr "Zameni _donje crte sa praznim prostorom" #: quodlibet/qltk/tagsfrompath.py:56 msgid "_Title-case tags" msgstr "_Veliko-slovo oznake" #: quodlibet/qltk/tagsfrompath.py:66 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 #, python-format msgid "" "The pattern\n" "\t<b>%s</b>\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/tagsfrompath.py:215 msgid "Invalid tags" msgstr "Nevažeće oznake" #: quodlibet/qltk/tagsfrompath.py:216 #, 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." #: 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:923 #, python-format msgid "and %d more…" msgstr "i %d još…" #: quodlibet/qltk/wlw.py:199 msgid "Saving the songs you changed." msgstr "Čuvam izmenjene pesme." #: quodlibet/qltk/wlw.py:200 #, 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:233 #, 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:425 msgid "Playlists must have a name" msgstr "Lista izvođenja mora imati ime" #: quodlibet/util/collection.py:608 #, python-format msgid "A playlist named %s already exists." msgstr "Lista izvođenja %s već postoji." #: quodlibet/util/cover/built_in.py:32 msgid "Embedded album covers" msgstr "Ugrađeni omoti albuma" #: quodlibet/util/cover/built_in.py:33 msgid "Uses covers embedded into audio files." msgstr "Koristi omote ugrađene u audio datoteke." #: quodlibet/util/cover/built_in.py:55 msgid "Filesystem cover" msgstr "Omoti fascikle" #: quodlibet/util/cover/built_in.py:56 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:76 msgid "Display brief usage information" msgstr "Prikaži ukratke informacije korišćenja" #: quodlibet/util/__init__.py:78 msgid "Display version and copyright" msgstr "Prikaži verziju i autorska prava" #: quodlibet/util/__init__.py:79 msgid "Print debugging information" msgstr "Odštampaj informacije ispravljanja grešaka" #: quodlibet/util/__init__.py:118 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "Korišćenje: %(program)s %(usage)s" #: quodlibet/util/__init__.py:120 msgid "[options]" msgstr "[opcije]" #: quodlibet/util/__init__.py:165 #, python-format msgid "Option %r not recognized." msgstr "Opcija %r nije prepoznata." #: quodlibet/util/__init__.py:168 #, python-format msgid "Option %r requires an argument." msgstr "Opcija %r zahteva argument." #: quodlibet/util/__init__.py:171 #, python-format msgid "%r is not a unique prefix." msgstr "%r nije jedinstven prefiks." #: quodlibet/util/__init__.py:347 #, python-format msgid "%d kbps" msgstr "%d kbps" #: quodlibet/util/__init__.py:402 #, 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:415 msgid "No time information" msgstr "Nema informacija o trajanju" #: quodlibet/util/__init__.py:418 #, 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:419 #, 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:420 #, 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:421 #, 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:422 #, 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:514 msgctxt "check" msgid "titlecase?" msgstr "ne" #: quodlibet/util/massagers.py:114 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:129 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:150 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:172 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:194 msgid "" "MusicBrainz release status must be 'official', 'promotional', or 'bootleg'." msgstr "" "MusicBrainz status izdanja mora biti 'official', 'promotional', ili " "'bootleg'." #: quodlibet/util/massagers.py:207 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:116 msgid "Unable to edit song" msgstr "Ne mogu urediti pesmu" #: quodlibet/util/songwrapper.py:117 #, python-format msgid "" "Saving <b>%s</b> 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:151 msgid "disc" msgstr "disk" #: quodlibet/util/tags.py:115 quodlibet/util/tags.py:153 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" #. 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:130 msgid "MusicBrainz recording ID" msgstr "MusicBrainz ID snimanja" #: quodlibet/util/tags.py:131 msgid "MusicBrainz release track ID" msgstr "MusicBrainz ID izdanja zapisa" #: quodlibet/util/tags.py:132 msgid "MusicBrainz release ID" msgstr "MusicBrainz ID izdanja" #: quodlibet/util/tags.py:133 msgid "MusicBrainz artist ID" msgstr "MusicBrainz ID umetnika" #: quodlibet/util/tags.py:134 msgid "MusicBrainz release artist ID" msgstr "MusicBrainz ID izdanja umetnika" #: quodlibet/util/tags.py:135 msgid "MusicBrainz TRM ID" msgstr "MusicBrainz TRM ID" #: quodlibet/util/tags.py:136 msgid "MusicIP PUID" msgstr "MusicIP PUID" #: quodlibet/util/tags.py:137 msgid "MusicBrainz album status" msgstr "MusicBrainz status albuma" #: quodlibet/util/tags.py:138 msgid "MusicBrainz album type" msgstr "MusicBrainz tip albuma" #: quodlibet/util/tags.py:139 msgid "MusicBrainz release group ID" msgstr "MusicBrainz ID izdanja grupe" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:142 msgid "track gain" msgstr "track gain" #: quodlibet/util/tags.py:143 msgid "track peak" msgstr "track peak" #. Translators: "gain" means a volume adjustment, not "to acquire". #: quodlibet/util/tags.py:145 msgid "album gain" msgstr "album gain" #: quodlibet/util/tags.py:146 msgid "album peak" msgstr "album peak" #: quodlibet/util/tags.py:147 msgid "reference loudness" msgstr "referenca jačine zvuka" #: quodlibet/util/tags.py:152 msgid "discs" msgstr "diskovi" #: quodlibet/util/tags.py:154 msgid "tracks" msgstr "zapisi" #: quodlibet/util/tags.py:155 msgid "last started" msgstr "zadnje pokretano" #: quodlibet/util/tags.py:156 msgid "full name" msgstr "puno ime" #: quodlibet/util/tags.py:163 msgid "mount point" msgstr "tačka kačenja" #: quodlibet/util/tags.py:165 msgid "people" msgstr "ljudi" #: quodlibet/util/tags.py:167 msgid "year" msgstr "godina" #: quodlibet/util/tags.py:168 msgid "original release year" msgstr "originalna godina izdanja" #: quodlibet/util/tags.py:169 msgid "bookmark" msgstr "obeleživač" #: quodlibet/util/tags.py:170 msgid "bitdepth" msgstr "dubina bita" #: quodlibet/util/tags.py:173 msgid "file format" msgstr "format datoteke" #: quodlibet/util/tags.py:176 msgid "playlists" msgstr "liste puštanja" #: quodlibet/util/tags.py:177 msgid "sample rate" msgstr "brzina uzorka" #: quodlibet/util/tags.py:178 msgid "channel count" msgstr "broj kanala" #. Translators: e.g. "artist (sort)" #: quodlibet/util/tags.py:268 msgid "sort" msgstr "razvrstaj" #. Translators: e.g. "performer (roles)" #: quodlibet/util/tags.py:276 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." �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9751859 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/po/sv.po����������������������������������������������������������������������������0000644�0001750�0001750�00000546666�00000000000�014133� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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: 2017-05-17 18:58+0200\n" "PO-Revision-Date: 2013-07-20 22:30+0100\n" "Last-Translator: Daniel Nyberg <p.daniel.nyberg@gmail.com>\n" "Language-Team: SWEDISH\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: Poedit 1.5.4\n" #: ../data/exfalso.appdata.xml.in.h:1 ../data/exfalso.desktop.in.h:2 msgid "Edit tags in your audio files" msgstr "Redigera taggar i ljudfiler" #: ../data/exfalso.appdata.xml.in.h:2 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/exfalso.appdata.xml.in.h:3 ../data/quodlibet.appdata.xml.in.h:3 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/exfalso.desktop.in.h:1 msgid "Audio tag editor" msgstr "Ljudtaggsredigerare" #: ../data/quodlibet.appdata.xml.in.h:1 ../data/quodlibet.desktop.in.h:2 msgid "Listen to, browse, or edit your audio collection" msgstr "Lyssna på, bläddra i eller redigera din ljudsamling" #: ../data/quodlibet.appdata.xml.in.h:2 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 "" #: ../data/quodlibet.desktop.in.h:1 msgid "Music Player" msgstr "Musikspelare" #: ../quodlibet/browsers/albums/main.py:168 #: ../quodlibet/browsers/covergrid/main.py:54 msgid "_Title" msgstr "_Titel" #: ../quodlibet/browsers/albums/main.py:169 #: ../quodlibet/browsers/covergrid/main.py:55 ../quodlibet/qltk/prefs.py:49 msgid "_Artist" msgstr "_Artist" #: ../quodlibet/browsers/albums/main.py:170 #: ../quodlibet/browsers/covergrid/main.py:56 ../quodlibet/qltk/prefs.py:54 msgid "_Date" msgstr "_Datum" #: ../quodlibet/browsers/albums/main.py:171 #: ../quodlibet/browsers/covergrid/main.py:57 ../quodlibet/qltk/prefs.py:53 msgid "_Genre" msgstr "_Genre" #: ../quodlibet/browsers/albums/main.py:172 #: ../quodlibet/browsers/covergrid/main.py:58 ../quodlibet/qltk/prefs.py:58 #: ../quodlibet/qltk/ratingsmenu.py:39 msgid "_Rating" msgstr "_Betyg" #: ../quodlibet/browsers/albums/main.py:178 #: ../quodlibet/browsers/covergrid/main.py:64 #, fuzzy msgid "Sort _by…" msgstr "Sortera _på..." #: ../quodlibet/browsers/albums/main.py:199 #: ../quodlibet/browsers/covergrid/main.py:85 #: ../quodlibet/browsers/paned/prefs.py:166 #: ../quodlibet/browsers/playlists/main.py:629 #: ../quodlibet/qltk/exfalsowindow.py:109 ../quodlibet/qltk/pluginwin.py:341 #: ../quodlibet/qltk/quodlibetwindow.py:1016 msgid "_Preferences" msgstr "_Inställningar" #: ../quodlibet/browsers/albums/main.py:361 msgid "Album List" msgstr "Albumlista" #: ../quodlibet/browsers/albums/main.py:362 msgid "_Album List" msgstr "_Albumlista" #: ../quodlibet/browsers/albums/main.py:472 #: ../quodlibet/browsers/covergrid/main.py:279 #: ../quodlibet/browsers/covergrid/main.py:488 msgid "All Albums" msgstr "Alla album" #: ../quodlibet/browsers/albums/main.py:473 #: ../quodlibet/browsers/covergrid/main.py:280 #: ../quodlibet/browsers/covergrid/main.py:489 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d album" msgstr[1] "%d album" #: ../quodlibet/browsers/albums/main.py:650 #: ../quodlibet/browsers/covergrid/main.py:467 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:381 ../quodlibet/util/collection.py:245 #, 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:379 ../quodlibet/util/collection.py:249 #, 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 #, fuzzy msgid "An Example Album" msgstr "Alla album" #: ../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:120 #, fuzzy msgid "Options" msgstr "[alternativ]" #: ../quodlibet/browsers/albums/prefs.py:74 #: ../quodlibet/browsers/covergrid/prefs.py:123 msgid "Album Display" msgstr "Albumvisning" #: ../quodlibet/browsers/albums/prefs.py:78 #: ../quodlibet/browsers/covergrid/prefs.py:127 #: ../quodlibet/browsers/media.py:39 #: ../quodlibet/browsers/playlists/prefs.py:56 #: ../quodlibet/ext/songsmenu/albumart.py:326 #: ../quodlibet/ext/songsmenu/duplicates.py:350 #: ../quodlibet/ext/songsmenu/filterall.py:48 #: ../quodlibet/qltk/bookmarks.py:101 ../quodlibet/qltk/cbes.py:93 #: ../quodlibet/qltk/data_editors.py:99 ../quodlibet/qltk/data_editors.py:324 #: ../quodlibet/qltk/exfalsowindow.py:297 ../quodlibet/qltk/pluginwin.py:79 #: ../quodlibet/qltk/pluginwin.py:427 ../quodlibet/qltk/prefs.py:707 #: ../quodlibet/qltk/textedit.py:164 ../quodlibet/update.py:148 msgid "_Close" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:55 #: ../quodlibet/browsers/audiofeeds.py:67 #: ../quodlibet/browsers/audiofeeds.py:69 #: ../quodlibet/browsers/audiofeeds.py:159 #: ../quodlibet/browsers/paned/models.py:86 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:46 #: ../quodlibet/formats/_audio.py:495 ../quodlibet/order/__init__.py:27 #: ../quodlibet/qltk/information.py:240 ../quodlibet/qltk/information.py:247 #: ../quodlibet/qltk/information.py:273 ../quodlibet/qltk/wlw.py:70 msgid "Unknown" msgstr "Okänd" #: ../quodlibet/browsers/audiofeeds.py:246 msgid "New Feed" msgstr "Ny feed" #: ../quodlibet/browsers/audiofeeds.py:247 msgid "Enter the location of an audio feed:" msgstr "Ange platsen för en ljud-feed:" #: ../quodlibet/browsers/audiofeeds.py:248 #: ../quodlibet/browsers/collection/prefs.py:90 #: ../quodlibet/browsers/iradio.py:341 ../quodlibet/browsers/paned/prefs.py:78 #: ../quodlibet/browsers/playlists/menu.py:96 #: ../quodlibet/browsers/playlists/util.py:52 ../quodlibet/qltk/bookmarks.py:62 #: ../quodlibet/qltk/cbes.py:55 ../quodlibet/qltk/data_editors.py:311 #: ../quodlibet/qltk/edittags.py:288 ../quodlibet/qltk/edittags.py:488 #: ../quodlibet/qltk/quodlibetwindow.py:1354 ../quodlibet/qltk/scanbox.py:61 msgid "_Add" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:265 msgid "Audio Feeds" msgstr "Ljudfeeds" #: ../quodlibet/browsers/audiofeeds.py:266 msgid "_Audio Feeds" msgstr "_Ljudfeeds" #: ../quodlibet/browsers/audiofeeds.py:345 #: ../quodlibet/browsers/audiofeeds.py:350 #, fuzzy msgid "_Download…" msgstr "_Hämta" #: ../quodlibet/browsers/audiofeeds.py:359 msgid "Download Files" msgstr "Hämta filer" #. Save button #: ../quodlibet/browsers/audiofeeds.py:359 #: ../quodlibet/browsers/audiofeeds.py:371 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:81 #: ../quodlibet/ext/songsmenu/albumart.py:322 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:355 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:278 #: ../quodlibet/ext/songsmenu/html.py:76 #: ../quodlibet/ext/songsmenu/lastfmsync.py:216 #: ../quodlibet/ext/songsmenu/playlist.py:51 #: ../quodlibet/ext/songsmenu/replaygain.py:365 #: ../quodlibet/ext/songsmenu/tapbpm.py:182 ../quodlibet/qltk/_editutils.py:39 #: ../quodlibet/qltk/lyrics.py:38 ../quodlibet/qltk/msg.py:52 #: ../quodlibet/qltk/renamefiles.py:168 ../quodlibet/qltk/tracknumbers.py:113 msgid "_Save" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:371 msgid "Download File" msgstr "Hämta fil" #: ../quodlibet/browsers/audiofeeds.py:394 #: ../quodlibet/browsers/playlists/main.py:213 #: ../quodlibet/qltk/data_editors.py:96 msgid "_New" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:454 #: ../quodlibet/browsers/audiofeeds.py:513 msgid "Unable to add feed" msgstr "Kunde ej lägga till feed" #: ../quodlibet/browsers/audiofeeds.py:455 #: ../quodlibet/browsers/audiofeeds.py:514 #, fuzzy, python-format msgid "" "%s could not be added. The server may be down, or the location may not be an " "audio feed." msgstr "" "<b>%s</b> kunde ej läggas till. Servern kan vara nere eller så innehåller " "platsen ej en ljudfeed." #. refresh button #: ../quodlibet/browsers/audiofeeds.py:462 ../quodlibet/browsers/media.py:217 #: ../quodlibet/browsers/media.py:386 ../quodlibet/qltk/filesel.py:259 #: ../quodlibet/qltk/pluginwin.py:413 #, fuzzy msgid "_Refresh" msgstr "Uppdatera biblioteket" #: ../quodlibet/browsers/audiofeeds.py:463 #: ../quodlibet/browsers/playlists/main.py:457 #: ../quodlibet/browsers/playlists/util.py:43 ../quodlibet/qltk/delete.py:143 #: ../quodlibet/qltk/filesel.py:256 ../quodlibet/qltk/lyrics.py:39 #: ../quodlibet/qltk/maskedbox.py:28 ../quodlibet/qltk/songsmenu.py:392 #, fuzzy msgid "_Delete" msgstr "Ta bort filer" #: ../quodlibet/browsers/audiofeeds.py:530 msgid "" "The current audio backend does not support URLs, Audio Feeds browser " "disabled." msgstr "" "Nuvarande ljud-backend stödjer inte URL:er. Ljudströmsbläddraren avaktiverad." #: ../quodlibet/browsers/_base.py:147 ../quodlibet/browsers/_base.py:150 msgid "Library Browser" msgstr "Biblioteksbläddrare" #: ../quodlibet/browsers/_base.py:274 ../quodlibet/ext/songsmenu/refresh.py:30 #: ../quodlibet/qltk/exfalsowindow.py:241 ../quodlibet/qltk/information.py:542 #: ../quodlibet/qltk/maskedbox.py:68 ../quodlibet/util/collection.py:527 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d låt" msgstr[1] "%d låtar" #: ../quodlibet/browsers/_base.py:402 ../quodlibet/browsers/_base.py:407 #: ../quodlibet/qltk/tagsfrompath.py:194 ../quodlibet/qltk/textedit.py:141 #: ../quodlibet/util/__init__.py:622 msgid "Invalid pattern" msgstr "Ogiltigt mönster" #: ../quodlibet/browsers/collection/main.py:78 msgid "Album Collection" msgstr "Albumsamling" #: ../quodlibet/browsers/collection/main.py:79 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:66 #: ../quodlibet/browsers/paned/prefs.py:51 msgid "_Custom" msgstr "_Anpassad" #. Remove button #: ../quodlibet/browsers/collection/prefs.py:94 #: ../quodlibet/browsers/paned/prefs.py:82 #: ../quodlibet/browsers/playlists/menu.py:97 #: ../quodlibet/ext/playlist/remove_duplicates.py:60 #: ../quodlibet/qltk/bookmarks.py:97 ../quodlibet/qltk/bookmarks.py:127 #: ../quodlibet/qltk/cbes.py:82 ../quodlibet/qltk/cbes.py:89 #: ../quodlibet/qltk/data_editors.py:81 ../quodlibet/qltk/data_editors.py:94 #: ../quodlibet/qltk/data_editors.py:301 ../quodlibet/qltk/data_editors.py:314 #: ../quodlibet/qltk/data_editors.py:322 ../quodlibet/qltk/edittags.py:494 #: ../quodlibet/qltk/edittags.py:634 ../quodlibet/qltk/maskedbox.py:48 #: ../quodlibet/qltk/maskedbox.py:88 ../quodlibet/qltk/queue.py:350 #: ../quodlibet/qltk/scanbox.py:36 ../quodlibet/qltk/scanbox.py:63 #, fuzzy msgid "_Remove" msgstr "Ta bort taggar" #: ../quodlibet/browsers/collection/prefs.py:122 #: ../quodlibet/ext/songsmenu/filterall.py:34 #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:92 #: ../quodlibet/qltk/edittags.py:431 msgid "Tag" msgstr "Tagg" #: ../quodlibet/browsers/collection/prefs.py:128 msgid "Merge" msgstr "Slå samman" #: ../quodlibet/browsers/collection/prefs.py:188 msgid "Album Collection Preferences" msgstr "Inställningar för skivsamling" #: ../quodlibet/browsers/collection/prefs.py:195 #: ../quodlibet/browsers/paned/prefs.py:209 #: ../quodlibet/ext/songsmenu/editplaycount.py:45 #: ../quodlibet/ext/songsmenu/exact_rating.py:38 #: ../quodlibet/player/gstbe/prefs.py:40 ../quodlibet/qltk/prefs.py:127 #: ../quodlibet/qltk/textedit.py:65 msgid "_Apply" msgstr "" #: ../quodlibet/browsers/collection/prefs.py:198 #: ../quodlibet/browsers/paned/prefs.py:213 #: ../quodlibet/browsers/playlists/menu.py:95 #: ../quodlibet/browsers/playlists/util.py:42 #: ../quodlibet/errorreport/ui.py:108 #: ../quodlibet/ext/playlist/export_to_folder.py:37 #: ../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:44 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:281 #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:88 #: ../quodlibet/ext/songsmenu/importexport.py:35 #: ../quodlibet/ext/songsmenu/lastfmsync.py:215 #: ../quodlibet/ext/songsmenu/playlist.py:50 #: ../quodlibet/ext/songsmenu/replaygain.py:364 #: ../quodlibet/ext/songsmenu/tapbpm.py:181 ../quodlibet/plugins/playlist.py:39 #: ../quodlibet/qltk/chooser.py:184 ../quodlibet/qltk/chooser.py:205 #: ../quodlibet/qltk/chooser.py:229 ../quodlibet/qltk/chooser.py:253 #: ../quodlibet/qltk/delete.py:90 ../quodlibet/qltk/delete.py:133 #: ../quodlibet/qltk/edittags.py:287 ../quodlibet/qltk/_editutils.py:38 #: ../quodlibet/qltk/getstring.py:28 ../quodlibet/qltk/maskedbox.py:27 #: ../quodlibet/qltk/msg.py:54 ../quodlibet/qltk/msg.py:93 #: ../quodlibet/qltk/ratingsmenu.py:33 ../quodlibet/qltk/songsmenu.py:45 #: ../quodlibet/qltk/songsmenu.py:73 ../quodlibet/update.py:94 msgid "_Cancel" msgstr "" #: ../quodlibet/browsers/covergrid/main.py:125 #, fuzzy msgid "Cover Grid" msgstr "Total storlek:" #: ../quodlibet/browsers/covergrid/main.py:126 #, 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:71 #, fuzzy msgid "Show \"All Albums\" Item" msgstr "Alla album" #: ../quodlibet/browsers/covergrid/prefs.py:78 msgid "Vertical Split" msgstr "" #: ../quodlibet/browsers/covergrid/prefs.py:110 #: ../quodlibet/browsers/covergrid/prefs.py:111 #, fuzzy msgid "Cover Magnification" msgstr "Inga nya stationer" #: ../quodlibet/browsers/filesystem.py:40 msgid "File System" msgstr "Filsystem" #: ../quodlibet/browsers/filesystem.py:41 msgid "_File System" msgstr "_Filsystem" #: ../quodlibet/browsers/filesystem.py:113 ../quodlibet/browsers/media.py:491 #: ../quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "Kunde ej kopiera låtar" #: ../quodlibet/browsers/filesystem.py:114 ../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:189 msgid "_Add to Library" msgstr "Lägg _till i bibliotek" #: ../quodlibet/browsers/iradio.py:178 msgid "Unsupported file type" msgstr "Filtypen stödjs ej" #: ../quodlibet/browsers/iradio.py:179 #, 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:219 ../quodlibet/browsers/iradio.py:232 #: ../quodlibet/browsers/iradio.py:810 msgid "Unable to add station" msgstr "Kunde ej lägga till station" #: ../quodlibet/browsers/iradio.py:243 ../quodlibet/browsers/iradio.py:471 msgid "Internet Radio" msgstr "Internetradio" #: ../quodlibet/browsers/iradio.py:243 msgid "Downloading station list" msgstr "Ladda hem stationslista" #: ../quodlibet/browsers/iradio.py:339 msgid "New Station" msgstr "Ny station" #: ../quodlibet/browsers/iradio.py:340 msgid "Enter the location of an Internet radio station:" msgstr "Ange adressen till en internetradiostation:" #: ../quodlibet/browsers/iradio.py:358 msgid "Electronic" msgstr "Elektrinisk" #: ../quodlibet/browsers/iradio.py:361 msgid "Hip Hop / Rap" msgstr "Hip Hop / Rap" #: ../quodlibet/browsers/iradio.py:362 msgid "Oldies" msgstr "Gamla favoriter" #: ../quodlibet/browsers/iradio.py:363 msgid "R&B" msgstr "R&B" #: ../quodlibet/browsers/iradio.py:364 msgid "Japanese" msgstr "Japanskt" #: ../quodlibet/browsers/iradio.py:365 msgid "Indian" msgstr "indisk" #: ../quodlibet/browsers/iradio.py:367 msgid "Religious" msgstr "Religiöst" #: ../quodlibet/browsers/iradio.py:369 msgid "Charts" msgstr "Topplistemusik" #: ../quodlibet/browsers/iradio.py:370 msgid "Turkish" msgstr "Turkiskt" #: ../quodlibet/browsers/iradio.py:371 msgid "Reggae / Dancehall" msgstr "Reggae / Dancehall" #: ../quodlibet/browsers/iradio.py:372 msgid "Latin" msgstr "Latin" #: ../quodlibet/browsers/iradio.py:373 msgid "College Radio" msgstr "Universitetsradio" #: ../quodlibet/browsers/iradio.py:374 msgid "Talk / News" msgstr "Prat / Nyheter" #: ../quodlibet/browsers/iradio.py:375 msgid "Ambient" msgstr "Ambient" #: ../quodlibet/browsers/iradio.py:376 msgid "Jazz" msgstr "Jazz" #: ../quodlibet/browsers/iradio.py:377 ../quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "Klassiskt" #: ../quodlibet/browsers/iradio.py:378 ../quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "Pop" #: ../quodlibet/browsers/iradio.py:379 msgid "Alternative" msgstr "Alternativ" #: ../quodlibet/browsers/iradio.py:380 msgid "Metal" msgstr "Metal" #: ../quodlibet/browsers/iradio.py:381 msgid "Country" msgstr "Country" #: ../quodlibet/browsers/iradio.py:382 msgid "News" msgstr "Nyheter" #: ../quodlibet/browsers/iradio.py:383 msgid "Schlager" msgstr "Schlager" #: ../quodlibet/browsers/iradio.py:384 msgid "Funk" msgstr "Funk" #: ../quodlibet/browsers/iradio.py:385 msgid "Indie" msgstr "Indie" #: ../quodlibet/browsers/iradio.py:386 msgid "Blues" msgstr "Blues" #: ../quodlibet/browsers/iradio.py:387 msgid "Soul" msgstr "Soul" #: ../quodlibet/browsers/iradio.py:388 msgid "Lounge" msgstr "Lounge" #: ../quodlibet/browsers/iradio.py:389 msgid "Punk" msgstr "Punk" #: ../quodlibet/browsers/iradio.py:390 msgid "Reggaeton" msgstr "Reggaeton" #: ../quodlibet/browsers/iradio.py:392 msgid "Slavic" msgstr "Slavisk" #: ../quodlibet/browsers/iradio.py:394 msgid "Greek" msgstr "Grekiskt" #: ../quodlibet/browsers/iradio.py:395 msgid "Gothic" msgstr "Gothic" #: ../quodlibet/browsers/iradio.py:396 ../quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "Rock" #: ../quodlibet/browsers/iradio.py:449 msgid "Would you like to load a list of popular radio stations?" msgstr "" #: ../quodlibet/browsers/iradio.py:455 #, fuzzy msgid "_Load Stations" msgstr "_Uppdatera stationer" #: ../quodlibet/browsers/iradio.py:472 msgid "_Internet Radio" msgstr "_Internetradio" #: ../quodlibet/browsers/iradio.py:538 #, fuzzy msgid "_New Station…" msgstr "Ny station" #: ../quodlibet/browsers/iradio.py:541 msgid "_Update Stations" msgstr "_Uppdatera stationer" #: ../quodlibet/browsers/iradio.py:568 msgid "All Stations" msgstr "Alla stationer" #. TODO: support for ~#rating=!None etc (#1940) #: ../quodlibet/browsers/iradio.py:572 #: ../quodlibet/browsers/soundcloud/main.py:64 msgid "Favorites" msgstr "Favoriter" #: ../quodlibet/browsers/iradio.py:580 msgid "No Category" msgstr "Ingen kategori" #: ../quodlibet/browsers/iradio.py:802 msgid "No stations found" msgstr "Inga stationer funna" #: ../quodlibet/browsers/iradio.py:803 #, python-format msgid "No Internet radio stations were found at %s." msgstr "Inga internetradiostationer hittades på %s" #: ../quodlibet/browsers/iradio.py:811 msgid "All stations listed are already in your library." msgstr "Alla listade stationer finns redan i biblioteket" #: ../quodlibet/browsers/iradio.py:828 msgid "Add to Favorites" msgstr "_Lägg till som favorit" #: ../quodlibet/browsers/iradio.py:832 msgid "Remove from Favorites" msgstr "Ta bort från favoriter" #: ../quodlibet/browsers/iradio.py:932 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "%(count)d station" msgstr[1] "%(count)d stationer" #: ../quodlibet/browsers/media.py:36 msgid "Device Properties" msgstr "Enhetsinställningar" #: ../quodlibet/browsers/media.py:52 msgid "Device:" msgstr "Enhet:" #: ../quodlibet/browsers/media.py:54 msgid "Not mounted" msgstr "Ej monterad" #: ../quodlibet/browsers/media.py:55 #, fuzzy msgid "Mount point:" msgstr "Monteringspunkt:" #: ../quodlibet/browsers/media.py:61 ../quodlibet/qltk/cbes.py:40 msgid "_Name:" msgstr "_Namn:" #: ../quodlibet/browsers/media.py:135 msgid "Media Devices" msgstr "Mediaenheter" #: ../quodlibet/browsers/media.py:136 msgid "_Media Devices" msgstr "_Mediaenheter" #. eject button #: ../quodlibet/browsers/media.py:224 ../quodlibet/browsers/media.py:378 msgid "_Eject" msgstr "_Mata ut" #: ../quodlibet/browsers/media.py:360 #, fuzzy msgid "_Properties" msgstr "Egenskaper" #: ../quodlibet/browsers/media.py:365 #: ../quodlibet/browsers/playlists/main.py:464 msgid "_Rename" msgstr "_Byt namn" #: ../quodlibet/browsers/media.py:461 #, fuzzy, python-format msgid "%(used-size)s used, %(free-size)s available" msgstr "<b>%s</b> använt, <b>%s</b> tillgängligt" #: ../quodlibet/browsers/media.py:479 #, fuzzy, python-format msgid "%s is not connected." msgstr "<b>%s</b> is ej ansluten." #: ../quodlibet/browsers/media.py:499 #, fuzzy, python-format msgid "Copying %(song)s" msgstr "Kopierar <b>%(song)s</b>" #: ../quodlibet/browsers/media.py:513 ../quodlibet/browsers/media.py:529 msgid "Unable to copy song" msgstr "Kunde ej kopiera låt" #: ../quodlibet/browsers/media.py:514 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." #: ../quodlibet/browsers/media.py:526 #, fuzzy, python-format msgid "%s could not be copied." msgstr "<b>%s</b> kunde inte kopieras." #: ../quodlibet/browsers/media.py:545 msgid "Unable to delete songs" msgstr "Kunde ej ta bort låtar." #: ../quodlibet/browsers/media.py:557 #, fuzzy, python-format msgid "Deleting %(song)s" msgstr "Tar bort <b>%(song)s</b>" #: ../quodlibet/browsers/media.py:575 #, fuzzy, python-format msgid "%s could not be deleted." msgstr "<b>%s</b> kunde inte tas bort." #: ../quodlibet/browsers/media.py:579 msgid "Unable to delete song" msgstr "Kunde ej ta bort låt" #: ../quodlibet/browsers/media.py:594 #, fuzzy, python-format msgid "Ejecting %s failed." msgstr "Utmatning av <b>%s</b> misslyckades." #: ../quodlibet/browsers/media.py:597 msgid "Unable to eject device" msgstr "Kunde inte mata ut enhet" #: ../quodlibet/browsers/media.py:603 msgid "No device backend, Media Devices browser disabled." msgstr "Ingen enhetsdrivrutin. Mediaenheter avaktiverade." #: ../quodlibet/browsers/paned/main.py:40 ../quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "Panelbläddrare" #: ../quodlibet/browsers/paned/main.py:41 msgid "_Paned Browser" msgstr "_Panelbläddrare" #: ../quodlibet/browsers/paned/main.py:90 msgid "Select _All" msgstr "Välj _alla" #: ../quodlibet/browsers/paned/models.py:104 ../quodlibet/qltk/pluginwin.py:122 #: ../quodlibet/qltk/pluginwin.py:164 msgid "All" msgstr "Alla" #: ../quodlibet/browsers/paned/prefs.py:67 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "<tt>%s</tt>" msgstr "" #: ../quodlibet/browsers/paned/prefs.py:162 msgid "_Wide Mode" msgstr "" #: ../quodlibet/browsers/paned/prefs.py:197 msgid "Paned Browser Preferences" msgstr "Inställningar för panelbläddrare" #: ../quodlibet/browsers/paned/prefs.py:204 msgid "Equal pane width" msgstr "" #: ../quodlibet/browsers/playlists/main.py:48 #: ../quodlibet/browsers/playlists/main.py:575 #: ../quodlibet/qltk/pluginwin.py:168 msgid "Playlists" msgstr "Spellistor" #: ../quodlibet/browsers/playlists/main.py:49 msgid "_Playlists" msgstr "Spellistor" #: ../quodlibet/browsers/playlists/main.py:152 msgid "_Remove from Playlist" msgstr "Ta _bort från spellista" #: ../quodlibet/browsers/playlists/main.py:215 #: ../quodlibet/browsers/playlists/main.py:576 msgid "_Import" msgstr "_Importera" #: ../quodlibet/browsers/playlists/main.py:391 #: ../quodlibet/browsers/playlists/util.py:50 #: ../quodlibet/util/collection.py:570 msgid "New Playlist" msgstr "Ny spellista" #: ../quodlibet/browsers/playlists/main.py:413 msgid "Unable to import playlist" msgstr "Kan ej importera spellistor" #: ../quodlibet/browsers/playlists/main.py:414 msgid "Quod Libet can only import playlists in the M3U and PLS formats." msgstr "Quod Libet kan endast importera spellistor i M3U- och PLS-format." #: ../quodlibet/browsers/playlists/main.py:565 msgid "Unable to rename playlist" msgstr "Kan ej byta namn på spellista" #: ../quodlibet/browsers/playlists/main.py:576 msgid "Import Playlist" msgstr "Importera spellista" #: ../quodlibet/browsers/playlists/menu.py:25 #, fuzzy msgid "_New Playlist…" msgstr "_Ny spellista" #: ../quodlibet/browsers/playlists/menu.py:86 #, 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:90 #, 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:33 #, 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:35 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:51 msgid "Enter a name for the new playlist:" msgstr "Ange ett namn på den nya spellistan:" #: ../quodlibet/browsers/playlists/util.py:102 #, 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/search.py:33 msgid "_Limit Results" msgstr "_Begränsa resultat" #: ../quodlibet/browsers/search.py:48 msgid "Search Library" msgstr "Sök i bibliotek" #: ../quodlibet/browsers/search.py:49 msgid "_Search Library" msgstr "_Sök i bibliotek" #: ../quodlibet/browsers/soundcloud/main.py:38 #, fuzzy msgid "Soundcloud Browser" msgstr "Panelbläddrare" #: ../quodlibet/browsers/soundcloud/main.py:39 msgid "Sound_cloud" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:59 #: ../quodlibet/qltk/searchbar.py:73 msgid "Search" msgstr "Sök" #: ../quodlibet/browsers/soundcloud/main.py:136 #, python-format msgid "Go to %s" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:380 #, fuzzy msgid "Connected" msgstr "plats" #: ../quodlibet/browsers/soundcloud/main.py:381 #, python-format msgid "Quod Libet is now connected, <b>%s</b>!" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:393 #, python-format msgid "Log out of %s" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:395 msgid "Enter code…" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:396 #, python-format msgid "Log in to %s" msgstr "" #: ../quodlibet/browsers/soundcloud/util.py:86 msgid "Soundcloud authorisation" msgstr "" #: ../quodlibet/browsers/soundcloud/util.py:87 msgid "Enter Soundcloud auth code:" msgstr "" #: ../quodlibet/cli.py:50 #, fuzzy msgid "Quod Libet is not running (add '--run' to start it)" msgstr "Quod Libet körs inte" #: ../quodlibet/cli.py:85 msgid "a music library and player" msgstr "musikbibliotek och -spelare" #: ../quodlibet/cli.py:86 msgid "[option]" msgstr "[alternativ]" #: ../quodlibet/cli.py:88 msgid "Print the playing song and exit" msgstr "Skriver ut den låt som spelas och avslutar" #: ../quodlibet/cli.py:89 msgid "Begin playing immediately" msgstr "Börja spela omgående" #: ../quodlibet/cli.py:90 msgid "Don't show any windows on start" msgstr "" #: ../quodlibet/cli.py:93 msgid "Jump to next song" msgstr "Hoppa till nästa låt" #: ../quodlibet/cli.py:95 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:96 msgid "Jump to previous song" msgstr "Hoppa till föregående låt" #: ../quodlibet/cli.py:97 msgid "Start playback" msgstr "Starta uppspelning" #: ../quodlibet/cli.py:98 msgid "Pause playback" msgstr "Pausa uppspelning" #: ../quodlibet/cli.py:99 msgid "Toggle play/pause mode" msgstr "Växla spelnings-/paus-läge" #: ../quodlibet/cli.py:100 msgid "Stop playback" msgstr "Stoppa uppspelning" #: ../quodlibet/cli.py:101 msgid "Turn up volume" msgstr "Höj volymen" #: ../quodlibet/cli.py:102 msgid "Turn down volume" msgstr "Sänk volymen" #: ../quodlibet/cli.py:103 msgid "Print player status" msgstr "Skriv ut spelarstatus" #: ../quodlibet/cli.py:104 msgid "Hide main window" msgstr "Dölj huvudfönstret" #: ../quodlibet/cli.py:105 msgid "Show main window" msgstr "Visa huvudfönstret" #: ../quodlibet/cli.py:106 msgid "Toggle main window visibility" msgstr "Växla synlighet för huvudfönstret" #: ../quodlibet/cli.py:107 msgid "Focus the running player" msgstr "Fokuserar på den spelare som körs" #: ../quodlibet/cli.py:108 msgid "Remove active browser filters" msgstr "Ta bort aktuella bläddrarfilter" #: ../quodlibet/cli.py:109 msgid "Refresh and rescan library" msgstr "Uppdatera och skanna om biblioteket" #: ../quodlibet/cli.py:110 #, fuzzy msgid "List available browsers" msgstr "Inaktivera bläddrare" #: ../quodlibet/cli.py:111 msgid "Print the current playlist" msgstr "Skriv ut nuvarande spellista" #: ../quodlibet/cli.py:112 msgid "Print the contents of the queue" msgstr "Skriv ut innehållet i kön" #: ../quodlibet/cli.py:113 #, fuzzy msgid "Print the active text query" msgstr "Skriv ut innehållet i kön" #: ../quodlibet/cli.py:114 msgid "Start without plugins" msgstr "Starta utan insticksmoduler" #: ../quodlibet/cli.py:115 #, fuzzy msgid "Start Quod Libet if it isn't running" msgstr "Quod Libet körs inte" #: ../quodlibet/cli.py:116 msgid "Exit Quod Libet" msgstr "Avsluta Quod Libet" #: ../quodlibet/cli.py:121 msgid "Seek within the playing song" msgstr "Sök innom spelande låt" #: ../quodlibet/cli.py:121 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: ../quodlibet/cli.py:122 #, fuzzy msgid "Set or toggle shuffle mode" msgstr "Växla spelnings-/paus-läge" #: ../quodlibet/cli.py:123 msgid "Turn repeat off, on, or toggle it" msgstr "Stäng av, på eller växla repetering" #: ../quodlibet/cli.py:124 msgid "Set the volume" msgstr "Ställ in volymen" #: ../quodlibet/cli.py:125 msgid "Search your audio library" msgstr "Sök i ljudbiblioteket" #: ../quodlibet/cli.py:125 ../quodlibet/cli.py:137 ../quodlibet/cli.py:141 #: ../quodlibet/cli.py:143 msgid "query" msgstr "fråga" #: ../quodlibet/cli.py:126 msgid "Play a file" msgstr "Spela en fil" #: ../quodlibet/cli.py:126 ../quodlibet/cli.py:137 ../quodlibet/cli.py:143 #, fuzzy msgctxt "command" msgid "filename" msgstr "filnamn" #: ../quodlibet/cli.py:127 msgid "Rate the playing song" msgstr "Betygsätt den spelande låten" #: ../quodlibet/cli.py:128 msgid "Set the current browser" msgstr "Ange nuvarande bläddrare" #: ../quodlibet/cli.py:129 #, fuzzy msgid "Stop after the playing song" msgstr "Betygsätt den spelande låten" #: ../quodlibet/cli.py:130 msgid "Open a new browser" msgstr "Öppna ny bläddrare" #: ../quodlibet/cli.py:131 msgid "Show or hide the queue" msgstr "Visa eller dölj bläddraren" #: ../quodlibet/cli.py:133 #, fuzzy msgid "Show or hide the main song list (deprecated)" msgstr "Visa eller dölj huvudlåtfönstret" #: ../quodlibet/cli.py:134 msgid "Filter on a random value" msgstr "Filtrera på slumpvis värde" #: ../quodlibet/cli.py:134 #, fuzzy msgctxt "command" msgid "tag" msgstr "tagg" #: ../quodlibet/cli.py:135 msgid "Filter on a tag value" msgstr "Filtrera på ett taggvärde" #: ../quodlibet/cli.py:135 msgid "tag=value" msgstr "tagg=värde" #: ../quodlibet/cli.py:136 msgid "Enqueue a file or query" msgstr "Kölägg en fil eller fråga" #: ../quodlibet/cli.py:138 msgid "Enqueue comma-separated files" msgstr "Kölägg kommaseparerad lista" #: ../quodlibet/cli.py:139 ../quodlibet/util/tags.py:147 msgid "filename" msgstr "filnamn" #: ../quodlibet/cli.py:140 msgid "Print filenames of results of query to stdout" msgstr "Skriv ut filnamnen på sökresultatet till stdout" #: ../quodlibet/cli.py:142 msgid "Unqueue a file or query" msgstr "Ta bort fil eller fråga från kö" #: ../quodlibet/cli.py:203 #, python-format msgid "Invalid argument for '%s'." msgstr "Ogiltigt argument för '%s'." #: ../quodlibet/cli.py:204 ../quodlibet/util/__init__.py:190 #, python-format msgid "Try %s --help." msgstr "Försök med %s --help." #: ../quodlibet/devices/_base.py:65 msgid "Unknown Device" msgstr "Okänd enhet" #: ../quodlibet/devices/__init__.py:32 #, python-format msgid "Could not import %s, which is needed for device support." msgstr "Kan inte importera %s, som behövs för enhetsstöd." #: ../quodlibet/devices/__init__.py:153 #, python-format msgid "%r is not a supported device." msgstr "%r stöds inte. " #: ../quodlibet/devices/__init__.py:245 ../quodlibet/devices/__init__.py:251 #, fuzzy, python-format msgid "Could not find '%s'." msgstr "%s: Kan inte hitta %s." #: ../quodlibet/devices/__init__.py:450 msgid "Initializing device backend." msgstr "Initialiserar enhetsdrivrutin." #: ../quodlibet/devices/__init__.py:451 #, python-format msgid "Trying '%s'" msgstr "Testar '%s'" #: ../quodlibet/devices/__init__.py:461 msgid "Couldn't connect to a device backend." msgstr "Kunde inte ansluta till enhetsdrivrutin." #: ../quodlibet/devices/__init__.py:463 msgid "Device backend initialized." msgstr "Enhetsdrivrutin initierad." #: ../quodlibet/devices/storage.py:57 #, fuzzy msgid "_Filename pattern:" msgstr "_Filnamn mönster:" #: ../quodlibet/devices/storage.py:61 msgid "Copy _album covers" msgstr "Kopiera _omslag" #: ../quodlibet/devices/storage.py:65 msgid "_Remove unused covers and directories" msgstr "_Ta bort oanvända omslag och kataloger" #: ../quodlibet/errorreport/ui.py:60 #, fuzzy msgid "An Error Occurred" msgstr "Ett fel har inträffat" #: ../quodlibet/errorreport/ui.py:62 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:72 msgid "File Bug Report" msgstr "" #: ../quodlibet/errorreport/ui.py:74 ../quodlibet/errorreport/ui.py:90 msgid "Submit Error Report" msgstr "" #: ../quodlibet/errorreport/ui.py:75 msgid "Quit Program" msgstr "" #: ../quodlibet/errorreport/ui.py:76 #, fuzzy msgid "Ignore Error" msgstr "Ignorera _alla fel" #: ../quodlibet/errorreport/ui.py:80 msgid "Error details:" msgstr "" #: ../quodlibet/errorreport/ui.py:92 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:100 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "" #: ../quodlibet/errorreport/ui.py:109 msgid "_Send" msgstr "" #: ../quodlibet/errorreport/ui.py:115 #, fuzzy msgid "Short description…" msgstr "beskrivning" #: ../quodlibet/errorreport/ui.py:118 msgid "Data to be sent:" msgstr "" #: ../quodlibet/exfalso.py:34 msgid "an audio tag editor" msgstr "en ljudtaggsredigerare" #: ../quodlibet/exfalso.py:34 ../quodlibet/util/tags.py:148 msgid "directory" msgstr "mapp" #: ../quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "" #: ../quodlibet/ext/covers/artwork_url.py:20 msgid "" "Downloads covers linked to by the artwork_url tag.This works with the " "Soundcloud browser." msgstr "" #: ../quodlibet/ext/covers/discogs.py:25 #, fuzzy msgid "Discogs Cover Source" msgstr "MusicBrainz spår-ID" #: ../quodlibet/ext/covers/discogs.py:26 msgid "Downloads covers from Discogs." msgstr "" #: ../quodlibet/ext/covers/lastfm.py:22 msgid "Last.fm Cover Source" msgstr "" #: ../quodlibet/ext/covers/lastfm.py:23 msgid "Downloads covers from Last.fm's cover art archive." msgstr "" #: ../quodlibet/ext/covers/musicbrainz.py:19 #, fuzzy msgid "MusicBrainz Cover Source" msgstr "MusicBrainz spår-ID" #: ../quodlibet/ext/covers/musicbrainz.py:20 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:25 msgid "Kana/Kanji Simple Inverter" msgstr "" #: ../quodlibet/ext/editing/kakasi.py:26 msgid "Converts kana/kanji to romaji before renaming." msgstr "" #: ../quodlibet/ext/editing/kakasi.py:35 msgid "Romanize _Japanese text" msgstr "" #: ../quodlibet/ext/editing/kakasi.py:63 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:19 msgid "" "Allows arbitrary regex substitutions (s///) 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:69 #, fuzzy msgid "Advanced Preferences" msgstr "Inställningar för panelbläddrare" #: ../quodlibet/ext/events/advanced_preferences.py:70 msgid "Allow editing of advanced config settings." msgstr "" #: ../quodlibet/ext/events/advanced_preferences.py:162 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:153 msgid "Top of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:154 msgid "Middle of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:155 msgid "Bottom of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:158 msgid "_Position:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:171 #, fuzzy msgid "_Cover size:" msgstr "Total storlek:" #: ../quodlibet/ext/events/animosd/prefs.py:177 #: ../quodlibet/ext/events/lyricswindow.py:334 ../quodlibet/qltk/prefs.py:266 #, fuzzy msgid "Display" msgstr "Redigera visning" #: ../quodlibet/ext/events/animosd/prefs.py:190 msgid "_Font:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:195 msgid "Left" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:196 msgid "Center" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:197 #, fuzzy msgid "Right" msgstr "_Vikt" #: ../quodlibet/ext/events/animosd/prefs.py:200 msgid "_Align text:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:206 msgid "Text" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:217 msgid "_Text:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:227 msgid "_Fill:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:232 #: ../quodlibet/ext/events/synchronizedlyrics.py:63 msgid "Colors" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:240 msgid "_Shadows" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:241 #, fuzzy msgid "_Outline" msgstr "_Utgångspipeline" #: ../quodlibet/ext/events/animosd/prefs.py:242 msgid "Rou_nded Corners" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:258 msgid "_Delay:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:264 #: ../quodlibet/qltk/pluginwin.py:172 msgid "Effects" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:270 #, fuzzy msgid "Ed_it Display Pattern…" msgstr "Redigera visning" #: ../quodlibet/ext/events/animosd/prefs.py:274 #: ../quodlibet/ext/events/trayicon/prefs.py:78 #, fuzzy msgid "Preview" msgstr "_Förhandsgranska" #: ../quodlibet/ext/events/auto_library_update.py:136 msgid "Automatic Library Update" msgstr "" #: ../quodlibet/ext/events/auto_library_update.py:137 #, python-format msgid "Keeps your library up to date with inotify. Requires %s." msgstr "" #: ../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 by Brian Nelson." 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/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:97 msgid "Equalizer" msgstr "" #: ../quodlibet/ext/events/equalizer.py:98 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:132 #, 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:138 #, python-format msgid "%.1f kHz" msgstr "" #: ../quodlibet/ext/events/equalizer.py:139 #: ../quodlibet/ext/gstreamer/crossfeed.py:93 #: ../quodlibet/ext/gstreamer/karaoke.py:95 #, python-format msgid "%d Hz" msgstr "" #: ../quodlibet/ext/events/equalizer.py:173 #: ../quodlibet/ext/gstreamer/crossfeed.py:112 #, fuzzy, python-format msgid "%.1f dB" msgstr "%.1f sekunder" #: ../quodlibet/ext/events/equalizer.py:192 #: ../quodlibet/ext/gstreamer/crossfeed.py:31 #, fuzzy msgid "Custom" msgstr "_Anpassad" #: ../quodlibet/ext/events/equalizer.py:199 #, fuzzy msgid "_Clear" msgstr "_Rensa fel" #. Translators: statuses relating to Instant Messenger apps #: ../quodlibet/ext/events/gajim_status.py:27 msgid "online" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:28 msgid "offline" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:29 msgid "chat" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:30 msgid "away" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:31 msgid "xa" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:32 msgid "invisible" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:37 msgid "Gajim Status Message" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:38 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:45 #: ../quodlibet/ext/events/telepathy_status.py:69 msgid "paused" 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:160 msgid "Add '[paused]'" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:163 msgid "If checked, '[paused]' will be added to status message on pause." msgstr "" #: ../quodlibet/ext/events/gajim_status.py:187 msgid "Statuses for which message will be changed" msgstr "" #: ../quodlibet/ext/events/headphonemon.py:156 msgid "Pause on Headphone Unplug" msgstr "" #: ../quodlibet/ext/events/headphonemon.py:157 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" #: ../quodlibet/ext/events/inhibit.py:41 msgid "Inhibit Screensaver" msgstr "" #: ../quodlibet/ext/events/inhibit.py:42 msgid "Prevents the GNOME screensaver from activating while a song is playing." msgstr "" #: ../quodlibet/ext/events/inhibit.py:51 #, fuzzy msgid "Music is playing" msgstr "Musikspelare" #: ../quodlibet/ext/events/iradiolog.py:16 #, fuzzy msgid "Internet Radio Log" msgstr "Internetradio" #: ../quodlibet/ext/events/iradiolog.py:17 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" #: ../quodlibet/ext/events/jep118.py:29 msgid "JEP-118" msgstr "" #: ../quodlibet/ext/events/jep118.py:30 msgid "Outputs a Jabber User Tunes file to ~/.quodlibet/jabber." 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 msgid "A restart is required for any changes to take effect" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:199 #, fuzzy msgid "No active song" msgstr "Kunde ej spara låt" #: ../quodlibet/ext/events/lyricswindow.py:215 #, fuzzy msgid "No lyrics found" msgstr "Inga insticksmoduler hittades." #: ../quodlibet/ext/events/lyricswindow.py:227 #, fuzzy msgid "Lyrics:" msgstr "Text" #: ../quodlibet/ext/events/lyricswindow.py:284 msgid "_Zoom level:" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:302 msgid "URL:" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:307 msgid "Revert to default" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:322 msgid "Search via above URL if the lyrics couldn't be found in LyricsWikia." msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:339 #, fuzzy msgid "Alternate search" msgstr "Töm sökning" #: ../quodlibet/ext/events/lyricswindow.py:347 #, fuzzy msgid "Lyrics Window" msgstr "Text" #: ../quodlibet/ext/events/lyricswindow.py:348 msgid "Shows a window containing lyrics of the playing song." msgstr "" #: ../quodlibet/ext/events/mediaserver.py:38 msgid "UPnP AV Media Server" msgstr "" #: ../quodlibet/ext/events/mediaserver.py:39 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." 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:39 msgid "" "Allows control of Quod Libet using the MPRIS 1.0/2.0 D-Bus Interface " "Specification." msgstr "" #: ../quodlibet/ext/events/mpris/__init__.py:45 #: ../quodlibet/ext/events/trayicon/prefs.py:30 #, fuzzy msgid "Hide main window on close" msgstr "Dölj huvudfönstret" #: ../quodlibet/ext/events/mpris/__init__.py:48 #: ../quodlibet/ext/events/themeswitcher.py:84 #: ../quodlibet/ext/gstreamer/compressor.py:99 #: ../quodlibet/ext/gstreamer/crossfeed.py:136 #: ../quodlibet/ext/gstreamer/karaoke.py:99 #: ../quodlibet/ext/gstreamer/pitch.py:83 ../quodlibet/qltk/prefs.py:688 msgid "Preferences" msgstr "Inställningar" #: ../quodlibet/ext/events/mqtt.py:50 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/mqtt.py:56 msgid "MQTT Publisher" msgstr "" #: ../quodlibet/ext/events/mqtt.py:57 msgid "Publishes status messages to an MQTT topic." msgstr "" #: ../quodlibet/ext/events/mqtt.py:122 msgid "Broker hostname" msgstr "" #: ../quodlibet/ext/events/mqtt.py:122 msgid "broker hostname / IP" msgstr "" #: ../quodlibet/ext/events/mqtt.py:124 msgid "Broker port" msgstr "" #: ../quodlibet/ext/events/mqtt.py:124 msgid "broker port" msgstr "" #: ../quodlibet/ext/events/mqtt.py:126 msgid "Topic" msgstr "" #: ../quodlibet/ext/events/mqtt.py:128 #, fuzzy msgid "Playing Pattern" msgstr "Sökvägsmönster" #: ../quodlibet/ext/events/mqtt.py:130 msgid "Status text when a song is started." msgstr "" #: ../quodlibet/ext/events/mqtt.py:132 #, fuzzy msgid "Paused Pattern" msgstr "Sökvägsmönster" #: ../quodlibet/ext/events/mqtt.py:134 msgid "Text when a song is paused." msgstr "" #: ../quodlibet/ext/events/mqtt.py:136 #, fuzzy msgid "No-song Text" msgstr "%d låt" #: ../quodlibet/ext/events/mqtt.py:138 msgid "Plain text for when there is no current song" msgstr "" #: ../quodlibet/ext/events/mqtt.py:149 #, fuzzy msgid "MQTT Configuration" msgstr "Utkonfiguration" #: ../quodlibet/ext/events/mqtt.py:153 #, fuzzy msgid "Status Text" msgstr "Sökvägsmönster" #: ../quodlibet/ext/events/mqtt.py:185 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "" #: ../quodlibet/ext/events/mqtt.py:189 #, 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:192 #, fuzzy msgid "Connection error" msgstr "plats" #: ../quodlibet/ext/events/notify.py:80 msgid "Notification text" msgstr "" #: ../quodlibet/ext/events/notify.py:88 #, fuzzy msgid "_Title:" msgstr "_Titel" #: ../quodlibet/ext/events/notify.py:99 ../quodlibet/ext/events/notify.py:128 msgid "Revert to default pattern" msgstr "" #: ../quodlibet/ext/events/notify.py:118 msgid "_Body:" msgstr "" #: ../quodlibet/ext/events/notify.py:138 msgid "_Show notification" msgstr "" #: ../quodlibet/ext/events/notify.py:156 #, fuzzy msgid "Show notifications" msgstr "Inga nya stationer" #: ../quodlibet/ext/events/notify.py:162 msgid "Only on <i>_manual</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:170 msgid "Only on <i>_automatic</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:178 msgid "On <i>a_ll</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:196 msgid "Only when the main window is not _focused" msgstr "" #: ../quodlibet/ext/events/notify.py:204 msgid "Show \"_Next\" button" msgstr "" #: ../quodlibet/ext/events/notify.py:236 msgid "Connection Error" msgstr "" #: ../quodlibet/ext/events/notify.py:237 ../quodlibet/ext/events/notify.py:391 #: ../quodlibet/ext/events/notify.py:433 #, fuzzy msgid "Couldn't connect to notification daemon." msgstr "Kunde inte ansluta till enhetsdrivrutin." #: ../quodlibet/ext/events/notify.py:251 #, fuzzy msgid "Song Notifications" msgstr "Inga nya stationer" #: ../quodlibet/ext/events/notify.py:252 msgid "Displays a notification when the song changes." msgstr "" #: ../quodlibet/ext/events/notify.py:415 ../quodlibet/qltk/unity.py:65 msgid "Next" msgstr "Nästa" #: ../quodlibet/ext/events/qlscrobbler.py:178 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:254 #, fuzzy, python-format msgid "Could not contact service '%s'." msgstr "Kunde inte ansluta till enhetsdrivrutin." #: ../quodlibet/ext/events/qlscrobbler.py:260 msgid "Authentication failed: invalid URL." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:277 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:282 msgid "Client is banned. Contact the author." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:286 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:351 msgid "AudioScrobbler Submission" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:352 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:450 msgid "Authentication successful." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:462 #, fuzzy msgid "_Service:" msgstr "Enhet:" #: ../quodlibet/ext/events/qlscrobbler.py:462 msgid "_URL:" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:462 #, fuzzy msgid "User_name:" msgstr "_Namn:" #: ../quodlibet/ext/events/qlscrobbler.py:463 msgid "_Password:" msgstr "" #. Translators: Other service #: ../quodlibet/ext/events/qlscrobbler.py:479 #, fuzzy msgid "Other…" msgstr "_Andra:" #. verify data #: ../quodlibet/ext/events/qlscrobbler.py:517 msgid "_Verify account data" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:522 #: ../quodlibet/ext/songsmenu/lastfmsync.py:304 msgid "Account" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:530 #, fuzzy msgid "_Artist pattern:" msgstr "_Artist" #: ../quodlibet/ext/events/qlscrobbler.py:530 #, fuzzy msgid "_Title pattern:" msgstr "_Filnamn mönster:" #: ../quodlibet/ext/events/qlscrobbler.py:531 msgid "Exclude _filter:" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:549 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:559 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:568 msgid "Songs matching this filter will not be submitted." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:576 msgid "_Offline mode (don't submit anything)" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:580 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:27 #, fuzzy msgid "Random Album Playback" msgstr "Slumpvis al_bum" #: ../quodlibet/ext/events/randomalbum.py:28 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:38 msgid "Rated higher" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:39 msgid "Played more often" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:40 msgid "Skipped more often" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:41 msgid "Played more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:42 msgid "Started more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:43 msgid "Added more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:44 #, fuzzy msgid "Longer albums" msgstr "album" #: ../quodlibet/ext/events/randomalbum.py:83 msgid "seconds before starting next album" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:87 #, fuzzy msgid "Weights" msgstr "_Vikt" #: ../quodlibet/ext/events/randomalbum.py:89 msgid "Play some albums more than others" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:103 msgid "avoid" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:114 msgid "prefer" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:201 #, fuzzy msgid "Random Album" msgstr "Slumpvis al_bum" #: ../quodlibet/ext/events/randomalbum.py:202 #, python-format msgid "Waiting to start %s" msgstr "" #: ../quodlibet/ext/events/rbimport.py:114 #, fuzzy msgid "Import Failed" msgstr "Importera spellista" #: ../quodlibet/ext/events/rbimport.py:119 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "" #: ../quodlibet/ext/events/rbimport.py:127 msgid "Rhythmbox Import" msgstr "" #: ../quodlibet/ext/events/rbimport.py:128 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "" #: ../quodlibet/ext/events/rbimport.py:132 #, fuzzy msgid "Start Import" msgstr "_Importera" #: ../quodlibet/ext/events/screensaver.py:25 msgid "Screensaver Pause" msgstr "" #: ../quodlibet/ext/events/screensaver.py:26 msgid "Pauses playback while the GNOME screensaver is active." msgstr "" #: ../quodlibet/ext/events/searchprovider.py:73 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "" #: ../quodlibet/ext/events/searchprovider.py:79 msgid "GNOME Search Provider" msgstr "" #: ../quodlibet/ext/events/searchprovider.py:80 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/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:29 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:57 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:58 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:34 #, fuzzy msgid "Synchronized Lyrics" msgstr "Text" #: ../quodlibet/ext/events/synchronizedlyrics.py:35 msgid "Shows synchronized lyrics from .lrc file with same name as the track." msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:66 msgid "Text:" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:76 msgid "Background:" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:87 msgid "Font" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:90 msgid "Size (px):" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:62 msgid "Telepathy Status Messages" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:63 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:122 #, fuzzy msgid "Playing:" msgstr "Spelar ej" #: ../quodlibet/ext/events/telepathy_status.py:123 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:139 msgid "Paused:" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:140 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:156 msgid "Plain text for status when there is no current song" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:157 #, fuzzy msgid "No song:" msgstr "%d låt" #. Frame #: ../quodlibet/ext/events/telepathy_status.py:164 #, 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/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:77 #: ../quodlibet/ext/events/trayicon/prefs.py:98 #: ../quodlibet/ext/events/trayicon/systemtray.py:177 #: ../quodlibet/qltk/info.py:47 msgid "Not playing" msgstr "Spelar ej" #: ../quodlibet/ext/events/trayicon/__init__.py:53 #, fuzzy msgid "Tray Icon" msgstr "Inställningar för notifieringsikon" #: ../quodlibet/ext/events/trayicon/__init__.py:54 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:183 #: ../quodlibet/qltk/quodlibetwindow.py:1046 #: ../quodlibet/qltk/quodlibetwindow.py:1238 #, fuzzy msgid "_Play" msgstr "Spellistor" #: ../quodlibet/ext/events/trayicon/menu.py:63 #: ../quodlibet/qltk/quodlibetwindow.py:185 #: ../quodlibet/qltk/quodlibetwindow.py:1240 ../quodlibet/qltk/wlw.py:51 #, fuzzy msgid "P_ause" msgstr "Spela upp/pausera" #: ../quodlibet/ext/events/trayicon/menu.py:68 #: ../quodlibet/qltk/quodlibetwindow.py:190 #: ../quodlibet/qltk/quodlibetwindow.py:1041 #, fuzzy msgid "Pre_vious" msgstr "Föregående" #: ../quodlibet/ext/events/trayicon/menu.py:71 #: ../quodlibet/qltk/quodlibetwindow.py:194 #: ../quodlibet/qltk/quodlibetwindow.py:1051 #, 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:1012 #, fuzzy msgid "Open _Browser" msgstr "Öppna ny bläddrare" #: ../quodlibet/ext/events/trayicon/menu.py:103 #: ../quodlibet/qltk/quodlibetwindow.py:1031 ../quodlibet/qltk/songsmenu.py:411 msgid "Edit _Tags" msgstr "Redigera _taggar" #: ../quodlibet/ext/events/trayicon/menu.py:112 #: ../quodlibet/qltk/quodlibetwindow.py:975 ../quodlibet/qltk/songsmenu.py:424 msgid "_Information" msgstr "_Information" #: ../quodlibet/ext/events/trayicon/menu.py:114 #: ../quodlibet/qltk/songsmenu.py:340 #, fuzzy msgid "Play_lists" msgstr "Spellistor" #: ../quodlibet/ext/events/trayicon/menu.py:132 #: ../quodlibet/qltk/quodlibetwindow.py:1026 msgid "_Quit" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:32 ../quodlibet/qltk/prefs.py:69 msgid "Behavior" msgstr "Beteende" #: ../quodlibet/ext/events/trayicon/prefs.py:42 #, fuzzy msgid "Scroll wheel adjusts volume" msgstr "" "Skrollhjulet justerar volymen\n" "Skift och skrollhjulet byter låt" #: ../quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel changes song" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll _Wheel" msgstr "Rullhjul" #: ../quodlibet/ext/events/trayicon/prefs.py:84 msgid "Tooltip Display" msgstr "Hjälptextvisning" #: ../quodlibet/ext/events/viewlyrics.py:23 #, fuzzy msgid "View Lyrics" msgstr "Text" #: ../quodlibet/ext/events/viewlyrics.py:24 msgid "Automatically displays lyrics beneath the song list in the main window." msgstr "" #: ../quodlibet/ext/events/viewlyrics.py:29 #, fuzzy msgid "_Lyrics" msgstr "Text" #: ../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:406 #, fuzzy msgid "Waveform Seek Bar" msgstr "Alternativ" #: ../quodlibet/ext/events/waveformseekbar.py:410 msgid "A seekbar in the shape of the waveform of the current song." msgstr "" #: ../quodlibet/ext/events/waveformseekbar.py:443 msgid "Override foreground color:" msgstr "" #: ../quodlibet/ext/events/write_cover.py:32 msgid "Picture Saver" msgstr "" #: ../quodlibet/ext/events/write_cover.py:33 msgid "Saves the cover image of the current song to a file." msgstr "" #: ../quodlibet/ext/events/write_cover.py:66 #, fuzzy msgid "File:" msgstr "Filer" #: ../quodlibet/ext/gstreamer/compressor.py:20 msgid "_Threshold:" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:21 msgid "Threshold until the filter is activated" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:22 msgid "R_atio:" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:22 msgid "Compression ratio" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:74 #: ../quodlibet/ext/gstreamer/karaoke.py:91 #, python-format msgid "%d %%" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:105 msgid "Audio Compressor" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:106 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:19 #, fuzzy msgid "_Preset:" msgstr "_Förhandsgranska" #: ../quodlibet/ext/gstreamer/crossfeed.py:19 #, fuzzy msgid "Filter preset" msgstr "Filtrera på _artist" #: ../quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Frequency cut:" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Low-pass filter cut frequency" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed _level:" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed level" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:25 #, fuzzy msgid "Default" msgstr "Förval" #: ../quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Chu Moy" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Jan Meier" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:31 #, fuzzy msgid "Custom settings" msgstr "Anpassad sortering" #: ../quodlibet/ext/gstreamer/crossfeed.py:152 msgid "Crossfeed" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:153 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:20 #, fuzzy msgid "Filter _band:" msgstr "Filtrera på _genre" #: ../quodlibet/ext/gstreamer/karaoke.py:21 msgid "The Frequency band of the filter" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:22 #, fuzzy msgid "Filter _width:" msgstr "Filtrera på _artist" #: ../quodlibet/ext/gstreamer/karaoke.py:23 msgid "The Frequency width of the filter" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:24 msgid "_Level:" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:24 msgid "Level of the effect" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:105 msgid "Karaoke" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:106 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:20 msgid "R_ate:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:21 msgid "_Tempo:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:22 msgid "_Pitch:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:89 #, fuzzy msgid "Audio Pitch / Speed" msgstr "Ljudfeeds" #: ../quodlibet/ext/gstreamer/pitch.py:90 #, fuzzy msgid "Controls the pitch of an audio stream." msgstr "Ange platsen för en ljud-feed:" #: ../quodlibet/ext/playlist/export_to_folder.py:29 #: ../quodlibet/ext/playlist/export_to_folder.py:97 #: ../quodlibet/ext/playlist/export_to_folder.py:138 #, fuzzy msgid "Export Playlist to Folder" msgstr "Importera spellista" #: ../quodlibet/ext/playlist/export_to_folder.py:38 #, fuzzy msgid "_Export" msgstr "_Importera" #: ../quodlibet/ext/playlist/export_to_folder.py:43 #, fuzzy msgid "Destination folder:" msgstr "Inga stationer funna" #: ../quodlibet/ext/playlist/export_to_folder.py:58 #, 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:156 #, fuzzy msgid "Default filename pattern:" msgstr "_Filnamn mönster:" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:23 msgid "Export to Squeezebox" msgstr "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:25 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 "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Export playlist to Squeezebox" msgstr "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:80 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 "" "Playback follows your selection, or the next song in the list once exhausted." msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:22 msgid "Playcount Equalizer" msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:23 msgid "Shuffle, preferring songs with fewer total plays." msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:25 #, fuzzy msgid "Prefer less played" msgstr "senast spelad" #: ../quodlibet/ext/playorder/queue.py:19 #, fuzzy msgid "Queue Only" msgstr "Köad" #: ../quodlibet/ext/playorder/queue.py:21 msgid "" "Limits playing of songs to the queue. Select this play order in the main " "window, then double-clicking any song will enqueue it instead of playing." msgstr "" #: ../quodlibet/ext/playorder/reverse.py:14 #, fuzzy msgid "Reverse" msgstr "Aldrig" #: ../quodlibet/ext/playorder/reverse.py:16 msgid "Reverses the play order of songs." msgstr "" #: ../quodlibet/ext/playorder/skip_songs.py:25 #, fuzzy msgid "Skip Songs" msgstr "Inga låtar" #: ../quodlibet/ext/playorder/skip_songs.py:27 msgid "" "Playback skips over songs with a rating equal or below a given threshold." msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:30 msgid "Repeat Each Track" msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:32 msgid "Shuffle songs, but repeat every track a set number of times." msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:51 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. Syntax is '@(if: " "condition, then, else)'." msgstr "" #: ../quodlibet/ext/query/pythonexpression.py:14 msgid "Python Query" msgstr "" #: ../quodlibet/ext/query/pythonexpression.py:15 msgid "" "Use Python expressions in queries. Syntax is '@(python: expression)'. The " "variable 's' is the song being matched." msgstr "" #: ../quodlibet/ext/query/savedsearch.py:19 #, fuzzy msgid "Include Saved Search" msgstr "Sparade sökningar" #: ../quodlibet/ext/query/savedsearch.py:20 msgid "" "Include the results of a saved search as part of another query. Syntax is " "'@(saved: search name)'." 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:116 msgid "Port:" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:121 #, fuzzy msgid "Username:" msgstr "_Byt namn" #: ../quodlibet/ext/_shared/squeezebox/base.py:126 msgid "Password:" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:130 msgid "Library directory the server connects to." msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:132 #, fuzzy msgid "Library path:" msgstr "Bibliotek" #. Add verify button #: ../quodlibet/ext/_shared/squeezebox/base.py:141 msgid "_Verify settings" msgstr "" #. Server settings Frame #: ../quodlibet/ext/_shared/squeezebox/base.py:147 msgid "Squeezebox Server" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:150 msgid "Debug" msgstr "Avlusa" #: ../quodlibet/ext/_shared/squeezebox/server.py:26 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:28 msgid "unidentified Squeezebox server" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:37 #, 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:20 #: ../quodlibet/ext/songsmenu/importexport.py:34 #: ../quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:329 #, fuzzy msgid "Fit image to _window" msgstr "Dölj huvudfönstret" #. Both labels #: ../quodlibet/ext/songsmenu/albumart.py:338 msgid "_Program:" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:343 msgid "_Edit image after saving" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:345 #, fuzzy msgid "File_name:" msgstr "Filnamn" #: ../quodlibet/ext/songsmenu/albumart.py:457 msgid "Saving failed" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:458 #, fuzzy, python-format msgid "Unable to save \"%s\"." msgstr "Kunde ej spara låt" #: ../quodlibet/ext/songsmenu/albumart.py:556 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:613 #, fuzzy msgid "Album Art Downloader" msgstr "Albumomslag" #: ../quodlibet/ext/songsmenu/albumart.py:666 #, python-format msgid "from %(source)s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:669 #, python-format msgid "Resolution: %s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:672 #, fuzzy, python-format msgid "Size: %s" msgstr "Storlek" #: ../quodlibet/ext/songsmenu/albumart.py:690 #, fuzzy msgid "_Search" msgstr "_Sök:" #: ../quodlibet/ext/songsmenu/albumart.py:741 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:451 #, fuzzy msgid "Searching…" msgstr "Sök" #: ../quodlibet/ext/songsmenu/albumart.py:804 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:922 #, fuzzy msgid "Download Album Art" msgstr "Albumomslag" #: ../quodlibet/ext/songsmenu/albumart.py:923 msgid "Downloads album covers from various websites." msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:936 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 #: ../quodlibet/qltk/downloader.py:52 msgid "Filename" msgstr "Filnamn" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:130 #, fuzzy msgid "Disc" msgstr "_Skiva" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:131 #: ../quodlibet/ext/songsmenu/replaygain.py:404 #: ../quodlibet/qltk/tracknumbers.py:92 msgid "Track" msgstr "Spår" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:132 #, 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:447 msgid "Please enter a query." msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:465 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:496 msgid "Error encountered. Please retry." msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:472 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:488 msgid "Loading result…" msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:475 #, fuzzy msgid "No results found." msgstr "Inga insticksmoduler hittades." #: ../quodlibet/ext/songsmenu/browsefolders.py:159 #, fuzzy msgid "Browse Folders" msgstr "Bläddrare" #: ../quodlibet/ext/songsmenu/browsefolders.py:160 msgid "Opens the songs' folders in a file manager." msgstr "" #: ../quodlibet/ext/songsmenu/browsefolders.py:172 #, fuzzy msgid "Unable to open folders" msgstr "Kunde ej skapa mapp" #: ../quodlibet/ext/songsmenu/browsefolders.py:173 msgid "No program available to open folders." msgstr "" #: ../quodlibet/ext/songsmenu/console.py:40 msgid "Python Console" msgstr "" #: ../quodlibet/ext/songsmenu/console.py:41 msgid "Interactive Python console." msgstr "" #: ../quodlibet/ext/songsmenu/console.py:72 msgid "You can access the following objects by default:" msgstr "" #: ../quodlibet/ext/songsmenu/console.py:82 msgid "Your current working directory is:" 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:55 #, fuzzy msgid "pattern" msgstr "Ogiltigt mönster" #: ../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:91 #, fuzzy msgid "Input value" msgstr "Ogiltigt värde" #: ../quodlibet/ext/songsmenu/custom_commands.py:92 #, python-format msgid "Value for %s?" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:136 #, fuzzy msgid "Custom Commands" msgstr "Anpassad sortering" #: ../quodlibet/ext/songsmenu/custom_commands.py:137 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:188 #: ../quodlibet/ext/songsmenu/custom_commands.py:198 #: ../quodlibet/ext/songsmenu/custom_commands.py:252 msgid "Edit Custom Commands" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:199 msgid "" "Supports QL patterns\n" "eg <tt><~artist~title></tt>" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:283 #, fuzzy, python-format msgid "Unable to run custom command %s" msgstr "Kunde ej kopiera låtar" #: ../quodlibet/ext/songsmenu/duplicates.py:290 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "" msgstr[1] "" #: ../quodlibet/ext/songsmenu/duplicates.py:343 msgid "Collapse / Expand all" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:347 #, python-format msgid "Duplicate key expression is '%s'" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:363 #, fuzzy msgid "Duplicates Browser" msgstr "Inaktivera bläddrare" #: ../quodlibet/ext/songsmenu/duplicates.py:364 msgid "Finds and displays similarly tagged versions of songs." msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:407 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:409 msgid "_Group duplicates by:" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:414 #, fuzzy msgid "Duplicate Key" msgstr "Ta bort dubletter" #: ../quodlibet/ext/songsmenu/duplicates.py:419 #, fuzzy msgid "Remove _Whitespace" msgstr "Ta bort dubletter" #: ../quodlibet/ext/songsmenu/duplicates.py:420 #, fuzzy msgid "Remove _Diacritics" msgstr "Ta bort dubletter" #: ../quodlibet/ext/songsmenu/duplicates.py:421 #, fuzzy msgid "Remove _Punctuation" msgstr "Ta bort taggar" #: ../quodlibet/ext/songsmenu/duplicates.py:422 msgid "Case _Insensitive" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:430 msgid "Matching options" msgstr "" #. Create a dialog. #: ../quodlibet/ext/songsmenu/editplaycount.py:19 #: ../quodlibet/ext/songsmenu/editplaycount.py:41 #, fuzzy msgid "Edit Playcount" msgstr "Redigera visning" #: ../quodlibet/ext/songsmenu/editplaycount.py:20 msgid "" "Edit a song's ~#playcount and ~#skipcount.\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's ~#playcount to 0, the ~#lastplayed and ~#laststarted " "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:68 msgid "Play Count" msgstr "" #: ../quodlibet/ext/songsmenu/editplaycount.py:69 msgid "Skip Count" msgstr "" #: ../quodlibet/ext/songsmenu/embedded.py:24 #, fuzzy msgid "Edit Embedded Images" msgstr "Extrahera inbäddade bilder" #: ../quodlibet/ext/songsmenu/embedded.py:25 #, fuzzy msgid "Removes or replaces embedded images." msgstr "Extrahera inbäddade bilder" #: ../quodlibet/ext/songsmenu/embedded.py:78 #, fuzzy msgid "_Remove all Images" msgstr "Ta bort alla taggar" #: ../quodlibet/ext/songsmenu/embedded.py:82 #, fuzzy msgid "_Embed Current Image" msgstr "Extrahera inbäddade bilder" #: ../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:41 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 #: ../quodlibet/qltk/downloader.py:67 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" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" 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 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:49 msgid "Generating fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:63 msgid "_Details" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:85 msgid "_Submit" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:115 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:118 msgid "Fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Songs with MBIDs:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with sufficient tags:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs to submit:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:162 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:178 msgid "Submitting fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:186 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/id3tlen.py:21 msgid "Fix MP3 Duration" msgstr "" #: ../quodlibet/ext/songsmenu/id3tlen.py:22 msgid "" "Removes TLEN frames from ID3 tags which can be the cause for invalid song " "durations." msgstr "" #: ../quodlibet/ext/songsmenu/ifp.py:20 msgid "Send to iFP" msgstr "" #: ../quodlibet/ext/songsmenu/ifp.py:21 msgid "Uploads songs to an iRiver iFP device." msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:51 msgid "Export Metadata" msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:52 msgid "Exports metadata of selected songs as a .tags file." msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:92 #, fuzzy msgid "Import Metadata" msgstr "Importera spellista" #: ../quodlibet/ext/songsmenu/importexport.py:93 msgid "Imports metadata for selected songs from a .tags file." msgstr "" #: ../quodlibet/ext/songsmenu/k3b.py:23 msgid "Burn CD" msgstr "" #: ../quodlibet/ext/songsmenu/k3b.py:24 msgid "Burns CDs with K3b, Brasero or xfburn." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:96 msgid "Updating chart list." msgstr "" #. No charts to fetch, no update scheduled. #: ../quodlibet/ext/songsmenu/lastfmsync.py:114 msgid "Already up-to-date." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:121 #, python-format msgid "Fetching chart for week of %s." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:143 msgid "Sync complete." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:149 #, fuzzy msgid "Error during sync" msgstr "Fel vid läsning av %r" #: ../quodlibet/ext/songsmenu/lastfmsync.py:214 #: ../quodlibet/ext/songsmenu/lastfmsync.py:244 msgid "Last.fm Sync" msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:245 msgid "Updates your library's statistics from your Last.fm profile." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:293 #, 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 "" #. Create a dialog. #: ../quodlibet/ext/songsmenu/migratemetadata.py:29 #: ../quodlibet/ext/songsmenu/migratemetadata.py:38 #, fuzzy msgid "Migrate Metadata" msgstr "Importera spellista" #: ../quodlibet/ext/songsmenu/migratemetadata.py:32 msgid "Copies the quodlibet-specific metadata between songs." msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:45 msgid "_Copy" msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:47 msgid "_Paste" msgstr "" #. Create the tag table. #: ../quodlibet/ext/songsmenu/migratemetadata.py:57 #, fuzzy msgid "Information to copy/paste" msgstr "Information" #. Create the indexing box. #: ../quodlibet/ext/songsmenu/migratemetadata.py:79 msgid "Map tracks by disc and track number" msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:80 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 "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:96 #, python-format msgid "There is %d stored track." msgid_plural "There are %d stored tracks." msgstr[0] "" msgstr[1] "" #: ../quodlibet/ext/songsmenu/playlist.py:31 #, fuzzy msgid "Export as Playlist" msgstr "Importera spellista" #: ../quodlibet/ext/songsmenu/playlist.py:32 msgid "Exports songs to an M3U or PLS playlist." msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:77 msgid "Use relative paths" msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:77 msgid "Use absolute paths" msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:132 #, fuzzy msgid "Unable to export playlist" msgstr "Kan ej importera spellistor" #: ../quodlibet/ext/songsmenu/playlist.py:133 #, fuzzy, python-format msgid "Writing to <b>%s</b> 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:362 msgid "ReplayGain Analyzer" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:418 msgid "Progress" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:433 msgid "Gain" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:448 msgid "Peak" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:463 #, python-format msgid "There is <b>%(to-process)s</b> album to update (of %(all)s)" msgid_plural "There are <b>%(to-process)s</b> albums to update (of %(all)s)" msgstr[0] "" msgstr[1] "" #: ../quodlibet/ext/songsmenu/replaygain.py:578 msgid "Replay Gain" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:579 msgid "" "Analyzes and updates ReplayGain information, using GStreamer. Results are " "grouped by album." msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:617 msgid "always" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:618 msgid "if <b>any</b> RG tags are missing" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:620 msgid "if <b>album</b> RG tags are missing" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:637 msgid "_Process albums:" msgstr "" #. Server settings Frame #: ../quodlibet/ext/songsmenu/replaygain.py:649 #, 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 "" #. TRANSLATORS: BPM mean "beats per minute" #: ../quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "" #: ../quodlibet/ext/songsmenu/tapbpm.py:32 #: ../quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" 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:172 #: ../quodlibet/ext/songsmenu/tapbpm.py:179 msgid "Tap BPM" msgstr "" #: ../quodlibet/ext/songsmenu/tapbpm.py:173 #, fuzzy msgid "Tap BPM for the selected song." msgstr "Kunde ej ta bort låtar." #: ../quodlibet/ext/songsmenu/website_search.py:35 #, fuzzy msgid "Website Search" msgstr "Sök" #: ../quodlibet/ext/songsmenu/website_search.py:36 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern-example)s." msgstr "" #: ../quodlibet/ext/songsmenu/website_search.py:78 #, fuzzy msgid "Search URL patterns" msgstr "Sökvägsmönster" #: ../quodlibet/ext/songsmenu/website_search.py:88 #, fuzzy msgid "Edit search URLs" msgstr "Redigera sparade sökningar..." #. Add link to editor #: ../quodlibet/ext/songsmenu/website_search.py:114 #, fuzzy msgid "Configure Searches…" msgstr "Färglägg _söktermer" #: ../quodlibet/ext/songsmenu/wikipedia.py:46 #, python-format msgid "Search at %(website)s" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:63 msgid "Search Artist in Wikipedia" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:64 msgid "" "Opens a browser window with Wikipedia article on the playing song artist." msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:71 msgid "Search Album in Wikipedia" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:72 msgid "" "Opens a browser window with Wikipedia article on the playing song album." msgstr "" #. then (try to) load all new files #: ../quodlibet/library/libraries.py:650 ../quodlibet/library/libraries.py:660 #: ../quodlibet/library/libraries.py:726 ../quodlibet/library/libraries.py:745 #: ../quodlibet/qltk/information.py:268 ../quodlibet/qltk/prefs.py:639 #: ../quodlibet/util/library.py:124 msgid "Library" msgstr "Bibliotek" #: ../quodlibet/library/libraries.py:650 msgid "Checking mount points" msgstr "Kontrollerar monteringspunkter" #: ../quodlibet/library/libraries.py:660 msgid "Scanning library" msgstr "Kontrollerar bibliotek" #: ../quodlibet/library/libraries.py:725 #, python-format msgid "Scanning %s" msgstr "Kontrollerar %s" #: ../quodlibet/library/libraries.py:745 msgid "Loading files" msgstr "" #: ../quodlibet/operon/base.py:70 #, python-format msgid "Failed to load file: %r" msgstr "Kunde inte ladda filen: %r" #: ../quodlibet/operon/commands.py:37 #, fuzzy msgid "List tags" msgstr "Lista alla taggar." #: ../quodlibet/operon/commands.py:42 ../quodlibet/operon/commands.py:81 #: ../quodlibet/operon/commands.py:461 msgid "Print terse output" msgstr "Koncis utmatning" #: ../quodlibet/operon/commands.py:44 ../quodlibet/operon/commands.py:83 #: ../quodlibet/operon/commands.py:463 #, 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:47 ../quodlibet/operon/commands.py:86 msgid "Also list programmatic tags" msgstr "Lista även programmatiska taggar" #: ../quodlibet/operon/commands.py:51 ../quodlibet/operon/commands.py:129 #: ../quodlibet/operon/commands.py:220 ../quodlibet/operon/commands.py:293 #: ../quodlibet/operon/commands.py:336 ../quodlibet/operon/commands.py:340 #: ../quodlibet/operon/commands.py:391 ../quodlibet/operon/commands.py:394 #: ../quodlibet/operon/commands.py:433 ../quodlibet/operon/commands.py:468 #: ../quodlibet/operon/commands.py:508 ../quodlibet/operon/commands.py:543 #: ../quodlibet/operon/commands.py:585 msgid "Not enough arguments" msgstr "Inte nog många argument" #: ../quodlibet/operon/commands.py:53 ../quodlibet/operon/commands.py:90 #: ../quodlibet/operon/commands.py:131 ../quodlibet/operon/commands.py:222 #: ../quodlibet/operon/commands.py:470 msgid "Too many arguments" msgstr "För många argument" #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:92 #: ../quodlibet/operon/commands.py:475 ../quodlibet/qltk/data_editors.py:363 msgid "Description" msgstr "Beskrivning" #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:475 #: ../quodlibet/qltk/edittags.py:454 msgid "Value" msgstr "Värde" #: ../quodlibet/operon/commands.py:76 msgid "List all common tags" msgstr "Visa alla gemensamma taggar" #: ../quodlibet/operon/commands.py:118 msgid "Copy tags from one file to another" msgstr "Kopiera taggar från en fil till en annan" #: ../quodlibet/operon/commands.py:123 ../quodlibet/operon/commands.py:164 #: ../quodlibet/operon/commands.py:289 ../quodlibet/operon/commands.py:324 #: ../quodlibet/operon/commands.py:384 msgid "Show changes, don't apply them" msgstr "Visa förändringar, verkställ dem inte" #: ../quodlibet/operon/commands.py:125 msgid "Skip tags that can't be written" msgstr "Hoppa över taggar som inte kan skrivas" #: ../quodlibet/operon/commands.py:145 #, python-format msgid "Can't copy tag %r to file: %r" 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:304 ../quodlibet/operon/commands.py:444 #: ../quodlibet/operon/commands.py:676 #, python-format msgid "Can not set %r" msgstr "Kunde inte sätta %r" #: ../quodlibet/operon/commands.py:319 msgid "Remove tags" msgstr "Ta bort taggar" #: ../quodlibet/operon/commands.py:326 ../quodlibet/operon/commands.py:386 msgid "Value is a regular expression" msgstr "Värdet är ett reguljärt uttryck" #: ../quodlibet/operon/commands.py:328 msgid "Remove all tags" msgstr "Ta bort alla taggar" #: ../quodlibet/operon/commands.py:332 msgid "Can't combine '--all' with '--regexp'" msgstr "Kan inte kombinera '--all' med '--regexp'" #: ../quodlibet/operon/commands.py:366 #, python-format msgid "Can't remove %r from %r" msgstr "Kan inte ta bort %r från %r" #: ../quodlibet/operon/commands.py:379 msgid "Remove a tag value" msgstr "Ta bort ett taggvärde" #: ../quodlibet/operon/commands.py:428 msgid "Add a tag value" msgstr "Lägg till ett taggvärde" #: ../quodlibet/operon/commands.py:456 #, fuzzy msgid "List file information" msgstr "Visa filinformation" #: ../quodlibet/operon/commands.py:502 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" #: ../quodlibet/operon/commands.py:515 #, fuzzy, python-format msgid "Failed to load image file: %r" msgstr "Kunde inte ladda filen: %r" #: ../quodlibet/operon/commands.py:522 ../quodlibet/operon/commands.py:551 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" #: ../quodlibet/operon/commands.py:538 #, fuzzy msgid "Remove all embedded images" msgstr "Extrahera inbäddade bilder" #: ../quodlibet/operon/commands.py:568 #, fuzzy, python-format msgid "Extract embedded images to %(filepath)s" msgstr "Extrahera inbäddade bilder" #: ../quodlibet/operon/commands.py:580 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" #: ../quodlibet/operon/commands.py:639 msgid "Rename files based on tags" msgstr "" #: ../quodlibet/operon/commands.py:654 msgid "Fill tags based on the file path" msgstr "" #: ../quodlibet/operon/commands.py:704 ../quodlibet/qltk/information.py:305 #: ../quodlibet/qltk/properties.py:84 ../quodlibet/qltk/renamefiles.py:176 #: ../quodlibet/qltk/tagsfrompath.py:229 ../quodlibet/qltk/tracknumbers.py:79 msgid "File" msgstr "Fil" #: ../quodlibet/operon/commands.py:712 msgid "Fill tracknumbers for all files" msgstr "" #: ../quodlibet/operon/commands.py:731 msgid "Print tags based on the given pattern" msgstr "" #: ../quodlibet/operon/commands.py:768 #, fuzzy msgid "Display help information" msgstr "Visa kortfattad användningsinformation" #: ../quodlibet/operon/util.py:40 #, 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:30 msgid "_Unknown" msgstr "_Okänd" #: ../quodlibet/order/__init__.py:142 msgid "In Order" msgstr "I ordning" #: ../quodlibet/order/__init__.py:143 msgid "_In Order" msgstr "_I ordning" #: ../quodlibet/order/reorder.py:23 #, fuzzy msgid "Random" msgstr "_Slumpvis" #: ../quodlibet/order/reorder.py:24 ../quodlibet/qltk/queue.py:119 msgid "_Random" msgstr "_Slumpvis" #: ../quodlibet/order/reorder.py:39 ../quodlibet/order/reorder.py:40 msgid "Prefer higher rated" msgstr "" #: ../quodlibet/order/repeat.py:43 ../quodlibet/order/repeat.py:44 msgid "Repeat this track" msgstr "" #: ../quodlibet/order/repeat.py:57 ../quodlibet/order/repeat.py:58 #, fuzzy msgid "Repeat all" msgstr "_Repetera" #: ../quodlibet/order/repeat.py:73 ../quodlibet/order/repeat.py:74 msgid "One Song" msgstr "En låt" #: ../quodlibet/player/gstbe/player.py:98 msgid "Stream" msgstr "Ström" #: ../quodlibet/player/gstbe/player.py:98 msgid "Buffering" msgstr "Buffrar" #: ../quodlibet/player/gstbe/player.py:319 #, fuzzy msgid "Could not create GStreamer pipeline" msgstr "Kunde inte skapa förvald GStreamer pipeline." #: ../quodlibet/player/gstbe/player.py:560 msgid "No GStreamer element found to handle media format" msgstr "" #: ../quodlibet/player/gstbe/player.py:561 #, 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:25 #, fuzzy msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. In case 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:36 msgid "_Output pipeline:" msgstr "_Utgångspipeline" #: ../quodlibet/player/gstbe/prefs.py:43 #, python-format msgid "%.1f seconds" msgstr "%.1f sekunder" #: ../quodlibet/player/gstbe/prefs.py:57 msgid "_Buffer duration:" msgstr "_Buffertlängd:" #: ../quodlibet/player/gstbe/prefs.py:66 msgid "Disable _gapless playback" msgstr "" #: ../quodlibet/player/gstbe/prefs.py:70 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions." msgstr "" #: ../quodlibet/player/gstbe/util.py:93 #, fuzzy msgid "No GStreamer audio sink found" msgstr "Inga stationer funna" #: ../quodlibet/player/gstbe/util.py:112 #, fuzzy msgid "Invalid GStreamer output pipeline" msgstr "Ogiltig GStreamer output pipeline, försöker med förvalt värde." #: ../quodlibet/player/xinebe/player.py:90 msgid "Unable to create audio output" msgstr "Kunde ej skapa audiodata" #: ../quodlibet/player/xinebe/player.py:91 #, 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:62 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" #: ../quodlibet/plugins/__init__.py:71 #, fuzzy, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "Kunde inte länka GStreamer-pipeline: '%s'" #: ../quodlibet/plugins/playlist.py:30 #, 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:41 ../quodlibet/qltk/songsmenu.py:46 #: ../quodlibet/qltk/songsmenu.py:74 #, fuzzy msgid "_Run Plugin" msgstr "_Insticksmoduler" #: ../quodlibet/qltk/about.py:40 #, python-format msgid "Supported formats: %s" msgstr "Format som stödjs: %s" #: ../quodlibet/qltk/about.py:43 #, python-format msgid "Audio device: %s" msgstr "Ljudenhet: %s" #. 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:207 ../quodlibet/qltk/information.py:131 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:48 ../quodlibet/qltk/edittags.py:311 msgid "_Value:" msgstr "_Värde:" #: ../quodlibet/qltk/cbes.py:262 msgid "Saved Values" msgstr "Sparade värden" #: ../quodlibet/qltk/cbes.py:263 #, fuzzy msgid "Edit saved values…" msgstr "Redigera sparade värden..." #: ../quodlibet/qltk/controls.py:111 msgid "Auto_matic" msgstr "Auto_matisk" #: ../quodlibet/qltk/controls.py:112 msgid "_Track Mode" msgstr "_Spårläge" #: ../quodlibet/qltk/controls.py:113 msgid "_Album Mode" msgstr "_Albumläge" #. Translators: player state, no action #: ../quodlibet/qltk/controls.py:122 msgid "_Mute" msgstr "" #: ../quodlibet/qltk/controls.py:128 #, fuzzy msgid "_Replay Gain Mode" msgstr "Replay Gain volymjusterning" #. Translators: New Command/Entry/Item/... #: ../quodlibet/qltk/data_editors.py:119 #, python-format msgid "New %s" msgstr "" #: ../quodlibet/qltk/data_editors.py:218 #, fuzzy msgid "(unknown)" msgstr "Okänd" #: ../quodlibet/qltk/data_editors.py:355 #, fuzzy msgid "Tag expression" msgstr "Värdet är ett reguljärt uttryck" #: ../quodlibet/qltk/data_editors.py:382 msgid "Tag expression e.g. people:real or ~album~year." msgstr "" #: ../quodlibet/qltk/data_editors.py:383 #, fuzzy msgid "Enter new tag" msgstr "Filtrera på ett taggvärde" #: ../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/downloader.py:38 msgid "Downloads" msgstr "Hämtningar" #: ../quodlibet/qltk/downloader.py:62 msgid "Size" msgstr "Storlek" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: ../quodlibet/qltk/downloader.py:94 ../quodlibet/qltk/renamefiles.py:265 #: ../quodlibet/qltk/wlw.py:50 msgid "_Stop" msgstr "" #: ../quodlibet/qltk/edittags.py:63 ../quodlibet/qltk/edittags.py:74 #, 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:67 ../quodlibet/qltk/edittags.py:71 #, 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:193 msgid "Split into _Multiple Values" msgstr "Dela till flera värden" #: ../quodlibet/qltk/edittags.py:211 msgid "Split Disc out of _Album" msgstr "Hämta skiva ur _album" #: ../quodlibet/qltk/edittags.py:228 msgid "Split _Version out of Title" msgstr "Hämta _version ur titel" #: ../quodlibet/qltk/edittags.py:259 msgid "Split Arranger out of Ar_tist" msgstr "Hämta arrangör ur ar_tist" #: ../quodlibet/qltk/edittags.py:264 msgid "Split _Performer out of Artist" msgstr "Hämta _uppträdande ut artist" #: ../quodlibet/qltk/edittags.py:270 msgid "Split _Performer out of Title" msgstr "Hämta _framträdanden från titel" #: ../quodlibet/qltk/edittags.py:276 msgid "Split _Originalartist out of Title" msgstr "Hämta _originalartist från titel" #: ../quodlibet/qltk/edittags.py:283 msgid "Add a Tag" msgstr "Lägg till en tagg" #: ../quodlibet/qltk/edittags.py:302 msgid "_Tag:" msgstr "_Tagg:" #: ../quodlibet/qltk/edittags.py:404 msgid "Edit Tags" msgstr "Redigera taggar" #: ../quodlibet/qltk/edittags.py:477 msgid "Show _programmatic tags" msgstr "Ta bort _programmatiska taggar" #: ../quodlibet/qltk/edittags.py:478 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" #. Translators: Revert button in the tag editor #: ../quodlibet/qltk/edittags.py:508 #, fuzzy msgctxt "edittags" msgid "_Revert" msgstr "Aldrig" #. Translators: Save button in the tag editor #: ../quodlibet/qltk/edittags.py:513 msgctxt "edittags" msgid "_Save" msgstr "" #: ../quodlibet/qltk/edittags.py:659 msgid "Unable to add tag" msgstr "Kunde ej lägga till tagg" #: ../quodlibet/qltk/edittags.py:660 #, fuzzy, python-format msgid "Unable to add <b>%s</b>" msgstr "Kunde ej lägga till låt" #: ../quodlibet/qltk/edittags.py:662 #, fuzzy, python-format msgid "" "The files currently selected do not support multiple values for <b>%s</b>." 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:689 ../quodlibet/qltk/edittags.py:856 #: ../quodlibet/qltk/tagsfrompath.py:212 ../quodlibet/util/__init__.py:554 #: ../quodlibet/util/tags.py:231 msgid "Invalid tag" msgstr "Ogiltig tall" #: ../quodlibet/qltk/edittags.py:690 ../quodlibet/qltk/edittags.py:857 #: ../quodlibet/qltk/tagsfrompath.py:213 #, python-format msgid "" "Invalid tag <b>%s</b>\n" "\n" "The files currently selected do not support editing this tag." msgstr "" "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:828 ../quodlibet/qltk/edittags.py:868 msgid "Invalid value" msgstr "Ogiltigt värde" #: ../quodlibet/qltk/edittags.py:829 ../quodlibet/qltk/edittags.py:869 #, python-format msgid "" "Invalid value: <b>%(value)s</b>\n" "\n" "%(error)s" msgstr "" "Felaktigt värde: <b>%(value)s</b>\n" "\n" "%(error)s" #: ../quodlibet/qltk/_editutils.py:28 msgid "Tag may not be accurate" msgstr "Taggen är möjligtvis ej korrekt" #: ../quodlibet/qltk/_editutils.py:31 #, 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:47 msgid "Unable to save song" msgstr "Kunde ej spara låt" #: ../quodlibet/qltk/_editutils.py:50 #, 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:142 #, 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:95 #: ../quodlibet/qltk/quodlibetwindow.py:1066 msgid "_About" msgstr "" #: ../quodlibet/qltk/exfalsowindow.py:99 #: ../quodlibet/qltk/quodlibetwindow.py:1088 msgid "_Check for Updates…" msgstr "" #: ../quodlibet/qltk/exfalsowindow.py:105 #: ../quodlibet/qltk/quodlibetwindow.py:1021 ../quodlibet/qltk/songsmenu.py:304 msgid "_Plugins" msgstr "_Insticksmoduler" #: ../quodlibet/qltk/exfalsowindow.py:267 #, 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:279 msgid "Ex Falso Preferences" msgstr "Ex Falso inställningar" #: ../quodlibet/qltk/exfalsowindow.py:289 ../quodlibet/qltk/prefs.py:598 msgid "Split _on:" msgstr "Dela _på:" #: ../quodlibet/qltk/exfalsowindow.py:295 ../quodlibet/qltk/prefs.py:613 msgid "Tag Editing" msgstr "Taggredigering" #: ../quodlibet/qltk/filesel.py:210 msgid "Folders" msgstr "Mappar" #: ../quodlibet/qltk/filesel.py:253 #, fuzzy msgid "_New Folder…" msgstr "Ny mapp" #: ../quodlibet/qltk/filesel.py:262 #, fuzzy msgid "_Select all Sub-Folders" msgstr "Välj _alla rekursivt" #: ../quodlibet/qltk/filesel.py:374 msgid "New Folder" msgstr "Ny mapp" #: ../quodlibet/qltk/filesel.py:374 msgid "Enter a name for the new folder:" msgstr "Namn på den nya mappen:" #: ../quodlibet/qltk/filesel.py:387 msgid "Unable to create folder" msgstr "Kunde ej skapa mapp" #: ../quodlibet/qltk/filesel.py:404 msgid "Unable to delete folder" msgstr "Kunde ej ta bort mapp" #: ../quodlibet/qltk/filesel.py:519 ../quodlibet/qltk/pluginwin.py:167 msgid "Songs" msgstr "Låtar" #. Translators: As in "by Artist Name" #: ../quodlibet/qltk/info.py:42 #, python-format msgid "by %s" msgstr "av %s" #: ../quodlibet/qltk/info.py:43 ../quodlibet/qltk/information.py:167 #: ../quodlibet/qltk/information.py:448 #, python-format msgid "Disc %s" msgstr "Skiva %s" #: ../quodlibet/qltk/info.py:44 ../quodlibet/qltk/information.py:172 #, python-format msgid "Track %s" msgstr "Spår %s" #: ../quodlibet/qltk/info.py:108 #, fuzzy msgid "_Edit Display…" msgstr "Redigera visning" #: ../quodlibet/qltk/information.py:105 msgid "No songs are selected." msgstr "Inga låtar är valda." #: ../quodlibet/qltk/information.py:106 msgid "No Songs" msgstr "Inga låtar" #: ../quodlibet/qltk/information.py:121 ../quodlibet/qltk/information.py:338 #: ../quodlibet/qltk/information.py:471 ../quodlibet/qltk/information.py:531 msgid "Information" msgstr "Information" #: ../quodlibet/qltk/information.py:126 msgid "Lyrics" msgstr "Text" #: ../quodlibet/qltk/information.py:184 ../quodlibet/qltk/information.py:396 #, python-format msgid "Produced by %s" msgstr "Producerad av %s" #: ../quodlibet/qltk/information.py:199 ../quodlibet/util/tags.py:76 msgid "artist" msgstr "artist" #: ../quodlibet/qltk/information.py:200 ../quodlibet/qltk/information.py:561 #: ../quodlibet/util/tags.py:76 msgid "artists" msgstr "artister" #. for backwards compat #: ../quodlibet/qltk/information.py:221 ../quodlibet/util/tags.py:86 #: ../quodlibet/util/tags.py:114 msgid "performers" msgstr "uppträdande" #: ../quodlibet/qltk/information.py:235 ../quodlibet/qltk/information.py:248 #: ../quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "Aldrig" #: ../quodlibet/qltk/information.py:236 #, 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:254 ../quodlibet/util/tags.py:139 msgid "added" msgstr "tillagd" #: ../quodlibet/qltk/information.py:255 ../quodlibet/util/tags.py:140 msgid "last played" msgstr "senast spelad" #: ../quodlibet/qltk/information.py:256 ../quodlibet/util/tags.py:150 msgid "plays" msgstr "spelningar" #: ../quodlibet/qltk/information.py:257 ../quodlibet/util/tags.py:151 msgid "skips" msgstr "överhoppningar" #: ../quodlibet/qltk/information.py:258 ../quodlibet/util/tags.py:156 msgid "rating" msgstr "betyg" #: ../quodlibet/qltk/information.py:287 msgid "path" msgstr "" #: ../quodlibet/qltk/information.py:288 ../quodlibet/util/tags.py:154 msgid "length" msgstr "längd" #: ../quodlibet/qltk/information.py:289 #, fuzzy msgid "format" msgstr "Information" #: ../quodlibet/qltk/information.py:290 ../quodlibet/util/tags.py:163 msgid "codec" msgstr "" #: ../quodlibet/qltk/information.py:291 ../quodlibet/util/tags.py:164 #, fuzzy msgid "encoding" msgstr "Ökande" #: ../quodlibet/qltk/information.py:292 ../quodlibet/util/tags.py:160 msgid "bitrate" msgstr "bitrate" #: ../quodlibet/qltk/information.py:293 ../quodlibet/util/tags.py:161 msgid "file size" msgstr "filstorlek" #: ../quodlibet/qltk/information.py:294 ../quodlibet/util/tags.py:149 msgid "modified" msgstr "ändrad" #: ../quodlibet/qltk/information.py:331 msgid "Additional" msgstr "" #: ../quodlibet/qltk/information.py:383 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d vald" msgstr[1] "%d valda" #: ../quodlibet/qltk/information.py:458 msgid "Track unavailable" msgstr "Spår otillgängligt" #: ../quodlibet/qltk/information.py:464 msgid "Track List" msgstr "Spårlista" #: ../quodlibet/qltk/information.py:505 ../quodlibet/qltk/information.py:578 #, 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:508 msgid "Selected Discography" msgstr "Vald discografi" #: ../quodlibet/qltk/information.py:558 #, 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:586 ../quodlibet/util/tags.py:74 msgid "albums" msgstr "album" #: ../quodlibet/qltk/information.py:599 msgid "Total length:" msgstr "Total längd:" #: ../quodlibet/qltk/information.py:603 msgid "Total size:" msgstr "Total storlek:" #: ../quodlibet/qltk/information.py:606 msgid "Files" msgstr "Filer" #: ../quodlibet/qltk/lyrics.py:37 msgid "_Download" msgstr "_Hämta" #: ../quodlibet/qltk/lyrics.py:40 #, fuzzy msgid "_Edit" msgstr "_Redigera visning..." #. buffer.set_text(_("No lyrics found.\n\nYou can click the " #. "Download button to have Quod Libet search " #. "for lyrics online. You can also enter them " #. "yourself and click save.")) #: ../quodlibet/qltk/lyrics.py:73 ../quodlibet/qltk/lyrics.py:109 msgid "No lyrics found for this song." msgstr "Ingen text hittades för denna låt." #: ../quodlibet/qltk/lyrics.py:82 #, fuzzy msgid "Searching for lyrics…" msgstr "Söker efter text..." #: ../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/msg.py:41 msgid "Discard tag changes?" msgstr "Förkasta taggändringar?" #: ../quodlibet/qltk/msg.py:42 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:55 ../quodlibet/qltk/prefs.py:595 #: ../quodlibet/qltk/textedit.py:64 ../quodlibet/qltk/tracknumbers.py:117 #, fuzzy msgid "_Revert" msgstr "Aldrig" #: ../quodlibet/qltk/msg.py:86 msgid "File exists" msgstr "Filen existerar" #: ../quodlibet/qltk/msg.py:88 #, python-format msgid "Replace %(file-name)s?" msgstr "" #: ../quodlibet/qltk/msg.py:94 #, fuzzy msgid "_Replace File" msgstr "Byt namn på filer" #: ../quodlibet/qltk/notif.py:182 msgid "Active tasks" msgstr "Aktiva uppgifter" #: ../quodlibet/qltk/notif.py:188 #, python-format msgid "%d tasks running" msgstr "%d uppgifter körs" #: ../quodlibet/qltk/playorder.py:254 #, fuzzy msgid "Toggle shuffle mode" msgstr "Växla spelnings-/paus-läge" #: ../quodlibet/qltk/playorder.py:270 #, fuzzy msgid "Toggle repeat mode" msgstr "Växla spelnings-/paus-läge" #: ../quodlibet/qltk/pluginwin.py:44 msgid "Plugin Errors" msgstr "Insticksmodulfel" #: ../quodlibet/qltk/pluginwin.py:124 msgid "Enabled" msgstr "Aktiverad" #: ../quodlibet/qltk/pluginwin.py:125 msgid "Disabled" msgstr "Inaktiverad" #: ../quodlibet/qltk/pluginwin.py:131 msgid "No category" msgstr "Ingen kategori" #: ../quodlibet/qltk/pluginwin.py:169 msgid "Events" msgstr "" #: ../quodlibet/qltk/pluginwin.py:170 #, fuzzy msgid "Play Order" msgstr "Spel_ordning" #: ../quodlibet/qltk/pluginwin.py:171 #, fuzzy msgid "Editing" msgstr "Taggredigering" #: ../quodlibet/qltk/pluginwin.py:173 #, fuzzy msgid "Covers" msgstr "Total storlek:" #: ../quodlibet/qltk/pluginwin.py:309 msgid "No plugins found." msgstr "Inga insticksmoduler hittades." #: ../quodlibet/qltk/pluginwin.py:358 msgid "Plugins" msgstr "Insticksmoduler" #: ../quodlibet/qltk/pluginwin.py:402 msgid "Show _Errors" msgstr "Visa _fel" #: ../quodlibet/qltk/prefs.py:45 msgid "_Disc" msgstr "_Skiva" #: ../quodlibet/qltk/prefs.py:46 msgid "_Track" msgstr "Sp_år" #: ../quodlibet/qltk/prefs.py:47 #, fuzzy msgid "Grou_ping" msgstr "gruppering" #: ../quodlibet/qltk/prefs.py:50 msgid "Al_bum" msgstr "Al_bum" #: ../quodlibet/qltk/prefs.py:55 msgid "_Filename" msgstr "_Filnamn" #: ../quodlibet/qltk/prefs.py:57 msgid "_Length" msgstr "_Längd" #: ../quodlibet/qltk/prefs.py:64 msgid "_Jump to playing song automatically" msgstr "_Hoppa automatiskt till spelande låt" #: ../quodlibet/qltk/prefs.py:66 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:82 msgid "_Others:" msgstr "_Andra:" #: ../quodlibet/qltk/prefs.py:88 #, fuzzy msgid "_Edit…" msgstr "_Redigera visning..." #: ../quodlibet/qltk/prefs.py:91 msgid "Add or remove additional column headers" msgstr "" #: ../quodlibet/qltk/prefs.py:101 msgid "Visible Columns" msgstr "Synliga kolumner" #: ../quodlibet/qltk/prefs.py:104 msgid "Title includes _version" msgstr "Titel innehåller _version" #: ../quodlibet/qltk/prefs.py:106 #, fuzzy msgid "Artist includes all _people" msgstr "Sökning inkluderar personer" #: ../quodlibet/qltk/prefs.py:108 msgid "Album includes _disc subtitle" msgstr "Album innehåller skivunderrubrik" #: ../quodlibet/qltk/prefs.py:110 msgid "Filename includes _folder" msgstr "Filnamn innehåller _mapp" #: ../quodlibet/qltk/prefs.py:123 #, fuzzy msgid "Column Preferences" msgstr "Inställningar" #: ../quodlibet/qltk/prefs.py:129 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "" #: ../quodlibet/qltk/prefs.py:142 ../quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Låtlista" #: ../quodlibet/qltk/prefs.py:222 #, fuzzy msgid "Edit Columns" msgstr "Synliga kolumner" #: ../quodlibet/qltk/prefs.py:259 msgid "Duration totals" msgstr "" #: ../quodlibet/qltk/prefs.py:271 msgid "_Global filter:" msgstr "_Globalt filter:" #: ../quodlibet/qltk/prefs.py:277 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:283 #, fuzzy msgctxt "heading" msgid "Search" msgstr "Sök" #: ../quodlibet/qltk/prefs.py:287 ../quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Bläddrare" #: ../quodlibet/qltk/prefs.py:293 msgid "Confirm _multiple ratings" msgstr "Bekräfta _multipla betyg" #: ../quodlibet/qltk/prefs.py:295 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:298 msgid "Enable _one-click ratings" msgstr "Aktivera_ enklicksbetyg" #: ../quodlibet/qltk/prefs.py:300 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:306 ../quodlibet/qltk/prefs.py:616 msgid "Ratings" msgstr "Betyg" #. Filename choice algorithm config #: ../quodlibet/qltk/prefs.py:312 msgid "Prefer _embedded art" msgstr "Föredra _inbäddade bilder" #: ../quodlibet/qltk/prefs.py:314 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:319 #, fuzzy msgid "_Fixed image filename:" msgstr "_Tvinga bildfilnamn:" #: ../quodlibet/qltk/prefs.py:321 #, fuzzy msgid "The single image filename to use if selected" msgstr "Albumbild som ska tvunget ska användas" #: ../quodlibet/qltk/prefs.py:327 msgid "The album art image file to use when forced" msgstr "Albumbild som ska tvunget ska användas" #: ../quodlibet/qltk/prefs.py:336 msgid "Album Art" msgstr "Albumomslag" #: ../quodlibet/qltk/prefs.py:357 msgid "Playback" msgstr "Uppspelning" #: ../quodlibet/qltk/prefs.py:362 msgid "Output Configuration" msgstr "Utkonfiguration" #: ../quodlibet/qltk/prefs.py:373 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:376 msgid "_Fall-back gain (dB):" msgstr "_Fall-back förstärkning (dB):" #: ../quodlibet/qltk/prefs.py:387 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:390 msgid "_Pre-amp gain (dB):" msgstr "_Pre-amp förstärkning (dB):" #: ../quodlibet/qltk/prefs.py:395 msgid "_Enable Replay Gain volume adjustment" msgstr "_Aktivera Replay Gain volymjusterning" #: ../quodlibet/qltk/prefs.py:420 msgid "Replay Gain Volume Adjustment" msgstr "Replay Gain volymjusterning" #: ../quodlibet/qltk/prefs.py:450 #, fuzzy msgid "_Default rating:" msgstr "Förval" #: ../quodlibet/qltk/prefs.py:493 #, fuzzy msgid "Rating _scale:" msgstr "Betyg" #: ../quodlibet/qltk/prefs.py:542 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:547 msgid "_Bayesian averaging amount:" msgstr "_Bayesisk medelvärdesfaktor" #: ../quodlibet/qltk/prefs.py:556 msgid "Save ratings and play _counts" msgstr "Spara betyg och antalet _spelningar" #: ../quodlibet/qltk/prefs.py:560 msgid "_Email:" msgstr "_Epost:" #: ../quodlibet/qltk/prefs.py:562 msgid "Ratings and play counts will be set for this email address" msgstr "" "Betyg och antalet spelningar kommer att sparas för denna epost adressen" #: ../quodlibet/qltk/prefs.py:577 msgid "Auto-save tag changes" msgstr "Spara taggförändringar automatiskt" #: ../quodlibet/qltk/prefs.py:579 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:587 #, 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:610 msgid "Tags" msgstr "Taggar" #: ../quodlibet/qltk/prefs.py:631 msgid "Updating for new ratings" msgstr "Uppdaterar betyg" #: ../quodlibet/qltk/prefs.py:641 #, fuzzy msgid "Scan library _on start" msgstr "_Uppdatera biblioteket vid programstart" #: ../quodlibet/qltk/prefs.py:651 ../quodlibet/qltk/quodlibetwindow.py:1100 #, fuzzy msgid "_Scan Library" msgstr "_Sök i bibliotek" #: ../quodlibet/qltk/prefs.py:653 ../quodlibet/qltk/quodlibetwindow.py:1162 msgid "Check for changes in your library" msgstr "Kontrollera ändringar i biblioteket" #: ../quodlibet/qltk/prefs.py:658 #, fuzzy msgid "Re_build Library" msgstr "Ladda om biblioteket" #: ../quodlibet/qltk/prefs.py:661 #, 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:671 msgid "Scan Directories" msgstr "Skanna mappar" #: ../quodlibet/qltk/prefs.py:677 #, fuzzy msgid "Hidden Songs" msgstr "Inga låtar" #: ../quodlibet/qltk/properties.py:158 ../quodlibet/util/collection.py:398 #, 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:162 ../quodlibet/qltk/properties.py:164 msgid "Properties" msgstr "Egenskaper" #: ../quodlibet/qltk/queue.py:101 msgid "_Queue" msgstr "_Kö" #: ../quodlibet/qltk/queue.py:126 msgid "Stop Once Empty" msgstr "" #: ../quodlibet/qltk/queue.py:130 #, fuzzy msgid "_Clear Queue" msgstr "_Rensa fel" #: ../quodlibet/qltk/queue.py:242 #, 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:198 msgid "_Browse Library" msgstr "_Bläddra i bibliotek" #: ../quodlibet/qltk/quodlibetwindow.py:395 #, fuzzy msgid "Toggle queue visibility" msgstr "Växla synlighet för huvudfönstret" #: ../quodlibet/qltk/quodlibetwindow.py:516 #, fuzzy msgid "Playback Error" msgstr "Uppspelning" #: ../quodlibet/qltk/quodlibetwindow.py:524 #, fuzzy msgid "Set up library directories?" msgstr "Välj mappar" #: ../quodlibet/qltk/quodlibetwindow.py:525 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:531 msgid "_Not Now" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:532 msgid "_Set Up" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:956 msgid "Unable to add songs" msgstr "Kunde ej lägga till låtar" #: ../quodlibet/qltk/quodlibetwindow.py:957 #: ../quodlibet/qltk/quodlibetwindow.py:1364 #, 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:980 msgid "_Jump to Playing Song" msgstr "_Hoppa till spelande låt" #: ../quodlibet/qltk/quodlibetwindow.py:986 #, fuzzy msgid "_File" msgstr "Fil" #: ../quodlibet/qltk/quodlibetwindow.py:987 #, fuzzy msgid "_Song" msgstr "Låtar" #: ../quodlibet/qltk/quodlibetwindow.py:988 msgid "_View" msgstr "_Visa" #: ../quodlibet/qltk/quodlibetwindow.py:989 #, fuzzy msgid "_Browse" msgstr "Bläddrare" #: ../quodlibet/qltk/quodlibetwindow.py:990 msgid "_Control" msgstr "_Kontroll" #: ../quodlibet/qltk/quodlibetwindow.py:991 msgid "_Help" msgstr "_Hjälp" #: ../quodlibet/qltk/quodlibetwindow.py:997 #, fuzzy msgid "_Add a Folder…" msgstr "Lägg _till mapp.." #: ../quodlibet/qltk/quodlibetwindow.py:1002 #, fuzzy msgid "_Add a File…" msgstr "Lägg _till fil..." #: ../quodlibet/qltk/quodlibetwindow.py:1007 #, fuzzy msgid "_Add a Location…" msgstr "Lägg till en plats" #: ../quodlibet/qltk/quodlibetwindow.py:1036 #, fuzzy msgid "Edit Bookmarks…" msgstr "_Redigera bokmärken" #: ../quodlibet/qltk/quodlibetwindow.py:1056 #, fuzzy msgid "Stop After This Song" msgstr "Stoppa efter denna låt" #: ../quodlibet/qltk/quodlibetwindow.py:1062 msgid "_Keyboard Shortcuts" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:1071 msgid "Online Help" msgstr "Onlinehjälp" #: ../quodlibet/qltk/quodlibetwindow.py:1080 msgid "Search Help" msgstr "Sök i hjälpen" #: ../quodlibet/qltk/quodlibetwindow.py:1352 msgid "Add a Location" msgstr "Lägg till en plats" #: ../quodlibet/qltk/quodlibetwindow.py:1353 msgid "Enter the location of an audio file:" msgstr "Ange platsen för en ljudfil:" #: ../quodlibet/qltk/quodlibetwindow.py:1358 #: ../quodlibet/qltk/quodlibetwindow.py:1363 msgid "Unable to add location" msgstr "Kan lägga till plats" #: ../quodlibet/qltk/quodlibetwindow.py:1359 #, fuzzy, python-format msgid "%s is not a valid location." msgstr "<b>%s</b> är ej en giltig plats." #: ../quodlibet/qltk/quodlibetwindow.py:1372 #: ../quodlibet/qltk/quodlibetwindow.py:1381 msgid "Add Music" msgstr "Lägg till musik" #: ../quodlibet/qltk/quodlibetwindow.py:1372 ../quodlibet/qltk/scanbox.py:99 #, fuzzy msgid "_Add Folders" msgstr "Lägg _till mapp.." #: ../quodlibet/qltk/quodlibetwindow.py:1379 #, fuzzy msgid "Music Files" msgstr "Musikspelare" #: ../quodlibet/qltk/quodlibetwindow.py:1381 #, fuzzy msgid "_Add Files" msgstr "Lägg _till fil..." #: ../quodlibet/qltk/ratingsmenu.py:24 #, 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:26 #, fuzzy msgid "The saved ratings will be removed" msgstr "Dubletter kommer att tas bort från spellistan '%s'." #: ../quodlibet/qltk/ratingsmenu.py:27 #, 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:57 ../quodlibet/qltk/ratingsmenu.py:111 #, fuzzy msgid "_Remove Rating" msgstr "Ta bort taggar" #: ../quodlibet/qltk/ratingsmenu.py:98 #, fuzzy msgid "Change _Rating" msgstr "_Betyg" #: ../quodlibet/qltk/renamefiles.py:46 msgid "Replace spaces with _underscores" msgstr "Ersätt mellanslag med _understreck" #: ../quodlibet/qltk/renamefiles.py:56 msgid "Strip _Windows-incompatible characters" msgstr "Ta bort _Windows-inkompatibla " #: ../quodlibet/qltk/renamefiles.py:74 msgid "Strip _diacritical marks" msgstr "Ta bort diakritiska tecken" #: ../quodlibet/qltk/renamefiles.py:85 msgid "Strip non-_ASCII characters" msgstr "Ta bort icke-ASCII-tecken" #: ../quodlibet/qltk/renamefiles.py:95 msgid "Use only _lowercase characters" msgstr "Använd enbart _gemener" #: ../quodlibet/qltk/renamefiles.py:123 msgid "Rename Files" msgstr "Byt namn på filer" #: ../quodlibet/qltk/renamefiles.py:139 ../quodlibet/qltk/tagsfrompath.py:116 msgid "Path Patterns" msgstr "Sökvägsmönster" #: ../quodlibet/qltk/renamefiles.py:140 ../quodlibet/qltk/tagsfrompath.py:117 #, fuzzy msgid "Edit saved patterns…" msgstr "Redigera sparade mönster" #: ../quodlibet/qltk/renamefiles.py:143 ../quodlibet/qltk/tagsfrompath.py:120 #: ../quodlibet/qltk/tracknumbers.py:58 msgid "_Preview" msgstr "_Förhandsgranska" #: ../quodlibet/qltk/renamefiles.py:190 msgid "New Name" msgstr "Nytt namn" #: ../quodlibet/qltk/renamefiles.py:255 msgid "Unable to rename file" msgstr "Kunde ej byta namn på fil" #: ../quodlibet/qltk/renamefiles.py:256 #, fuzzy, python-format msgid "" "Renaming <b>%(old-name)s</b> to <b>%(new-name)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." 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:264 msgid "Ignore _All Errors" msgstr "Ignorera _alla fel" #: ../quodlibet/qltk/renamefiles.py:267 msgid "_Continue" msgstr "_Fortsätt" #: ../quodlibet/qltk/renamefiles.py:296 msgid "Path is not absolute" msgstr "Sökvägen är ej absolut" #: ../quodlibet/qltk/renamefiles.py:297 #, python-format msgid "" "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 ~/." 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:47 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:99 msgid "Select Directories" msgstr "Välj mappar" #: ../quodlibet/qltk/searchbar.py:52 msgid "Saved Searches" msgstr "Sparade sökningar" #: ../quodlibet/qltk/searchbar.py:53 #, fuzzy msgid "Edit saved searches…" msgstr "Redigera sparade sökningar..." #: ../quodlibet/qltk/searchbar.py:74 msgid "Search your library, using free text or QL queries" msgstr "" #: ../quodlibet/qltk/searchbar.py:129 msgid "Search after _typing" msgstr "Sök när man slutat skriva" #: ../quodlibet/qltk/searchbar.py:132 msgid "Show search results after the user stops typing" msgstr "Visa sökresultat när användaren har slutat skriva" #: ../quodlibet/qltk/searchbar.py:187 msgid "_Limit:" msgstr "_Gräns:" #: ../quodlibet/qltk/searchbar.py:200 msgid "_Weight" msgstr "_Vikt" #: ../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 ../quodlibet/qltk/shortcuts.py:41 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: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:377 #, python-format msgid "_Filter on %s" msgstr "_Filtrera på %s" #: ../quodlibet/qltk/songlist.py:1094 msgid "All _Headers" msgstr "Alla _Kolumner" #: ../quodlibet/qltk/songlist.py:1095 msgid "_Track Headers" msgstr "_Spårkolumner" #: ../quodlibet/qltk/songlist.py:1096 msgid "_Album Headers" msgstr "_Albumkolumner" #: ../quodlibet/qltk/songlist.py:1097 msgid "_People Headers" msgstr "_Personkolumner" #: ../quodlibet/qltk/songlist.py:1098 msgid "_Date Headers" msgstr "_Datumkolumner" #: ../quodlibet/qltk/songlist.py:1099 msgid "_File Headers" msgstr "_Filkolumner" #: ../quodlibet/qltk/songlist.py:1100 msgid "_Production Headers" msgstr "_Produktionskolumner" #: ../quodlibet/qltk/songlist.py:1115 #, fuzzy msgid "_Customize Headers…" msgstr "_Kolumninställningar..." #: ../quodlibet/qltk/songlist.py:1120 msgid "_Expand Column" msgstr "" #: ../quodlibet/qltk/songsmenu.py:36 #, 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:64 #, 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:149 #, fuzzy msgid "Configure Plugins…" msgstr "Färglägg _söktermer" #: ../quodlibet/qltk/songsmenu.py:345 msgid "Add to _Queue" msgstr "Lägg till i _kö" #: ../quodlibet/qltk/songsmenu.py:368 msgid "_Copy to Device" msgstr "_Kopiera till enhet" #: ../quodlibet/qltk/songsmenu.py:379 #, fuzzy msgid "_Remove from Library" msgstr "_Ta bort från bibliotek" #: ../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:101 msgid "Tags From Path" msgstr "Taggar från sökväg" #: ../quodlibet/qltk/tagsfrompath.py:138 msgid "Tags replace existing ones" msgstr "Taggar ersätter redan existerande" #: ../quodlibet/qltk/tagsfrompath.py:139 msgid "Tags are added to existing ones" msgstr "Taggar läggs till till redan existerande" #. Save button #: ../quodlibet/qltk/tagsfrompath.py:153 msgid "Save" msgstr "" #: ../quodlibet/qltk/tagsfrompath.py:195 #, python-format msgid "" "The pattern\n" "\t<b>%s</b>\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/tagsfrompath.py:216 msgid "Invalid tags" msgstr "Ogiltiga taggar" #: ../quodlibet/qltk/tagsfrompath.py:217 #, 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." #: ../quodlibet/qltk/textedit.py:142 #, 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:158 msgid "Edit Display" msgstr "Redigera visning" #: ../quodlibet/qltk/tracknumbers.py:39 msgid "Track Numbers" msgstr "Spårnummer" #: ../quodlibet/qltk/tracknumbers.py:42 msgid "Start fro_m:" msgstr "Börja frå_n" #: ../quodlibet/qltk/tracknumbers.py:51 msgid "_Total tracks:" msgstr "_Antal spår:" #: ../quodlibet/qltk/unity.py:52 msgid "Play/Pause" msgstr "Spela upp/pausera" #: ../quodlibet/qltk/unity.py:75 msgid "Previous" msgstr "Föregående" #: ../quodlibet/qltk/views.py:923 #, 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:89 #, fuzzy msgid "Checking for Updates" msgstr "Kontrollerar monteringspunkter" #: ../quodlibet/update.py:124 #, fuzzy msgid "Connection failed" msgstr "plats" #: ../quodlibet/update.py:133 #, python-format msgid "You are already using the newest version %(version)s" msgstr "" #: ../quodlibet/update.py:136 #, 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:420 msgid "Playlists must have a name" msgstr "" #: ../quodlibet/util/collection.py:603 #, python-format msgid "A playlist named %s already exists." msgstr "En spellista med namnet %s finns redan." #: ../quodlibet/util/cover/built_in.py:26 #, fuzzy msgid "Embedded album covers" msgstr "Ladda om omslaget" #: ../quodlibet/util/cover/built_in.py:27 msgid "Uses covers embedded into audio files." msgstr "" #: ../quodlibet/util/cover/built_in.py:49 #, fuzzy msgid "Filesystem cover" msgstr "Filsystem" #: ../quodlibet/util/cover/built_in.py:50 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "" #: ../quodlibet/util/__init__.py:93 msgid "Display brief usage information" msgstr "Visa kortfattad användningsinformation" #: ../quodlibet/util/__init__.py:95 msgid "Display version and copyright" msgstr "Visa version och copyright" #: ../quodlibet/util/__init__.py:135 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "" #: ../quodlibet/util/__init__.py:137 msgid "[options]" msgstr "[alternativ]" #: ../quodlibet/util/__init__.py:182 #, python-format msgid "Option %r not recognized." msgstr "Alternativet %r känns ej igen." #: ../quodlibet/util/__init__.py:185 #, python-format msgid "Option %r requires an argument." msgstr "Alternativet %r kräver ett argument." #: ../quodlibet/util/__init__.py:188 #, python-format msgid "%r is not a unique prefix." msgstr "%r är ej ett unikt prefix." #: ../quodlibet/util/__init__.py:364 #, python-format msgid "%d kbps" msgstr "%d kbit/s" #: ../quodlibet/util/__init__.py:419 #, fuzzy, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%d sekund" msgstr[1] "%d sekunder" #: ../quodlibet/util/__init__.py:432 msgid "No time information" msgstr "Ingen tidsinformation" #: ../quodlibet/util/__init__.py:435 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d sekund" msgstr[1] "%d sekunder" #: ../quodlibet/util/__init__.py:436 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d minut" msgstr[1] "%d minuter" #: ../quodlibet/util/__init__.py:437 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d timma" msgstr[1] "%d timmar" #: ../quodlibet/util/__init__.py:438 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d dag" msgstr[1] "%d dagar" #: ../quodlibet/util/__init__.py:439 #, 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:563 #, 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 msgid "Unable to edit song" msgstr "Kunde ej redigera låt" #: ../quodlibet/util/songwrapper.py:113 #, python-format msgid "" "Saving <b>%s</b> 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:34 #: ../quodlibet/util/string/__init__.py:44 msgid "[Invalid Encoding]" msgstr "[Oglitig kodning]" #: ../quodlibet/util/tags.py:74 msgid "album" msgstr "album" #: ../quodlibet/util/tags.py:75 msgid "arranger" msgstr "arrangör" #: ../quodlibet/util/tags.py:75 msgid "arrangers" msgstr "arrangörer" #: ../quodlibet/util/tags.py:75 #, fuzzy msgid "arrangement" msgstr "arrangör" #: ../quodlibet/util/tags.py:77 msgid "author" msgstr "författare" #: ../quodlibet/util/tags.py:77 msgid "authors" msgstr "författare" #: ../quodlibet/util/tags.py:78 msgid "composer" msgstr "kompositör" #: ../quodlibet/util/tags.py:78 msgid "composers" msgstr "kompositörer" #: ../quodlibet/util/tags.py:78 #, fuzzy msgid "composition" msgstr "kompositör" #. Translators: conducting as in conducting a musical performance #: ../quodlibet/util/tags.py:80 msgid "conductor" msgstr "dirigent" #: ../quodlibet/util/tags.py:80 msgid "conductors" msgstr "dirigenter" #: ../quodlibet/util/tags.py:80 #, fuzzy msgid "conducting" msgstr "dirigent" #: ../quodlibet/util/tags.py:81 msgid "contact" msgstr "kontakt" #: ../quodlibet/util/tags.py:82 msgid "copyright" msgstr "copyright" #: ../quodlibet/util/tags.py:83 msgid "date" msgstr "datum" #: ../quodlibet/util/tags.py:84 msgid "description" msgstr "beskrivning" #: ../quodlibet/util/tags.py:85 msgid "genre" msgstr "genre" #: ../quodlibet/util/tags.py:85 #, fuzzy msgid "genres" msgstr "genre" #: ../quodlibet/util/tags.py:86 msgid "performer" msgstr "uppträdande" #: ../quodlibet/util/tags.py:87 msgid "grouping" msgstr "gruppering" #: ../quodlibet/util/tags.py:88 msgid "language" msgstr "språk" #: ../quodlibet/util/tags.py:89 msgid "license" msgstr "licens" #: ../quodlibet/util/tags.py:90 msgid "location" msgstr "plats" #: ../quodlibet/util/tags.py:91 msgid "lyricist" msgstr "lyrist" #: ../quodlibet/util/tags.py:91 msgid "lyricists" msgstr "lyrister" #: ../quodlibet/util/tags.py:91 #, fuzzy msgid "lyrics" msgstr "lyrist" #. Translators: Also e.g. "record label", "publisher" #: ../quodlibet/util/tags.py:93 msgid "organization" msgstr "organisation" #: ../quodlibet/util/tags.py:94 msgid "title" msgstr "titel" #: ../quodlibet/util/tags.py:95 msgid "version" msgstr "version" #: ../quodlibet/util/tags.py:96 msgid "website" msgstr "webbsida" #: ../quodlibet/util/tags.py:98 msgid "album artist" msgstr "album artist" #: ../quodlibet/util/tags.py:99 msgid "BPM" msgstr "BPM" #. Translators: This used to be called "part". #: ../quodlibet/util/tags.py:102 ../quodlibet/util/tags.py:103 msgid "disc subtitle" msgstr "Skivunderrubrik" #: ../quodlibet/util/tags.py:104 ../quodlibet/util/tags.py:141 msgid "disc" msgstr "skiva" #: ../quodlibet/util/tags.py:105 ../quodlibet/util/tags.py:143 msgid "track" msgstr "spår" #: ../quodlibet/util/tags.py:106 msgid "label ID" msgstr "katalognummer" #: ../quodlibet/util/tags.py:107 msgid "original release date" msgstr "ursprungligt släppdatum" #: ../quodlibet/util/tags.py:108 msgid "original album" msgstr "ursprungligt album" #: ../quodlibet/util/tags.py:109 msgid "original artist" msgstr "ursprunglig artist" #: ../quodlibet/util/tags.py:110 msgid "recording date" msgstr "inspelningsdatum" #: ../quodlibet/util/tags.py:111 msgid "release country" msgstr "utgivningsland" #. 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:120 #, fuzzy msgid "MusicBrainz recording ID" msgstr "MusicBrainz spår-ID" #: ../quodlibet/util/tags.py:121 #, fuzzy msgid "MusicBrainz release track ID" msgstr "MusicBrainz release-ID" #: ../quodlibet/util/tags.py:122 msgid "MusicBrainz release ID" msgstr "MusicBrainz release-ID" #: ../quodlibet/util/tags.py:123 #, fuzzy msgid "MusicBrainz artist ID" msgstr "MusicBrainz artist-ID" #: ../quodlibet/util/tags.py:124 #, fuzzy msgid "MusicBrainz release artist ID" msgstr "MusicBrainz release-ID" #: ../quodlibet/util/tags.py:125 msgid "MusicBrainz TRM ID" msgstr "MusicBrainz TRM ID" #: ../quodlibet/util/tags.py:126 msgid "MusicIP PUID" msgstr "MusicIP PUID" #: ../quodlibet/util/tags.py:127 msgid "MusicBrainz album status" msgstr "MusicBrainz album status" #: ../quodlibet/util/tags.py:128 msgid "MusicBrainz album type" msgstr "MusicBrainz album typ" #: ../quodlibet/util/tags.py:129 #, fuzzy msgid "MusicBrainz release group ID" msgstr "MusicBrainz release-ID" #. Translators: "gain" means a volume adjustment, not "to acquire". #: ../quodlibet/util/tags.py:132 msgid "track gain" msgstr "spårförstärkning" #: ../quodlibet/util/tags.py:133 msgid "track peak" msgstr "spårtopp" #. Translators: "gain" means a volume adjustment, not "to acquire". #: ../quodlibet/util/tags.py:135 msgid "album gain" msgstr "albumförstärkning" #: ../quodlibet/util/tags.py:136 msgid "album peak" msgstr "albumtopp" #: ../quodlibet/util/tags.py:137 msgid "reference loudness" msgstr "Referensljudstyrka" #: ../quodlibet/util/tags.py:142 msgid "discs" msgstr "skivor" #: ../quodlibet/util/tags.py:144 msgid "tracks" msgstr "spår" #: ../quodlibet/util/tags.py:145 msgid "last started" msgstr "senast spelad" #: ../quodlibet/util/tags.py:146 msgid "full name" msgstr "fullt namn" #: ../quodlibet/util/tags.py:153 msgid "mount point" msgstr "monteringspunkt" #: ../quodlibet/util/tags.py:155 msgid "people" msgstr "personer" #: ../quodlibet/util/tags.py:157 msgid "year" msgstr "år" #: ../quodlibet/util/tags.py:158 msgid "original release year" msgstr "ursprungligt släppdatum" #: ../quodlibet/util/tags.py:159 msgid "bookmark" msgstr "Bokmärke" #: ../quodlibet/util/tags.py:162 msgid "file format" msgstr "filformat" #: ../quodlibet/util/tags.py:165 #, fuzzy msgid "playlists" msgstr "Spellistor" #: ../quodlibet/util/tags.py:166 msgid "channel count" msgstr "" #. Translators: e.g. "artist (sort)" #: ../quodlibet/util/tags.py:256 msgid "sort" msgstr "" #. Translators: e.g. "performer (roles)" #: ../quodlibet/util/tags.py:264 msgid "roles" msgstr "" #, 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 "Remove all songs from the queue" #~ msgstr "Ta bort alla låtar från kön" #~ msgid "Watch this folder for new songs" #~ msgstr "Vaka över denna mapp för nya låtar" #~ 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 "Model:" #~ msgstr "Modell:" #~ msgid "Capacity:" #~ msgstr "Kapacitet:" #~ msgid "Firmware:" #~ msgstr "Firmware:" #~ msgid "Removing orphaned iPod track" #~ msgstr "Tar bort överblivna iPod-låtar" #, 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 "Unable to open input files" #~ msgstr "Kunde ej öppna infiler" #~ 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 "General" #~ msgstr "Övergripande" #~ 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 "_Select" #~ msgstr "_Välj" #~ 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 "Choose New Stations" #~ msgstr "Välj nya stationer" #~ msgid "Add" #~ msgstr "Lägg till" #, fuzzy #~ msgid "Bitrate" #~ msgstr "bitrate" #~ msgid "_Stations..." #~ msgstr "_Stationer..." #, fuzzy #~ msgid "Quod Libet" #~ msgstr "Avsluta Quod Libet" #~ 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9751859 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/po/tr.po����������������������������������������������������������������������������0000644�0001750�0001750�00000526175�00000000000�014121� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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: 2017-05-17 18:58+0200\n" "PO-Revision-Date: 2013-07-20 22:32+0100\n" "Last-Translator: Turerkan <turerkan@gmail.com>\n" "Language-Team: Turerkan <turerkan@gmail.com>\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: Poedit 1.5.4\n" #: ../data/exfalso.appdata.xml.in.h:1 ../data/exfalso.desktop.in.h:2 msgid "Edit tags in your audio files" msgstr "Ses dosyalarınızdaki etiketleri düzenler" #: ../data/exfalso.appdata.xml.in.h:2 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/exfalso.appdata.xml.in.h:3 ../data/quodlibet.appdata.xml.in.h:3 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/exfalso.desktop.in.h:1 msgid "Audio tag editor" msgstr "Müzik etiketleri düzenleyici" #: ../data/quodlibet.appdata.xml.in.h:1 ../data/quodlibet.desktop.in.h:2 msgid "Listen to, browse, or edit your audio collection" msgstr "Müzik arşivinizi gezin, dinleyin, düzenleyin" #: ../data/quodlibet.appdata.xml.in.h:2 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 "" #: ../data/quodlibet.desktop.in.h:1 msgid "Music Player" msgstr "Müzik Çalar" #: ../quodlibet/browsers/albums/main.py:168 #: ../quodlibet/browsers/covergrid/main.py:54 #, fuzzy msgid "_Title" msgstr "Ad" #: ../quodlibet/browsers/albums/main.py:169 #: ../quodlibet/browsers/covergrid/main.py:55 ../quodlibet/qltk/prefs.py:49 msgid "_Artist" msgstr "_Sanatçı" #: ../quodlibet/browsers/albums/main.py:170 #: ../quodlibet/browsers/covergrid/main.py:56 ../quodlibet/qltk/prefs.py:54 msgid "_Date" msgstr "_Tarih" #: ../quodlibet/browsers/albums/main.py:171 #: ../quodlibet/browsers/covergrid/main.py:57 ../quodlibet/qltk/prefs.py:53 #, fuzzy msgid "_Genre" msgstr "Tür" #: ../quodlibet/browsers/albums/main.py:172 #: ../quodlibet/browsers/covergrid/main.py:58 ../quodlibet/qltk/prefs.py:58 #: ../quodlibet/qltk/ratingsmenu.py:39 msgid "_Rating" msgstr "_Puan" #: ../quodlibet/browsers/albums/main.py:178 #: ../quodlibet/browsers/covergrid/main.py:64 #, fuzzy msgid "Sort _by…" msgstr "Tarihe göre sırala" #: ../quodlibet/browsers/albums/main.py:199 #: ../quodlibet/browsers/covergrid/main.py:85 #: ../quodlibet/browsers/paned/prefs.py:166 #: ../quodlibet/browsers/playlists/main.py:629 #: ../quodlibet/qltk/exfalsowindow.py:109 ../quodlibet/qltk/pluginwin.py:341 #: ../quodlibet/qltk/quodlibetwindow.py:1016 #, fuzzy msgid "_Preferences" msgstr "Ayarlar" #: ../quodlibet/browsers/albums/main.py:361 msgid "Album List" msgstr "Albüm Listesi" #: ../quodlibet/browsers/albums/main.py:362 msgid "_Album List" msgstr "_Albüm Listesi" #: ../quodlibet/browsers/albums/main.py:472 #: ../quodlibet/browsers/covergrid/main.py:279 #: ../quodlibet/browsers/covergrid/main.py:488 msgid "All Albums" msgstr "Tüm albümler" #: ../quodlibet/browsers/albums/main.py:473 #: ../quodlibet/browsers/covergrid/main.py:280 #: ../quodlibet/browsers/covergrid/main.py:489 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d albüm" msgstr[1] "%d albüm" #: ../quodlibet/browsers/albums/main.py:650 #: ../quodlibet/browsers/covergrid/main.py:467 #, fuzzy msgid "Reload album _cover" msgid_plural "Reload album _covers" msgstr[0] "Albüm _kapaklarını göster" msgstr[1] "Albüm _kapaklarını göster" #: ../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:381 ../quodlibet/util/collection.py:245 #, python-format msgid "%d track" msgid_plural "%d tracks" msgstr[0] "%d şarkı" msgstr[1] "%d şarkı" #: ../quodlibet/browsers/albums/prefs.py:42 #: ../quodlibet/browsers/covergrid/prefs.py:44 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:97 #: ../quodlibet/qltk/information.py:379 ../quodlibet/util/collection.py:249 #, 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 #, fuzzy msgid "An Example Album" msgstr "Tüm albümler" #: ../quodlibet/browsers/albums/prefs.py:52 msgid "Album List Preferences" msgstr "Albüm listesi ayarları" #: ../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:120 #, fuzzy msgid "Options" msgstr "[ayarlar]" #: ../quodlibet/browsers/albums/prefs.py:74 #: ../quodlibet/browsers/covergrid/prefs.py:123 msgid "Album Display" msgstr "Albüm Görünümü" #: ../quodlibet/browsers/albums/prefs.py:78 #: ../quodlibet/browsers/covergrid/prefs.py:127 #: ../quodlibet/browsers/media.py:39 #: ../quodlibet/browsers/playlists/prefs.py:56 #: ../quodlibet/ext/songsmenu/albumart.py:326 #: ../quodlibet/ext/songsmenu/duplicates.py:350 #: ../quodlibet/ext/songsmenu/filterall.py:48 #: ../quodlibet/qltk/bookmarks.py:101 ../quodlibet/qltk/cbes.py:93 #: ../quodlibet/qltk/data_editors.py:99 ../quodlibet/qltk/data_editors.py:324 #: ../quodlibet/qltk/exfalsowindow.py:297 ../quodlibet/qltk/pluginwin.py:79 #: ../quodlibet/qltk/pluginwin.py:427 ../quodlibet/qltk/prefs.py:707 #: ../quodlibet/qltk/textedit.py:164 ../quodlibet/update.py:148 msgid "_Close" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:55 #: ../quodlibet/browsers/audiofeeds.py:67 #: ../quodlibet/browsers/audiofeeds.py:69 #: ../quodlibet/browsers/audiofeeds.py:159 #: ../quodlibet/browsers/paned/models.py:86 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:46 #: ../quodlibet/formats/_audio.py:495 ../quodlibet/order/__init__.py:27 #: ../quodlibet/qltk/information.py:240 ../quodlibet/qltk/information.py:247 #: ../quodlibet/qltk/information.py:273 ../quodlibet/qltk/wlw.py:70 msgid "Unknown" msgstr "Bilinmeyen" #: ../quodlibet/browsers/audiofeeds.py:246 msgid "New Feed" msgstr "Yeni Bildirim" #: ../quodlibet/browsers/audiofeeds.py:247 msgid "Enter the location of an audio feed:" msgstr "Ses bildiriminin yerini girin:" #: ../quodlibet/browsers/audiofeeds.py:248 #: ../quodlibet/browsers/collection/prefs.py:90 #: ../quodlibet/browsers/iradio.py:341 ../quodlibet/browsers/paned/prefs.py:78 #: ../quodlibet/browsers/playlists/menu.py:96 #: ../quodlibet/browsers/playlists/util.py:52 ../quodlibet/qltk/bookmarks.py:62 #: ../quodlibet/qltk/cbes.py:55 ../quodlibet/qltk/data_editors.py:311 #: ../quodlibet/qltk/edittags.py:288 ../quodlibet/qltk/edittags.py:488 #: ../quodlibet/qltk/quodlibetwindow.py:1354 ../quodlibet/qltk/scanbox.py:61 msgid "_Add" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:265 msgid "Audio Feeds" msgstr "Ses bildirimleri" #: ../quodlibet/browsers/audiofeeds.py:266 msgid "_Audio Feeds" msgstr "_Ses Bildirimleri" #: ../quodlibet/browsers/audiofeeds.py:345 #: ../quodlibet/browsers/audiofeeds.py:350 #, fuzzy msgid "_Download…" msgstr "_İndir" #: ../quodlibet/browsers/audiofeeds.py:359 msgid "Download Files" msgstr "Dosyaları İndir" #. Save button #: ../quodlibet/browsers/audiofeeds.py:359 #: ../quodlibet/browsers/audiofeeds.py:371 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:81 #: ../quodlibet/ext/songsmenu/albumart.py:322 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:355 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:278 #: ../quodlibet/ext/songsmenu/html.py:76 #: ../quodlibet/ext/songsmenu/lastfmsync.py:216 #: ../quodlibet/ext/songsmenu/playlist.py:51 #: ../quodlibet/ext/songsmenu/replaygain.py:365 #: ../quodlibet/ext/songsmenu/tapbpm.py:182 ../quodlibet/qltk/_editutils.py:39 #: ../quodlibet/qltk/lyrics.py:38 ../quodlibet/qltk/msg.py:52 #: ../quodlibet/qltk/renamefiles.py:168 ../quodlibet/qltk/tracknumbers.py:113 msgid "_Save" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:371 msgid "Download File" msgstr "Dosyayı İndir" #: ../quodlibet/browsers/audiofeeds.py:394 #: ../quodlibet/browsers/playlists/main.py:213 #: ../quodlibet/qltk/data_editors.py:96 msgid "_New" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:454 #: ../quodlibet/browsers/audiofeeds.py:513 msgid "Unable to add feed" msgstr "Bildirim eklenemiyor" #: ../quodlibet/browsers/audiofeeds.py:455 #: ../quodlibet/browsers/audiofeeds.py:514 #, fuzzy, python-format msgid "" "%s could not be added. The server may be down, or the location may not be an " "audio feed." msgstr "" "<b>%s</b> eklenemedi. Sunucu çalışmıyor olabilir, veya adreste bir ses " "bildirimi olmayabilir." #. refresh button #: ../quodlibet/browsers/audiofeeds.py:462 ../quodlibet/browsers/media.py:217 #: ../quodlibet/browsers/media.py:386 ../quodlibet/qltk/filesel.py:259 #: ../quodlibet/qltk/pluginwin.py:413 #, fuzzy msgid "_Refresh" msgstr "Arşivi _Yenile" #: ../quodlibet/browsers/audiofeeds.py:463 #: ../quodlibet/browsers/playlists/main.py:457 #: ../quodlibet/browsers/playlists/util.py:43 ../quodlibet/qltk/delete.py:143 #: ../quodlibet/qltk/filesel.py:256 ../quodlibet/qltk/lyrics.py:39 #: ../quodlibet/qltk/maskedbox.py:28 ../quodlibet/qltk/songsmenu.py:392 #, fuzzy msgid "_Delete" msgstr "Dosyaları Sil" #: ../quodlibet/browsers/audiofeeds.py:530 msgid "" "The current audio backend does not support URLs, Audio Feeds browser " "disabled." msgstr "" #: ../quodlibet/browsers/_base.py:147 ../quodlibet/browsers/_base.py:150 msgid "Library Browser" msgstr "Arşiv Gezici" #: ../quodlibet/browsers/_base.py:274 ../quodlibet/ext/songsmenu/refresh.py:30 #: ../quodlibet/qltk/exfalsowindow.py:241 ../quodlibet/qltk/information.py:542 #: ../quodlibet/qltk/maskedbox.py:68 ../quodlibet/util/collection.py:527 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d şarkı" msgstr[1] "%d şarkı" #: ../quodlibet/browsers/_base.py:402 ../quodlibet/browsers/_base.py:407 #: ../quodlibet/qltk/tagsfrompath.py:194 ../quodlibet/qltk/textedit.py:141 #: ../quodlibet/util/__init__.py:622 msgid "Invalid pattern" msgstr "Geçersiz süzgeç" #: ../quodlibet/browsers/collection/main.py:78 msgid "Album Collection" msgstr "" #: ../quodlibet/browsers/collection/main.py:79 msgid "Album _Collection" msgstr "" #: ../quodlibet/browsers/collection/models.py:24 #, fuzzy, python-format msgid "Unknown %s" msgstr "Bilinmeyen" #: ../quodlibet/browsers/collection/models.py:25 #, fuzzy, python-format msgid "Multiple %s Values" msgstr "Birden fazla değelere _böl" #: ../quodlibet/browsers/collection/prefs.py:66 #: ../quodlibet/browsers/paned/prefs.py:51 msgid "_Custom" msgstr "_Özel" #. Remove button #: ../quodlibet/browsers/collection/prefs.py:94 #: ../quodlibet/browsers/paned/prefs.py:82 #: ../quodlibet/browsers/playlists/menu.py:97 #: ../quodlibet/ext/playlist/remove_duplicates.py:60 #: ../quodlibet/qltk/bookmarks.py:97 ../quodlibet/qltk/bookmarks.py:127 #: ../quodlibet/qltk/cbes.py:82 ../quodlibet/qltk/cbes.py:89 #: ../quodlibet/qltk/data_editors.py:81 ../quodlibet/qltk/data_editors.py:94 #: ../quodlibet/qltk/data_editors.py:301 ../quodlibet/qltk/data_editors.py:314 #: ../quodlibet/qltk/data_editors.py:322 ../quodlibet/qltk/edittags.py:494 #: ../quodlibet/qltk/edittags.py:634 ../quodlibet/qltk/maskedbox.py:48 #: ../quodlibet/qltk/maskedbox.py:88 ../quodlibet/qltk/queue.py:350 #: ../quodlibet/qltk/scanbox.py:36 ../quodlibet/qltk/scanbox.py:63 #, fuzzy msgid "_Remove" msgstr "_Puan" #: ../quodlibet/browsers/collection/prefs.py:122 #: ../quodlibet/ext/songsmenu/filterall.py:34 #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:92 #: ../quodlibet/qltk/edittags.py:431 msgid "Tag" msgstr "Etiket" #: ../quodlibet/browsers/collection/prefs.py:128 msgid "Merge" msgstr "" #: ../quodlibet/browsers/collection/prefs.py:188 #, fuzzy msgid "Album Collection Preferences" msgstr "Albüm listesi ayarları" #: ../quodlibet/browsers/collection/prefs.py:195 #: ../quodlibet/browsers/paned/prefs.py:209 #: ../quodlibet/ext/songsmenu/editplaycount.py:45 #: ../quodlibet/ext/songsmenu/exact_rating.py:38 #: ../quodlibet/player/gstbe/prefs.py:40 ../quodlibet/qltk/prefs.py:127 #: ../quodlibet/qltk/textedit.py:65 msgid "_Apply" msgstr "" #: ../quodlibet/browsers/collection/prefs.py:198 #: ../quodlibet/browsers/paned/prefs.py:213 #: ../quodlibet/browsers/playlists/menu.py:95 #: ../quodlibet/browsers/playlists/util.py:42 #: ../quodlibet/errorreport/ui.py:108 #: ../quodlibet/ext/playlist/export_to_folder.py:37 #: ../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:44 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:281 #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:88 #: ../quodlibet/ext/songsmenu/importexport.py:35 #: ../quodlibet/ext/songsmenu/lastfmsync.py:215 #: ../quodlibet/ext/songsmenu/playlist.py:50 #: ../quodlibet/ext/songsmenu/replaygain.py:364 #: ../quodlibet/ext/songsmenu/tapbpm.py:181 ../quodlibet/plugins/playlist.py:39 #: ../quodlibet/qltk/chooser.py:184 ../quodlibet/qltk/chooser.py:205 #: ../quodlibet/qltk/chooser.py:229 ../quodlibet/qltk/chooser.py:253 #: ../quodlibet/qltk/delete.py:90 ../quodlibet/qltk/delete.py:133 #: ../quodlibet/qltk/edittags.py:287 ../quodlibet/qltk/_editutils.py:38 #: ../quodlibet/qltk/getstring.py:28 ../quodlibet/qltk/maskedbox.py:27 #: ../quodlibet/qltk/msg.py:54 ../quodlibet/qltk/msg.py:93 #: ../quodlibet/qltk/ratingsmenu.py:33 ../quodlibet/qltk/songsmenu.py:45 #: ../quodlibet/qltk/songsmenu.py:73 ../quodlibet/update.py:94 msgid "_Cancel" msgstr "" #: ../quodlibet/browsers/covergrid/main.py:125 #, fuzzy msgid "Cover Grid" msgstr "Toplam boyut:" #: ../quodlibet/browsers/covergrid/main.py:126 #, fuzzy msgid "_Cover Grid" msgstr "Toplam boyut:" #: ../quodlibet/browsers/covergrid/prefs.py:54 #, fuzzy msgid "Cover Grid Preferences" msgstr "Panelli Gezici Ayarları" #: ../quodlibet/browsers/covergrid/prefs.py:64 #, fuzzy msgid "Show album _text" msgstr "Albüm _kapaklarını göster" #: ../quodlibet/browsers/covergrid/prefs.py:71 #, fuzzy msgid "Show \"All Albums\" Item" msgstr "Tüm albümler" #: ../quodlibet/browsers/covergrid/prefs.py:78 msgid "Vertical Split" msgstr "" #: ../quodlibet/browsers/covergrid/prefs.py:110 #: ../quodlibet/browsers/covergrid/prefs.py:111 #, fuzzy msgid "Cover Magnification" msgstr "organizasyon" #: ../quodlibet/browsers/filesystem.py:40 msgid "File System" msgstr "Dosya Sistemi" #: ../quodlibet/browsers/filesystem.py:41 msgid "_File System" msgstr "_Dosya Sistemi" #: ../quodlibet/browsers/filesystem.py:113 ../quodlibet/browsers/media.py:491 #: ../quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "Şarkılar kopyalanamıyor" #: ../quodlibet/browsers/filesystem.py:114 ../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:189 msgid "_Add to Library" msgstr "_Arşive Ekle" #: ../quodlibet/browsers/iradio.py:178 msgid "Unsupported file type" msgstr "Dosya türü desteklenmiyor" #: ../quodlibet/browsers/iradio.py:179 #, 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 "" "Kanal listesi sadece kanal adresi içerebilir. Diğer kanal listelerini veya " "çalma listelerini içeremez. Bu adres yüklenemedi:\n" "%s" #: ../quodlibet/browsers/iradio.py:219 ../quodlibet/browsers/iradio.py:232 #: ../quodlibet/browsers/iradio.py:810 msgid "Unable to add station" msgstr "Kanal eklenemedi" #: ../quodlibet/browsers/iradio.py:243 ../quodlibet/browsers/iradio.py:471 msgid "Internet Radio" msgstr "İnternet Radyosu" #: ../quodlibet/browsers/iradio.py:243 #, fuzzy msgid "Downloading station list" msgstr "Dosyaları İndir" #: ../quodlibet/browsers/iradio.py:339 msgid "New Station" msgstr "Yeni Kanal" #: ../quodlibet/browsers/iradio.py:340 msgid "Enter the location of an Internet radio station:" msgstr "İnternet radyo kanalı adresi girin:" #: ../quodlibet/browsers/iradio.py:358 msgid "Electronic" msgstr "" #: ../quodlibet/browsers/iradio.py:361 msgid "Hip Hop / Rap" msgstr "" #: ../quodlibet/browsers/iradio.py:362 msgid "Oldies" msgstr "" #: ../quodlibet/browsers/iradio.py:363 msgid "R&B" msgstr "" #: ../quodlibet/browsers/iradio.py:364 msgid "Japanese" msgstr "" #: ../quodlibet/browsers/iradio.py:365 msgid "Indian" msgstr "" #: ../quodlibet/browsers/iradio.py:367 msgid "Religious" msgstr "" #: ../quodlibet/browsers/iradio.py:369 msgid "Charts" msgstr "" #: ../quodlibet/browsers/iradio.py:370 msgid "Turkish" msgstr "" #: ../quodlibet/browsers/iradio.py:371 msgid "Reggae / Dancehall" msgstr "" #: ../quodlibet/browsers/iradio.py:372 #, fuzzy msgid "Latin" msgstr "puan" #: ../quodlibet/browsers/iradio.py:373 msgid "College Radio" msgstr "" #: ../quodlibet/browsers/iradio.py:374 msgid "Talk / News" msgstr "" #: ../quodlibet/browsers/iradio.py:375 msgid "Ambient" msgstr "" #: ../quodlibet/browsers/iradio.py:376 msgid "Jazz" msgstr "" #: ../quodlibet/browsers/iradio.py:377 ../quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "" #: ../quodlibet/browsers/iradio.py:378 ../quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "" #: ../quodlibet/browsers/iradio.py:379 msgid "Alternative" msgstr "" #: ../quodlibet/browsers/iradio.py:380 msgid "Metal" msgstr "" #: ../quodlibet/browsers/iradio.py:381 msgid "Country" msgstr "" #: ../quodlibet/browsers/iradio.py:382 msgid "News" msgstr "" #: ../quodlibet/browsers/iradio.py:383 msgid "Schlager" msgstr "" #: ../quodlibet/browsers/iradio.py:384 msgid "Funk" msgstr "" #: ../quodlibet/browsers/iradio.py:385 msgid "Indie" msgstr "" #: ../quodlibet/browsers/iradio.py:386 msgid "Blues" msgstr "" #: ../quodlibet/browsers/iradio.py:387 msgid "Soul" msgstr "" #: ../quodlibet/browsers/iradio.py:388 msgid "Lounge" msgstr "" #: ../quodlibet/browsers/iradio.py:389 msgid "Punk" msgstr "" #: ../quodlibet/browsers/iradio.py:390 msgid "Reggaeton" msgstr "" #: ../quodlibet/browsers/iradio.py:392 msgid "Slavic" msgstr "" #: ../quodlibet/browsers/iradio.py:394 msgid "Greek" msgstr "" #: ../quodlibet/browsers/iradio.py:395 msgid "Gothic" msgstr "" #: ../quodlibet/browsers/iradio.py:396 ../quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "" #: ../quodlibet/browsers/iradio.py:449 msgid "Would you like to load a list of popular radio stations?" msgstr "" #: ../quodlibet/browsers/iradio.py:455 #, fuzzy msgid "_Load Stations" msgstr "_Yeni Kanal" #: ../quodlibet/browsers/iradio.py:472 msgid "_Internet Radio" msgstr "_İnternet Radyosu" #: ../quodlibet/browsers/iradio.py:538 #, fuzzy msgid "_New Station…" msgstr "Yeni Kanal" #: ../quodlibet/browsers/iradio.py:541 #, fuzzy msgid "_Update Stations" msgstr "_Yeni Kanal" #: ../quodlibet/browsers/iradio.py:568 #, fuzzy msgid "All Stations" msgstr "Yeni Kanal" #. TODO: support for ~#rating=!None etc (#1940) #: ../quodlibet/browsers/iradio.py:572 #: ../quodlibet/browsers/soundcloud/main.py:64 msgid "Favorites" msgstr "" #: ../quodlibet/browsers/iradio.py:580 msgid "No Category" msgstr "" #: ../quodlibet/browsers/iradio.py:802 msgid "No stations found" msgstr "Kanal bulunamadı" #: ../quodlibet/browsers/iradio.py:803 #, python-format msgid "No Internet radio stations were found at %s." msgstr "%s adresinde İnternet radyo kanalı bulunamadı." #: ../quodlibet/browsers/iradio.py:811 msgid "All stations listed are already in your library." msgstr "Listelenen tüm radyolar zaten arşivinizde." #: ../quodlibet/browsers/iradio.py:828 #, fuzzy msgid "Add to Favorites" msgstr "Çalma Listesine _Ekle" #: ../quodlibet/browsers/iradio.py:832 #, fuzzy msgid "Remove from Favorites" msgstr "Çalma Listesinden _Çıkar" #: ../quodlibet/browsers/iradio.py:932 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "%(count)d kanal" msgstr[1] "%(count)d kanal" #: ../quodlibet/browsers/media.py:36 msgid "Device Properties" msgstr "Aygıt Özellikleri" #: ../quodlibet/browsers/media.py:52 msgid "Device:" msgstr "Aygıt:" #: ../quodlibet/browsers/media.py:54 msgid "Not mounted" msgstr "Bağlanmamış" #: ../quodlibet/browsers/media.py:55 #, fuzzy msgid "Mount point:" msgstr "Bağlama Yeri:" #: ../quodlibet/browsers/media.py:61 ../quodlibet/qltk/cbes.py:40 msgid "_Name:" msgstr "_İsim:" #: ../quodlibet/browsers/media.py:135 msgid "Media Devices" msgstr "Ortam Aygıtları" #: ../quodlibet/browsers/media.py:136 msgid "_Media Devices" msgstr "_Ortam Aygıtları" #. eject button #: ../quodlibet/browsers/media.py:224 ../quodlibet/browsers/media.py:378 msgid "_Eject" msgstr "_Çıkart" #: ../quodlibet/browsers/media.py:360 #, fuzzy msgid "_Properties" msgstr "Özellikler" #: ../quodlibet/browsers/media.py:365 #: ../quodlibet/browsers/playlists/main.py:464 msgid "_Rename" msgstr "_Yeniden Adlandır" #: ../quodlibet/browsers/media.py:461 #, fuzzy, python-format msgid "%(used-size)s used, %(free-size)s available" msgstr "<b>%s</b> kullanılmış, <b>%s</b> boş" #: ../quodlibet/browsers/media.py:479 #, fuzzy, python-format msgid "%s is not connected." msgstr "<b>%s</b> takılı değil." #: ../quodlibet/browsers/media.py:499 #, fuzzy, python-format msgid "Copying %(song)s" msgstr "<b>%(song)s</b> Kopyalanıyor" #: ../quodlibet/browsers/media.py:513 ../quodlibet/browsers/media.py:529 msgid "Unable to copy song" msgstr "Şarkı kopyalanamadı" #: ../quodlibet/browsers/media.py:514 msgid "There is not enough free space for this song." msgstr "Bu şarkı için yeterli boş yer yok." #: ../quodlibet/browsers/media.py:526 #, fuzzy, python-format msgid "%s could not be copied." msgstr "<b>%s</b> kopyalanamadı." #: ../quodlibet/browsers/media.py:545 msgid "Unable to delete songs" msgstr "Şarkılar silinemiyor" #: ../quodlibet/browsers/media.py:557 #, fuzzy, python-format msgid "Deleting %(song)s" msgstr "<b>%(song)s</b> siliniyor" #: ../quodlibet/browsers/media.py:575 #, fuzzy, python-format msgid "%s could not be deleted." msgstr "<b>%s</b> silinemedi." #: ../quodlibet/browsers/media.py:579 msgid "Unable to delete song" msgstr "Şarkı silinemedi" #: ../quodlibet/browsers/media.py:594 #, fuzzy, python-format msgid "Ejecting %s failed." msgstr "<b>%s</b> çıkartılamadı." #: ../quodlibet/browsers/media.py:597 msgid "Unable to eject device" msgstr "Aygıt çıkartılamadı" #: ../quodlibet/browsers/media.py:603 msgid "No device backend, Media Devices browser disabled." msgstr "" #: ../quodlibet/browsers/paned/main.py:40 ../quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "Panelli Gezici" #: ../quodlibet/browsers/paned/main.py:41 msgid "_Paned Browser" msgstr "_Panelli Gezici" #: ../quodlibet/browsers/paned/main.py:90 msgid "Select _All" msgstr "Hepsini _Seç" #: ../quodlibet/browsers/paned/models.py:104 ../quodlibet/qltk/pluginwin.py:122 #: ../quodlibet/qltk/pluginwin.py:164 msgid "All" msgstr "Hepsi" #: ../quodlibet/browsers/paned/prefs.py:67 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "<tt>%s</tt>" msgstr "" #: ../quodlibet/browsers/paned/prefs.py:162 msgid "_Wide Mode" msgstr "" #: ../quodlibet/browsers/paned/prefs.py:197 msgid "Paned Browser Preferences" msgstr "Panelli Gezici Ayarları" #: ../quodlibet/browsers/paned/prefs.py:204 msgid "Equal pane width" msgstr "" #: ../quodlibet/browsers/playlists/main.py:48 #: ../quodlibet/browsers/playlists/main.py:575 #: ../quodlibet/qltk/pluginwin.py:168 msgid "Playlists" msgstr "Çalma Listeleri" #: ../quodlibet/browsers/playlists/main.py:49 msgid "_Playlists" msgstr "_Çalma Listeleri" #: ../quodlibet/browsers/playlists/main.py:152 msgid "_Remove from Playlist" msgstr "Çalma Listesinden _Çıkar" #: ../quodlibet/browsers/playlists/main.py:215 #: ../quodlibet/browsers/playlists/main.py:576 msgid "_Import" msgstr "İçe _Aktar" #: ../quodlibet/browsers/playlists/main.py:391 #: ../quodlibet/browsers/playlists/util.py:50 #: ../quodlibet/util/collection.py:570 msgid "New Playlist" msgstr "Yeni Çalma Listesi" #: ../quodlibet/browsers/playlists/main.py:413 msgid "Unable to import playlist" msgstr "Çalma listesi içe aktarılamadı" #: ../quodlibet/browsers/playlists/main.py:414 msgid "Quod Libet can only import playlists in the M3U and PLS formats." msgstr "" "Quod Libet sadece M3u ve PLS biçimli çalma listelerini içe aktarabilir." #: ../quodlibet/browsers/playlists/main.py:565 msgid "Unable to rename playlist" msgstr "Çalma Listesinin adı değiştirilemedi" #: ../quodlibet/browsers/playlists/main.py:576 msgid "Import Playlist" msgstr "Çalma Listesi İçe Aktar" #: ../quodlibet/browsers/playlists/menu.py:25 #, fuzzy msgid "_New Playlist…" msgstr "_Yeni Çalma Listesi" #: ../quodlibet/browsers/playlists/menu.py:86 #, 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:90 #, 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 "Yeni Çalma Listesi" #: ../quodlibet/browsers/playlists/prefs.py:47 #, fuzzy msgid "Playlist Browser Preferences" msgstr "Panelli Gezici Ayarları" #: ../quodlibet/browsers/playlists/prefs.py:52 #, fuzzy msgid "Playlist display" msgstr "Çalma Listeleri" #: ../quodlibet/browsers/playlists/util.py:33 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "" #: ../quodlibet/browsers/playlists/util.py:35 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" #: ../quodlibet/browsers/playlists/util.py:51 #, fuzzy msgid "Enter a name for the new playlist:" msgstr "Yeni dizin için isim girin:" #: ../quodlibet/browsers/playlists/util.py:102 #, 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/search.py:33 msgid "_Limit Results" msgstr "Sonuçları _Sınırla" #: ../quodlibet/browsers/search.py:48 msgid "Search Library" msgstr "Arşivde Ara" #: ../quodlibet/browsers/search.py:49 msgid "_Search Library" msgstr "Arşivde _Ara" #: ../quodlibet/browsers/soundcloud/main.py:38 #, fuzzy msgid "Soundcloud Browser" msgstr "Panelli Gezici" #: ../quodlibet/browsers/soundcloud/main.py:39 msgid "Sound_cloud" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:59 #: ../quodlibet/qltk/searchbar.py:73 msgid "Search" msgstr "Ara" #: ../quodlibet/browsers/soundcloud/main.py:136 #, python-format msgid "Go to %s" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:380 #, fuzzy msgid "Connected" msgstr "konum" #: ../quodlibet/browsers/soundcloud/main.py:381 #, python-format msgid "Quod Libet is now connected, <b>%s</b>!" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:393 #, python-format msgid "Log out of %s" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:395 msgid "Enter code…" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:396 #, python-format msgid "Log in to %s" msgstr "" #: ../quodlibet/browsers/soundcloud/util.py:86 msgid "Soundcloud authorisation" msgstr "" #: ../quodlibet/browsers/soundcloud/util.py:87 msgid "Enter Soundcloud auth code:" msgstr "" #: ../quodlibet/cli.py:50 #, fuzzy msgid "Quod Libet is not running (add '--run' to start it)" msgstr "Quod Libet çalışmıyor." #: ../quodlibet/cli.py:85 msgid "a music library and player" msgstr "bir müzik arşivleyici ve çalıcı" #: ../quodlibet/cli.py:86 #, fuzzy msgid "[option]" msgstr "[ayarlar]" #: ../quodlibet/cli.py:88 msgid "Print the playing song and exit" msgstr "Çalan şarkıyı göster ve çık" #: ../quodlibet/cli.py:89 msgid "Begin playing immediately" msgstr "Hemen çalmaya başla" #: ../quodlibet/cli.py:90 msgid "Don't show any windows on start" msgstr "" #: ../quodlibet/cli.py:93 msgid "Jump to next song" msgstr "Sonraki şarkıya atla" #: ../quodlibet/cli.py:95 msgid "Jump to previous song or restart if near the beginning" msgstr "" #: ../quodlibet/cli.py:96 msgid "Jump to previous song" msgstr "Önceki şarkıya atla" #: ../quodlibet/cli.py:97 msgid "Start playback" msgstr "Çalmaya başla" #: ../quodlibet/cli.py:98 msgid "Pause playback" msgstr "Çalmayı duraklat" #: ../quodlibet/cli.py:99 msgid "Toggle play/pause mode" msgstr "çalma/duraklama durumunu değiştir" #: ../quodlibet/cli.py:100 #, fuzzy msgid "Stop playback" msgstr "Çalmaya başla" #: ../quodlibet/cli.py:101 msgid "Turn up volume" msgstr "Sesi aç" #: ../quodlibet/cli.py:102 msgid "Turn down volume" msgstr "Sesi kıs" #: ../quodlibet/cli.py:103 msgid "Print player status" msgstr "Durum bilgisini göster" #: ../quodlibet/cli.py:104 msgid "Hide main window" msgstr "Ana pencereyi gizle" #: ../quodlibet/cli.py:105 msgid "Show main window" msgstr "Ana pencereyi göster" #: ../quodlibet/cli.py:106 msgid "Toggle main window visibility" msgstr "Ana pencere görünürlüğünü değiştir" #: ../quodlibet/cli.py:107 msgid "Focus the running player" msgstr "Çalışan müzikçalara odaklan" #: ../quodlibet/cli.py:108 msgid "Remove active browser filters" msgstr "Geçerli gezici süzgeçlerini kaldır" #: ../quodlibet/cli.py:109 msgid "Refresh and rescan library" msgstr "Arşivi yenile ve tekrar tara" #: ../quodlibet/cli.py:110 #, fuzzy msgid "List available browsers" msgstr "Geziciyi Gizle" #: ../quodlibet/cli.py:111 msgid "Print the current playlist" msgstr "Şu anki çalma listesini göster" #: ../quodlibet/cli.py:112 msgid "Print the contents of the queue" msgstr "Çalma kuyruğunu göster" #: ../quodlibet/cli.py:113 #, fuzzy msgid "Print the active text query" msgstr "Çalma kuyruğunu göster" #: ../quodlibet/cli.py:114 msgid "Start without plugins" msgstr "" #: ../quodlibet/cli.py:115 #, fuzzy msgid "Start Quod Libet if it isn't running" msgstr "Quod Libet çalışmıyor." #: ../quodlibet/cli.py:116 msgid "Exit Quod Libet" msgstr "Quod Libet'ten çık" #: ../quodlibet/cli.py:121 msgid "Seek within the playing song" msgstr "Şarkı içinde ileri/geri git" #: ../quodlibet/cli.py:121 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][SS:]DD:SS" #: ../quodlibet/cli.py:122 #, fuzzy msgid "Set or toggle shuffle mode" msgstr "çalma/duraklama durumunu değiştir" #: ../quodlibet/cli.py:123 msgid "Turn repeat off, on, or toggle it" msgstr "Başa dönmeyi aç, kapat veya değiştir" #: ../quodlibet/cli.py:124 msgid "Set the volume" msgstr "Ses yüksekliğini değiştir" #: ../quodlibet/cli.py:125 msgid "Search your audio library" msgstr "Müzik arşivinde arama yap" #: ../quodlibet/cli.py:125 ../quodlibet/cli.py:137 ../quodlibet/cli.py:141 #: ../quodlibet/cli.py:143 msgid "query" msgstr "sorgu" #: ../quodlibet/cli.py:126 msgid "Play a file" msgstr "Bir ses dosyası çal" #: ../quodlibet/cli.py:126 ../quodlibet/cli.py:137 ../quodlibet/cli.py:143 #, fuzzy msgctxt "command" msgid "filename" msgstr "dosya adı" #: ../quodlibet/cli.py:127 msgid "Rate the playing song" msgstr "Çalan şarkıya puan ver" #: ../quodlibet/cli.py:128 msgid "Set the current browser" msgstr "Geziciyi değiştir" #: ../quodlibet/cli.py:129 #, fuzzy msgid "Stop after the playing song" msgstr "Çalan şarkıya puan ver" #: ../quodlibet/cli.py:130 msgid "Open a new browser" msgstr "Yeni bir gezici aç" #: ../quodlibet/cli.py:131 msgid "Show or hide the queue" msgstr "Çalma kuyruğunu göster veya sakla" #: ../quodlibet/cli.py:133 #, fuzzy msgid "Show or hide the main song list (deprecated)" msgstr "Şarkı listesini göster veya sakla" #: ../quodlibet/cli.py:134 msgid "Filter on a random value" msgstr "Rastgele bir değerle süz" #: ../quodlibet/cli.py:134 #, fuzzy msgctxt "command" msgid "tag" msgstr "Etiket" #: ../quodlibet/cli.py:135 msgid "Filter on a tag value" msgstr "Bir etiket değerine göre süz" #: ../quodlibet/cli.py:135 msgid "tag=value" msgstr "etiket=değer" #: ../quodlibet/cli.py:136 msgid "Enqueue a file or query" msgstr "bir dosya veya sorguyu çalma kuyruğuna koy" #: ../quodlibet/cli.py:138 msgid "Enqueue comma-separated files" msgstr "" #: ../quodlibet/cli.py:139 ../quodlibet/util/tags.py:147 msgid "filename" msgstr "dosya adı" #: ../quodlibet/cli.py:140 msgid "Print filenames of results of query to stdout" msgstr "" #: ../quodlibet/cli.py:142 msgid "Unqueue a file or query" msgstr "bir dosya veya sorguyu çalma kuyruğundan çıkar" #: ../quodlibet/cli.py:203 #, python-format msgid "Invalid argument for '%s'." msgstr "'%s' için geçersiz parametre." #: ../quodlibet/cli.py:204 ../quodlibet/util/__init__.py:190 #, python-format msgid "Try %s --help." msgstr "Yardım için %s --help komutunu deneyin." #: ../quodlibet/devices/_base.py:65 msgid "Unknown Device" msgstr "Bilinmeyen Aygıt" #: ../quodlibet/devices/__init__.py:32 #, python-format msgid "Could not import %s, which is needed for device support." msgstr "" #: ../quodlibet/devices/__init__.py:153 #, python-format msgid "%r is not a supported device." msgstr "%r desteklenen bir aygıt değil." #: ../quodlibet/devices/__init__.py:245 ../quodlibet/devices/__init__.py:251 #, python-format msgid "Could not find '%s'." msgstr "" #: ../quodlibet/devices/__init__.py:450 #, fuzzy msgid "Initializing device backend." msgstr "Ses altsistemi yükleniyor (%s)" #: ../quodlibet/devices/__init__.py:451 #, python-format msgid "Trying '%s'" msgstr "" #: ../quodlibet/devices/__init__.py:461 msgid "Couldn't connect to a device backend." msgstr "" #: ../quodlibet/devices/__init__.py:463 #, fuzzy msgid "Device backend initialized." msgstr "%r ses altsistemi kurulu değil." #: ../quodlibet/devices/storage.py:57 #, fuzzy msgid "_Filename pattern:" msgstr "_Dosya Adı Süzgeci:" #: ../quodlibet/devices/storage.py:61 msgid "Copy _album covers" msgstr "Albüm kapaklarını kopyala" #: ../quodlibet/devices/storage.py:65 msgid "_Remove unused covers and directories" msgstr "Kullanılmayan albüm kapakları ve dizinleri _sil" #: ../quodlibet/errorreport/ui.py:60 #, fuzzy msgid "An Error Occurred" msgstr "Hata Oldu" #: ../quodlibet/errorreport/ui.py:62 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:72 msgid "File Bug Report" msgstr "" #: ../quodlibet/errorreport/ui.py:74 ../quodlibet/errorreport/ui.py:90 msgid "Submit Error Report" msgstr "" #: ../quodlibet/errorreport/ui.py:75 msgid "Quit Program" msgstr "" #: ../quodlibet/errorreport/ui.py:76 #, fuzzy msgid "Ignore Error" msgstr "_Hataları Göster" #: ../quodlibet/errorreport/ui.py:80 msgid "Error details:" msgstr "" #: ../quodlibet/errorreport/ui.py:92 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:100 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "" #: ../quodlibet/errorreport/ui.py:109 msgid "_Send" msgstr "" #: ../quodlibet/errorreport/ui.py:115 #, fuzzy msgid "Short description…" msgstr "açıklama" #: ../quodlibet/errorreport/ui.py:118 msgid "Data to be sent:" msgstr "" #: ../quodlibet/exfalso.py:34 msgid "an audio tag editor" msgstr "bir müzik etiketleyicisi" #: ../quodlibet/exfalso.py:34 ../quodlibet/util/tags.py:148 msgid "directory" msgstr "dizin" #: ../quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "" #: ../quodlibet/ext/covers/artwork_url.py:20 msgid "" "Downloads covers linked to by the artwork_url tag.This works with the " "Soundcloud browser." msgstr "" #: ../quodlibet/ext/covers/discogs.py:25 #, fuzzy msgid "Discogs Cover Source" msgstr "MusicBrainz şarkı ID'si" #: ../quodlibet/ext/covers/discogs.py:26 msgid "Downloads covers from Discogs." msgstr "" #: ../quodlibet/ext/covers/lastfm.py:22 msgid "Last.fm Cover Source" msgstr "" #: ../quodlibet/ext/covers/lastfm.py:23 msgid "Downloads covers from Last.fm's cover art archive." msgstr "" #: ../quodlibet/ext/covers/musicbrainz.py:19 #, fuzzy msgid "MusicBrainz Cover Source" msgstr "MusicBrainz şarkı ID'si" #: ../quodlibet/ext/covers/musicbrainz.py:20 msgid "Downloads covers from MusicBrainz's cover art archive." msgstr "" #: ../quodlibet/ext/editing/iconv.py:26 #, fuzzy msgid "Convert Encodings" msgstr "[kodlama Hatası]" #: ../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:25 msgid "Kana/Kanji Simple Inverter" msgstr "" #: ../quodlibet/ext/editing/kakasi.py:26 msgid "Converts kana/kanji to romaji before renaming." msgstr "" #: ../quodlibet/ext/editing/kakasi.py:35 msgid "Romanize _Japanese text" msgstr "" #: ../quodlibet/ext/editing/kakasi.py:63 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:19 msgid "" "Allows arbitrary regex substitutions (s///) when tagging or renaming files." msgstr "" #: ../quodlibet/ext/editing/titlecase.py:20 #, fuzzy msgid "Title Case" msgstr "Ad" #: ../quodlibet/ext/editing/titlecase.py:21 #, fuzzy msgid "Title-cases tag values in the tag editor." msgstr "Müzik etiketleri düzenleyici" #: ../quodlibet/ext/editing/titlecase.py:40 #, fuzzy msgid "Title-_case Value" msgstr "Etiketlerde _büyük/küçük harfleri düzelt" #: ../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:69 #, fuzzy msgid "Advanced Preferences" msgstr "Panelli Gezici Ayarları" #: ../quodlibet/ext/events/advanced_preferences.py:70 msgid "Allow editing of advanced config settings." msgstr "" #: ../quodlibet/ext/events/advanced_preferences.py:162 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:153 msgid "Top of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:154 msgid "Middle of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:155 msgid "Bottom of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:158 msgid "_Position:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:171 #, fuzzy msgid "_Cover size:" msgstr "Toplam boyut:" #: ../quodlibet/ext/events/animosd/prefs.py:177 #: ../quodlibet/ext/events/lyricswindow.py:334 ../quodlibet/qltk/prefs.py:266 #, fuzzy msgid "Display" msgstr "Görünümü Değiştir" #: ../quodlibet/ext/events/animosd/prefs.py:190 msgid "_Font:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:195 msgid "Left" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:196 msgid "Center" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:197 #, fuzzy msgid "Right" msgstr "_Ağırlık" #: ../quodlibet/ext/events/animosd/prefs.py:200 msgid "_Align text:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:206 msgid "Text" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:217 msgid "_Text:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:227 msgid "_Fill:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:232 #: ../quodlibet/ext/events/synchronizedlyrics.py:63 msgid "Colors" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:240 msgid "_Shadows" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:241 msgid "_Outline" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:242 msgid "Rou_nded Corners" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:258 msgid "_Delay:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:264 #: ../quodlibet/qltk/pluginwin.py:172 msgid "Effects" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:270 #, fuzzy msgid "Ed_it Display Pattern…" msgstr "Görünümü Değiştir" #: ../quodlibet/ext/events/animosd/prefs.py:274 #: ../quodlibet/ext/events/trayicon/prefs.py:78 #, fuzzy msgid "Preview" msgstr "_Önizleme" #: ../quodlibet/ext/events/auto_library_update.py:136 msgid "Automatic Library Update" msgstr "" #: ../quodlibet/ext/events/auto_library_update.py:137 #, python-format msgid "Keeps your library up to date with inotify. Requires %s." 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 by Brian Nelson." 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/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:97 msgid "Equalizer" msgstr "" #: ../quodlibet/ext/events/equalizer.py:98 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:132 msgid "The current backend does not support equalization." msgstr "" #: ../quodlibet/ext/events/equalizer.py:138 #, python-format msgid "%.1f kHz" msgstr "" #: ../quodlibet/ext/events/equalizer.py:139 #: ../quodlibet/ext/gstreamer/crossfeed.py:93 #: ../quodlibet/ext/gstreamer/karaoke.py:95 #, python-format msgid "%d Hz" msgstr "" #: ../quodlibet/ext/events/equalizer.py:173 #: ../quodlibet/ext/gstreamer/crossfeed.py:112 #, fuzzy, python-format msgid "%.1f dB" msgstr "%d saniye" #: ../quodlibet/ext/events/equalizer.py:192 #: ../quodlibet/ext/gstreamer/crossfeed.py:31 #, fuzzy msgid "Custom" msgstr "_Özel" #: ../quodlibet/ext/events/equalizer.py:199 #, fuzzy msgid "_Clear" msgstr "Hataları _Sil" #. Translators: statuses relating to Instant Messenger apps #: ../quodlibet/ext/events/gajim_status.py:27 msgid "online" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:28 msgid "offline" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:29 msgid "chat" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:30 msgid "away" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:31 msgid "xa" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:32 msgid "invisible" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:37 msgid "Gajim Status Message" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:38 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:45 #: ../quodlibet/ext/events/telepathy_status.py:69 msgid "paused" 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:160 msgid "Add '[paused]'" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:163 msgid "If checked, '[paused]' will be added to status message on pause." msgstr "" #: ../quodlibet/ext/events/gajim_status.py:187 msgid "Statuses for which message will be changed" msgstr "" #: ../quodlibet/ext/events/headphonemon.py:156 msgid "Pause on Headphone Unplug" msgstr "" #: ../quodlibet/ext/events/headphonemon.py:157 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" #: ../quodlibet/ext/events/inhibit.py:41 msgid "Inhibit Screensaver" msgstr "" #: ../quodlibet/ext/events/inhibit.py:42 msgid "Prevents the GNOME screensaver from activating while a song is playing." msgstr "" #: ../quodlibet/ext/events/inhibit.py:51 #, fuzzy msgid "Music is playing" msgstr "Müzik Çalar" #: ../quodlibet/ext/events/iradiolog.py:16 #, fuzzy msgid "Internet Radio Log" msgstr "İnternet Radyosu" #: ../quodlibet/ext/events/iradiolog.py:17 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" #: ../quodlibet/ext/events/jep118.py:29 msgid "JEP-118" msgstr "" #: ../quodlibet/ext/events/jep118.py:30 msgid "Outputs a Jabber User Tunes file to ~/.quodlibet/jabber." msgstr "" #: ../quodlibet/ext/events/language.py:21 #, fuzzy msgid "Change Language" msgstr "_Puan" #: ../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 msgid "A restart is required for any changes to take effect" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:199 #, fuzzy msgid "No active song" msgstr "Şarkı kaydedilemedi" #: ../quodlibet/ext/events/lyricswindow.py:215 #, fuzzy msgid "No lyrics found" msgstr "Eklenti bulunamadı." #: ../quodlibet/ext/events/lyricswindow.py:227 #, fuzzy msgid "Lyrics:" msgstr "Sözler" #: ../quodlibet/ext/events/lyricswindow.py:284 msgid "_Zoom level:" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:302 msgid "URL:" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:307 msgid "Revert to default" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:322 msgid "Search via above URL if the lyrics couldn't be found in LyricsWikia." msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:339 #, fuzzy msgid "Alternate search" msgstr "Aramayı temizle" #: ../quodlibet/ext/events/lyricswindow.py:347 #, fuzzy msgid "Lyrics Window" msgstr "Sözler" #: ../quodlibet/ext/events/lyricswindow.py:348 msgid "Shows a window containing lyrics of the playing song." msgstr "" #: ../quodlibet/ext/events/mediaserver.py:38 msgid "UPnP AV Media Server" msgstr "" #: ../quodlibet/ext/events/mediaserver.py:39 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." 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 "konum" #: ../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:39 msgid "" "Allows control of Quod Libet using the MPRIS 1.0/2.0 D-Bus Interface " "Specification." msgstr "" #: ../quodlibet/ext/events/mpris/__init__.py:45 #: ../quodlibet/ext/events/trayicon/prefs.py:30 #, fuzzy msgid "Hide main window on close" msgstr "Ana pencereyi gizle" #: ../quodlibet/ext/events/mpris/__init__.py:48 #: ../quodlibet/ext/events/themeswitcher.py:84 #: ../quodlibet/ext/gstreamer/compressor.py:99 #: ../quodlibet/ext/gstreamer/crossfeed.py:136 #: ../quodlibet/ext/gstreamer/karaoke.py:99 #: ../quodlibet/ext/gstreamer/pitch.py:83 ../quodlibet/qltk/prefs.py:688 #, fuzzy msgid "Preferences" msgstr "Ayarlar" #: ../quodlibet/ext/events/mqtt.py:50 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/mqtt.py:56 msgid "MQTT Publisher" msgstr "" #: ../quodlibet/ext/events/mqtt.py:57 msgid "Publishes status messages to an MQTT topic." msgstr "" #: ../quodlibet/ext/events/mqtt.py:122 msgid "Broker hostname" msgstr "" #: ../quodlibet/ext/events/mqtt.py:122 msgid "broker hostname / IP" msgstr "" #: ../quodlibet/ext/events/mqtt.py:124 msgid "Broker port" msgstr "" #: ../quodlibet/ext/events/mqtt.py:124 msgid "broker port" msgstr "" #: ../quodlibet/ext/events/mqtt.py:126 msgid "Topic" msgstr "" #: ../quodlibet/ext/events/mqtt.py:128 #, fuzzy msgid "Playing Pattern" msgstr "süzgeç" #: ../quodlibet/ext/events/mqtt.py:130 msgid "Status text when a song is started." msgstr "" #: ../quodlibet/ext/events/mqtt.py:132 #, fuzzy msgid "Paused Pattern" msgstr "süzgeç" #: ../quodlibet/ext/events/mqtt.py:134 msgid "Text when a song is paused." msgstr "" #: ../quodlibet/ext/events/mqtt.py:136 #, fuzzy msgid "No-song Text" msgstr "%d şarkı" #: ../quodlibet/ext/events/mqtt.py:138 msgid "Plain text for when there is no current song" msgstr "" #: ../quodlibet/ext/events/mqtt.py:149 #, fuzzy msgid "MQTT Configuration" msgstr "Çıktı Kaydı" #: ../quodlibet/ext/events/mqtt.py:153 #, fuzzy msgid "Status Text" msgstr "süzgeç" #: ../quodlibet/ext/events/mqtt.py:185 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "" #: ../quodlibet/ext/events/mqtt.py:189 #, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s" msgstr "" #: ../quodlibet/ext/events/mqtt.py:192 #, fuzzy msgid "Connection error" msgstr "konum" #: ../quodlibet/ext/events/notify.py:80 msgid "Notification text" msgstr "" #: ../quodlibet/ext/events/notify.py:88 #, fuzzy msgid "_Title:" msgstr "Ad" #: ../quodlibet/ext/events/notify.py:99 ../quodlibet/ext/events/notify.py:128 msgid "Revert to default pattern" msgstr "" #: ../quodlibet/ext/events/notify.py:118 msgid "_Body:" msgstr "" #: ../quodlibet/ext/events/notify.py:138 msgid "_Show notification" msgstr "" #: ../quodlibet/ext/events/notify.py:156 msgid "Show notifications" msgstr "" #: ../quodlibet/ext/events/notify.py:162 msgid "Only on <i>_manual</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:170 msgid "Only on <i>_automatic</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:178 msgid "On <i>a_ll</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:196 msgid "Only when the main window is not _focused" msgstr "" #: ../quodlibet/ext/events/notify.py:204 msgid "Show \"_Next\" button" msgstr "" #: ../quodlibet/ext/events/notify.py:236 msgid "Connection Error" msgstr "" #: ../quodlibet/ext/events/notify.py:237 ../quodlibet/ext/events/notify.py:391 #: ../quodlibet/ext/events/notify.py:433 msgid "Couldn't connect to notification daemon." msgstr "" #: ../quodlibet/ext/events/notify.py:251 msgid "Song Notifications" msgstr "" #: ../quodlibet/ext/events/notify.py:252 msgid "Displays a notification when the song changes." msgstr "" #: ../quodlibet/ext/events/notify.py:415 ../quodlibet/qltk/unity.py:65 msgid "Next" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:178 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:254 #, python-format msgid "Could not contact service '%s'." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:260 msgid "Authentication failed: invalid URL." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:277 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:282 msgid "Client is banned. Contact the author." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:286 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:351 msgid "AudioScrobbler Submission" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:352 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:450 msgid "Authentication successful." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:462 #, fuzzy msgid "_Service:" msgstr "Aygıt:" #: ../quodlibet/ext/events/qlscrobbler.py:462 msgid "_URL:" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:462 #, fuzzy msgid "User_name:" msgstr "_İsim:" #: ../quodlibet/ext/events/qlscrobbler.py:463 msgid "_Password:" msgstr "" #. Translators: Other service #: ../quodlibet/ext/events/qlscrobbler.py:479 #, fuzzy msgid "Other…" msgstr "_Diğerleri:" #. verify data #: ../quodlibet/ext/events/qlscrobbler.py:517 msgid "_Verify account data" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:522 #: ../quodlibet/ext/songsmenu/lastfmsync.py:304 msgid "Account" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:530 #, fuzzy msgid "_Artist pattern:" msgstr "_Sanatçı" #: ../quodlibet/ext/events/qlscrobbler.py:530 #, fuzzy msgid "_Title pattern:" msgstr "_Dosya Adı Süzgeci:" #: ../quodlibet/ext/events/qlscrobbler.py:531 msgid "Exclude _filter:" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:549 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:559 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:568 msgid "Songs matching this filter will not be submitted." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:576 msgid "_Offline mode (don't submit anything)" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:580 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:27 #, fuzzy msgid "Random Album Playback" msgstr "_Rastgele Albüm" #: ../quodlibet/ext/events/randomalbum.py:28 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:38 msgid "Rated higher" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:39 msgid "Played more often" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:40 msgid "Skipped more often" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:41 msgid "Played more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:42 msgid "Started more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:43 msgid "Added more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:44 #, fuzzy msgid "Longer albums" msgstr "albümler" #: ../quodlibet/ext/events/randomalbum.py:83 msgid "seconds before starting next album" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:87 #, fuzzy msgid "Weights" msgstr "_Ağırlık" #: ../quodlibet/ext/events/randomalbum.py:89 msgid "Play some albums more than others" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:103 msgid "avoid" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:114 msgid "prefer" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:201 #, fuzzy msgid "Random Album" msgstr "_Rastgele Albüm" #: ../quodlibet/ext/events/randomalbum.py:202 #, python-format msgid "Waiting to start %s" msgstr "" #: ../quodlibet/ext/events/rbimport.py:114 #, fuzzy msgid "Import Failed" msgstr "Çalma Listesi İçe Aktar" #: ../quodlibet/ext/events/rbimport.py:119 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "" #: ../quodlibet/ext/events/rbimport.py:127 msgid "Rhythmbox Import" msgstr "" #: ../quodlibet/ext/events/rbimport.py:128 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "" #: ../quodlibet/ext/events/rbimport.py:132 #, fuzzy msgid "Start Import" msgstr "İçe _Aktar" #: ../quodlibet/ext/events/screensaver.py:25 msgid "Screensaver Pause" msgstr "" #: ../quodlibet/ext/events/screensaver.py:26 msgid "Pauses playback while the GNOME screensaver is active." msgstr "" #: ../quodlibet/ext/events/searchprovider.py:73 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "" #: ../quodlibet/ext/events/searchprovider.py:79 msgid "GNOME Search Provider" msgstr "" #: ../quodlibet/ext/events/searchprovider.py:80 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/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:29 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:57 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:58 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:34 #, fuzzy msgid "Synchronized Lyrics" msgstr "Sözler" #: ../quodlibet/ext/events/synchronizedlyrics.py:35 msgid "Shows synchronized lyrics from .lrc file with same name as the track." msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:66 msgid "Text:" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:76 msgid "Background:" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:87 msgid "Font" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:90 msgid "Size (px):" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:62 msgid "Telepathy Status Messages" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:63 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:122 #, fuzzy msgid "Playing:" msgstr "Çalmıyor" #: ../quodlibet/ext/events/telepathy_status.py:123 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:139 msgid "Paused:" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:140 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:156 msgid "Plain text for status when there is no current song" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:157 #, fuzzy msgid "No song:" msgstr "%d şarkı" #. Frame #: ../quodlibet/ext/events/telepathy_status.py:164 #, fuzzy msgid "Status Patterns" msgstr "süzgeç" #: ../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/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:77 #: ../quodlibet/ext/events/trayicon/prefs.py:98 #: ../quodlibet/ext/events/trayicon/systemtray.py:177 #: ../quodlibet/qltk/info.py:47 msgid "Not playing" msgstr "Çalmıyor" #: ../quodlibet/ext/events/trayicon/__init__.py:53 msgid "Tray Icon" msgstr "" #: ../quodlibet/ext/events/trayicon/__init__.py:54 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:183 #: ../quodlibet/qltk/quodlibetwindow.py:1046 #: ../quodlibet/qltk/quodlibetwindow.py:1238 #, fuzzy msgid "_Play" msgstr "_Çalma Listeleri" #: ../quodlibet/ext/events/trayicon/menu.py:63 #: ../quodlibet/qltk/quodlibetwindow.py:185 #: ../quodlibet/qltk/quodlibetwindow.py:1240 ../quodlibet/qltk/wlw.py:51 #, fuzzy msgid "P_ause" msgstr "Çalıcı" #: ../quodlibet/ext/events/trayicon/menu.py:68 #: ../quodlibet/qltk/quodlibetwindow.py:190 #: ../quodlibet/qltk/quodlibetwindow.py:1041 #, fuzzy msgid "Pre_vious" msgstr "_Önizleme" #: ../quodlibet/ext/events/trayicon/menu.py:71 #: ../quodlibet/qltk/quodlibetwindow.py:194 #: ../quodlibet/qltk/quodlibetwindow.py:1051 msgid "_Next" msgstr "" #: ../quodlibet/ext/events/trayicon/menu.py:76 msgid "_Shuffle" msgstr "_Rastgele" #: ../quodlibet/ext/events/trayicon/menu.py:81 msgid "_Repeat" msgstr "_Başa dön" #: ../quodlibet/ext/events/trayicon/menu.py:86 #, fuzzy msgid "Stop _After This Song" msgstr "Bu şarkıdan sonra dur" #: ../quodlibet/ext/events/trayicon/menu.py:92 #: ../quodlibet/qltk/quodlibetwindow.py:1012 #, fuzzy msgid "Open _Browser" msgstr "Yeni bir gezici aç" #: ../quodlibet/ext/events/trayicon/menu.py:103 #: ../quodlibet/qltk/quodlibetwindow.py:1031 ../quodlibet/qltk/songsmenu.py:411 msgid "Edit _Tags" msgstr "_Etiketleri Değiştir" #: ../quodlibet/ext/events/trayicon/menu.py:112 #: ../quodlibet/qltk/quodlibetwindow.py:975 ../quodlibet/qltk/songsmenu.py:424 msgid "_Information" msgstr "_Bilgi" #: ../quodlibet/ext/events/trayicon/menu.py:114 #: ../quodlibet/qltk/songsmenu.py:340 #, fuzzy msgid "Play_lists" msgstr "Çalma Listeleri" #: ../quodlibet/ext/events/trayicon/menu.py:132 #: ../quodlibet/qltk/quodlibetwindow.py:1026 msgid "_Quit" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:32 ../quodlibet/qltk/prefs.py:69 msgid "Behavior" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:42 msgid "Scroll wheel adjusts volume" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel changes song" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll _Wheel" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:84 #, fuzzy msgid "Tooltip Display" msgstr "Görünümü Değiştir" #: ../quodlibet/ext/events/viewlyrics.py:23 #, fuzzy msgid "View Lyrics" msgstr "Sözler" #: ../quodlibet/ext/events/viewlyrics.py:24 msgid "Automatically displays lyrics beneath the song list in the main window." msgstr "" #: ../quodlibet/ext/events/viewlyrics.py:29 #, fuzzy msgid "_Lyrics" msgstr "Sözler" #: ../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 "Hatalar" #: ../quodlibet/ext/events/visualisations.py:76 msgid "Visualiser executable:" msgstr "" #: ../quodlibet/ext/events/visualisations.py:91 msgid "Reload" msgstr "" #: ../quodlibet/ext/events/waveformseekbar.py:406 msgid "Waveform Seek Bar" msgstr "" #: ../quodlibet/ext/events/waveformseekbar.py:410 msgid "A seekbar in the shape of the waveform of the current song." msgstr "" #: ../quodlibet/ext/events/waveformseekbar.py:443 msgid "Override foreground color:" msgstr "" #: ../quodlibet/ext/events/write_cover.py:32 msgid "Picture Saver" msgstr "" #: ../quodlibet/ext/events/write_cover.py:33 msgid "Saves the cover image of the current song to a file." msgstr "" #: ../quodlibet/ext/events/write_cover.py:66 #, fuzzy msgid "File:" msgstr "Dosyalar" #: ../quodlibet/ext/gstreamer/compressor.py:20 msgid "_Threshold:" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:21 msgid "Threshold until the filter is activated" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:22 msgid "R_atio:" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:22 msgid "Compression ratio" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:74 #: ../quodlibet/ext/gstreamer/karaoke.py:91 #, python-format msgid "%d %%" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:105 msgid "Audio Compressor" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:106 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:19 #, fuzzy msgid "_Preset:" msgstr "_Önizleme" #: ../quodlibet/ext/gstreamer/crossfeed.py:19 #, fuzzy msgid "Filter preset" msgstr "_Sanatçıya göre süz" #: ../quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Frequency cut:" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Low-pass filter cut frequency" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed _level:" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed level" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:25 msgid "Default" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Chu Moy" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Jan Meier" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:31 #, fuzzy msgid "Custom settings" msgstr "_Özel" #: ../quodlibet/ext/gstreamer/crossfeed.py:152 msgid "Crossfeed" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:153 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:20 #, fuzzy msgid "Filter _band:" msgstr "_Türe göre süz" #: ../quodlibet/ext/gstreamer/karaoke.py:21 msgid "The Frequency band of the filter" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:22 #, fuzzy msgid "Filter _width:" msgstr "_Sanatçıya göre süz" #: ../quodlibet/ext/gstreamer/karaoke.py:23 msgid "The Frequency width of the filter" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:24 msgid "_Level:" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:24 msgid "Level of the effect" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:105 msgid "Karaoke" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:106 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:20 msgid "R_ate:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:21 msgid "_Tempo:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:22 msgid "_Pitch:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:89 #, fuzzy msgid "Audio Pitch / Speed" msgstr "Ses bildirimleri" #: ../quodlibet/ext/gstreamer/pitch.py:90 #, fuzzy msgid "Controls the pitch of an audio stream." msgstr "Ses bildiriminin yerini girin:" #: ../quodlibet/ext/playlist/export_to_folder.py:29 #: ../quodlibet/ext/playlist/export_to_folder.py:97 #: ../quodlibet/ext/playlist/export_to_folder.py:138 #, fuzzy msgid "Export Playlist to Folder" msgstr "Çalma Listesi İçe Aktar" #: ../quodlibet/ext/playlist/export_to_folder.py:38 #, fuzzy msgid "_Export" msgstr "İçe _Aktar" #: ../quodlibet/ext/playlist/export_to_folder.py:43 #, fuzzy msgid "Destination folder:" msgstr "Kanal bulunamadı" #: ../quodlibet/ext/playlist/export_to_folder.py:58 #, fuzzy msgid "Filename pattern:" msgstr "_Dosya Adı Süzgeci:" #: ../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:156 #, fuzzy msgid "Default filename pattern:" msgstr "_Dosya Adı Süzgeci:" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:23 msgid "Export to Squeezebox" msgstr "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:25 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 "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Export playlist to Squeezebox" msgstr "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:80 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 "Çalma Listesinden _Çıkar" #: ../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 "Yeni Çalma Listesi" #: ../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 "" "Playback follows your selection, or the next song in the list once exhausted." msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:22 msgid "Playcount Equalizer" msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:23 msgid "Shuffle, preferring songs with fewer total plays." msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:25 #, fuzzy msgid "Prefer less played" msgstr "en son çalındı" #: ../quodlibet/ext/playorder/queue.py:19 #, fuzzy msgid "Queue Only" msgstr "Çalma _Kuyruğu" #: ../quodlibet/ext/playorder/queue.py:21 msgid "" "Limits playing of songs to the queue. Select this play order in the main " "window, then double-clicking any song will enqueue it instead of playing." msgstr "" #: ../quodlibet/ext/playorder/reverse.py:14 #, fuzzy msgid "Reverse" msgstr "Hiçbir Zaman" #: ../quodlibet/ext/playorder/reverse.py:16 msgid "Reverses the play order of songs." msgstr "" #: ../quodlibet/ext/playorder/skip_songs.py:25 #, fuzzy msgid "Skip Songs" msgstr "Şarkı yok" #: ../quodlibet/ext/playorder/skip_songs.py:27 msgid "" "Playback skips over songs with a rating equal or below a given threshold." msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:30 msgid "Repeat Each Track" msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:32 msgid "Shuffle songs, but repeat every track a set number of times." msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:51 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. Syntax is '@(if: " "condition, then, else)'." msgstr "" #: ../quodlibet/ext/query/pythonexpression.py:14 msgid "Python Query" msgstr "" #: ../quodlibet/ext/query/pythonexpression.py:15 msgid "" "Use Python expressions in queries. Syntax is '@(python: expression)'. The " "variable 's' is the song being matched." msgstr "" #: ../quodlibet/ext/query/savedsearch.py:19 #, fuzzy msgid "Include Saved Search" msgstr "Kayıtlı Değerler" #: ../quodlibet/ext/query/savedsearch.py:20 msgid "" "Include the results of a saved search as part of another query. Syntax is " "'@(saved: search name)'." 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:116 msgid "Port:" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:121 #, fuzzy msgid "Username:" msgstr "_Yeniden Adlandır" #: ../quodlibet/ext/_shared/squeezebox/base.py:126 msgid "Password:" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:130 msgid "Library directory the server connects to." msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:132 #, fuzzy msgid "Library path:" msgstr "Arşiv" #. Add verify button #: ../quodlibet/ext/_shared/squeezebox/base.py:141 msgid "_Verify settings" msgstr "" #. Server settings Frame #: ../quodlibet/ext/_shared/squeezebox/base.py:147 msgid "Squeezebox Server" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:150 msgid "Debug" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:26 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:28 msgid "unidentified Squeezebox server" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:37 #, 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:20 #: ../quodlibet/ext/songsmenu/importexport.py:34 #: ../quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:329 #, fuzzy msgid "Fit image to _window" msgstr "Ana pencereyi gizle" #. Both labels #: ../quodlibet/ext/songsmenu/albumart.py:338 msgid "_Program:" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:343 msgid "_Edit image after saving" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:345 #, fuzzy msgid "File_name:" msgstr "Dosya Adı" #: ../quodlibet/ext/songsmenu/albumart.py:457 msgid "Saving failed" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:458 #, fuzzy, python-format msgid "Unable to save \"%s\"." msgstr "Şarkı kaydedilemedi" #: ../quodlibet/ext/songsmenu/albumart.py:556 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:613 #, fuzzy msgid "Album Art Downloader" msgstr "Albüm Listesi" #: ../quodlibet/ext/songsmenu/albumart.py:666 #, python-format msgid "from %(source)s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:669 #, python-format msgid "Resolution: %s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:672 #, fuzzy, python-format msgid "Size: %s" msgstr "Boyut" #: ../quodlibet/ext/songsmenu/albumart.py:690 #, fuzzy msgid "_Search" msgstr "_Ara:" #: ../quodlibet/ext/songsmenu/albumart.py:741 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:451 #, fuzzy msgid "Searching…" msgstr "Ara" #: ../quodlibet/ext/songsmenu/albumart.py:804 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:922 #, fuzzy msgid "Download Album Art" msgstr "Albüm Listesi" #: ../quodlibet/ext/songsmenu/albumart.py:923 msgid "Downloads album covers from various websites." msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:936 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 "Yer imlerini _değiştir" #: ../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 "Yer imlerini _değiştir" #: ../quodlibet/ext/songsmenu/bookmarks.py:73 #, fuzzy msgid "No Bookmarks" msgstr "Yer imleri" #: ../quodlibet/ext/songsmenu/brainz/__init__.py:24 #, fuzzy msgid "MusicBrainz Lookup" msgstr "MusicBrainz albüm türü" #: ../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 #: ../quodlibet/qltk/downloader.py:52 msgid "Filename" msgstr "Dosya Adı" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:130 #, fuzzy msgid "Disc" msgstr "_Disk" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:131 #: ../quodlibet/ext/songsmenu/replaygain.py:404 #: ../quodlibet/qltk/tracknumbers.py:92 msgid "Track" msgstr "Şarkı" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:132 #, fuzzy msgid "Title" msgstr "Ad" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:133 #, fuzzy msgid "Artist" msgstr "_Sanatçı" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:352 #, fuzzy msgid "MusicBrainz lookup" msgstr "MusicBrainz albüm türü" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:375 #, fuzzy msgid "_Query:" msgstr "sorgu" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:378 #, fuzzy msgid "S_earch" msgstr "Ara" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:391 msgid "Results <i>(drag to reorder)</i>" msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:447 msgid "Please enter a query." msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:465 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:496 msgid "Error encountered. Please retry." msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:472 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:488 msgid "Loading result…" msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:475 #, fuzzy msgid "No results found." msgstr "Eklenti bulunamadı." #: ../quodlibet/ext/songsmenu/browsefolders.py:159 #, fuzzy msgid "Browse Folders" msgstr "Geziciler" #: ../quodlibet/ext/songsmenu/browsefolders.py:160 msgid "Opens the songs' folders in a file manager." msgstr "" #: ../quodlibet/ext/songsmenu/browsefolders.py:172 #, fuzzy msgid "Unable to open folders" msgstr "Dizin yaratılamadı" #: ../quodlibet/ext/songsmenu/browsefolders.py:173 msgid "No program available to open folders." msgstr "" #: ../quodlibet/ext/songsmenu/console.py:40 msgid "Python Console" msgstr "" #: ../quodlibet/ext/songsmenu/console.py:41 msgid "Interactive Python console." msgstr "" #: ../quodlibet/ext/songsmenu/console.py:72 msgid "You can access the following objects by default:" msgstr "" #: ../quodlibet/ext/songsmenu/console.py:82 msgid "Your current working directory is:" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:41 #, fuzzy msgid "Command" msgstr "etiket" #: ../quodlibet/ext/songsmenu/custom_commands.py:44 #, fuzzy msgid "name" msgstr "_Yeniden Adlandır" #: ../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 "etiket" #: ../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:55 #, fuzzy msgid "pattern" msgstr "Geçersiz süzgeç" #: ../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:91 #, fuzzy msgid "Input value" msgstr "Geçersiz değer" #: ../quodlibet/ext/songsmenu/custom_commands.py:92 #, python-format msgid "Value for %s?" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:136 #, fuzzy msgid "Custom Commands" msgstr "_Özel" #: ../quodlibet/ext/songsmenu/custom_commands.py:137 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:188 #: ../quodlibet/ext/songsmenu/custom_commands.py:198 #: ../quodlibet/ext/songsmenu/custom_commands.py:252 msgid "Edit Custom Commands" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:199 msgid "" "Supports QL patterns\n" "eg <tt><~artist~title></tt>" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:283 #, fuzzy, python-format msgid "Unable to run custom command %s" msgstr "Şarkılar kopyalanamıyor" #: ../quodlibet/ext/songsmenu/duplicates.py:290 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "" msgstr[1] "" #: ../quodlibet/ext/songsmenu/duplicates.py:343 msgid "Collapse / Expand all" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:347 #, python-format msgid "Duplicate key expression is '%s'" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:363 #, fuzzy msgid "Duplicates Browser" msgstr "Geziciyi Gizle" #: ../quodlibet/ext/songsmenu/duplicates.py:364 msgid "Finds and displays similarly tagged versions of songs." msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:407 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:409 msgid "_Group duplicates by:" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:414 msgid "Duplicate Key" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:419 msgid "Remove _Whitespace" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:420 #, fuzzy msgid "Remove _Diacritics" msgstr "_Puan" #: ../quodlibet/ext/songsmenu/duplicates.py:421 #, fuzzy msgid "Remove _Punctuation" msgstr "_Puan" #: ../quodlibet/ext/songsmenu/duplicates.py:422 msgid "Case _Insensitive" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:430 msgid "Matching options" msgstr "" #. Create a dialog. #: ../quodlibet/ext/songsmenu/editplaycount.py:19 #: ../quodlibet/ext/songsmenu/editplaycount.py:41 #, fuzzy msgid "Edit Playcount" msgstr "Görünümü Değiştir" #: ../quodlibet/ext/songsmenu/editplaycount.py:20 msgid "" "Edit a song's ~#playcount and ~#skipcount.\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's ~#playcount to 0, the ~#lastplayed and ~#laststarted " "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:68 msgid "Play Count" msgstr "" #: ../quodlibet/ext/songsmenu/editplaycount.py:69 msgid "Skip Count" msgstr "" #: ../quodlibet/ext/songsmenu/embedded.py:24 msgid "Edit Embedded Images" msgstr "" #: ../quodlibet/ext/songsmenu/embedded.py:25 msgid "Removes or replaces embedded images." msgstr "" #: ../quodlibet/ext/songsmenu/embedded.py:78 #, fuzzy msgid "_Remove all Images" msgstr "_Puan" #: ../quodlibet/ext/songsmenu/embedded.py:82 msgid "_Embed Current 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 "Bir etiket değerine göre süz" #: ../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 "_Türe göre süz" #: ../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:41 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 #: ../quodlibet/qltk/downloader.py:67 #, fuzzy msgid "Queued" msgstr "Çalma _Kuyruğu" #: ../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 "Yaz" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" 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 şarkı ID'si" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:296 #, fuzzy msgid "Group by directory" msgstr "dizin" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:305 #, fuzzy msgid "Album Mode" msgstr "_Albüm Etiketleri" #: ../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:49 msgid "Generating fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:63 msgid "_Details" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:85 msgid "_Submit" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:115 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:118 msgid "Fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Songs with MBIDs:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with sufficient tags:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs to submit:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:162 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:178 msgid "Submitting fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:186 msgid "Submitting…" msgstr "" #: ../quodlibet/ext/songsmenu/forcewrite.py:17 #, fuzzy msgid "Update Tags in Files" msgstr "_Yeni Kanal" #: ../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/id3tlen.py:21 msgid "Fix MP3 Duration" msgstr "" #: ../quodlibet/ext/songsmenu/id3tlen.py:22 msgid "" "Removes TLEN frames from ID3 tags which can be the cause for invalid song " "durations." msgstr "" #: ../quodlibet/ext/songsmenu/ifp.py:20 msgid "Send to iFP" msgstr "" #: ../quodlibet/ext/songsmenu/ifp.py:21 msgid "Uploads songs to an iRiver iFP device." msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:51 msgid "Export Metadata" msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:52 msgid "Exports metadata of selected songs as a .tags file." msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:92 #, fuzzy msgid "Import Metadata" msgstr "Çalma Listesi İçe Aktar" #: ../quodlibet/ext/songsmenu/importexport.py:93 msgid "Imports metadata for selected songs from a .tags file." msgstr "" #: ../quodlibet/ext/songsmenu/k3b.py:23 msgid "Burn CD" msgstr "" #: ../quodlibet/ext/songsmenu/k3b.py:24 msgid "Burns CDs with K3b, Brasero or xfburn." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:96 msgid "Updating chart list." msgstr "" #. No charts to fetch, no update scheduled. #: ../quodlibet/ext/songsmenu/lastfmsync.py:114 msgid "Already up-to-date." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:121 #, python-format msgid "Fetching chart for week of %s." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:143 msgid "Sync complete." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:149 #, fuzzy msgid "Error during sync" msgstr "%r yüklenemedi." #: ../quodlibet/ext/songsmenu/lastfmsync.py:214 #: ../quodlibet/ext/songsmenu/lastfmsync.py:244 msgid "Last.fm Sync" msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:245 msgid "Updates your library's statistics from your Last.fm profile." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:293 #, fuzzy msgid "_Username:" msgstr "_Yeniden Adlandır" #: ../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 "" #. Create a dialog. #: ../quodlibet/ext/songsmenu/migratemetadata.py:29 #: ../quodlibet/ext/songsmenu/migratemetadata.py:38 #, fuzzy msgid "Migrate Metadata" msgstr "Çalma Listesi İçe Aktar" #: ../quodlibet/ext/songsmenu/migratemetadata.py:32 msgid "Copies the quodlibet-specific metadata between songs." msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:45 msgid "_Copy" msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:47 msgid "_Paste" msgstr "" #. Create the tag table. #: ../quodlibet/ext/songsmenu/migratemetadata.py:57 #, fuzzy msgid "Information to copy/paste" msgstr "Bilgi" #. Create the indexing box. #: ../quodlibet/ext/songsmenu/migratemetadata.py:79 msgid "Map tracks by disc and track number" msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:80 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 "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:96 #, python-format msgid "There is %d stored track." msgid_plural "There are %d stored tracks." msgstr[0] "" msgstr[1] "" #: ../quodlibet/ext/songsmenu/playlist.py:31 #, fuzzy msgid "Export as Playlist" msgstr "Çalma Listesi İçe Aktar" #: ../quodlibet/ext/songsmenu/playlist.py:32 msgid "Exports songs to an M3U or PLS playlist." msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:77 msgid "Use relative paths" msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:77 msgid "Use absolute paths" msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:132 #, fuzzy msgid "Unable to export playlist" msgstr "Çalma listesi içe aktarılamadı" #: ../quodlibet/ext/songsmenu/playlist.py:133 #, fuzzy, python-format msgid "Writing to <b>%s</b> failed." msgstr "<b>%s</b> çıkartılamadı." #. Translators: Plugin name #: ../quodlibet/ext/songsmenu/refresh.py:22 #, fuzzy msgid "Rescan Songs" msgstr "Arşivi _Yenile" #: ../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 "Arşivi _Yenile" #: ../quodlibet/ext/songsmenu/replaygain.py:362 msgid "ReplayGain Analyzer" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:418 msgid "Progress" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:433 msgid "Gain" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:448 msgid "Peak" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:463 #, python-format msgid "There is <b>%(to-process)s</b> album to update (of %(all)s)" msgid_plural "There are <b>%(to-process)s</b> albums to update (of %(all)s)" msgstr[0] "" msgstr[1] "" #: ../quodlibet/ext/songsmenu/replaygain.py:578 msgid "Replay Gain" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:579 msgid "" "Analyzes and updates ReplayGain information, using GStreamer. Results are " "grouped by album." msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:617 msgid "always" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:618 msgid "if <b>any</b> RG tags are missing" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:620 msgid "if <b>album</b> RG tags are missing" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:637 msgid "_Process albums:" msgstr "" #. Server settings Frame #: ../quodlibet/ext/songsmenu/replaygain.py:649 #, fuzzy msgid "Existing Tags" msgstr "Etiketleri değiştir" #: ../quodlibet/ext/songsmenu/splitting.py:31 #, fuzzy msgid "Split Tags" msgstr "Etiketleri değiştir" #: ../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 "Tüm albümler" #: ../quodlibet/ext/songsmenu/splitting.py:57 msgid "Split out disc number." msgstr "" #. TRANSLATORS: BPM mean "beats per minute" #: ../quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "" #: ../quodlibet/ext/songsmenu/tapbpm.py:32 #: ../quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" msgstr "" #: ../quodlibet/ext/songsmenu/tapbpm.py:36 #, fuzzy msgid "Reset" msgstr "_Önizleme" #: ../quodlibet/ext/songsmenu/tapbpm.py:42 #, fuzzy msgid "Tap" msgstr "Etiket" #: ../quodlibet/ext/songsmenu/tapbpm.py:172 #: ../quodlibet/ext/songsmenu/tapbpm.py:179 msgid "Tap BPM" msgstr "" #: ../quodlibet/ext/songsmenu/tapbpm.py:173 #, fuzzy msgid "Tap BPM for the selected song." msgstr "Şarkılar silinemiyor" #: ../quodlibet/ext/songsmenu/website_search.py:35 #, fuzzy msgid "Website Search" msgstr "Ara" #: ../quodlibet/ext/songsmenu/website_search.py:36 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern-example)s." msgstr "" #: ../quodlibet/ext/songsmenu/website_search.py:78 #, fuzzy msgid "Search URL patterns" msgstr "süzgeç" #: ../quodlibet/ext/songsmenu/website_search.py:88 #, fuzzy msgid "Edit search URLs" msgstr "Kayıtlı değerleri değiştir..." #. Add link to editor #: ../quodlibet/ext/songsmenu/website_search.py:114 #, fuzzy msgid "Configure Searches…" msgstr "Arama kriterlerini _renklendir" #: ../quodlibet/ext/songsmenu/wikipedia.py:46 #, python-format msgid "Search at %(website)s" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:63 msgid "Search Artist in Wikipedia" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:64 msgid "" "Opens a browser window with Wikipedia article on the playing song artist." msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:71 msgid "Search Album in Wikipedia" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:72 msgid "" "Opens a browser window with Wikipedia article on the playing song album." msgstr "" #. then (try to) load all new files #: ../quodlibet/library/libraries.py:650 ../quodlibet/library/libraries.py:660 #: ../quodlibet/library/libraries.py:726 ../quodlibet/library/libraries.py:745 #: ../quodlibet/qltk/information.py:268 ../quodlibet/qltk/prefs.py:639 #: ../quodlibet/util/library.py:124 msgid "Library" msgstr "Arşiv" #: ../quodlibet/library/libraries.py:650 msgid "Checking mount points" msgstr "Bağlama yerleri denetleniyor" #: ../quodlibet/library/libraries.py:660 msgid "Scanning library" msgstr "Arşiv taranıyor" #: ../quodlibet/library/libraries.py:725 #, python-format msgid "Scanning %s" msgstr "%s taranıyor" #: ../quodlibet/library/libraries.py:745 msgid "Loading files" msgstr "" #: ../quodlibet/operon/base.py:70 #, python-format msgid "Failed to load file: %r" msgstr "" #: ../quodlibet/operon/commands.py:37 msgid "List tags" msgstr "" #: ../quodlibet/operon/commands.py:42 ../quodlibet/operon/commands.py:81 #: ../quodlibet/operon/commands.py:461 msgid "Print terse output" msgstr "" #: ../quodlibet/operon/commands.py:44 ../quodlibet/operon/commands.py:83 #: ../quodlibet/operon/commands.py:463 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "" #: ../quodlibet/operon/commands.py:47 ../quodlibet/operon/commands.py:86 #, fuzzy msgid "Also list programmatic tags" msgstr "_Programatik etiketleri göster" #: ../quodlibet/operon/commands.py:51 ../quodlibet/operon/commands.py:129 #: ../quodlibet/operon/commands.py:220 ../quodlibet/operon/commands.py:293 #: ../quodlibet/operon/commands.py:336 ../quodlibet/operon/commands.py:340 #: ../quodlibet/operon/commands.py:391 ../quodlibet/operon/commands.py:394 #: ../quodlibet/operon/commands.py:433 ../quodlibet/operon/commands.py:468 #: ../quodlibet/operon/commands.py:508 ../quodlibet/operon/commands.py:543 #: ../quodlibet/operon/commands.py:585 msgid "Not enough arguments" msgstr "" #: ../quodlibet/operon/commands.py:53 ../quodlibet/operon/commands.py:90 #: ../quodlibet/operon/commands.py:131 ../quodlibet/operon/commands.py:222 #: ../quodlibet/operon/commands.py:470 #, fuzzy msgid "Too many arguments" msgstr "Çok Fazla Hata" #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:92 #: ../quodlibet/operon/commands.py:475 ../quodlibet/qltk/data_editors.py:363 #, fuzzy msgid "Description" msgstr "açıklama" #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:475 #: ../quodlibet/qltk/edittags.py:454 msgid "Value" msgstr "Değer" #: ../quodlibet/operon/commands.py:76 msgid "List all common tags" msgstr "" #: ../quodlibet/operon/commands.py:118 msgid "Copy tags from one file to another" msgstr "" #: ../quodlibet/operon/commands.py:123 ../quodlibet/operon/commands.py:164 #: ../quodlibet/operon/commands.py:289 ../quodlibet/operon/commands.py:324 #: ../quodlibet/operon/commands.py:384 msgid "Show changes, don't apply them" msgstr "" #: ../quodlibet/operon/commands.py:125 msgid "Skip tags that can't be written" msgstr "" #: ../quodlibet/operon/commands.py:145 #, python-format msgid "Can't copy tag %r to file: %r" msgstr "" #: ../quodlibet/operon/commands.py:157 #, fuzzy msgid "Edit tags in a text editor" msgstr "Müzik etiketleri düzenleyici" #: ../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 "Seçili şarkı yok." #: ../quodlibet/operon/commands.py:284 msgid "Set a tag and remove existing values" msgstr "" #: ../quodlibet/operon/commands.py:304 ../quodlibet/operon/commands.py:444 #: ../quodlibet/operon/commands.py:676 #, python-format msgid "Can not set %r" msgstr "" #: ../quodlibet/operon/commands.py:319 msgid "Remove tags" msgstr "" #: ../quodlibet/operon/commands.py:326 ../quodlibet/operon/commands.py:386 msgid "Value is a regular expression" msgstr "" #: ../quodlibet/operon/commands.py:328 msgid "Remove all tags" msgstr "" #: ../quodlibet/operon/commands.py:332 msgid "Can't combine '--all' with '--regexp'" msgstr "" #: ../quodlibet/operon/commands.py:366 #, python-format msgid "Can't remove %r from %r" msgstr "" #: ../quodlibet/operon/commands.py:379 #, fuzzy msgid "Remove a tag value" msgstr "Bir etiket değerine göre süz" #: ../quodlibet/operon/commands.py:428 #, fuzzy msgid "Add a tag value" msgstr "Bir etiket değerine göre süz" #: ../quodlibet/operon/commands.py:456 #, fuzzy msgid "List file information" msgstr "Süre bilgisi yok" #: ../quodlibet/operon/commands.py:502 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" #: ../quodlibet/operon/commands.py:515 #, fuzzy, python-format msgid "Failed to load image file: %r" msgstr "Dosya yeniden adlandırılamadı" #: ../quodlibet/operon/commands.py:522 ../quodlibet/operon/commands.py:551 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" #: ../quodlibet/operon/commands.py:538 msgid "Remove all embedded images" msgstr "" #: ../quodlibet/operon/commands.py:568 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "" #: ../quodlibet/operon/commands.py:580 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" #: ../quodlibet/operon/commands.py:639 msgid "Rename files based on tags" msgstr "" #: ../quodlibet/operon/commands.py:654 msgid "Fill tags based on the file path" msgstr "" #: ../quodlibet/operon/commands.py:704 ../quodlibet/qltk/information.py:305 #: ../quodlibet/qltk/properties.py:84 ../quodlibet/qltk/renamefiles.py:176 #: ../quodlibet/qltk/tagsfrompath.py:229 ../quodlibet/qltk/tracknumbers.py:79 msgid "File" msgstr "Dosya" #: ../quodlibet/operon/commands.py:712 msgid "Fill tracknumbers for all files" msgstr "" #: ../quodlibet/operon/commands.py:731 msgid "Print tags based on the given pattern" msgstr "" #: ../quodlibet/operon/commands.py:768 #, fuzzy msgid "Display help information" msgstr "Özet kullanım bilgisi göster" #: ../quodlibet/operon/util.py:40 #, fuzzy, python-format msgid "'%(column-id)s' is not a valid column name (%(all-column-ids)s)." msgstr "<b>%s</b> geçerli bir adres değil." #: ../quodlibet/order/__init__.py:30 msgid "_Unknown" msgstr "_Bilinmeyen" #: ../quodlibet/order/__init__.py:142 msgid "In Order" msgstr "Sırayla" #: ../quodlibet/order/__init__.py:143 msgid "_In Order" msgstr "_Sırayla" #: ../quodlibet/order/reorder.py:23 #, fuzzy msgid "Random" msgstr "_Rastgele" #: ../quodlibet/order/reorder.py:24 ../quodlibet/qltk/queue.py:119 msgid "_Random" msgstr "_Rastgele" #: ../quodlibet/order/reorder.py:39 ../quodlibet/order/reorder.py:40 msgid "Prefer higher rated" msgstr "" #: ../quodlibet/order/repeat.py:43 ../quodlibet/order/repeat.py:44 msgid "Repeat this track" msgstr "" #: ../quodlibet/order/repeat.py:57 ../quodlibet/order/repeat.py:58 #, fuzzy msgid "Repeat all" msgstr "_Başa dön" #: ../quodlibet/order/repeat.py:73 ../quodlibet/order/repeat.py:74 msgid "One Song" msgstr "Bir Şarkı" #: ../quodlibet/player/gstbe/player.py:98 msgid "Stream" msgstr "" #: ../quodlibet/player/gstbe/player.py:98 msgid "Buffering" msgstr "" #: ../quodlibet/player/gstbe/player.py:319 msgid "Could not create GStreamer pipeline" msgstr "" #: ../quodlibet/player/gstbe/player.py:560 msgid "No GStreamer element found to handle media format" msgstr "" #: ../quodlibet/player/gstbe/player.py:561 #, 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:25 msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. In case the pipeline contains a sink, it will be used instead of " "the default one." msgstr "" #: ../quodlibet/player/gstbe/prefs.py:36 msgid "_Output pipeline:" msgstr "" #: ../quodlibet/player/gstbe/prefs.py:43 #, fuzzy, python-format msgid "%.1f seconds" msgstr "%d saniye" #: ../quodlibet/player/gstbe/prefs.py:57 msgid "_Buffer duration:" msgstr "" #: ../quodlibet/player/gstbe/prefs.py:66 msgid "Disable _gapless playback" msgstr "" #: ../quodlibet/player/gstbe/prefs.py:70 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions." msgstr "" #: ../quodlibet/player/gstbe/util.py:93 #, fuzzy msgid "No GStreamer audio sink found" msgstr "Kanal bulunamadı" #: ../quodlibet/player/gstbe/util.py:112 msgid "Invalid GStreamer output pipeline" msgstr "" #: ../quodlibet/player/xinebe/player.py:90 msgid "Unable to create audio output" msgstr "Ses çıkışı yaratılamadı." #: ../quodlibet/player/xinebe/player.py:91 #, 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:62 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" #: ../quodlibet/plugins/__init__.py:71 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "" #: ../quodlibet/plugins/playlist.py:30 #, 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:41 ../quodlibet/qltk/songsmenu.py:46 #: ../quodlibet/qltk/songsmenu.py:74 #, fuzzy msgid "_Run Plugin" msgstr "_Eklentiler" #: ../quodlibet/qltk/about.py:40 #, python-format msgid "Supported formats: %s" msgstr "Desteklenen biçimler: %s" #: ../quodlibet/qltk/about.py:43 #, python-format msgid "Audio device: %s" msgstr "Ses aygıtı: %s" #. 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:207 ../quodlibet/qltk/information.py:131 msgid "Bookmarks" msgstr "Yer imleri" #: ../quodlibet/qltk/browser.py:56 msgid "_Filters" msgstr "_Süzgeçler" #: ../quodlibet/qltk/browser.py:57 #, fuzzy msgid "Recently _Played" msgstr "_Hiç çalınmadı" #: ../quodlibet/qltk/browser.py:59 msgid "Recently _Added" msgstr "" #: ../quodlibet/qltk/browser.py:61 msgid "_Top 40" msgstr "_Tepe 40" #: ../quodlibet/qltk/browser.py:63 #, fuzzy msgid "All _Songs" msgstr "Yeni Kanal" #: ../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 "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:48 ../quodlibet/qltk/edittags.py:311 msgid "_Value:" msgstr "_Değer:" #: ../quodlibet/qltk/cbes.py:262 msgid "Saved Values" msgstr "Kayıtlı Değerler" #: ../quodlibet/qltk/cbes.py:263 #, fuzzy msgid "Edit saved values…" msgstr "Kayıtlı değerleri değiştir..." #: ../quodlibet/qltk/controls.py:111 msgid "Auto_matic" msgstr "" #: ../quodlibet/qltk/controls.py:112 #, fuzzy msgid "_Track Mode" msgstr "Şarkı _Numarası Etiketleri" #: ../quodlibet/qltk/controls.py:113 #, fuzzy msgid "_Album Mode" msgstr "_Albüm Etiketleri" #. Translators: player state, no action #: ../quodlibet/qltk/controls.py:122 msgid "_Mute" msgstr "" #: ../quodlibet/qltk/controls.py:128 #, fuzzy msgid "_Replay Gain Mode" msgstr "Ses Düzeyi Düzeltmesi" #. Translators: New Command/Entry/Item/... #: ../quodlibet/qltk/data_editors.py:119 #, python-format msgid "New %s" msgstr "" #: ../quodlibet/qltk/data_editors.py:218 #, fuzzy msgid "(unknown)" msgstr "Bilinmeyen" #: ../quodlibet/qltk/data_editors.py:355 msgid "Tag expression" msgstr "" #: ../quodlibet/qltk/data_editors.py:382 msgid "Tag expression e.g. people:real or ~album~year." msgstr "" #: ../quodlibet/qltk/data_editors.py:383 #, fuzzy msgid "Enter new tag" msgstr "Bir etiket değerine göre süz" #: ../quodlibet/qltk/delete.py:37 #, fuzzy 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 "" #: ../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 "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 "" #: ../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 "_Çö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 #, fuzzy msgid "Unable to move to trash" msgstr "iPod veritabanı kaydedilemedi" #: ../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> çıkartılamadı." #: ../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 #, fuzzy msgid "Unable to delete files" msgstr "Dosya silinemedi" #: ../quodlibet/qltk/delete.py:237 ../quodlibet/qltk/delete.py:270 #, fuzzy msgid "Deleting one or more files failed." msgstr "<b>%s</b> silinemedi." #: ../quodlibet/qltk/downloader.py:38 msgid "Downloads" msgstr "İndirilenler" #: ../quodlibet/qltk/downloader.py:62 msgid "Size" msgstr "Boyut" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: ../quodlibet/qltk/downloader.py:94 ../quodlibet/qltk/renamefiles.py:265 #: ../quodlibet/qltk/wlw.py:50 msgid "_Stop" msgstr "" #: ../quodlibet/qltk/edittags.py:63 ../quodlibet/qltk/edittags.py:74 #, 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:67 ../quodlibet/qltk/edittags.py:71 #, 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:193 msgid "Split into _Multiple Values" msgstr "Birden fazla değelere _böl" #: ../quodlibet/qltk/edittags.py:211 msgid "Split Disc out of _Album" msgstr "Diski _Albümden ayır" #: ../quodlibet/qltk/edittags.py:228 msgid "Split _Version out of Title" msgstr "_Versiyonu İsimden ayır" #: ../quodlibet/qltk/edittags.py:259 msgid "Split Arranger out of Ar_tist" msgstr "Aranjörü _Sanatçıdan ayır" #: ../quodlibet/qltk/edittags.py:264 msgid "Split _Performer out of Artist" msgstr "Seslendireni Sanatçıdan ayır" #: ../quodlibet/qltk/edittags.py:270 #, fuzzy msgid "Split _Performer out of Title" msgstr "Seslendireni Sanatçıdan ayır" #: ../quodlibet/qltk/edittags.py:276 #, fuzzy msgid "Split _Originalartist out of Title" msgstr "_Versiyonu İsimden ayır" #: ../quodlibet/qltk/edittags.py:283 msgid "Add a Tag" msgstr "Etiket ekle" #: ../quodlibet/qltk/edittags.py:302 msgid "_Tag:" msgstr "_Etiket:" #: ../quodlibet/qltk/edittags.py:404 msgid "Edit Tags" msgstr "Etiketleri değiştir" #: ../quodlibet/qltk/edittags.py:477 msgid "Show _programmatic tags" msgstr "_Programatik etiketleri göster" #: ../quodlibet/qltk/edittags.py:478 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" #. Translators: Revert button in the tag editor #: ../quodlibet/qltk/edittags.py:508 #, fuzzy msgctxt "edittags" msgid "_Revert" msgstr "Hiçbir Zaman" #. Translators: Save button in the tag editor #: ../quodlibet/qltk/edittags.py:513 msgctxt "edittags" msgid "_Save" msgstr "" #: ../quodlibet/qltk/edittags.py:659 msgid "Unable to add tag" msgstr "Etiket eklenemedi" #: ../quodlibet/qltk/edittags.py:660 #, fuzzy, python-format msgid "Unable to add <b>%s</b>" msgstr "Şarkı eklenemedi" #: ../quodlibet/qltk/edittags.py:662 #, fuzzy, python-format msgid "" "The files currently selected do not support multiple values for <b>%s</b>." msgstr "" "<b>%s</b> eklenemedi\n" "\n" "Seçili dosyalar birden fazla değeri desteklemiyor." #. Can't add the new tag. #: ../quodlibet/qltk/edittags.py:689 ../quodlibet/qltk/edittags.py:856 #: ../quodlibet/qltk/tagsfrompath.py:212 ../quodlibet/util/__init__.py:554 #: ../quodlibet/util/tags.py:231 msgid "Invalid tag" msgstr "Geçersiz etiket" #: ../quodlibet/qltk/edittags.py:690 ../quodlibet/qltk/edittags.py:857 #: ../quodlibet/qltk/tagsfrompath.py:213 #, python-format msgid "" "Invalid tag <b>%s</b>\n" "\n" "The files currently selected do not support editing this tag." msgstr "" "<b>%s</b> geçersiz bir etiket\n" "\n" "Seçili dosyalar bu etiketi değiştirmeyi desteklemiyor." #: ../quodlibet/qltk/edittags.py:828 ../quodlibet/qltk/edittags.py:868 msgid "Invalid value" msgstr "Geçersiz değer" #: ../quodlibet/qltk/edittags.py:829 ../quodlibet/qltk/edittags.py:869 #, python-format msgid "" "Invalid value: <b>%(value)s</b>\n" "\n" "%(error)s" msgstr "" "Geçersiz değer: <b>%(value)s</b>\n" "\n" "%(error)s" #: ../quodlibet/qltk/_editutils.py:28 msgid "Tag may not be accurate" msgstr "Etiket doğru olmayabilir" #: ../quodlibet/qltk/_editutils.py:31 #, 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> program çalışıyorken değişti. Arşivi yenilemeden kaydetmek arada " "yapılan değişiklikleri yokedebilir.\n" "\n" "Yine de kaydedilsin mi?" #: ../quodlibet/qltk/_editutils.py:47 msgid "Unable to save song" msgstr "Şarkı kaydedilemedi" #: ../quodlibet/qltk/_editutils.py:50 #, 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> kaydedilemedi. Dosya salt okunur olabilir veya sizin dosyayı " "değiştirme izniniz olmayabilir." #: ../quodlibet/qltk/_editutils.py:142 #, fuzzy msgid "_More options…" msgstr "_Daha çok seçenek..." #: ../quodlibet/qltk/entry.py:80 msgid "_Undo" msgstr "" #: ../quodlibet/qltk/entry.py:82 msgid "_Redo" msgstr "" #: ../quodlibet/qltk/exfalsowindow.py:95 #: ../quodlibet/qltk/quodlibetwindow.py:1066 msgid "_About" msgstr "" #: ../quodlibet/qltk/exfalsowindow.py:99 #: ../quodlibet/qltk/quodlibetwindow.py:1088 msgid "_Check for Updates…" msgstr "" #: ../quodlibet/qltk/exfalsowindow.py:105 #: ../quodlibet/qltk/quodlibetwindow.py:1021 ../quodlibet/qltk/songsmenu.py:304 msgid "_Plugins" msgstr "_Eklentiler" #: ../quodlibet/qltk/exfalsowindow.py:267 #, fuzzy, python-format msgid "%(title)s and %(count)s more" msgid_plural "%(title)s and %(count)s more" msgstr[0] "%(title)s ve %(count)d tane daha" msgstr[1] "%(title)s ve %(count)d tane daha" #: ../quodlibet/qltk/exfalsowindow.py:279 msgid "Ex Falso Preferences" msgstr "Ex Falso Ayarları" #: ../quodlibet/qltk/exfalsowindow.py:289 ../quodlibet/qltk/prefs.py:598 msgid "Split _on:" msgstr "Buna göre _ayır:" #: ../quodlibet/qltk/exfalsowindow.py:295 ../quodlibet/qltk/prefs.py:613 msgid "Tag Editing" msgstr "Etiket değiştirme" #: ../quodlibet/qltk/filesel.py:210 msgid "Folders" msgstr "Dizinler" #: ../quodlibet/qltk/filesel.py:253 #, fuzzy msgid "_New Folder…" msgstr "Yeni Dizin" #: ../quodlibet/qltk/filesel.py:262 #, fuzzy msgid "_Select all Sub-Folders" msgstr "_Tüm Alt Dizinleri Seç" #: ../quodlibet/qltk/filesel.py:374 msgid "New Folder" msgstr "Yeni Dizin" #: ../quodlibet/qltk/filesel.py:374 msgid "Enter a name for the new folder:" msgstr "Yeni dizin için isim girin:" #: ../quodlibet/qltk/filesel.py:387 msgid "Unable to create folder" msgstr "Dizin yaratılamadı" #: ../quodlibet/qltk/filesel.py:404 msgid "Unable to delete folder" msgstr "Dizin silinemedi" #: ../quodlibet/qltk/filesel.py:519 ../quodlibet/qltk/pluginwin.py:167 msgid "Songs" msgstr "Şarkılar" #. Translators: As in "by Artist Name" #: ../quodlibet/qltk/info.py:42 #, python-format msgid "by %s" msgstr "%s eseri" #: ../quodlibet/qltk/info.py:43 ../quodlibet/qltk/information.py:167 #: ../quodlibet/qltk/information.py:448 #, python-format msgid "Disc %s" msgstr "Disk %s" #: ../quodlibet/qltk/info.py:44 ../quodlibet/qltk/information.py:172 #, python-format msgid "Track %s" msgstr "Şarkı %s" #: ../quodlibet/qltk/info.py:108 #, fuzzy msgid "_Edit Display…" msgstr "Görünümü Değiştir" #: ../quodlibet/qltk/information.py:105 msgid "No songs are selected." msgstr "Seçili şarkı yok." #: ../quodlibet/qltk/information.py:106 msgid "No Songs" msgstr "Şarkı yok" #: ../quodlibet/qltk/information.py:121 ../quodlibet/qltk/information.py:338 #: ../quodlibet/qltk/information.py:471 ../quodlibet/qltk/information.py:531 msgid "Information" msgstr "Bilgi" #: ../quodlibet/qltk/information.py:126 msgid "Lyrics" msgstr "Sözler" #: ../quodlibet/qltk/information.py:184 ../quodlibet/qltk/information.py:396 #, python-format msgid "Produced by %s" msgstr "Yapımcı %s" #: ../quodlibet/qltk/information.py:199 ../quodlibet/util/tags.py:76 msgid "artist" msgstr "sanatçı" #: ../quodlibet/qltk/information.py:200 ../quodlibet/qltk/information.py:561 #: ../quodlibet/util/tags.py:76 msgid "artists" msgstr "sanatçılar" #. for backwards compat #: ../quodlibet/qltk/information.py:221 ../quodlibet/util/tags.py:86 #: ../quodlibet/util/tags.py:114 msgid "performers" msgstr "seslendirenler" #: ../quodlibet/qltk/information.py:235 ../quodlibet/qltk/information.py:248 #: ../quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "Hiçbir Zaman" #: ../quodlibet/qltk/information.py:236 #, fuzzy, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "%d defa" msgstr[1] "%d defa" #: ../quodlibet/qltk/information.py:254 ../quodlibet/util/tags.py:139 msgid "added" msgstr "eklendi" #: ../quodlibet/qltk/information.py:255 ../quodlibet/util/tags.py:140 msgid "last played" msgstr "en son çalındı" #: ../quodlibet/qltk/information.py:256 ../quodlibet/util/tags.py:150 msgid "plays" msgstr "defa çalındı" #: ../quodlibet/qltk/information.py:257 ../quodlibet/util/tags.py:151 msgid "skips" msgstr "defa geçildi" #: ../quodlibet/qltk/information.py:258 ../quodlibet/util/tags.py:156 msgid "rating" msgstr "puan" #: ../quodlibet/qltk/information.py:287 msgid "path" msgstr "" #: ../quodlibet/qltk/information.py:288 ../quodlibet/util/tags.py:154 msgid "length" msgstr "uzunluk" #: ../quodlibet/qltk/information.py:289 #, fuzzy msgid "format" msgstr "Bilgi" #: ../quodlibet/qltk/information.py:290 ../quodlibet/util/tags.py:163 msgid "codec" msgstr "" #: ../quodlibet/qltk/information.py:291 ../quodlibet/util/tags.py:164 #, fuzzy msgid "encoding" msgstr "[kodlama Hatası]" #: ../quodlibet/qltk/information.py:292 ../quodlibet/util/tags.py:160 msgid "bitrate" msgstr "bit oranı" #: ../quodlibet/qltk/information.py:293 ../quodlibet/util/tags.py:161 msgid "file size" msgstr "dosya boyutu" #: ../quodlibet/qltk/information.py:294 ../quodlibet/util/tags.py:149 msgid "modified" msgstr "değiştirildi" #: ../quodlibet/qltk/information.py:331 msgid "Additional" msgstr "" #: ../quodlibet/qltk/information.py:383 #, 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:458 msgid "Track unavailable" msgstr "Şarkı yok" #: ../quodlibet/qltk/information.py:464 msgid "Track List" msgstr "Şarkı Listesi" #: ../quodlibet/qltk/information.py:505 ../quodlibet/qltk/information.py:578 #, 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:508 msgid "Selected Discography" msgstr "Seçili Diskografi" #: ../quodlibet/qltk/information.py:558 #, 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:586 ../quodlibet/util/tags.py:74 msgid "albums" msgstr "albümler" #: ../quodlibet/qltk/information.py:599 msgid "Total length:" msgstr "Toplam uzunluk:" #: ../quodlibet/qltk/information.py:603 msgid "Total size:" msgstr "Toplam boyut:" #: ../quodlibet/qltk/information.py:606 msgid "Files" msgstr "Dosyalar" #: ../quodlibet/qltk/lyrics.py:37 msgid "_Download" msgstr "_İndir" #: ../quodlibet/qltk/lyrics.py:40 #, fuzzy msgid "_Edit" msgstr "_Görünümü düzenle..." #. buffer.set_text(_("No lyrics found.\n\nYou can click the " #. "Download button to have Quod Libet search " #. "for lyrics online. You can also enter them " #. "yourself and click save.")) #: ../quodlibet/qltk/lyrics.py:73 ../quodlibet/qltk/lyrics.py:109 msgid "No lyrics found for this song." msgstr "Bu şarkının sözleri bulunamadı." #: ../quodlibet/qltk/lyrics.py:82 #, fuzzy msgid "Searching for lyrics…" msgstr "Şarkı sözleri aranıyor..." #: ../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/msg.py:41 msgid "Discard tag changes?" msgstr "Etiket değişikliklerini gözardı et?" #: ../quodlibet/qltk/msg.py:42 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:55 ../quodlibet/qltk/prefs.py:595 #: ../quodlibet/qltk/textedit.py:64 ../quodlibet/qltk/tracknumbers.py:117 #, fuzzy msgid "_Revert" msgstr "Hiçbir Zaman" #: ../quodlibet/qltk/msg.py:86 msgid "File exists" msgstr "Dosya zaten var" #: ../quodlibet/qltk/msg.py:88 #, python-format msgid "Replace %(file-name)s?" msgstr "" #: ../quodlibet/qltk/msg.py:94 #, fuzzy msgid "_Replace File" msgstr "Yeniden Adlandır" #: ../quodlibet/qltk/notif.py:182 msgid "Active tasks" msgstr "" #: ../quodlibet/qltk/notif.py:188 #, python-format msgid "%d tasks running" msgstr "" #: ../quodlibet/qltk/playorder.py:254 #, fuzzy msgid "Toggle shuffle mode" msgstr "çalma/duraklama durumunu değiştir" #: ../quodlibet/qltk/playorder.py:270 #, fuzzy msgid "Toggle repeat mode" msgstr "çalma/duraklama durumunu değiştir" #: ../quodlibet/qltk/pluginwin.py:44 msgid "Plugin Errors" msgstr "Eklenti Hataları" #: ../quodlibet/qltk/pluginwin.py:124 msgid "Enabled" msgstr "" #: ../quodlibet/qltk/pluginwin.py:125 #, fuzzy msgid "Disabled" msgstr "Geziciyi Gizle" #: ../quodlibet/qltk/pluginwin.py:131 msgid "No category" msgstr "" #: ../quodlibet/qltk/pluginwin.py:169 msgid "Events" msgstr "" #: ../quodlibet/qltk/pluginwin.py:170 #, fuzzy msgid "Play Order" msgstr "_Sıralama:" #: ../quodlibet/qltk/pluginwin.py:171 #, fuzzy msgid "Editing" msgstr "Etiket değiştirme" #: ../quodlibet/qltk/pluginwin.py:173 #, fuzzy msgid "Covers" msgstr "Toplam boyut:" #: ../quodlibet/qltk/pluginwin.py:309 msgid "No plugins found." msgstr "Eklenti bulunamadı." #: ../quodlibet/qltk/pluginwin.py:358 #, fuzzy msgid "Plugins" msgstr "_Eklentiler" #: ../quodlibet/qltk/pluginwin.py:402 msgid "Show _Errors" msgstr "_Hataları Göster" #: ../quodlibet/qltk/prefs.py:45 msgid "_Disc" msgstr "_Disk" #: ../quodlibet/qltk/prefs.py:46 msgid "_Track" msgstr "Şarkı _No" #: ../quodlibet/qltk/prefs.py:47 #, fuzzy msgid "Grou_ping" msgstr "grup" #: ../quodlibet/qltk/prefs.py:50 #, fuzzy msgid "Al_bum" msgstr "_Albüm" #: ../quodlibet/qltk/prefs.py:55 msgid "_Filename" msgstr "_Dosya Adı" #: ../quodlibet/qltk/prefs.py:57 msgid "_Length" msgstr "_Uzunluk" #: ../quodlibet/qltk/prefs.py:64 msgid "_Jump to playing song automatically" msgstr "Çalan şarkıya otomatik olarak _atla" #: ../quodlibet/qltk/prefs.py:66 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:82 msgid "_Others:" msgstr "_Diğerleri:" #: ../quodlibet/qltk/prefs.py:88 #, fuzzy msgid "_Edit…" msgstr "_Görünümü düzenle..." #: ../quodlibet/qltk/prefs.py:91 msgid "Add or remove additional column headers" msgstr "" #: ../quodlibet/qltk/prefs.py:101 msgid "Visible Columns" msgstr "Görünen Sütunlar" #: ../quodlibet/qltk/prefs.py:104 msgid "Title includes _version" msgstr "İsim _versiyonları içersin" #: ../quodlibet/qltk/prefs.py:106 #, fuzzy msgid "Artist includes all _people" msgstr "_Arama kişileri de içerir" #: ../quodlibet/qltk/prefs.py:108 msgid "Album includes _disc subtitle" msgstr "Albüm _disk altyazısını içersin" #: ../quodlibet/qltk/prefs.py:110 msgid "Filename includes _folder" msgstr "Dosya adı _dizinleri içersin" #: ../quodlibet/qltk/prefs.py:123 #, fuzzy msgid "Column Preferences" msgstr "Ayarlar" #: ../quodlibet/qltk/prefs.py:129 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "" #: ../quodlibet/qltk/prefs.py:142 ../quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Şarkı Listesi" #: ../quodlibet/qltk/prefs.py:222 #, fuzzy msgid "Edit Columns" msgstr "Görünen Sütunlar" #: ../quodlibet/qltk/prefs.py:259 msgid "Duration totals" msgstr "" #: ../quodlibet/qltk/prefs.py:271 msgid "_Global filter:" msgstr "_Evrensel süzgeç:" #: ../quodlibet/qltk/prefs.py:277 msgid "Apply this query in addition to all others" msgstr "" #. Translators: The heading of the preference group, no action #: ../quodlibet/qltk/prefs.py:283 #, fuzzy msgctxt "heading" msgid "Search" msgstr "Ara" #: ../quodlibet/qltk/prefs.py:287 ../quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Geziciler" #: ../quodlibet/qltk/prefs.py:293 msgid "Confirm _multiple ratings" msgstr "" #: ../quodlibet/qltk/prefs.py:295 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "" #: ../quodlibet/qltk/prefs.py:298 msgid "Enable _one-click ratings" msgstr "" #: ../quodlibet/qltk/prefs.py:300 #, fuzzy msgid "Enable rating by clicking on the rating column in the song list" msgstr "Çalan şarkı değişince listede yeni şarkıya git" #: ../quodlibet/qltk/prefs.py:306 ../quodlibet/qltk/prefs.py:616 #, fuzzy msgid "Ratings" msgstr "_Puan" #. Filename choice algorithm config #: ../quodlibet/qltk/prefs.py:312 msgid "Prefer _embedded art" msgstr "" #: ../quodlibet/qltk/prefs.py:314 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" #: ../quodlibet/qltk/prefs.py:319 msgid "_Fixed image filename:" msgstr "" #: ../quodlibet/qltk/prefs.py:321 msgid "The single image filename to use if selected" msgstr "" #: ../quodlibet/qltk/prefs.py:327 msgid "The album art image file to use when forced" msgstr "" #: ../quodlibet/qltk/prefs.py:336 #, fuzzy msgid "Album Art" msgstr "Albüm Listesi" #: ../quodlibet/qltk/prefs.py:357 #, fuzzy msgid "Playback" msgstr "Çalmayı duraklat" #: ../quodlibet/qltk/prefs.py:362 #, fuzzy msgid "Output Configuration" msgstr "Çıktı Kaydı" #: ../quodlibet/qltk/prefs.py:373 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "Ses Düzeyi Düzeltmesi bilgisi yoksa, sesi buna ayarla" #: ../quodlibet/qltk/prefs.py:376 #, fuzzy msgid "_Fall-back gain (dB):" msgstr "Öntanımlı ses (dB):" #: ../quodlibet/qltk/prefs.py:387 #, fuzzy msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "Kesilme olmadığı sürece bütün şarkıların ses düzeyini buna ayarla" #: ../quodlibet/qltk/prefs.py:390 #, fuzzy msgid "_Pre-amp gain (dB):" msgstr "Pre-amp düzeyi (dB):" #: ../quodlibet/qltk/prefs.py:395 msgid "_Enable Replay Gain volume adjustment" msgstr "Ses Düzeyi Düzeltmesini etkinleştir (Replay Gain)" #: ../quodlibet/qltk/prefs.py:420 msgid "Replay Gain Volume Adjustment" msgstr "Ses Düzeyi Düzeltmesi" #: ../quodlibet/qltk/prefs.py:450 msgid "_Default rating:" msgstr "" #: ../quodlibet/qltk/prefs.py:493 #, fuzzy msgid "Rating _scale:" msgstr "_Puan" #: ../quodlibet/qltk/prefs.py:542 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:547 msgid "_Bayesian averaging amount:" msgstr "" #: ../quodlibet/qltk/prefs.py:556 msgid "Save ratings and play _counts" msgstr "_Puan ve çalma seferlerini kaydet" #: ../quodlibet/qltk/prefs.py:560 msgid "_Email:" msgstr "_E-posta:" #: ../quodlibet/qltk/prefs.py:562 msgid "Ratings and play counts will be set for this email address" msgstr "Puan ve çalma seferleri bu posta adresi için kaydedilecek" #: ../quodlibet/qltk/prefs.py:577 #, fuzzy msgid "Auto-save tag changes" msgstr "Etiket değişikliklerini gözardı et?" #: ../quodlibet/qltk/prefs.py:579 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "" #: ../quodlibet/qltk/prefs.py:587 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:610 #, fuzzy msgid "Tags" msgstr "Etiketleri değiştir" #: ../quodlibet/qltk/prefs.py:631 #, fuzzy msgid "Updating for new ratings" msgstr "_Yeni Kanal" #: ../quodlibet/qltk/prefs.py:641 #, fuzzy msgid "Scan library _on start" msgstr "Başlangıçta arşivi _yenile" #: ../quodlibet/qltk/prefs.py:651 ../quodlibet/qltk/quodlibetwindow.py:1100 #, fuzzy msgid "_Scan Library" msgstr "Arşivde _Ara" #: ../quodlibet/qltk/prefs.py:653 ../quodlibet/qltk/quodlibetwindow.py:1162 msgid "Check for changes in your library" msgstr "Arşivinizdeki değişiklikleri denetle" #: ../quodlibet/qltk/prefs.py:658 #, fuzzy msgid "Re_build Library" msgstr "Arşivi _Baştan Yükle" #: ../quodlibet/qltk/prefs.py:661 #, fuzzy msgid "Reload all songs in your library. This can take a long time." msgstr "Arşivi baştan yükle (uzun sürebilir)" #: ../quodlibet/qltk/prefs.py:671 #, fuzzy msgid "Scan Directories" msgstr "_Dizinleri tara" #: ../quodlibet/qltk/prefs.py:677 #, fuzzy msgid "Hidden Songs" msgstr "Şarkı yok" #: ../quodlibet/qltk/properties.py:158 ../quodlibet/util/collection.py:398 #, 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:162 ../quodlibet/qltk/properties.py:164 msgid "Properties" msgstr "Özellikler" #: ../quodlibet/qltk/queue.py:101 msgid "_Queue" msgstr "Çalma _Kuyruğu" #: ../quodlibet/qltk/queue.py:126 msgid "Stop Once Empty" msgstr "" #: ../quodlibet/qltk/queue.py:130 #, fuzzy msgid "_Clear Queue" msgstr "Hataları _Sil" #: ../quodlibet/qltk/queue.py:242 #, 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:198 msgid "_Browse Library" msgstr "Arşivi _Gez" #: ../quodlibet/qltk/quodlibetwindow.py:395 #, fuzzy msgid "Toggle queue visibility" msgstr "Ana pencere görünürlüğünü değiştir" #: ../quodlibet/qltk/quodlibetwindow.py:516 #, fuzzy msgid "Playback Error" msgstr "Çalmayı duraklat" #: ../quodlibet/qltk/quodlibetwindow.py:524 #, fuzzy msgid "Set up library directories?" msgstr "Dizin Seç" #: ../quodlibet/qltk/quodlibetwindow.py:525 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:531 msgid "_Not Now" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:532 msgid "_Set Up" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:956 msgid "Unable to add songs" msgstr "Şarkılar eklenemedi" #: ../quodlibet/qltk/quodlibetwindow.py:957 #: ../quodlibet/qltk/quodlibetwindow.py:1364 #, fuzzy, python-format msgid "%s uses an unsupported protocol." msgstr "<b>%s</b> desteklenmeyen bir protokol kullanıyor." #: ../quodlibet/qltk/quodlibetwindow.py:980 msgid "_Jump to Playing Song" msgstr "Çalan Şarkıya _Atla" #: ../quodlibet/qltk/quodlibetwindow.py:986 #, fuzzy msgid "_File" msgstr "Dosya" #: ../quodlibet/qltk/quodlibetwindow.py:987 #, fuzzy msgid "_Song" msgstr "Şarkılar" #: ../quodlibet/qltk/quodlibetwindow.py:988 msgid "_View" msgstr "_Görünüm" #: ../quodlibet/qltk/quodlibetwindow.py:989 #, fuzzy msgid "_Browse" msgstr "Geziciler" #: ../quodlibet/qltk/quodlibetwindow.py:990 msgid "_Control" msgstr "_Kontrol" #: ../quodlibet/qltk/quodlibetwindow.py:991 msgid "_Help" msgstr "_Yardım" #: ../quodlibet/qltk/quodlibetwindow.py:997 #, fuzzy msgid "_Add a Folder…" msgstr "Dizin _Ekle..." #: ../quodlibet/qltk/quodlibetwindow.py:1002 #, fuzzy msgid "_Add a File…" msgstr "Dosya _Ekle..." #: ../quodlibet/qltk/quodlibetwindow.py:1007 #, fuzzy msgid "_Add a Location…" msgstr "Adres Ekle" #: ../quodlibet/qltk/quodlibetwindow.py:1036 #, fuzzy msgid "Edit Bookmarks…" msgstr "Yer imlerini _değiştir" #: ../quodlibet/qltk/quodlibetwindow.py:1056 #, fuzzy msgid "Stop After This Song" msgstr "Bu şarkıdan sonra dur" #: ../quodlibet/qltk/quodlibetwindow.py:1062 msgid "_Keyboard Shortcuts" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:1071 msgid "Online Help" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:1080 #, fuzzy msgid "Search Help" msgstr "Ara" #: ../quodlibet/qltk/quodlibetwindow.py:1352 msgid "Add a Location" msgstr "Adres Ekle" #: ../quodlibet/qltk/quodlibetwindow.py:1353 msgid "Enter the location of an audio file:" msgstr "Ses dosyasının yerini gir:" #: ../quodlibet/qltk/quodlibetwindow.py:1358 #: ../quodlibet/qltk/quodlibetwindow.py:1363 msgid "Unable to add location" msgstr "Adres eklenemedi" #: ../quodlibet/qltk/quodlibetwindow.py:1359 #, fuzzy, python-format msgid "%s is not a valid location." msgstr "<b>%s</b> geçerli bir adres değil." #: ../quodlibet/qltk/quodlibetwindow.py:1372 #: ../quodlibet/qltk/quodlibetwindow.py:1381 msgid "Add Music" msgstr "Şarkı Ekle" #: ../quodlibet/qltk/quodlibetwindow.py:1372 ../quodlibet/qltk/scanbox.py:99 #, fuzzy msgid "_Add Folders" msgstr "Dizin _Ekle..." #: ../quodlibet/qltk/quodlibetwindow.py:1379 #, fuzzy msgid "Music Files" msgstr "Müzik Çalar" #: ../quodlibet/qltk/quodlibetwindow.py:1381 #, fuzzy msgid "_Add Files" msgstr "Dosya _Ekle..." #: ../quodlibet/qltk/ratingsmenu.py:24 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "" #: ../quodlibet/qltk/ratingsmenu.py:26 msgid "The saved ratings will be removed" msgstr "" #: ../quodlibet/qltk/ratingsmenu.py:27 #, python-format msgid "The rating of all selected songs will be changed to '%s'" msgstr "" #: ../quodlibet/qltk/ratingsmenu.py:57 ../quodlibet/qltk/ratingsmenu.py:111 #, fuzzy msgid "_Remove Rating" msgstr "_Puan" #: ../quodlibet/qltk/ratingsmenu.py:98 #, fuzzy msgid "Change _Rating" msgstr "_Puan" #: ../quodlibet/qltk/renamefiles.py:46 msgid "Replace spaces with _underscores" msgstr "Boşlukları _altçizgi ile değiştir" #: ../quodlibet/qltk/renamefiles.py:56 msgid "Strip _Windows-incompatible characters" msgstr "_Windows'la uyumsuz karakterleri çıkart" #: ../quodlibet/qltk/renamefiles.py:74 msgid "Strip _diacritical marks" msgstr "_Düzeltme işaretlerini çıkart" #: ../quodlibet/qltk/renamefiles.py:85 msgid "Strip non-_ASCII characters" msgstr "_ASCII olmayan karakterleri çıkart" #: ../quodlibet/qltk/renamefiles.py:95 msgid "Use only _lowercase characters" msgstr "" #: ../quodlibet/qltk/renamefiles.py:123 msgid "Rename Files" msgstr "Yeniden Adlandır" #: ../quodlibet/qltk/renamefiles.py:139 ../quodlibet/qltk/tagsfrompath.py:116 #, fuzzy msgid "Path Patterns" msgstr "süzgeç" #: ../quodlibet/qltk/renamefiles.py:140 ../quodlibet/qltk/tagsfrompath.py:117 #, fuzzy msgid "Edit saved patterns…" msgstr "Kayıtlı değerleri değiştir..." #: ../quodlibet/qltk/renamefiles.py:143 ../quodlibet/qltk/tagsfrompath.py:120 #: ../quodlibet/qltk/tracknumbers.py:58 msgid "_Preview" msgstr "_Önizleme" #: ../quodlibet/qltk/renamefiles.py:190 msgid "New Name" msgstr "Yeni İsim" #: ../quodlibet/qltk/renamefiles.py:255 msgid "Unable to rename file" msgstr "Dosya yeniden adlandırılamadı" #: ../quodlibet/qltk/renamefiles.py:256 #, fuzzy, python-format msgid "" "Renaming <b>%(old-name)s</b> to <b>%(new-name)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." msgstr "" "<b>%s</b>, <b>%s</b> olarak yeniden adlandırılamadı. Yeni isimle zaten bir " "dosya olabilir, yeni bir dosya yaratmak veya eskisini silmek için izniniz " "olmayabilir." #: ../quodlibet/qltk/renamefiles.py:264 #, fuzzy msgid "Ignore _All Errors" msgstr "_Hataları Göster" #: ../quodlibet/qltk/renamefiles.py:267 msgid "_Continue" msgstr "_Devam" #: ../quodlibet/qltk/renamefiles.py:296 msgid "Path is not absolute" msgstr "Yol mutlak değil" #: ../quodlibet/qltk/renamefiles.py:297 #, python-format msgid "" "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 ~/." msgstr "" "Girdiğiniz bu süzgeç;\n" "\t<b>%s</b>\n" "/ karakteri içermekle beraber kök dizininden başlamıyor. Hatalı " "isimlendirmelerden sakınmak için süzgeçinize / veya ~/ şeklinde bir kök " "verin." #: ../quodlibet/qltk/scanbox.py:47 #, fuzzy msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "Bu (':' ile ayrılmış) dizinlerdeki şarkılar arşivinize eklenecek" #: ../quodlibet/qltk/scanbox.py:99 msgid "Select Directories" msgstr "Dizin Seç" #: ../quodlibet/qltk/searchbar.py:52 #, fuzzy msgid "Saved Searches" msgstr "Kayıtlı Değerler" #: ../quodlibet/qltk/searchbar.py:53 #, fuzzy msgid "Edit saved searches…" msgstr "Kayıtlı değerleri değiştir..." #: ../quodlibet/qltk/searchbar.py:74 msgid "Search your library, using free text or QL queries" msgstr "" #: ../quodlibet/qltk/searchbar.py:129 #, fuzzy msgid "Search after _typing" msgstr "Bu şarkıdan sonra dur" #: ../quodlibet/qltk/searchbar.py:132 msgid "Show search results after the user stops typing." msgstr "" #: ../quodlibet/qltk/searchbar.py:187 msgid "_Limit:" msgstr "_Sınır:" #: ../quodlibet/qltk/searchbar.py:200 msgid "_Weight" msgstr "_Ağırlık" #: ../quodlibet/qltk/seekbutton.py:238 msgid "Display remaining time" msgstr "Kalan süreyi göster" #: ../quodlibet/qltk/shortcuts.py:16 #, fuzzy msgid "Main Window" msgstr "Sözler" #: ../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 "Çalışan müzikçalara odaklan" #: ../quodlibet/qltk/shortcuts.py:22 #, fuzzy msgid "Reset filters and jump to the playing song" msgstr "Şarkı içinde ileri/geri git" #: ../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 "Şarkılar silinemiyor" #: ../quodlibet/qltk/shortcuts.py:29 #, fuzzy msgid "Delete the selected songs" msgstr "Şarkılar silinemiyor" #: ../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 ../quodlibet/qltk/shortcuts.py:41 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: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:377 #, python-format msgid "_Filter on %s" msgstr "%s etiketine göre süz" #: ../quodlibet/qltk/songlist.py:1094 #, fuzzy msgid "All _Headers" msgstr "_Albüm Etiketleri" #: ../quodlibet/qltk/songlist.py:1095 msgid "_Track Headers" msgstr "Şarkı _Numarası Etiketleri" #: ../quodlibet/qltk/songlist.py:1096 msgid "_Album Headers" msgstr "_Albüm Etiketleri" #: ../quodlibet/qltk/songlist.py:1097 msgid "_People Headers" msgstr "_Kişi Etiketleri" #: ../quodlibet/qltk/songlist.py:1098 msgid "_Date Headers" msgstr "_Tarih Etiketleri" #: ../quodlibet/qltk/songlist.py:1099 msgid "_File Headers" msgstr "_Dosya Etiketleri" #: ../quodlibet/qltk/songlist.py:1100 msgid "_Production Headers" msgstr "_Yapımcı Etiketleri" #: ../quodlibet/qltk/songlist.py:1115 #, fuzzy msgid "_Customize Headers…" msgstr "_Etiketleri Özelleştir..." #: ../quodlibet/qltk/songlist.py:1120 msgid "_Expand Column" msgstr "" #: ../quodlibet/qltk/songsmenu.py:36 #, 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:64 #, 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:149 #, fuzzy msgid "Configure Plugins…" msgstr "Arama kriterlerini _renklendir" #: ../quodlibet/qltk/songsmenu.py:345 msgid "Add to _Queue" msgstr "Çalma _Kuyruğuna Ekle" #: ../quodlibet/qltk/songsmenu.py:368 msgid "_Copy to Device" msgstr "Aygıta _Kopyala" #: ../quodlibet/qltk/songsmenu.py:379 #, fuzzy msgid "_Remove from Library" msgstr "Çalma Listesinden _Çıkar" #: ../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 "Etiketlerde _büyük/küçük harfleri düzelt" #: ../quodlibet/qltk/tagsfrompath.py:67 msgid "Split into multiple _values" msgstr "Birden fazla değere _ayır" #: ../quodlibet/qltk/tagsfrompath.py:101 msgid "Tags From Path" msgstr "Dosya Yolundan Etiket" #: ../quodlibet/qltk/tagsfrompath.py:138 msgid "Tags replace existing ones" msgstr "Yeni etiketler eskilerin yerine geçsin" #: ../quodlibet/qltk/tagsfrompath.py:139 msgid "Tags are added to existing ones" msgstr "Yeni etiketler eskilerine eklensin" #. Save button #: ../quodlibet/qltk/tagsfrompath.py:153 msgid "Save" msgstr "" #: ../quodlibet/qltk/tagsfrompath.py:195 #, python-format msgid "" "The pattern\n" "\t<b>%s</b>\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" "Girdiğiniz bu süzgeç;\n" "\t<b>%s</b>\n" "geçersiz. Aynı etiketi iki defa içeriyor olabilir veya parantezleri hatalı " "olabilir (< / >)." #: ../quodlibet/qltk/tagsfrompath.py:216 msgid "Invalid tags" msgstr "Geçersiz etiketler" #: ../quodlibet/qltk/tagsfrompath.py:217 #, 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." #: ../quodlibet/qltk/textedit.py:142 #, 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 süzgeç geçersiz. \\< ve \\> yerine < ve > kullanmaya " "ve parantez sayılarına dikkat edin.\n" "\n" "%s" #: ../quodlibet/qltk/textedit.py:158 msgid "Edit Display" msgstr "Görünümü Değiştir" #: ../quodlibet/qltk/tracknumbers.py:39 msgid "Track Numbers" msgstr "Şarkı Numaraları" #: ../quodlibet/qltk/tracknumbers.py:42 msgid "Start fro_m:" msgstr "_Başlangıç:" #: ../quodlibet/qltk/tracknumbers.py:51 msgid "_Total tracks:" msgstr "_Toplam Şarkı:" #: ../quodlibet/qltk/unity.py:52 #, fuzzy msgid "Play/Pause" msgstr "Çalıcı" #: ../quodlibet/qltk/unity.py:75 #, fuzzy msgid "Previous" msgstr "_Önizleme" #: ../quodlibet/qltk/views.py:923 #, fuzzy, 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 #, fuzzy, python-format msgid "%(current)s of %(all)s" msgstr "%(current)d/%(total)d Taşınıyor." #: ../quodlibet/update.py:89 #, fuzzy msgid "Checking for Updates" msgstr "Bağlama yerleri denetleniyor" #: ../quodlibet/update.py:124 #, fuzzy msgid "Connection failed" msgstr "konum" #: ../quodlibet/update.py:133 #, python-format msgid "You are already using the newest version %(version)s" msgstr "" #: ../quodlibet/update.py:136 #, 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:420 msgid "Playlists must have a name" msgstr "" #: ../quodlibet/util/collection.py:603 #, python-format msgid "A playlist named %s already exists." msgstr "%s adında bir çalma listesi zaten var." #: ../quodlibet/util/cover/built_in.py:26 #, fuzzy msgid "Embedded album covers" msgstr "Albüm _kapaklarını göster" #: ../quodlibet/util/cover/built_in.py:27 msgid "Uses covers embedded into audio files." msgstr "" #: ../quodlibet/util/cover/built_in.py:49 #, fuzzy msgid "Filesystem cover" msgstr "Dosya Sistemi" #: ../quodlibet/util/cover/built_in.py:50 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "" #: ../quodlibet/util/__init__.py:93 msgid "Display brief usage information" msgstr "Özet kullanım bilgisi göster" #: ../quodlibet/util/__init__.py:95 msgid "Display version and copyright" msgstr "Versiyon ve telif haklarını göster" #: ../quodlibet/util/__init__.py:135 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "" #: ../quodlibet/util/__init__.py:137 msgid "[options]" msgstr "[ayarlar]" #: ../quodlibet/util/__init__.py:182 #, python-format msgid "Option %r not recognized." msgstr "%r parametresi anlaşılmadı." #: ../quodlibet/util/__init__.py:185 #, python-format msgid "Option %r requires an argument." msgstr "%r için bir parametre vermelisiniz." #: ../quodlibet/util/__init__.py:188 #, python-format msgid "%r is not a unique prefix." msgstr "%r eşsiz bir önek değil." #: ../quodlibet/util/__init__.py:364 #, python-format msgid "%d kbps" msgstr "%d kb/s" #: ../quodlibet/util/__init__.py:419 #, fuzzy, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%d saniye" msgstr[1] "%d saniye" #: ../quodlibet/util/__init__.py:432 msgid "No time information" msgstr "Süre bilgisi yok" #: ../quodlibet/util/__init__.py:435 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d saniye" msgstr[1] "%d saniye" #: ../quodlibet/util/__init__.py:436 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d dakika" msgstr[1] "%d dakika" #: ../quodlibet/util/__init__.py:437 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d saat" msgstr[1] "%d saat" #: ../quodlibet/util/__init__.py:438 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d gün" msgstr[1] "%d gün" #: ../quodlibet/util/__init__.py:439 #, 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:563 #, fuzzy msgctxt "check" msgid "titlecase?" msgstr "Ad" #: ../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 "" "Ses Düzeyi Düzeltmesi (Replay Gain) değeri 'x.yy dB' biçminde girilmelidir." #: ../quodlibet/util/massagers.py:151 msgid "Replay Gain peaks must be entered in 'x.yy' format." msgstr "" "Ses Düzeyi Düzeltmesi (Replay Gain) tepe değerleri 'x.yy' biçminde " "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 "" #: ../quodlibet/util/songwrapper.py:112 msgid "Unable to edit song" msgstr "Şarkı değiştirilemedi" #: ../quodlibet/util/songwrapper.py:113 #, python-format msgid "" "Saving <b>%s</b> failed. The file may be read-only, corrupted, or you do not " "have permission to edit it." msgstr "" "<b>%s</b> kaydedilemedi. Dosya salt okunur olabilir veya sizin dosyayı " "değiştirme izniniz olmayabilir." #: ../quodlibet/util/string/__init__.py:34 #: ../quodlibet/util/string/__init__.py:44 msgid "[Invalid Encoding]" msgstr "[kodlama Hatası]" #: ../quodlibet/util/tags.py:74 msgid "album" msgstr "albüm" #: ../quodlibet/util/tags.py:75 msgid "arranger" msgstr "aranjör" #: ../quodlibet/util/tags.py:75 msgid "arrangers" msgstr "aranjörler" #: ../quodlibet/util/tags.py:75 #, fuzzy msgid "arrangement" msgstr "aranjör" #: ../quodlibet/util/tags.py:77 msgid "author" msgstr "yazar" #: ../quodlibet/util/tags.py:77 msgid "authors" msgstr "yazarlar" #: ../quodlibet/util/tags.py:78 msgid "composer" msgstr "besteci" #: ../quodlibet/util/tags.py:78 msgid "composers" msgstr "besteciler" #: ../quodlibet/util/tags.py:78 #, fuzzy msgid "composition" msgstr "besteci" #. Translators: conducting as in conducting a musical performance #: ../quodlibet/util/tags.py:80 msgid "conductor" msgstr "orkestra şefi" #: ../quodlibet/util/tags.py:80 msgid "conductors" msgstr "orkestra şefleri" #: ../quodlibet/util/tags.py:80 #, fuzzy msgid "conducting" msgstr "orkestra şefi" #: ../quodlibet/util/tags.py:81 msgid "contact" msgstr "iletişim" #: ../quodlibet/util/tags.py:82 msgid "copyright" msgstr "telif hakkı" #: ../quodlibet/util/tags.py:83 msgid "date" msgstr "tarih" #: ../quodlibet/util/tags.py:84 msgid "description" msgstr "açıklama" #: ../quodlibet/util/tags.py:85 msgid "genre" msgstr "tür" #: ../quodlibet/util/tags.py:85 #, fuzzy msgid "genres" msgstr "tür" #: ../quodlibet/util/tags.py:86 msgid "performer" msgstr "seslendiren" #: ../quodlibet/util/tags.py:87 msgid "grouping" msgstr "grup" #: ../quodlibet/util/tags.py:88 msgid "language" msgstr "dil" #: ../quodlibet/util/tags.py:89 msgid "license" msgstr "lisans" #: ../quodlibet/util/tags.py:90 msgid "location" msgstr "konum" #: ../quodlibet/util/tags.py:91 msgid "lyricist" msgstr "söz yazarı" #: ../quodlibet/util/tags.py:91 msgid "lyricists" msgstr "söz yazarları" #: ../quodlibet/util/tags.py:91 #, fuzzy msgid "lyrics" msgstr "söz yazarı" #. Translators: Also e.g. "record label", "publisher" #: ../quodlibet/util/tags.py:93 msgid "organization" msgstr "organizasyon" #: ../quodlibet/util/tags.py:94 msgid "title" msgstr "isim" #: ../quodlibet/util/tags.py:95 msgid "version" msgstr "versiyon" #: ../quodlibet/util/tags.py:96 msgid "website" msgstr "web" #: ../quodlibet/util/tags.py:98 msgid "album artist" msgstr "albüm sanatçısı" #: ../quodlibet/util/tags.py:99 msgid "BPM" msgstr "BPM" #. Translators: This used to be called "part". #: ../quodlibet/util/tags.py:102 ../quodlibet/util/tags.py:103 msgid "disc subtitle" msgstr "disk altyazısı" #: ../quodlibet/util/tags.py:104 ../quodlibet/util/tags.py:141 msgid "disc" msgstr "disk" #: ../quodlibet/util/tags.py:105 ../quodlibet/util/tags.py:143 msgid "track" msgstr "şarkı no" #: ../quodlibet/util/tags.py:106 msgid "label ID" msgstr "yapımcı ID" #: ../quodlibet/util/tags.py:107 msgid "original release date" msgstr "asıl yayım tarihi" #: ../quodlibet/util/tags.py:108 msgid "original album" msgstr "asıl albüm" #: ../quodlibet/util/tags.py:109 msgid "original artist" msgstr "asıl sanatçı" #: ../quodlibet/util/tags.py:110 msgid "recording date" msgstr "kayıt tarihi" #: ../quodlibet/util/tags.py:111 msgid "release country" msgstr "yayımlandığı ülke" #. 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:120 #, fuzzy msgid "MusicBrainz recording ID" msgstr "MusicBrainz şarkı ID'si" #: ../quodlibet/util/tags.py:121 #, fuzzy msgid "MusicBrainz release track ID" msgstr "MusicBrainz yayın ID'si" #: ../quodlibet/util/tags.py:122 msgid "MusicBrainz release ID" msgstr "MusicBrainz yayın ID'si" #: ../quodlibet/util/tags.py:123 #, fuzzy msgid "MusicBrainz artist ID" msgstr "MusicBrainz sanatçı ID'si" #: ../quodlibet/util/tags.py:124 #, fuzzy msgid "MusicBrainz release artist ID" msgstr "MusicBrainz yayın ID'si" #: ../quodlibet/util/tags.py:125 msgid "MusicBrainz TRM ID" msgstr "MusicBrainz TRM ID'si" #: ../quodlibet/util/tags.py:126 msgid "MusicIP PUID" msgstr "MusicIP PUID" #: ../quodlibet/util/tags.py:127 msgid "MusicBrainz album status" msgstr "MusicBrainz albüm durumu" #: ../quodlibet/util/tags.py:128 msgid "MusicBrainz album type" msgstr "MusicBrainz albüm türü" #: ../quodlibet/util/tags.py:129 #, fuzzy msgid "MusicBrainz release group ID" msgstr "MusicBrainz yayın ID'si" #. Translators: "gain" means a volume adjustment, not "to acquire". #: ../quodlibet/util/tags.py:132 msgid "track gain" msgstr "şarkı ses seviyesi" #: ../quodlibet/util/tags.py:133 msgid "track peak" msgstr "şarkı tepe ses seviyesi" #. Translators: "gain" means a volume adjustment, not "to acquire". #: ../quodlibet/util/tags.py:135 msgid "album gain" msgstr "albüm ses seviyesi" #: ../quodlibet/util/tags.py:136 msgid "album peak" msgstr "albüm tepe ses seviyesi" #: ../quodlibet/util/tags.py:137 #, fuzzy msgid "reference loudness" msgstr "Ayarlar" #: ../quodlibet/util/tags.py:142 msgid "discs" msgstr "diskler" #: ../quodlibet/util/tags.py:144 msgid "tracks" msgstr "şarkılar" #: ../quodlibet/util/tags.py:145 msgid "last started" msgstr "son başlatılan" #: ../quodlibet/util/tags.py:146 msgid "full name" msgstr "tam isim" #: ../quodlibet/util/tags.py:153 msgid "mount point" msgstr "bağlama yeri" #: ../quodlibet/util/tags.py:155 msgid "people" msgstr "kişiler" #: ../quodlibet/util/tags.py:157 msgid "year" msgstr "yıl" #: ../quodlibet/util/tags.py:158 #, fuzzy msgid "original release year" msgstr "asıl yayım tarihi" #: ../quodlibet/util/tags.py:159 msgid "bookmark" msgstr "yer imi" #: ../quodlibet/util/tags.py:162 #, fuzzy msgid "file format" msgstr "Süre bilgisi yok" #: ../quodlibet/util/tags.py:165 #, fuzzy msgid "playlists" msgstr "Çalma Listeleri" #: ../quodlibet/util/tags.py:166 msgid "channel count" msgstr "" #. Translators: e.g. "artist (sort)" #: ../quodlibet/util/tags.py:256 msgid "sort" msgstr "" #. Translators: e.g. "performer (roles)" #: ../quodlibet/util/tags.py:264 msgid "roles" msgstr "" #, 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 "Remove all songs from the queue" #~ msgstr "Kuyruğu temizle" #~ msgid "Watch this folder for new songs" #~ msgstr "Bu dizini yeni şarkılar için denetle" #~ 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 "Model:" #~ msgstr "Model:" #~ msgid "Capacity:" #~ msgstr "Kapasite:" #~ msgid "Firmware:" #~ msgstr "Firmware:" #~ msgid "Removing orphaned iPod track" #~ msgstr "Boşta kalan iPod parçası silindi" #, 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 "Unable to open input files" #~ msgstr "Giriş dosyaları açılamadı" #~ 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 "_Select" #~ msgstr "_Seç" #~ 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 "Choose New Stations" #~ msgstr "Yeni Kanal Seç" #~ msgid "Add" #~ msgstr "Ekle" #~ msgid "Bitrate" #~ msgstr "Bit oranı" #~ msgid "_Stations..." #~ msgstr "_Kanallar..." #, fuzzy #~ msgid "Quod Libet" #~ msgstr "Quod Libet'ten çık" #~ 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9791858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/po/uk.po����������������������������������������������������������������������������0000644�0001750�0001750�00000560673�00000000000�014114� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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: 2017-05-17 18:58+0200\n" "PO-Revision-Date: 2013-07-20 22:33+0100\n" "Last-Translator: Mykola Lynnyk <pydefiner@gmail.com>\n" "Language-Team: Ukrainian\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: Poedit 1.5.4\n" #: ../data/exfalso.appdata.xml.in.h:1 ../data/exfalso.desktop.in.h:2 msgid "Edit tags in your audio files" msgstr "Програма для редагування тегів аудіо-файлів" #: ../data/exfalso.appdata.xml.in.h:2 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/exfalso.appdata.xml.in.h:3 ../data/quodlibet.appdata.xml.in.h:3 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/exfalso.desktop.in.h:1 msgid "Audio tag editor" msgstr "Редактор аудіо-тегів" #: ../data/quodlibet.appdata.xml.in.h:1 ../data/quodlibet.desktop.in.h:2 msgid "Listen to, browse, or edit your audio collection" msgstr "Програма для прослуховування і керування аудіо-колекцією" #: ../data/quodlibet.appdata.xml.in.h:2 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 "" #: ../data/quodlibet.desktop.in.h:1 msgid "Music Player" msgstr "Музичний програвач" #: ../quodlibet/browsers/albums/main.py:168 #: ../quodlibet/browsers/covergrid/main.py:54 #, fuzzy msgid "_Title" msgstr "Назва" #: ../quodlibet/browsers/albums/main.py:169 #: ../quodlibet/browsers/covergrid/main.py:55 ../quodlibet/qltk/prefs.py:49 msgid "_Artist" msgstr "_Виконавець" #: ../quodlibet/browsers/albums/main.py:170 #: ../quodlibet/browsers/covergrid/main.py:56 ../quodlibet/qltk/prefs.py:54 msgid "_Date" msgstr "_Дата" #: ../quodlibet/browsers/albums/main.py:171 #: ../quodlibet/browsers/covergrid/main.py:57 ../quodlibet/qltk/prefs.py:53 #, fuzzy msgid "_Genre" msgstr "жанр" #: ../quodlibet/browsers/albums/main.py:172 #: ../quodlibet/browsers/covergrid/main.py:58 ../quodlibet/qltk/prefs.py:58 #: ../quodlibet/qltk/ratingsmenu.py:39 msgid "_Rating" msgstr "_Рейтинг" #: ../quodlibet/browsers/albums/main.py:178 #: ../quodlibet/browsers/covergrid/main.py:64 #, fuzzy msgid "Sort _by…" msgstr "За датою" #: ../quodlibet/browsers/albums/main.py:199 #: ../quodlibet/browsers/covergrid/main.py:85 #: ../quodlibet/browsers/paned/prefs.py:166 #: ../quodlibet/browsers/playlists/main.py:629 #: ../quodlibet/qltk/exfalsowindow.py:109 ../quodlibet/qltk/pluginwin.py:341 #: ../quodlibet/qltk/quodlibetwindow.py:1016 #, fuzzy msgid "_Preferences" msgstr "Налаштування" #: ../quodlibet/browsers/albums/main.py:361 msgid "Album List" msgstr "Список альбомів" #: ../quodlibet/browsers/albums/main.py:362 msgid "_Album List" msgstr "Список _альбомів" #: ../quodlibet/browsers/albums/main.py:472 #: ../quodlibet/browsers/covergrid/main.py:279 #: ../quodlibet/browsers/covergrid/main.py:488 msgid "All Albums" msgstr "Всі альбоми" #: ../quodlibet/browsers/albums/main.py:473 #: ../quodlibet/browsers/covergrid/main.py:280 #: ../quodlibet/browsers/covergrid/main.py:489 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d альбом" msgstr[1] "%d альбомb" msgstr[2] "%d альбомів" #: ../quodlibet/browsers/albums/main.py:650 #: ../quodlibet/browsers/covergrid/main.py:467 #, fuzzy 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:381 ../quodlibet/util/collection.py:245 #, 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:379 ../quodlibet/util/collection.py:249 #, 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 #, 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:120 #, fuzzy msgid "Options" msgstr "[параметри]" #: ../quodlibet/browsers/albums/prefs.py:74 #: ../quodlibet/browsers/covergrid/prefs.py:123 msgid "Album Display" msgstr "Перегляд альбомів" #: ../quodlibet/browsers/albums/prefs.py:78 #: ../quodlibet/browsers/covergrid/prefs.py:127 #: ../quodlibet/browsers/media.py:39 #: ../quodlibet/browsers/playlists/prefs.py:56 #: ../quodlibet/ext/songsmenu/albumart.py:326 #: ../quodlibet/ext/songsmenu/duplicates.py:350 #: ../quodlibet/ext/songsmenu/filterall.py:48 #: ../quodlibet/qltk/bookmarks.py:101 ../quodlibet/qltk/cbes.py:93 #: ../quodlibet/qltk/data_editors.py:99 ../quodlibet/qltk/data_editors.py:324 #: ../quodlibet/qltk/exfalsowindow.py:297 ../quodlibet/qltk/pluginwin.py:79 #: ../quodlibet/qltk/pluginwin.py:427 ../quodlibet/qltk/prefs.py:707 #: ../quodlibet/qltk/textedit.py:164 ../quodlibet/update.py:148 msgid "_Close" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:55 #: ../quodlibet/browsers/audiofeeds.py:67 #: ../quodlibet/browsers/audiofeeds.py:69 #: ../quodlibet/browsers/audiofeeds.py:159 #: ../quodlibet/browsers/paned/models.py:86 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:46 #: ../quodlibet/formats/_audio.py:495 ../quodlibet/order/__init__.py:27 #: ../quodlibet/qltk/information.py:240 ../quodlibet/qltk/information.py:247 #: ../quodlibet/qltk/information.py:273 ../quodlibet/qltk/wlw.py:70 msgid "Unknown" msgstr "Невідомо" #: ../quodlibet/browsers/audiofeeds.py:246 msgid "New Feed" msgstr "Новий фід" #: ../quodlibet/browsers/audiofeeds.py:247 msgid "Enter the location of an audio feed:" msgstr "Введіть адресу аудіо-фіду" #: ../quodlibet/browsers/audiofeeds.py:248 #: ../quodlibet/browsers/collection/prefs.py:90 #: ../quodlibet/browsers/iradio.py:341 ../quodlibet/browsers/paned/prefs.py:78 #: ../quodlibet/browsers/playlists/menu.py:96 #: ../quodlibet/browsers/playlists/util.py:52 ../quodlibet/qltk/bookmarks.py:62 #: ../quodlibet/qltk/cbes.py:55 ../quodlibet/qltk/data_editors.py:311 #: ../quodlibet/qltk/edittags.py:288 ../quodlibet/qltk/edittags.py:488 #: ../quodlibet/qltk/quodlibetwindow.py:1354 ../quodlibet/qltk/scanbox.py:61 msgid "_Add" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:265 msgid "Audio Feeds" msgstr "Аудіо-фіди" #: ../quodlibet/browsers/audiofeeds.py:266 msgid "_Audio Feeds" msgstr "_Аудіо-фіди" #: ../quodlibet/browsers/audiofeeds.py:345 #: ../quodlibet/browsers/audiofeeds.py:350 #, fuzzy msgid "_Download…" msgstr "_Завантажити" #: ../quodlibet/browsers/audiofeeds.py:359 msgid "Download Files" msgstr "Завантажити файли" #. Save button #: ../quodlibet/browsers/audiofeeds.py:359 #: ../quodlibet/browsers/audiofeeds.py:371 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:81 #: ../quodlibet/ext/songsmenu/albumart.py:322 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:355 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:278 #: ../quodlibet/ext/songsmenu/html.py:76 #: ../quodlibet/ext/songsmenu/lastfmsync.py:216 #: ../quodlibet/ext/songsmenu/playlist.py:51 #: ../quodlibet/ext/songsmenu/replaygain.py:365 #: ../quodlibet/ext/songsmenu/tapbpm.py:182 ../quodlibet/qltk/_editutils.py:39 #: ../quodlibet/qltk/lyrics.py:38 ../quodlibet/qltk/msg.py:52 #: ../quodlibet/qltk/renamefiles.py:168 ../quodlibet/qltk/tracknumbers.py:113 msgid "_Save" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:371 msgid "Download File" msgstr "Завантажити файл" #: ../quodlibet/browsers/audiofeeds.py:394 #: ../quodlibet/browsers/playlists/main.py:213 #: ../quodlibet/qltk/data_editors.py:96 msgid "_New" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:454 #: ../quodlibet/browsers/audiofeeds.py:513 msgid "Unable to add feed" msgstr "Не вдалося додати фід" #: ../quodlibet/browsers/audiofeeds.py:455 #: ../quodlibet/browsers/audiofeeds.py:514 #, fuzzy, python-format msgid "" "%s could not be added. The server may be down, or the location may not be an " "audio feed." msgstr "" "Не вдається додати <b>%s</b>. Можливо, вказаний сервер не працює, або адреса " "не є аудіо-фідом." #. refresh button #: ../quodlibet/browsers/audiofeeds.py:462 ../quodlibet/browsers/media.py:217 #: ../quodlibet/browsers/media.py:386 ../quodlibet/qltk/filesel.py:259 #: ../quodlibet/qltk/pluginwin.py:413 #, fuzzy msgid "_Refresh" msgstr "_Оновити бібліотеку" #: ../quodlibet/browsers/audiofeeds.py:463 #: ../quodlibet/browsers/playlists/main.py:457 #: ../quodlibet/browsers/playlists/util.py:43 ../quodlibet/qltk/delete.py:143 #: ../quodlibet/qltk/filesel.py:256 ../quodlibet/qltk/lyrics.py:39 #: ../quodlibet/qltk/maskedbox.py:28 ../quodlibet/qltk/songsmenu.py:392 #, fuzzy msgid "_Delete" msgstr "Видалення фалів" #: ../quodlibet/browsers/audiofeeds.py:530 msgid "" "The current audio backend does not support URLs, Audio Feeds browser " "disabled." msgstr "" #: ../quodlibet/browsers/_base.py:147 ../quodlibet/browsers/_base.py:150 msgid "Library Browser" msgstr "Перегляд бібліотеки" #: ../quodlibet/browsers/_base.py:274 ../quodlibet/ext/songsmenu/refresh.py:30 #: ../quodlibet/qltk/exfalsowindow.py:241 ../quodlibet/qltk/information.py:542 #: ../quodlibet/qltk/maskedbox.py:68 ../quodlibet/util/collection.py:527 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d пісня" msgstr[1] "%d пісні" msgstr[2] "%d пісень" #: ../quodlibet/browsers/_base.py:402 ../quodlibet/browsers/_base.py:407 #: ../quodlibet/qltk/tagsfrompath.py:194 ../quodlibet/qltk/textedit.py:141 #: ../quodlibet/util/__init__.py:622 msgid "Invalid pattern" msgstr "Неправильний шаблон" #: ../quodlibet/browsers/collection/main.py:78 msgid "Album Collection" msgstr "" #: ../quodlibet/browsers/collection/main.py:79 msgid "Album _Collection" msgstr "" #: ../quodlibet/browsers/collection/models.py:24 #, fuzzy, python-format msgid "Unknown %s" msgstr "Невідомо" #: ../quodlibet/browsers/collection/models.py:25 #, fuzzy, python-format msgid "Multiple %s Values" msgstr "_Розділити на кілька значень" #: ../quodlibet/browsers/collection/prefs.py:66 #: ../quodlibet/browsers/paned/prefs.py:51 msgid "_Custom" msgstr "_Інший" #. Remove button #: ../quodlibet/browsers/collection/prefs.py:94 #: ../quodlibet/browsers/paned/prefs.py:82 #: ../quodlibet/browsers/playlists/menu.py:97 #: ../quodlibet/ext/playlist/remove_duplicates.py:60 #: ../quodlibet/qltk/bookmarks.py:97 ../quodlibet/qltk/bookmarks.py:127 #: ../quodlibet/qltk/cbes.py:82 ../quodlibet/qltk/cbes.py:89 #: ../quodlibet/qltk/data_editors.py:81 ../quodlibet/qltk/data_editors.py:94 #: ../quodlibet/qltk/data_editors.py:301 ../quodlibet/qltk/data_editors.py:314 #: ../quodlibet/qltk/data_editors.py:322 ../quodlibet/qltk/edittags.py:494 #: ../quodlibet/qltk/edittags.py:634 ../quodlibet/qltk/maskedbox.py:48 #: ../quodlibet/qltk/maskedbox.py:88 ../quodlibet/qltk/queue.py:350 #: ../quodlibet/qltk/scanbox.py:36 ../quodlibet/qltk/scanbox.py:63 #, fuzzy msgid "_Remove" msgstr "_Рейтинг" #: ../quodlibet/browsers/collection/prefs.py:122 #: ../quodlibet/ext/songsmenu/filterall.py:34 #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:92 #: ../quodlibet/qltk/edittags.py:431 msgid "Tag" msgstr "Тег" #: ../quodlibet/browsers/collection/prefs.py:128 msgid "Merge" msgstr "" #: ../quodlibet/browsers/collection/prefs.py:188 #, fuzzy msgid "Album Collection Preferences" msgstr "Налаштування списку альбомів" #: ../quodlibet/browsers/collection/prefs.py:195 #: ../quodlibet/browsers/paned/prefs.py:209 #: ../quodlibet/ext/songsmenu/editplaycount.py:45 #: ../quodlibet/ext/songsmenu/exact_rating.py:38 #: ../quodlibet/player/gstbe/prefs.py:40 ../quodlibet/qltk/prefs.py:127 #: ../quodlibet/qltk/textedit.py:65 msgid "_Apply" msgstr "" #: ../quodlibet/browsers/collection/prefs.py:198 #: ../quodlibet/browsers/paned/prefs.py:213 #: ../quodlibet/browsers/playlists/menu.py:95 #: ../quodlibet/browsers/playlists/util.py:42 #: ../quodlibet/errorreport/ui.py:108 #: ../quodlibet/ext/playlist/export_to_folder.py:37 #: ../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:44 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:281 #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:88 #: ../quodlibet/ext/songsmenu/importexport.py:35 #: ../quodlibet/ext/songsmenu/lastfmsync.py:215 #: ../quodlibet/ext/songsmenu/playlist.py:50 #: ../quodlibet/ext/songsmenu/replaygain.py:364 #: ../quodlibet/ext/songsmenu/tapbpm.py:181 ../quodlibet/plugins/playlist.py:39 #: ../quodlibet/qltk/chooser.py:184 ../quodlibet/qltk/chooser.py:205 #: ../quodlibet/qltk/chooser.py:229 ../quodlibet/qltk/chooser.py:253 #: ../quodlibet/qltk/delete.py:90 ../quodlibet/qltk/delete.py:133 #: ../quodlibet/qltk/edittags.py:287 ../quodlibet/qltk/_editutils.py:38 #: ../quodlibet/qltk/getstring.py:28 ../quodlibet/qltk/maskedbox.py:27 #: ../quodlibet/qltk/msg.py:54 ../quodlibet/qltk/msg.py:93 #: ../quodlibet/qltk/ratingsmenu.py:33 ../quodlibet/qltk/songsmenu.py:45 #: ../quodlibet/qltk/songsmenu.py:73 ../quodlibet/update.py:94 msgid "_Cancel" msgstr "" #: ../quodlibet/browsers/covergrid/main.py:125 #, fuzzy msgid "Cover Grid" msgstr "Загальний розмір:" #: ../quodlibet/browsers/covergrid/main.py:126 #, 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:71 #, fuzzy msgid "Show \"All Albums\" Item" msgstr "Всі альбоми" #: ../quodlibet/browsers/covergrid/prefs.py:78 msgid "Vertical Split" msgstr "" #: ../quodlibet/browsers/covergrid/prefs.py:110 #: ../quodlibet/browsers/covergrid/prefs.py:111 #, fuzzy msgid "Cover Magnification" msgstr "організація" #: ../quodlibet/browsers/filesystem.py:40 msgid "File System" msgstr "Файлова система" #: ../quodlibet/browsers/filesystem.py:41 msgid "_File System" msgstr "_Файлова система" #: ../quodlibet/browsers/filesystem.py:113 ../quodlibet/browsers/media.py:491 #: ../quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "Не вдалося скопіювати пісню" #: ../quodlibet/browsers/filesystem.py:114 ../quodlibet/qltk/songlist.py:268 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "" "Вибрані файли не можуть бути скопійовані до іншого списку пісень або черги." #: ../quodlibet/browsers/filesystem.py:189 msgid "_Add to Library" msgstr "_Додати до бібліотеки" #: ../quodlibet/browsers/iradio.py:178 msgid "Unsupported file type" msgstr "Непідтримуваний тип файлу" #: ../quodlibet/browsers/iradio.py:179 #, 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:219 ../quodlibet/browsers/iradio.py:232 #: ../quodlibet/browsers/iradio.py:810 msgid "Unable to add station" msgstr "Не вдалося додати станцію" #: ../quodlibet/browsers/iradio.py:243 ../quodlibet/browsers/iradio.py:471 msgid "Internet Radio" msgstr "Інтернет-радіо" #: ../quodlibet/browsers/iradio.py:243 #, fuzzy msgid "Downloading station list" msgstr "Завантажити файли" #: ../quodlibet/browsers/iradio.py:339 msgid "New Station" msgstr "Нова станція" #: ../quodlibet/browsers/iradio.py:340 msgid "Enter the location of an Internet radio station:" msgstr "Введіть адресу інтернет-радіостанції:" #: ../quodlibet/browsers/iradio.py:358 msgid "Electronic" msgstr "" #: ../quodlibet/browsers/iradio.py:361 msgid "Hip Hop / Rap" msgstr "" #: ../quodlibet/browsers/iradio.py:362 msgid "Oldies" msgstr "" #: ../quodlibet/browsers/iradio.py:363 msgid "R&B" msgstr "" #: ../quodlibet/browsers/iradio.py:364 msgid "Japanese" msgstr "" #: ../quodlibet/browsers/iradio.py:365 msgid "Indian" msgstr "" #: ../quodlibet/browsers/iradio.py:367 msgid "Religious" msgstr "" #: ../quodlibet/browsers/iradio.py:369 msgid "Charts" msgstr "" #: ../quodlibet/browsers/iradio.py:370 msgid "Turkish" msgstr "" #: ../quodlibet/browsers/iradio.py:371 msgid "Reggae / Dancehall" msgstr "" #: ../quodlibet/browsers/iradio.py:372 #, fuzzy msgid "Latin" msgstr "рейтинг" #: ../quodlibet/browsers/iradio.py:373 msgid "College Radio" msgstr "" #: ../quodlibet/browsers/iradio.py:374 msgid "Talk / News" msgstr "" #: ../quodlibet/browsers/iradio.py:375 msgid "Ambient" msgstr "" #: ../quodlibet/browsers/iradio.py:376 msgid "Jazz" msgstr "" #: ../quodlibet/browsers/iradio.py:377 ../quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "" #: ../quodlibet/browsers/iradio.py:378 ../quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "" #: ../quodlibet/browsers/iradio.py:379 msgid "Alternative" msgstr "" #: ../quodlibet/browsers/iradio.py:380 msgid "Metal" msgstr "" #: ../quodlibet/browsers/iradio.py:381 msgid "Country" msgstr "" #: ../quodlibet/browsers/iradio.py:382 msgid "News" msgstr "" #: ../quodlibet/browsers/iradio.py:383 msgid "Schlager" msgstr "" #: ../quodlibet/browsers/iradio.py:384 msgid "Funk" msgstr "" #: ../quodlibet/browsers/iradio.py:385 msgid "Indie" msgstr "" #: ../quodlibet/browsers/iradio.py:386 msgid "Blues" msgstr "" #: ../quodlibet/browsers/iradio.py:387 msgid "Soul" msgstr "" #: ../quodlibet/browsers/iradio.py:388 msgid "Lounge" msgstr "" #: ../quodlibet/browsers/iradio.py:389 msgid "Punk" msgstr "" #: ../quodlibet/browsers/iradio.py:390 msgid "Reggaeton" msgstr "" #: ../quodlibet/browsers/iradio.py:392 msgid "Slavic" msgstr "" #: ../quodlibet/browsers/iradio.py:394 msgid "Greek" msgstr "" #: ../quodlibet/browsers/iradio.py:395 msgid "Gothic" msgstr "" #: ../quodlibet/browsers/iradio.py:396 ../quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "" #: ../quodlibet/browsers/iradio.py:449 msgid "Would you like to load a list of popular radio stations?" msgstr "" #: ../quodlibet/browsers/iradio.py:455 #, fuzzy msgid "_Load Stations" msgstr "_Нова станція" #: ../quodlibet/browsers/iradio.py:472 msgid "_Internet Radio" msgstr "_Інтернет-радіо" #: ../quodlibet/browsers/iradio.py:538 #, fuzzy msgid "_New Station…" msgstr "Нова станція" #: ../quodlibet/browsers/iradio.py:541 #, fuzzy msgid "_Update Stations" msgstr "_Нова станція" #: ../quodlibet/browsers/iradio.py:568 #, fuzzy msgid "All Stations" msgstr "Нова станція" #. TODO: support for ~#rating=!None etc (#1940) #: ../quodlibet/browsers/iradio.py:572 #: ../quodlibet/browsers/soundcloud/main.py:64 msgid "Favorites" msgstr "" #: ../quodlibet/browsers/iradio.py:580 msgid "No Category" msgstr "" #: ../quodlibet/browsers/iradio.py:802 msgid "No stations found" msgstr "Станцій не знайдено" #: ../quodlibet/browsers/iradio.py:803 #, python-format msgid "No Internet radio stations were found at %s." msgstr "За адресою %s інтернет-радіостанцій не знайдено" #: ../quodlibet/browsers/iradio.py:811 msgid "All stations listed are already in your library." msgstr "Всі перелічені станції вже є в бібліотеці." #: ../quodlibet/browsers/iradio.py:828 #, fuzzy msgid "Add to Favorites" msgstr "_Додати до списку програвання" #: ../quodlibet/browsers/iradio.py:832 #, fuzzy msgid "Remove from Favorites" msgstr "_Вилучити зі cписку програвання" #: ../quodlibet/browsers/iradio.py:932 #, 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/media.py:36 msgid "Device Properties" msgstr "Властивості пристрою" #: ../quodlibet/browsers/media.py:52 msgid "Device:" msgstr "Пристрій:" #: ../quodlibet/browsers/media.py:54 msgid "Not mounted" msgstr "Не змонтовано" #: ../quodlibet/browsers/media.py:55 #, fuzzy msgid "Mount point:" msgstr "Точка монтування:" #: ../quodlibet/browsers/media.py:61 ../quodlibet/qltk/cbes.py:40 msgid "_Name:" msgstr "_Назва:" #: ../quodlibet/browsers/media.py:135 msgid "Media Devices" msgstr "Медіа-пристрої:" #: ../quodlibet/browsers/media.py:136 msgid "_Media Devices" msgstr "_Медіа-пристрої" #. eject button #: ../quodlibet/browsers/media.py:224 ../quodlibet/browsers/media.py:378 msgid "_Eject" msgstr "_Витягнути" #: ../quodlibet/browsers/media.py:360 #, fuzzy msgid "_Properties" msgstr "Властивості" #: ../quodlibet/browsers/media.py:365 #: ../quodlibet/browsers/playlists/main.py:464 msgid "_Rename" msgstr "_Перейменувати" #: ../quodlibet/browsers/media.py:461 #, fuzzy, python-format msgid "%(used-size)s used, %(free-size)s available" msgstr "<b>%s</b> використано, <b>%s</b> наявно" #: ../quodlibet/browsers/media.py:479 #, fuzzy, python-format msgid "%s is not connected." msgstr "<b>%s</b> не під'єднано" #: ../quodlibet/browsers/media.py:499 #, fuzzy, python-format msgid "Copying %(song)s" msgstr "Копіювання <b>%s</b>" #: ../quodlibet/browsers/media.py:513 ../quodlibet/browsers/media.py:529 msgid "Unable to copy song" msgstr "Не вдалося скопіювати пісню" #: ../quodlibet/browsers/media.py:514 msgid "There is not enough free space for this song." msgstr "Недостатньо вільного місця для цієї пісні." #: ../quodlibet/browsers/media.py:526 #, fuzzy, python-format msgid "%s could not be copied." msgstr "<b>%s</b> не може бути скопійовано." #: ../quodlibet/browsers/media.py:545 msgid "Unable to delete songs" msgstr "Не вдалося видалити пісні" #: ../quodlibet/browsers/media.py:557 #, fuzzy, python-format msgid "Deleting %(song)s" msgstr "Видалення <b>%s</b>" #: ../quodlibet/browsers/media.py:575 #, fuzzy, python-format msgid "%s could not be deleted." msgstr "<b>%s</b> не може бути видалений." #: ../quodlibet/browsers/media.py:579 msgid "Unable to delete song" msgstr "Не вдалося видалити пісню" #: ../quodlibet/browsers/media.py:594 #, fuzzy, python-format msgid "Ejecting %s failed." msgstr "Не вдалося витягнути <b>%s</b>." #: ../quodlibet/browsers/media.py:597 msgid "Unable to eject device" msgstr "Не вдалося витягнути пристрій" #: ../quodlibet/browsers/media.py:603 msgid "No device backend, Media Devices browser disabled." msgstr "" #: ../quodlibet/browsers/paned/main.py:40 ../quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "Вибір пісень" #: ../quodlibet/browsers/paned/main.py:41 msgid "_Paned Browser" msgstr "В_ибір пісень" #: ../quodlibet/browsers/paned/main.py:90 msgid "Select _All" msgstr "Вибрати _все" #: ../quodlibet/browsers/paned/models.py:104 ../quodlibet/qltk/pluginwin.py:122 #: ../quodlibet/qltk/pluginwin.py:164 msgid "All" msgstr "Всі" #: ../quodlibet/browsers/paned/prefs.py:67 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "<tt>%s</tt>" msgstr "" #: ../quodlibet/browsers/paned/prefs.py:162 msgid "_Wide Mode" msgstr "" #: ../quodlibet/browsers/paned/prefs.py:197 msgid "Paned Browser Preferences" msgstr "Налаштування 'Вибору пісень''" #: ../quodlibet/browsers/paned/prefs.py:204 msgid "Equal pane width" msgstr "" #: ../quodlibet/browsers/playlists/main.py:48 #: ../quodlibet/browsers/playlists/main.py:575 #: ../quodlibet/qltk/pluginwin.py:168 msgid "Playlists" msgstr "Списки програвання" #: ../quodlibet/browsers/playlists/main.py:49 msgid "_Playlists" msgstr "_Списки програвання" #: ../quodlibet/browsers/playlists/main.py:152 msgid "_Remove from Playlist" msgstr "_Вилучити зі cписку програвання" #: ../quodlibet/browsers/playlists/main.py:215 #: ../quodlibet/browsers/playlists/main.py:576 msgid "_Import" msgstr "_Імпортувати" #: ../quodlibet/browsers/playlists/main.py:391 #: ../quodlibet/browsers/playlists/util.py:50 #: ../quodlibet/util/collection.py:570 msgid "New Playlist" msgstr "Новий список програвання" #: ../quodlibet/browsers/playlists/main.py:413 msgid "Unable to import playlist" msgstr "Не вдалося імпортувати список програвання" #: ../quodlibet/browsers/playlists/main.py:414 msgid "Quod Libet can only import playlists in the M3U and PLS formats." msgstr "" "Quod Libet здатне імпортувати списки програвання тільки у форматах M3U та " "PLS." #: ../quodlibet/browsers/playlists/main.py:565 msgid "Unable to rename playlist" msgstr "Не вдалося перейменувати список програвання" #: ../quodlibet/browsers/playlists/main.py:576 msgid "Import Playlist" msgstr "Імпортувати список програвання" #: ../quodlibet/browsers/playlists/menu.py:25 #, fuzzy msgid "_New Playlist…" msgstr "_Новий список програвання" #: ../quodlibet/browsers/playlists/menu.py:86 #, 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:90 #, 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:33 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "" #: ../quodlibet/browsers/playlists/util.py:35 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" #: ../quodlibet/browsers/playlists/util.py:51 #, fuzzy msgid "Enter a name for the new playlist:" msgstr "Введіть назву нового каталоги" #: ../quodlibet/browsers/playlists/util.py:102 #, fuzzy, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" "Імпортується список програвання.\n" "\n" "%d/%d пісень додано." #: ../quodlibet/browsers/search.py:33 msgid "_Limit Results" msgstr "_Обмежити результати" #: ../quodlibet/browsers/search.py:48 msgid "Search Library" msgstr "Пошук в бібліотеці" #: ../quodlibet/browsers/search.py:49 msgid "_Search Library" msgstr "_Пошук бібліотекою" #: ../quodlibet/browsers/soundcloud/main.py:38 #, fuzzy msgid "Soundcloud Browser" msgstr "Вибір пісень" #: ../quodlibet/browsers/soundcloud/main.py:39 msgid "Sound_cloud" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:59 #: ../quodlibet/qltk/searchbar.py:73 msgid "Search" msgstr "Пошук" #: ../quodlibet/browsers/soundcloud/main.py:136 #, python-format msgid "Go to %s" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:380 #, fuzzy msgid "Connected" msgstr "місце запису" #: ../quodlibet/browsers/soundcloud/main.py:381 #, python-format msgid "Quod Libet is now connected, <b>%s</b>!" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:393 #, python-format msgid "Log out of %s" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:395 msgid "Enter code…" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:396 #, python-format msgid "Log in to %s" msgstr "" #: ../quodlibet/browsers/soundcloud/util.py:86 msgid "Soundcloud authorisation" msgstr "" #: ../quodlibet/browsers/soundcloud/util.py:87 msgid "Enter Soundcloud auth code:" msgstr "" #: ../quodlibet/cli.py:50 #, fuzzy msgid "Quod Libet is not running (add '--run' to start it)" msgstr "Quod Libet не запущено." #: ../quodlibet/cli.py:85 msgid "a music library and player" msgstr "музична бібліотека та програвач" #: ../quodlibet/cli.py:86 #, fuzzy msgid "[option]" msgstr "[параметри]" #: ../quodlibet/cli.py:88 msgid "Print the playing song and exit" msgstr "Показати, яка пісня програється, і вийти" #: ../quodlibet/cli.py:89 msgid "Begin playing immediately" msgstr "Відразу почати програвання" #: ../quodlibet/cli.py:90 msgid "Don't show any windows on start" msgstr "" #: ../quodlibet/cli.py:93 msgid "Jump to next song" msgstr "Перейти до наступної пісні" #: ../quodlibet/cli.py:95 msgid "Jump to previous song or restart if near the beginning" msgstr "" #: ../quodlibet/cli.py:96 msgid "Jump to previous song" msgstr "Перейти до попередньої пісні" #: ../quodlibet/cli.py:97 msgid "Start playback" msgstr "Почати програвання" #: ../quodlibet/cli.py:98 msgid "Pause playback" msgstr "Призупинити програвання" #: ../quodlibet/cli.py:99 msgid "Toggle play/pause mode" msgstr "Перемикнути режим програвання/паузи" #: ../quodlibet/cli.py:100 #, fuzzy msgid "Stop playback" msgstr "Почати програвання" #: ../quodlibet/cli.py:101 msgid "Turn up volume" msgstr "Збільшити гучність" #: ../quodlibet/cli.py:102 msgid "Turn down volume" msgstr "Зменшити гучність" #: ../quodlibet/cli.py:103 msgid "Print player status" msgstr "Показати стан програвача" #: ../quodlibet/cli.py:104 msgid "Hide main window" msgstr "Сховати головне вікно" #: ../quodlibet/cli.py:105 msgid "Show main window" msgstr "Показати головне вікно" #: ../quodlibet/cli.py:106 msgid "Toggle main window visibility" msgstr "Показати/сховати головне вікно" #: ../quodlibet/cli.py:107 msgid "Focus the running player" msgstr "Помістити фокус на вікно Quod Libet" #: ../quodlibet/cli.py:108 msgid "Remove active browser filters" msgstr "Видалити фільтри активного переглядача" #: ../quodlibet/cli.py:109 #, fuzzy msgid "Refresh and rescan library" msgstr "_Оновити бібліотеку" #: ../quodlibet/cli.py:110 #, fuzzy msgid "List available browsers" msgstr "Вимкнути переглядач" #: ../quodlibet/cli.py:111 msgid "Print the current playlist" msgstr "Показати поточний список програвання" #: ../quodlibet/cli.py:112 msgid "Print the contents of the queue" msgstr "Показати вміст черги" #: ../quodlibet/cli.py:113 #, fuzzy msgid "Print the active text query" msgstr "Показати вміст черги" #: ../quodlibet/cli.py:114 msgid "Start without plugins" msgstr "" #: ../quodlibet/cli.py:115 #, fuzzy msgid "Start Quod Libet if it isn't running" msgstr "Quod Libet не запущено." #: ../quodlibet/cli.py:116 msgid "Exit Quod Libet" msgstr "Вийти з Quod Libet" #: ../quodlibet/cli.py:121 msgid "Seek within the playing song" msgstr "Переміститись всередині відтворюваної пісні" #: ../quodlibet/cli.py:121 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][ГГ:]ХХ:СС" #: ../quodlibet/cli.py:122 #, fuzzy msgid "Set or toggle shuffle mode" msgstr "Перемикнути режим програвання/паузи" #: ../quodlibet/cli.py:123 msgid "Turn repeat off, on, or toggle it" msgstr "Увімкнути/вимкнути/перемикнути повторення" #: ../quodlibet/cli.py:124 msgid "Set the volume" msgstr "Встановити гучність" #: ../quodlibet/cli.py:125 msgid "Search your audio library" msgstr "Шукати в бібліотеці" #: ../quodlibet/cli.py:125 ../quodlibet/cli.py:137 ../quodlibet/cli.py:141 #: ../quodlibet/cli.py:143 msgid "query" msgstr "запит" #: ../quodlibet/cli.py:126 msgid "Play a file" msgstr "Відтворити файл" #: ../quodlibet/cli.py:126 ../quodlibet/cli.py:137 ../quodlibet/cli.py:143 #, fuzzy msgctxt "command" msgid "filename" msgstr "назва файлу" #: ../quodlibet/cli.py:127 msgid "Rate the playing song" msgstr "Оцінити відтворювану пісню" #: ../quodlibet/cli.py:128 msgid "Set the current browser" msgstr "Встановити режим перегляду бібліотеки" #: ../quodlibet/cli.py:129 #, fuzzy msgid "Stop after the playing song" msgstr "Оцінити відтворювану пісню" #: ../quodlibet/cli.py:130 msgid "Open a new browser" msgstr "Відкрити новий переглядач" #: ../quodlibet/cli.py:131 msgid "Show or hide the queue" msgstr "Показати/сховати чергу" #: ../quodlibet/cli.py:133 #, fuzzy msgid "Show or hide the main song list (deprecated)" msgstr "Показати/сховати список пісень" #: ../quodlibet/cli.py:134 msgid "Filter on a random value" msgstr "Фільтрувати за випадковим параметром" #: ../quodlibet/cli.py:134 #, fuzzy msgctxt "command" msgid "tag" msgstr "Тег" #: ../quodlibet/cli.py:135 msgid "Filter on a tag value" msgstr "Фільтрувати за тегом" #: ../quodlibet/cli.py:135 msgid "tag=value" msgstr "тег=значення" #: ../quodlibet/cli.py:136 msgid "Enqueue a file or query" msgstr "Додати в чергу файл або результат пошуку" #: ../quodlibet/cli.py:138 msgid "Enqueue comma-separated files" msgstr "" #: ../quodlibet/cli.py:139 ../quodlibet/util/tags.py:147 msgid "filename" msgstr "назва файлу" #: ../quodlibet/cli.py:140 msgid "Print filenames of results of query to stdout" msgstr "" #: ../quodlibet/cli.py:142 msgid "Unqueue a file or query" msgstr "Видалити з черги файл або результат пошуку" #: ../quodlibet/cli.py:203 #, fuzzy, python-format msgid "Invalid argument for '%s'." msgstr "E: Неправильний аргумент для '%s'." #: ../quodlibet/cli.py:204 ../quodlibet/util/__init__.py:190 #, fuzzy, python-format msgid "Try %s --help." msgstr "E: Спробуйте %s --help." #: ../quodlibet/devices/_base.py:65 msgid "Unknown Device" msgstr "Невідомий пристрій" #: ../quodlibet/devices/__init__.py:32 #, python-format msgid "Could not import %s, which is needed for device support." msgstr "" #: ../quodlibet/devices/__init__.py:153 #, fuzzy, python-format msgid "%r is not a supported device." msgstr "E: '%s' неоднозначний" #: ../quodlibet/devices/__init__.py:245 ../quodlibet/devices/__init__.py:251 #, python-format msgid "Could not find '%s'." msgstr "" #: ../quodlibet/devices/__init__.py:450 #, fuzzy msgid "Initializing device backend." msgstr "Неправильне значення" #: ../quodlibet/devices/__init__.py:451 #, python-format msgid "Trying '%s'" msgstr "" #: ../quodlibet/devices/__init__.py:461 msgid "Couldn't connect to a device backend." msgstr "" #: ../quodlibet/devices/__init__.py:463 msgid "Device backend initialized." msgstr "" #: ../quodlibet/devices/storage.py:57 #, fuzzy msgid "_Filename pattern:" msgstr "_Шаблон назви файлу:" #: ../quodlibet/devices/storage.py:61 msgid "Copy _album covers" msgstr "Копіювати обкладинки _альбомів" #: ../quodlibet/devices/storage.py:65 msgid "_Remove unused covers and directories" msgstr "_Видалити невикористовувані обкладинки та каталоги" #: ../quodlibet/errorreport/ui.py:60 msgid "An Error Occurred" msgstr "" #: ../quodlibet/errorreport/ui.py:62 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:72 msgid "File Bug Report" msgstr "" #: ../quodlibet/errorreport/ui.py:74 ../quodlibet/errorreport/ui.py:90 msgid "Submit Error Report" msgstr "" #: ../quodlibet/errorreport/ui.py:75 msgid "Quit Program" msgstr "" #: ../quodlibet/errorreport/ui.py:76 #, fuzzy msgid "Ignore Error" msgstr "_Помилки" #: ../quodlibet/errorreport/ui.py:80 msgid "Error details:" msgstr "" #: ../quodlibet/errorreport/ui.py:92 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:100 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "" #: ../quodlibet/errorreport/ui.py:109 msgid "_Send" msgstr "" #: ../quodlibet/errorreport/ui.py:115 #, fuzzy msgid "Short description…" msgstr "опис" #: ../quodlibet/errorreport/ui.py:118 msgid "Data to be sent:" msgstr "" #: ../quodlibet/exfalso.py:34 msgid "an audio tag editor" msgstr "програма для редагування аудіо-тегів" #: ../quodlibet/exfalso.py:34 ../quodlibet/util/tags.py:148 msgid "directory" msgstr "каталог" #: ../quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "" #: ../quodlibet/ext/covers/artwork_url.py:20 msgid "" "Downloads covers linked to by the artwork_url tag.This works with the " "Soundcloud browser." msgstr "" #: ../quodlibet/ext/covers/discogs.py:25 #, fuzzy msgid "Discogs Cover Source" msgstr "Ідентифікатор треку MusicBrainz" #: ../quodlibet/ext/covers/discogs.py:26 msgid "Downloads covers from Discogs." msgstr "" #: ../quodlibet/ext/covers/lastfm.py:22 msgid "Last.fm Cover Source" msgstr "" #: ../quodlibet/ext/covers/lastfm.py:23 msgid "Downloads covers from Last.fm's cover art archive." msgstr "" #: ../quodlibet/ext/covers/musicbrainz.py:19 #, fuzzy msgid "MusicBrainz Cover Source" msgstr "Ідентифікатор треку MusicBrainz" #: ../quodlibet/ext/covers/musicbrainz.py:20 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:25 msgid "Kana/Kanji Simple Inverter" msgstr "" #: ../quodlibet/ext/editing/kakasi.py:26 msgid "Converts kana/kanji to romaji before renaming." msgstr "" #: ../quodlibet/ext/editing/kakasi.py:35 msgid "Romanize _Japanese text" msgstr "" #: ../quodlibet/ext/editing/kakasi.py:63 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:19 msgid "" "Allows arbitrary regex substitutions (s///) 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:69 #, fuzzy msgid "Advanced Preferences" msgstr "Налаштування 'Вибору пісень''" #: ../quodlibet/ext/events/advanced_preferences.py:70 msgid "Allow editing of advanced config settings." msgstr "" #: ../quodlibet/ext/events/advanced_preferences.py:162 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:153 msgid "Top of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:154 msgid "Middle of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:155 msgid "Bottom of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:158 msgid "_Position:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:171 #, fuzzy msgid "_Cover size:" msgstr "Загальний розмір:" #: ../quodlibet/ext/events/animosd/prefs.py:177 #: ../quodlibet/ext/events/lyricswindow.py:334 ../quodlibet/qltk/prefs.py:266 #, fuzzy msgid "Display" msgstr "Змінити зовнішній вигляд" #: ../quodlibet/ext/events/animosd/prefs.py:190 msgid "_Font:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:195 msgid "Left" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:196 msgid "Center" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:197 #, fuzzy msgid "Right" msgstr "За _оцінками" #: ../quodlibet/ext/events/animosd/prefs.py:200 msgid "_Align text:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:206 msgid "Text" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:217 msgid "_Text:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:227 msgid "_Fill:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:232 #: ../quodlibet/ext/events/synchronizedlyrics.py:63 msgid "Colors" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:240 msgid "_Shadows" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:241 msgid "_Outline" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:242 msgid "Rou_nded Corners" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:258 msgid "_Delay:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:264 #: ../quodlibet/qltk/pluginwin.py:172 msgid "Effects" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:270 #, fuzzy msgid "Ed_it Display Pattern…" msgstr "Змінити зовнішній вигляд" #: ../quodlibet/ext/events/animosd/prefs.py:274 #: ../quodlibet/ext/events/trayicon/prefs.py:78 #, fuzzy msgid "Preview" msgstr "_Попередній перегляд" #: ../quodlibet/ext/events/auto_library_update.py:136 msgid "Automatic Library Update" msgstr "" #: ../quodlibet/ext/events/auto_library_update.py:137 #, python-format msgid "Keeps your library up to date with inotify. Requires %s." 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 by Brian Nelson." 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/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:97 msgid "Equalizer" msgstr "" #: ../quodlibet/ext/events/equalizer.py:98 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:132 msgid "The current backend does not support equalization." msgstr "" #: ../quodlibet/ext/events/equalizer.py:138 #, python-format msgid "%.1f kHz" msgstr "" #: ../quodlibet/ext/events/equalizer.py:139 #: ../quodlibet/ext/gstreamer/crossfeed.py:93 #: ../quodlibet/ext/gstreamer/karaoke.py:95 #, python-format msgid "%d Hz" msgstr "" #: ../quodlibet/ext/events/equalizer.py:173 #: ../quodlibet/ext/gstreamer/crossfeed.py:112 #, fuzzy, python-format msgid "%.1f dB" msgstr "%d секунда" #: ../quodlibet/ext/events/equalizer.py:192 #: ../quodlibet/ext/gstreamer/crossfeed.py:31 #, fuzzy msgid "Custom" msgstr "_Інший" #: ../quodlibet/ext/events/equalizer.py:199 #, fuzzy msgid "_Clear" msgstr "_Очистити помилки" #. Translators: statuses relating to Instant Messenger apps #: ../quodlibet/ext/events/gajim_status.py:27 msgid "online" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:28 msgid "offline" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:29 msgid "chat" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:30 msgid "away" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:31 msgid "xa" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:32 msgid "invisible" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:37 msgid "Gajim Status Message" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:38 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:45 #: ../quodlibet/ext/events/telepathy_status.py:69 msgid "paused" 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:160 msgid "Add '[paused]'" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:163 msgid "If checked, '[paused]' will be added to status message on pause." msgstr "" #: ../quodlibet/ext/events/gajim_status.py:187 msgid "Statuses for which message will be changed" msgstr "" #: ../quodlibet/ext/events/headphonemon.py:156 msgid "Pause on Headphone Unplug" msgstr "" #: ../quodlibet/ext/events/headphonemon.py:157 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" #: ../quodlibet/ext/events/inhibit.py:41 msgid "Inhibit Screensaver" msgstr "" #: ../quodlibet/ext/events/inhibit.py:42 msgid "Prevents the GNOME screensaver from activating while a song is playing." msgstr "" #: ../quodlibet/ext/events/inhibit.py:51 #, fuzzy msgid "Music is playing" msgstr "Музичний програвач" #: ../quodlibet/ext/events/iradiolog.py:16 #, fuzzy msgid "Internet Radio Log" msgstr "Інтернет-радіо" #: ../quodlibet/ext/events/iradiolog.py:17 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" #: ../quodlibet/ext/events/jep118.py:29 msgid "JEP-118" msgstr "" #: ../quodlibet/ext/events/jep118.py:30 msgid "Outputs a Jabber User Tunes file to ~/.quodlibet/jabber." 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 msgid "A restart is required for any changes to take effect" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:199 #, fuzzy msgid "No active song" msgstr "Не вдалося зберегти пісню" #: ../quodlibet/ext/events/lyricswindow.py:215 #, fuzzy msgid "No lyrics found" msgstr "Розширень не знайдено" #: ../quodlibet/ext/events/lyricswindow.py:227 #, fuzzy msgid "Lyrics:" msgstr "Текст пісні" #: ../quodlibet/ext/events/lyricswindow.py:284 msgid "_Zoom level:" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:302 msgid "URL:" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:307 msgid "Revert to default" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:322 msgid "Search via above URL if the lyrics couldn't be found in LyricsWikia." msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:339 #, fuzzy msgid "Alternate search" msgstr "Очистити поле пошуку" #: ../quodlibet/ext/events/lyricswindow.py:347 #, fuzzy msgid "Lyrics Window" msgstr "Текст пісні" #: ../quodlibet/ext/events/lyricswindow.py:348 msgid "Shows a window containing lyrics of the playing song." msgstr "" #: ../quodlibet/ext/events/mediaserver.py:38 msgid "UPnP AV Media Server" msgstr "" #: ../quodlibet/ext/events/mediaserver.py:39 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." 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:39 msgid "" "Allows control of Quod Libet using the MPRIS 1.0/2.0 D-Bus Interface " "Specification." msgstr "" #: ../quodlibet/ext/events/mpris/__init__.py:45 #: ../quodlibet/ext/events/trayicon/prefs.py:30 #, fuzzy msgid "Hide main window on close" msgstr "Сховати головне вікно" #: ../quodlibet/ext/events/mpris/__init__.py:48 #: ../quodlibet/ext/events/themeswitcher.py:84 #: ../quodlibet/ext/gstreamer/compressor.py:99 #: ../quodlibet/ext/gstreamer/crossfeed.py:136 #: ../quodlibet/ext/gstreamer/karaoke.py:99 #: ../quodlibet/ext/gstreamer/pitch.py:83 ../quodlibet/qltk/prefs.py:688 #, fuzzy msgid "Preferences" msgstr "Налаштування" #: ../quodlibet/ext/events/mqtt.py:50 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/mqtt.py:56 msgid "MQTT Publisher" msgstr "" #: ../quodlibet/ext/events/mqtt.py:57 msgid "Publishes status messages to an MQTT topic." msgstr "" #: ../quodlibet/ext/events/mqtt.py:122 msgid "Broker hostname" msgstr "" #: ../quodlibet/ext/events/mqtt.py:122 msgid "broker hostname / IP" msgstr "" #: ../quodlibet/ext/events/mqtt.py:124 msgid "Broker port" msgstr "" #: ../quodlibet/ext/events/mqtt.py:124 msgid "broker port" msgstr "" #: ../quodlibet/ext/events/mqtt.py:126 msgid "Topic" msgstr "" #: ../quodlibet/ext/events/mqtt.py:128 #, fuzzy msgid "Playing Pattern" msgstr "шаблон" #: ../quodlibet/ext/events/mqtt.py:130 msgid "Status text when a song is started." msgstr "" #: ../quodlibet/ext/events/mqtt.py:132 #, fuzzy msgid "Paused Pattern" msgstr "шаблон" #: ../quodlibet/ext/events/mqtt.py:134 msgid "Text when a song is paused." msgstr "" #: ../quodlibet/ext/events/mqtt.py:136 #, fuzzy msgid "No-song Text" msgstr "%d пісня" #: ../quodlibet/ext/events/mqtt.py:138 msgid "Plain text for when there is no current song" msgstr "" #: ../quodlibet/ext/events/mqtt.py:149 #, fuzzy msgid "MQTT Configuration" msgstr "Інформація" #: ../quodlibet/ext/events/mqtt.py:153 #, fuzzy msgid "Status Text" msgstr "шаблон" #: ../quodlibet/ext/events/mqtt.py:185 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "" #: ../quodlibet/ext/events/mqtt.py:189 #, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s" msgstr "" #: ../quodlibet/ext/events/mqtt.py:192 #, fuzzy msgid "Connection error" msgstr "місце запису" #: ../quodlibet/ext/events/notify.py:80 msgid "Notification text" msgstr "" #: ../quodlibet/ext/events/notify.py:88 #, fuzzy msgid "_Title:" msgstr "Назва" #: ../quodlibet/ext/events/notify.py:99 ../quodlibet/ext/events/notify.py:128 msgid "Revert to default pattern" msgstr "" #: ../quodlibet/ext/events/notify.py:118 msgid "_Body:" msgstr "" #: ../quodlibet/ext/events/notify.py:138 msgid "_Show notification" msgstr "" #: ../quodlibet/ext/events/notify.py:156 msgid "Show notifications" msgstr "" #: ../quodlibet/ext/events/notify.py:162 msgid "Only on <i>_manual</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:170 msgid "Only on <i>_automatic</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:178 msgid "On <i>a_ll</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:196 msgid "Only when the main window is not _focused" msgstr "" #: ../quodlibet/ext/events/notify.py:204 msgid "Show \"_Next\" button" msgstr "" #: ../quodlibet/ext/events/notify.py:236 msgid "Connection Error" msgstr "" #: ../quodlibet/ext/events/notify.py:237 ../quodlibet/ext/events/notify.py:391 #: ../quodlibet/ext/events/notify.py:433 msgid "Couldn't connect to notification daemon." msgstr "" #: ../quodlibet/ext/events/notify.py:251 msgid "Song Notifications" msgstr "" #: ../quodlibet/ext/events/notify.py:252 msgid "Displays a notification when the song changes." msgstr "" #: ../quodlibet/ext/events/notify.py:415 ../quodlibet/qltk/unity.py:65 msgid "Next" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:178 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:254 #, python-format msgid "Could not contact service '%s'." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:260 msgid "Authentication failed: invalid URL." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:277 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:282 msgid "Client is banned. Contact the author." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:286 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:351 msgid "AudioScrobbler Submission" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:352 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:450 msgid "Authentication successful." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:462 #, fuzzy msgid "_Service:" msgstr "Пристрій:" #: ../quodlibet/ext/events/qlscrobbler.py:462 msgid "_URL:" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:462 #, fuzzy msgid "User_name:" msgstr "_Назва:" #: ../quodlibet/ext/events/qlscrobbler.py:463 msgid "_Password:" msgstr "" #. Translators: Other service #: ../quodlibet/ext/events/qlscrobbler.py:479 #, fuzzy msgid "Other…" msgstr "_Інші:" #. verify data #: ../quodlibet/ext/events/qlscrobbler.py:517 msgid "_Verify account data" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:522 #: ../quodlibet/ext/songsmenu/lastfmsync.py:304 msgid "Account" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:530 #, fuzzy msgid "_Artist pattern:" msgstr "_Виконавець" #: ../quodlibet/ext/events/qlscrobbler.py:530 #, fuzzy msgid "_Title pattern:" msgstr "_Шаблон назви файлу:" #: ../quodlibet/ext/events/qlscrobbler.py:531 msgid "Exclude _filter:" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:549 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:559 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:568 msgid "Songs matching this filter will not be submitted." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:576 msgid "_Offline mode (don't submit anything)" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:580 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:27 #, fuzzy msgid "Random Album Playback" msgstr "Випадковий _альбом" #: ../quodlibet/ext/events/randomalbum.py:28 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:38 msgid "Rated higher" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:39 msgid "Played more often" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:40 msgid "Skipped more often" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:41 msgid "Played more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:42 msgid "Started more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:43 msgid "Added more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:44 #, fuzzy msgid "Longer albums" msgstr "альбоми" #: ../quodlibet/ext/events/randomalbum.py:83 msgid "seconds before starting next album" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:87 #, fuzzy msgid "Weights" msgstr "За _оцінками" #: ../quodlibet/ext/events/randomalbum.py:89 msgid "Play some albums more than others" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:103 msgid "avoid" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:114 msgid "prefer" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:201 #, fuzzy msgid "Random Album" msgstr "Випадковий _альбом" #: ../quodlibet/ext/events/randomalbum.py:202 #, python-format msgid "Waiting to start %s" msgstr "" #: ../quodlibet/ext/events/rbimport.py:114 #, fuzzy msgid "Import Failed" msgstr "Імпортувати список програвання" #: ../quodlibet/ext/events/rbimport.py:119 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "" #: ../quodlibet/ext/events/rbimport.py:127 msgid "Rhythmbox Import" msgstr "" #: ../quodlibet/ext/events/rbimport.py:128 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "" #: ../quodlibet/ext/events/rbimport.py:132 #, fuzzy msgid "Start Import" msgstr "_Імпортувати" #: ../quodlibet/ext/events/screensaver.py:25 msgid "Screensaver Pause" msgstr "" #: ../quodlibet/ext/events/screensaver.py:26 msgid "Pauses playback while the GNOME screensaver is active." msgstr "" #: ../quodlibet/ext/events/searchprovider.py:73 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "" #: ../quodlibet/ext/events/searchprovider.py:79 msgid "GNOME Search Provider" msgstr "" #: ../quodlibet/ext/events/searchprovider.py:80 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/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:29 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:57 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:58 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:34 #, fuzzy msgid "Synchronized Lyrics" msgstr "Текст пісні" #: ../quodlibet/ext/events/synchronizedlyrics.py:35 msgid "Shows synchronized lyrics from .lrc file with same name as the track." msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:66 msgid "Text:" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:76 msgid "Background:" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:87 msgid "Font" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:90 msgid "Size (px):" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:62 msgid "Telepathy Status Messages" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:63 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:122 #, fuzzy msgid "Playing:" msgstr "Не грає" #: ../quodlibet/ext/events/telepathy_status.py:123 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:139 msgid "Paused:" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:140 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:156 msgid "Plain text for status when there is no current song" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:157 #, fuzzy msgid "No song:" msgstr "%d пісня" #. Frame #: ../quodlibet/ext/events/telepathy_status.py:164 #, 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/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:77 #: ../quodlibet/ext/events/trayicon/prefs.py:98 #: ../quodlibet/ext/events/trayicon/systemtray.py:177 #: ../quodlibet/qltk/info.py:47 msgid "Not playing" msgstr "Не грає" #: ../quodlibet/ext/events/trayicon/__init__.py:53 msgid "Tray Icon" msgstr "" #: ../quodlibet/ext/events/trayicon/__init__.py:54 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:183 #: ../quodlibet/qltk/quodlibetwindow.py:1046 #: ../quodlibet/qltk/quodlibetwindow.py:1238 #, fuzzy msgid "_Play" msgstr "_Списки програвання" #: ../quodlibet/ext/events/trayicon/menu.py:63 #: ../quodlibet/qltk/quodlibetwindow.py:185 #: ../quodlibet/qltk/quodlibetwindow.py:1240 ../quodlibet/qltk/wlw.py:51 #, fuzzy msgid "P_ause" msgstr "Програвач" #: ../quodlibet/ext/events/trayicon/menu.py:68 #: ../quodlibet/qltk/quodlibetwindow.py:190 #: ../quodlibet/qltk/quodlibetwindow.py:1041 #, fuzzy msgid "Pre_vious" msgstr "_Попередній перегляд" #: ../quodlibet/ext/events/trayicon/menu.py:71 #: ../quodlibet/qltk/quodlibetwindow.py:194 #: ../quodlibet/qltk/quodlibetwindow.py:1051 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:1012 #, fuzzy msgid "Open _Browser" msgstr "Відкрити новий переглядач" #: ../quodlibet/ext/events/trayicon/menu.py:103 #: ../quodlibet/qltk/quodlibetwindow.py:1031 ../quodlibet/qltk/songsmenu.py:411 msgid "Edit _Tags" msgstr "Редагувати _теги" #: ../quodlibet/ext/events/trayicon/menu.py:112 #: ../quodlibet/qltk/quodlibetwindow.py:975 ../quodlibet/qltk/songsmenu.py:424 msgid "_Information" msgstr "_Інформація" #: ../quodlibet/ext/events/trayicon/menu.py:114 #: ../quodlibet/qltk/songsmenu.py:340 #, fuzzy msgid "Play_lists" msgstr "Списки програвання" #: ../quodlibet/ext/events/trayicon/menu.py:132 #: ../quodlibet/qltk/quodlibetwindow.py:1026 msgid "_Quit" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:32 ../quodlibet/qltk/prefs.py:69 msgid "Behavior" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:42 msgid "Scroll wheel adjusts volume" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel changes song" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll _Wheel" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:84 #, fuzzy msgid "Tooltip Display" msgstr "Змінити зовнішній вигляд" #: ../quodlibet/ext/events/viewlyrics.py:23 #, fuzzy msgid "View Lyrics" msgstr "Текст пісні" #: ../quodlibet/ext/events/viewlyrics.py:24 msgid "Automatically displays lyrics beneath the song list in the main window." msgstr "" #: ../quodlibet/ext/events/viewlyrics.py:29 #, fuzzy msgid "_Lyrics" 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:406 msgid "Waveform Seek Bar" msgstr "" #: ../quodlibet/ext/events/waveformseekbar.py:410 msgid "A seekbar in the shape of the waveform of the current song." msgstr "" #: ../quodlibet/ext/events/waveformseekbar.py:443 msgid "Override foreground color:" msgstr "" #: ../quodlibet/ext/events/write_cover.py:32 msgid "Picture Saver" msgstr "" #: ../quodlibet/ext/events/write_cover.py:33 msgid "Saves the cover image of the current song to a file." msgstr "" #: ../quodlibet/ext/events/write_cover.py:66 #, fuzzy msgid "File:" msgstr "Файли" #: ../quodlibet/ext/gstreamer/compressor.py:20 msgid "_Threshold:" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:21 msgid "Threshold until the filter is activated" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:22 msgid "R_atio:" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:22 msgid "Compression ratio" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:74 #: ../quodlibet/ext/gstreamer/karaoke.py:91 #, python-format msgid "%d %%" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:105 msgid "Audio Compressor" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:106 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:19 #, fuzzy msgid "_Preset:" msgstr "_Попередній перегляд" #: ../quodlibet/ext/gstreamer/crossfeed.py:19 #, fuzzy msgid "Filter preset" msgstr "Фільтрувати за _виконавцем" #: ../quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Frequency cut:" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Low-pass filter cut frequency" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed _level:" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed level" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:25 msgid "Default" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Chu Moy" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Jan Meier" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:31 #, fuzzy msgid "Custom settings" msgstr "_Інший" #: ../quodlibet/ext/gstreamer/crossfeed.py:152 msgid "Crossfeed" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:153 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:20 #, fuzzy msgid "Filter _band:" msgstr "Фільтрувати за _жанром" #: ../quodlibet/ext/gstreamer/karaoke.py:21 msgid "The Frequency band of the filter" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:22 #, fuzzy msgid "Filter _width:" msgstr "Фільтрувати за _виконавцем" #: ../quodlibet/ext/gstreamer/karaoke.py:23 msgid "The Frequency width of the filter" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:24 msgid "_Level:" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:24 msgid "Level of the effect" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:105 msgid "Karaoke" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:106 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:20 msgid "R_ate:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:21 msgid "_Tempo:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:22 msgid "_Pitch:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:89 #, fuzzy msgid "Audio Pitch / Speed" msgstr "Аудіо-фіди" #: ../quodlibet/ext/gstreamer/pitch.py:90 #, fuzzy msgid "Controls the pitch of an audio stream." msgstr "Введіть адресу аудіо-фіду" #: ../quodlibet/ext/playlist/export_to_folder.py:29 #: ../quodlibet/ext/playlist/export_to_folder.py:97 #: ../quodlibet/ext/playlist/export_to_folder.py:138 #, fuzzy msgid "Export Playlist to Folder" msgstr "Імпортувати список програвання" #: ../quodlibet/ext/playlist/export_to_folder.py:38 #, fuzzy msgid "_Export" msgstr "_Імпортувати" #: ../quodlibet/ext/playlist/export_to_folder.py:43 #, fuzzy msgid "Destination folder:" msgstr "Станцій не знайдено" #: ../quodlibet/ext/playlist/export_to_folder.py:58 #, 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:156 #, fuzzy msgid "Default filename pattern:" msgstr "_Шаблон назви файлу:" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:23 msgid "Export to Squeezebox" msgstr "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:25 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 "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Export playlist to Squeezebox" msgstr "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:80 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 "" "Playback follows your selection, or the next song in the list once exhausted." msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:22 msgid "Playcount Equalizer" msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:23 msgid "Shuffle, preferring songs with fewer total plays." msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:25 #, fuzzy msgid "Prefer less played" msgstr "востаннє відтворено" #: ../quodlibet/ext/playorder/queue.py:19 #, fuzzy msgid "Queue Only" msgstr "_Черга" #: ../quodlibet/ext/playorder/queue.py:21 msgid "" "Limits playing of songs to the queue. Select this play order in the main " "window, then double-clicking any song will enqueue it instead of playing." msgstr "" #: ../quodlibet/ext/playorder/reverse.py:14 #, fuzzy msgid "Reverse" msgstr "Ніколи" #: ../quodlibet/ext/playorder/reverse.py:16 msgid "Reverses the play order of songs." msgstr "" #: ../quodlibet/ext/playorder/skip_songs.py:25 #, fuzzy msgid "Skip Songs" msgstr "Немає пісень" #: ../quodlibet/ext/playorder/skip_songs.py:27 msgid "" "Playback skips over songs with a rating equal or below a given threshold." msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:30 msgid "Repeat Each Track" msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:32 msgid "Shuffle songs, but repeat every track a set number of times." msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:51 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. Syntax is '@(if: " "condition, then, else)'." msgstr "" #: ../quodlibet/ext/query/pythonexpression.py:14 msgid "Python Query" msgstr "" #: ../quodlibet/ext/query/pythonexpression.py:15 msgid "" "Use Python expressions in queries. Syntax is '@(python: expression)'. The " "variable 's' is the song being matched." msgstr "" #: ../quodlibet/ext/query/savedsearch.py:19 #, fuzzy msgid "Include Saved Search" msgstr "Збережені значення" #: ../quodlibet/ext/query/savedsearch.py:20 msgid "" "Include the results of a saved search as part of another query. Syntax is " "'@(saved: search name)'." 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:116 msgid "Port:" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:121 #, fuzzy msgid "Username:" msgstr "_Перейменувати" #: ../quodlibet/ext/_shared/squeezebox/base.py:126 msgid "Password:" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:130 msgid "Library directory the server connects to." msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:132 #, fuzzy msgid "Library path:" msgstr "Бібліотека" #. Add verify button #: ../quodlibet/ext/_shared/squeezebox/base.py:141 msgid "_Verify settings" msgstr "" #. Server settings Frame #: ../quodlibet/ext/_shared/squeezebox/base.py:147 msgid "Squeezebox Server" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:150 msgid "Debug" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:26 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:28 msgid "unidentified Squeezebox server" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:37 #, 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:20 #: ../quodlibet/ext/songsmenu/importexport.py:34 #: ../quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:329 #, fuzzy msgid "Fit image to _window" msgstr "Сховати головне вікно" #. Both labels #: ../quodlibet/ext/songsmenu/albumart.py:338 msgid "_Program:" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:343 msgid "_Edit image after saving" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:345 #, fuzzy msgid "File_name:" msgstr "Назва файлу" #: ../quodlibet/ext/songsmenu/albumart.py:457 msgid "Saving failed" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:458 #, fuzzy, python-format msgid "Unable to save \"%s\"." msgstr "Не вдалося зберегти пісню" #: ../quodlibet/ext/songsmenu/albumart.py:556 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:613 #, fuzzy msgid "Album Art Downloader" msgstr "Список альбомів" #: ../quodlibet/ext/songsmenu/albumart.py:666 #, python-format msgid "from %(source)s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:669 #, python-format msgid "Resolution: %s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:672 #, fuzzy, python-format msgid "Size: %s" msgstr "Розмір" #: ../quodlibet/ext/songsmenu/albumart.py:690 #, fuzzy msgid "_Search" msgstr "_Пошук" #: ../quodlibet/ext/songsmenu/albumart.py:741 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:451 #, fuzzy msgid "Searching…" msgstr "Пошук" #: ../quodlibet/ext/songsmenu/albumart.py:804 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:922 #, fuzzy msgid "Download Album Art" msgstr "Список альбомів" #: ../quodlibet/ext/songsmenu/albumart.py:923 msgid "Downloads album covers from various websites." msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:936 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 "Тип альбому 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 #: ../quodlibet/qltk/downloader.py:52 msgid "Filename" msgstr "Назва файлу" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:130 #, fuzzy msgid "Disc" msgstr "_Диск" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:131 #: ../quodlibet/ext/songsmenu/replaygain.py:404 #: ../quodlibet/qltk/tracknumbers.py:92 msgid "Track" msgstr "Трек" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:132 #, 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:447 msgid "Please enter a query." msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:465 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:496 msgid "Error encountered. Please retry." msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:472 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:488 msgid "Loading result…" msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:475 #, fuzzy msgid "No results found." msgstr "Розширень не знайдено" #: ../quodlibet/ext/songsmenu/browsefolders.py:159 #, fuzzy msgid "Browse Folders" msgstr "Вибір пісень" #: ../quodlibet/ext/songsmenu/browsefolders.py:160 msgid "Opens the songs' folders in a file manager." msgstr "" #: ../quodlibet/ext/songsmenu/browsefolders.py:172 #, fuzzy msgid "Unable to open folders" msgstr "Не вдалося створити каталог" #: ../quodlibet/ext/songsmenu/browsefolders.py:173 msgid "No program available to open folders." msgstr "" #: ../quodlibet/ext/songsmenu/console.py:40 msgid "Python Console" msgstr "" #: ../quodlibet/ext/songsmenu/console.py:41 msgid "Interactive Python console." msgstr "" #: ../quodlibet/ext/songsmenu/console.py:72 msgid "You can access the following objects by default:" msgstr "" #: ../quodlibet/ext/songsmenu/console.py:82 msgid "Your current working directory is:" msgstr "" #: ../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:55 #, fuzzy msgid "pattern" 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:91 #, fuzzy msgid "Input value" msgstr "Неправильне значення" #: ../quodlibet/ext/songsmenu/custom_commands.py:92 #, python-format msgid "Value for %s?" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:136 #, fuzzy msgid "Custom Commands" msgstr "_Інший" #: ../quodlibet/ext/songsmenu/custom_commands.py:137 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:188 #: ../quodlibet/ext/songsmenu/custom_commands.py:198 #: ../quodlibet/ext/songsmenu/custom_commands.py:252 msgid "Edit Custom Commands" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:199 msgid "" "Supports QL patterns\n" "eg <tt><~artist~title></tt>" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:283 #, fuzzy, python-format msgid "Unable to run custom command %s" msgstr "Не вдалося скопіювати пісню" #: ../quodlibet/ext/songsmenu/duplicates.py:290 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: ../quodlibet/ext/songsmenu/duplicates.py:343 msgid "Collapse / Expand all" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:347 #, python-format msgid "Duplicate key expression is '%s'" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:363 #, fuzzy msgid "Duplicates Browser" msgstr "Вимкнути переглядач" #: ../quodlibet/ext/songsmenu/duplicates.py:364 msgid "Finds and displays similarly tagged versions of songs." msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:407 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:409 msgid "_Group duplicates by:" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:414 msgid "Duplicate Key" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:419 msgid "Remove _Whitespace" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:420 #, fuzzy msgid "Remove _Diacritics" msgstr "_Рейтинг" #: ../quodlibet/ext/songsmenu/duplicates.py:421 #, fuzzy msgid "Remove _Punctuation" msgstr "_Рейтинг" #: ../quodlibet/ext/songsmenu/duplicates.py:422 msgid "Case _Insensitive" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:430 msgid "Matching options" msgstr "" #. Create a dialog. #: ../quodlibet/ext/songsmenu/editplaycount.py:19 #: ../quodlibet/ext/songsmenu/editplaycount.py:41 #, fuzzy msgid "Edit Playcount" msgstr "Змінити зовнішній вигляд" #: ../quodlibet/ext/songsmenu/editplaycount.py:20 msgid "" "Edit a song's ~#playcount and ~#skipcount.\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's ~#playcount to 0, the ~#lastplayed and ~#laststarted " "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:68 msgid "Play Count" msgstr "" #: ../quodlibet/ext/songsmenu/editplaycount.py:69 msgid "Skip Count" msgstr "" #: ../quodlibet/ext/songsmenu/embedded.py:24 msgid "Edit Embedded Images" msgstr "" #: ../quodlibet/ext/songsmenu/embedded.py:25 msgid "Removes or replaces embedded images." msgstr "" #: ../quodlibet/ext/songsmenu/embedded.py:78 #, fuzzy msgid "_Remove all Images" msgstr "_Рейтинг" #: ../quodlibet/ext/songsmenu/embedded.py:82 msgid "_Embed Current 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:41 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 #: ../quodlibet/qltk/downloader.py:67 #, 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 "Записати" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" 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:49 msgid "Generating fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:63 msgid "_Details" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:85 msgid "_Submit" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:115 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:118 msgid "Fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Songs with MBIDs:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with sufficient tags:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs to submit:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:162 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:178 msgid "Submitting fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:186 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/id3tlen.py:21 msgid "Fix MP3 Duration" msgstr "" #: ../quodlibet/ext/songsmenu/id3tlen.py:22 msgid "" "Removes TLEN frames from ID3 tags which can be the cause for invalid song " "durations." msgstr "" #: ../quodlibet/ext/songsmenu/ifp.py:20 msgid "Send to iFP" msgstr "" #: ../quodlibet/ext/songsmenu/ifp.py:21 msgid "Uploads songs to an iRiver iFP device." msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:51 msgid "Export Metadata" msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:52 msgid "Exports metadata of selected songs as a .tags file." msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:92 #, fuzzy msgid "Import Metadata" msgstr "Імпортувати список програвання" #: ../quodlibet/ext/songsmenu/importexport.py:93 msgid "Imports metadata for selected songs from a .tags file." msgstr "" #: ../quodlibet/ext/songsmenu/k3b.py:23 msgid "Burn CD" msgstr "" #: ../quodlibet/ext/songsmenu/k3b.py:24 msgid "Burns CDs with K3b, Brasero or xfburn." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:96 msgid "Updating chart list." msgstr "" #. No charts to fetch, no update scheduled. #: ../quodlibet/ext/songsmenu/lastfmsync.py:114 msgid "Already up-to-date." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:121 #, python-format msgid "Fetching chart for week of %s." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:143 msgid "Sync complete." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:149 msgid "Error during sync" msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:214 #: ../quodlibet/ext/songsmenu/lastfmsync.py:244 msgid "Last.fm Sync" msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:245 msgid "Updates your library's statistics from your Last.fm profile." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:293 #, 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 "" #. Create a dialog. #: ../quodlibet/ext/songsmenu/migratemetadata.py:29 #: ../quodlibet/ext/songsmenu/migratemetadata.py:38 #, fuzzy msgid "Migrate Metadata" msgstr "Імпортувати список програвання" #: ../quodlibet/ext/songsmenu/migratemetadata.py:32 msgid "Copies the quodlibet-specific metadata between songs." msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:45 msgid "_Copy" msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:47 msgid "_Paste" msgstr "" #. Create the tag table. #: ../quodlibet/ext/songsmenu/migratemetadata.py:57 #, fuzzy msgid "Information to copy/paste" msgstr "Інформація" #. Create the indexing box. #: ../quodlibet/ext/songsmenu/migratemetadata.py:79 msgid "Map tracks by disc and track number" msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:80 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 "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:96 #, python-format msgid "There is %d stored track." msgid_plural "There are %d stored tracks." msgstr[0] "" msgstr[1] "" msgstr[2] "" #: ../quodlibet/ext/songsmenu/playlist.py:31 #, fuzzy msgid "Export as Playlist" msgstr "Імпортувати список програвання" #: ../quodlibet/ext/songsmenu/playlist.py:32 msgid "Exports songs to an M3U or PLS playlist." msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:77 msgid "Use relative paths" msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:77 msgid "Use absolute paths" msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:132 #, fuzzy msgid "Unable to export playlist" msgstr "Не вдалося імпортувати список програвання" #: ../quodlibet/ext/songsmenu/playlist.py:133 #, fuzzy, python-format msgid "Writing to <b>%s</b> 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:362 msgid "ReplayGain Analyzer" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:418 msgid "Progress" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:433 msgid "Gain" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:448 msgid "Peak" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:463 #, python-format msgid "There is <b>%(to-process)s</b> album to update (of %(all)s)" msgid_plural "There are <b>%(to-process)s</b> albums to update (of %(all)s)" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: ../quodlibet/ext/songsmenu/replaygain.py:578 msgid "Replay Gain" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:579 msgid "" "Analyzes and updates ReplayGain information, using GStreamer. Results are " "grouped by album." msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:617 msgid "always" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:618 msgid "if <b>any</b> RG tags are missing" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:620 msgid "if <b>album</b> RG tags are missing" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:637 msgid "_Process albums:" msgstr "" #. Server settings Frame #: ../quodlibet/ext/songsmenu/replaygain.py:649 #, 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 "" #. TRANSLATORS: BPM mean "beats per minute" #: ../quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "" #: ../quodlibet/ext/songsmenu/tapbpm.py:32 #: ../quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" 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:172 #: ../quodlibet/ext/songsmenu/tapbpm.py:179 msgid "Tap BPM" msgstr "" #: ../quodlibet/ext/songsmenu/tapbpm.py:173 #, fuzzy msgid "Tap BPM for the selected song." msgstr "Не вдалося видалити пісні" #: ../quodlibet/ext/songsmenu/website_search.py:35 #, fuzzy msgid "Website Search" msgstr "Пошук" #: ../quodlibet/ext/songsmenu/website_search.py:36 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern-example)s." msgstr "" #: ../quodlibet/ext/songsmenu/website_search.py:78 #, fuzzy msgid "Search URL patterns" msgstr "шаблон" #: ../quodlibet/ext/songsmenu/website_search.py:88 #, fuzzy msgid "Edit search URLs" msgstr "Редагувати збережені параметри..." #. Add link to editor #: ../quodlibet/ext/songsmenu/website_search.py:114 #, fuzzy msgid "Configure Searches…" msgstr "_Виділяти кольором критерій пошуку" #: ../quodlibet/ext/songsmenu/wikipedia.py:46 #, python-format msgid "Search at %(website)s" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:63 msgid "Search Artist in Wikipedia" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:64 msgid "" "Opens a browser window with Wikipedia article on the playing song artist." msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:71 msgid "Search Album in Wikipedia" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:72 msgid "" "Opens a browser window with Wikipedia article on the playing song album." msgstr "" #. then (try to) load all new files #: ../quodlibet/library/libraries.py:650 ../quodlibet/library/libraries.py:660 #: ../quodlibet/library/libraries.py:726 ../quodlibet/library/libraries.py:745 #: ../quodlibet/qltk/information.py:268 ../quodlibet/qltk/prefs.py:639 #: ../quodlibet/util/library.py:124 msgid "Library" msgstr "Бібліотека" #: ../quodlibet/library/libraries.py:650 msgid "Checking mount points" msgstr "Перевірка точок монтування" #: ../quodlibet/library/libraries.py:660 msgid "Scanning library" msgstr "Сканування бібліотеки" #: ../quodlibet/library/libraries.py:725 #, python-format msgid "Scanning %s" msgstr "Сканування %s" #: ../quodlibet/library/libraries.py:745 msgid "Loading files" msgstr "" #: ../quodlibet/operon/base.py:70 #, python-format msgid "Failed to load file: %r" msgstr "" #: ../quodlibet/operon/commands.py:37 msgid "List tags" msgstr "" #: ../quodlibet/operon/commands.py:42 ../quodlibet/operon/commands.py:81 #: ../quodlibet/operon/commands.py:461 msgid "Print terse output" msgstr "" #: ../quodlibet/operon/commands.py:44 ../quodlibet/operon/commands.py:83 #: ../quodlibet/operon/commands.py:463 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "" #: ../quodlibet/operon/commands.py:47 ../quodlibet/operon/commands.py:86 #, fuzzy msgid "Also list programmatic tags" msgstr "Показувати _програмні теги" #: ../quodlibet/operon/commands.py:51 ../quodlibet/operon/commands.py:129 #: ../quodlibet/operon/commands.py:220 ../quodlibet/operon/commands.py:293 #: ../quodlibet/operon/commands.py:336 ../quodlibet/operon/commands.py:340 #: ../quodlibet/operon/commands.py:391 ../quodlibet/operon/commands.py:394 #: ../quodlibet/operon/commands.py:433 ../quodlibet/operon/commands.py:468 #: ../quodlibet/operon/commands.py:508 ../quodlibet/operon/commands.py:543 #: ../quodlibet/operon/commands.py:585 msgid "Not enough arguments" msgstr "" #: ../quodlibet/operon/commands.py:53 ../quodlibet/operon/commands.py:90 #: ../quodlibet/operon/commands.py:131 ../quodlibet/operon/commands.py:222 #: ../quodlibet/operon/commands.py:470 msgid "Too many arguments" msgstr "" #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:92 #: ../quodlibet/operon/commands.py:475 ../quodlibet/qltk/data_editors.py:363 #, fuzzy msgid "Description" msgstr "опис" #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:475 #: ../quodlibet/qltk/edittags.py:454 msgid "Value" msgstr "Значення" #: ../quodlibet/operon/commands.py:76 msgid "List all common tags" msgstr "" #: ../quodlibet/operon/commands.py:118 msgid "Copy tags from one file to another" msgstr "" #: ../quodlibet/operon/commands.py:123 ../quodlibet/operon/commands.py:164 #: ../quodlibet/operon/commands.py:289 ../quodlibet/operon/commands.py:324 #: ../quodlibet/operon/commands.py:384 msgid "Show changes, don't apply them" msgstr "" #: ../quodlibet/operon/commands.py:125 msgid "Skip tags that can't be written" msgstr "" #: ../quodlibet/operon/commands.py:145 #, python-format msgid "Can't copy tag %r to file: %r" 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:304 ../quodlibet/operon/commands.py:444 #: ../quodlibet/operon/commands.py:676 #, python-format msgid "Can not set %r" msgstr "" #: ../quodlibet/operon/commands.py:319 msgid "Remove tags" msgstr "" #: ../quodlibet/operon/commands.py:326 ../quodlibet/operon/commands.py:386 msgid "Value is a regular expression" msgstr "" #: ../quodlibet/operon/commands.py:328 msgid "Remove all tags" msgstr "" #: ../quodlibet/operon/commands.py:332 msgid "Can't combine '--all' with '--regexp'" msgstr "" #: ../quodlibet/operon/commands.py:366 #, python-format msgid "Can't remove %r from %r" msgstr "" #: ../quodlibet/operon/commands.py:379 #, fuzzy msgid "Remove a tag value" msgstr "Фільтрувати за тегом" #: ../quodlibet/operon/commands.py:428 #, fuzzy msgid "Add a tag value" msgstr "Фільтрувати за тегом" #: ../quodlibet/operon/commands.py:456 #, fuzzy msgid "List file information" msgstr "Немає інформації про час" #: ../quodlibet/operon/commands.py:502 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" #: ../quodlibet/operon/commands.py:515 #, fuzzy, python-format msgid "Failed to load image file: %r" msgstr "Не вдалося перейменувати файл" #: ../quodlibet/operon/commands.py:522 ../quodlibet/operon/commands.py:551 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" #: ../quodlibet/operon/commands.py:538 msgid "Remove all embedded images" msgstr "" #: ../quodlibet/operon/commands.py:568 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "" #: ../quodlibet/operon/commands.py:580 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" #: ../quodlibet/operon/commands.py:639 msgid "Rename files based on tags" msgstr "" #: ../quodlibet/operon/commands.py:654 msgid "Fill tags based on the file path" msgstr "" #: ../quodlibet/operon/commands.py:704 ../quodlibet/qltk/information.py:305 #: ../quodlibet/qltk/properties.py:84 ../quodlibet/qltk/renamefiles.py:176 #: ../quodlibet/qltk/tagsfrompath.py:229 ../quodlibet/qltk/tracknumbers.py:79 msgid "File" msgstr "Файл" #: ../quodlibet/operon/commands.py:712 msgid "Fill tracknumbers for all files" msgstr "" #: ../quodlibet/operon/commands.py:731 msgid "Print tags based on the given pattern" msgstr "" #: ../quodlibet/operon/commands.py:768 #, fuzzy msgid "Display help information" msgstr "Вивести коротку інформацію з користування" #: ../quodlibet/operon/util.py:40 #, 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:30 #, fuzzy msgid "_Unknown" msgstr "Невідомо" #: ../quodlibet/order/__init__.py:142 msgid "In Order" msgstr "По порядку" #: ../quodlibet/order/__init__.py:143 msgid "_In Order" msgstr "_По порядку" #: ../quodlibet/order/reorder.py:23 #, fuzzy msgid "Random" msgstr "_Випадково" #: ../quodlibet/order/reorder.py:24 ../quodlibet/qltk/queue.py:119 msgid "_Random" msgstr "_Випадково" #: ../quodlibet/order/reorder.py:39 ../quodlibet/order/reorder.py:40 msgid "Prefer higher rated" msgstr "" #: ../quodlibet/order/repeat.py:43 ../quodlibet/order/repeat.py:44 msgid "Repeat this track" msgstr "" #: ../quodlibet/order/repeat.py:57 ../quodlibet/order/repeat.py:58 #, fuzzy msgid "Repeat all" msgstr "_Повторювати" #: ../quodlibet/order/repeat.py:73 ../quodlibet/order/repeat.py:74 msgid "One Song" msgstr "Одна пісня" #: ../quodlibet/player/gstbe/player.py:98 msgid "Stream" msgstr "" #: ../quodlibet/player/gstbe/player.py:98 msgid "Buffering" msgstr "" #: ../quodlibet/player/gstbe/player.py:319 msgid "Could not create GStreamer pipeline" msgstr "" #: ../quodlibet/player/gstbe/player.py:560 msgid "No GStreamer element found to handle media format" msgstr "" #: ../quodlibet/player/gstbe/player.py:561 #, 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:25 msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. In case the pipeline contains a sink, it will be used instead of " "the default one." msgstr "" #: ../quodlibet/player/gstbe/prefs.py:36 msgid "_Output pipeline:" msgstr "" #: ../quodlibet/player/gstbe/prefs.py:43 #, fuzzy, python-format msgid "%.1f seconds" msgstr "%d секунда" #: ../quodlibet/player/gstbe/prefs.py:57 msgid "_Buffer duration:" msgstr "" #: ../quodlibet/player/gstbe/prefs.py:66 msgid "Disable _gapless playback" msgstr "" #: ../quodlibet/player/gstbe/prefs.py:70 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions." msgstr "" #: ../quodlibet/player/gstbe/util.py:93 #, fuzzy msgid "No GStreamer audio sink found" msgstr "Станцій не знайдено" #: ../quodlibet/player/gstbe/util.py:112 msgid "Invalid GStreamer output pipeline" msgstr "" #: ../quodlibet/player/xinebe/player.py:90 #, fuzzy msgid "Unable to create audio output" msgstr "Не вдалося створити каталог" #: ../quodlibet/player/xinebe/player.py:91 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "" #: ../quodlibet/plugins/__init__.py:62 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" #: ../quodlibet/plugins/__init__.py:71 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "" #: ../quodlibet/plugins/playlist.py:30 #, 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:41 ../quodlibet/qltk/songsmenu.py:46 #: ../quodlibet/qltk/songsmenu.py:74 #, fuzzy msgid "_Run Plugin" msgstr "_Розширення" #: ../quodlibet/qltk/about.py:40 #, python-format msgid "Supported formats: %s" msgstr "Підтримуються формати: %s" #: ../quodlibet/qltk/about.py:43 #, python-format msgid "Audio device: %s" msgstr "Аудіо-пристрій: %s" #. 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:207 ../quodlibet/qltk/information.py:131 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:48 ../quodlibet/qltk/edittags.py:311 msgid "_Value:" msgstr "_Значення:" #: ../quodlibet/qltk/cbes.py:262 msgid "Saved Values" msgstr "Збережені значення" #: ../quodlibet/qltk/cbes.py:263 #, fuzzy msgid "Edit saved values…" msgstr "Редагувати збережені параметри..." #: ../quodlibet/qltk/controls.py:111 msgid "Auto_matic" msgstr "" #: ../quodlibet/qltk/controls.py:112 #, fuzzy msgid "_Track Mode" msgstr "_Трек" #: ../quodlibet/qltk/controls.py:113 #, fuzzy msgid "_Album Mode" msgstr "_Альбом" #. Translators: player state, no action #: ../quodlibet/qltk/controls.py:122 msgid "_Mute" msgstr "" #: ../quodlibet/qltk/controls.py:128 #, fuzzy msgid "_Replay Gain Mode" msgstr "Корегування гучності Replay Gain" #. Translators: New Command/Entry/Item/... #: ../quodlibet/qltk/data_editors.py:119 #, python-format msgid "New %s" msgstr "" #: ../quodlibet/qltk/data_editors.py:218 #, fuzzy msgid "(unknown)" msgstr "Невідомо" #: ../quodlibet/qltk/data_editors.py:355 msgid "Tag expression" msgstr "" #: ../quodlibet/qltk/data_editors.py:382 msgid "Tag expression e.g. people:real or ~album~year." msgstr "" #: ../quodlibet/qltk/data_editors.py:383 #, fuzzy msgid "Enter new tag" 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/downloader.py:38 msgid "Downloads" msgstr "Завантаження" #: ../quodlibet/qltk/downloader.py:62 msgid "Size" msgstr "Розмір" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: ../quodlibet/qltk/downloader.py:94 ../quodlibet/qltk/renamefiles.py:265 #: ../quodlibet/qltk/wlw.py:50 msgid "_Stop" msgstr "" #: ../quodlibet/qltk/edittags.py:63 ../quodlibet/qltk/edittags.py:74 #, 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:67 ../quodlibet/qltk/edittags.py:71 #, 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:193 msgid "Split into _Multiple Values" msgstr "_Розділити на кілька значень" #: ../quodlibet/qltk/edittags.py:211 msgid "Split Disc out of _Album" msgstr "Відділити номер диску від альбому" #: ../quodlibet/qltk/edittags.py:228 msgid "Split _Version out of Title" msgstr "Відділити _версію від назви" #: ../quodlibet/qltk/edittags.py:259 msgid "Split Arranger out of Ar_tist" msgstr "Відділити аранжувальника від _виконавця" #: ../quodlibet/qltk/edittags.py:264 msgid "Split _Performer out of Artist" msgstr "Відділити поле \"виконавець \" від поля \"артист\"" #: ../quodlibet/qltk/edittags.py:270 #, fuzzy msgid "Split _Performer out of Title" msgstr "Відділити поле \"виконавець \" від поля \"артист\"" #: ../quodlibet/qltk/edittags.py:276 #, fuzzy msgid "Split _Originalartist out of Title" msgstr "Відділити _версію від назви" #: ../quodlibet/qltk/edittags.py:283 msgid "Add a Tag" msgstr "Додати тег" #: ../quodlibet/qltk/edittags.py:302 msgid "_Tag:" msgstr "_Тег" #: ../quodlibet/qltk/edittags.py:404 msgid "Edit Tags" msgstr "Редагувати теги" #: ../quodlibet/qltk/edittags.py:477 msgid "Show _programmatic tags" msgstr "Показувати _програмні теги" #: ../quodlibet/qltk/edittags.py:478 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" #. Translators: Revert button in the tag editor #: ../quodlibet/qltk/edittags.py:508 #, fuzzy msgctxt "edittags" msgid "_Revert" msgstr "Ніколи" #. Translators: Save button in the tag editor #: ../quodlibet/qltk/edittags.py:513 msgctxt "edittags" msgid "_Save" msgstr "" #: ../quodlibet/qltk/edittags.py:659 msgid "Unable to add tag" msgstr "Не вдалося додати тег" #: ../quodlibet/qltk/edittags.py:660 #, fuzzy, python-format msgid "Unable to add <b>%s</b>" msgstr "Не вдалося додати пісню" #: ../quodlibet/qltk/edittags.py:662 #, fuzzy, python-format msgid "" "The files currently selected do not support multiple values for <b>%s</b>." msgstr "" "Не вдалося додати <b>%s</b>\n" "\n" "Вибрані файли не підтримують множинні значення." #. Can't add the new tag. #: ../quodlibet/qltk/edittags.py:689 ../quodlibet/qltk/edittags.py:856 #: ../quodlibet/qltk/tagsfrompath.py:212 ../quodlibet/util/__init__.py:554 #: ../quodlibet/util/tags.py:231 msgid "Invalid tag" msgstr "Неправильний тег" #: ../quodlibet/qltk/edittags.py:690 ../quodlibet/qltk/edittags.py:857 #: ../quodlibet/qltk/tagsfrompath.py:213 #, python-format msgid "" "Invalid tag <b>%s</b>\n" "\n" "The files currently selected do not support editing this tag." msgstr "" "Неправильний тег <b>%s</b>\n" "\n" "Вибрані файли не підтримують редагування цього тега." #: ../quodlibet/qltk/edittags.py:828 ../quodlibet/qltk/edittags.py:868 msgid "Invalid value" msgstr "Неправильне значення" #: ../quodlibet/qltk/edittags.py:829 ../quodlibet/qltk/edittags.py:869 #, python-format msgid "" "Invalid value: <b>%(value)s</b>\n" "\n" "%(error)s" msgstr "" "Неправильне значення: <b>%(value)s</b>\n" "\n" "%(error)s" #: ../quodlibet/qltk/_editutils.py:28 msgid "Tag may not be accurate" msgstr "Тег може бути невірним" #: ../quodlibet/qltk/_editutils.py:31 #, 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:47 msgid "Unable to save song" msgstr "Не вдалося зберегти пісню" #: ../quodlibet/qltk/_editutils.py:50 #, 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:142 #, 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:95 #: ../quodlibet/qltk/quodlibetwindow.py:1066 msgid "_About" msgstr "" #: ../quodlibet/qltk/exfalsowindow.py:99 #: ../quodlibet/qltk/quodlibetwindow.py:1088 msgid "_Check for Updates…" msgstr "" #: ../quodlibet/qltk/exfalsowindow.py:105 #: ../quodlibet/qltk/quodlibetwindow.py:1021 ../quodlibet/qltk/songsmenu.py:304 msgid "_Plugins" msgstr "_Розширення" #: ../quodlibet/qltk/exfalsowindow.py:267 #, 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:279 msgid "Ex Falso Preferences" msgstr "Налаштування Ex Falso" #: ../quodlibet/qltk/exfalsowindow.py:289 ../quodlibet/qltk/prefs.py:598 msgid "Split _on:" msgstr "_Розділяти по:" #: ../quodlibet/qltk/exfalsowindow.py:295 ../quodlibet/qltk/prefs.py:613 msgid "Tag Editing" msgstr "Редагування тегів" #: ../quodlibet/qltk/filesel.py:210 msgid "Folders" msgstr "Каталоги" #: ../quodlibet/qltk/filesel.py:253 #, fuzzy msgid "_New Folder…" msgstr "Створення каталогу" #: ../quodlibet/qltk/filesel.py:262 #, fuzzy msgid "_Select all Sub-Folders" msgstr "_Вибрати всі підкаталоги" #: ../quodlibet/qltk/filesel.py:374 msgid "New Folder" msgstr "Створення каталогу" #: ../quodlibet/qltk/filesel.py:374 msgid "Enter a name for the new folder:" msgstr "Введіть назву нового каталоги" #: ../quodlibet/qltk/filesel.py:387 msgid "Unable to create folder" msgstr "Не вдалося створити каталог" #: ../quodlibet/qltk/filesel.py:404 msgid "Unable to delete folder" msgstr "Не вдалося видалити каталог" #: ../quodlibet/qltk/filesel.py:519 ../quodlibet/qltk/pluginwin.py:167 msgid "Songs" msgstr "Пісні" #. Translators: As in "by Artist Name" #: ../quodlibet/qltk/info.py:42 #, python-format msgid "by %s" msgstr "%s" #: ../quodlibet/qltk/info.py:43 ../quodlibet/qltk/information.py:167 #: ../quodlibet/qltk/information.py:448 #, python-format msgid "Disc %s" msgstr "Диск %s" #: ../quodlibet/qltk/info.py:44 ../quodlibet/qltk/information.py:172 #, python-format msgid "Track %s" msgstr "Трек %s" #: ../quodlibet/qltk/info.py:108 #, fuzzy msgid "_Edit Display…" msgstr "Змінити зовнішній вигляд" #: ../quodlibet/qltk/information.py:105 msgid "No songs are selected." msgstr "Не вибрано жодної пісні" #: ../quodlibet/qltk/information.py:106 msgid "No Songs" msgstr "Немає пісень" #: ../quodlibet/qltk/information.py:121 ../quodlibet/qltk/information.py:338 #: ../quodlibet/qltk/information.py:471 ../quodlibet/qltk/information.py:531 msgid "Information" msgstr "Інформація" #: ../quodlibet/qltk/information.py:126 msgid "Lyrics" msgstr "Текст пісні" #: ../quodlibet/qltk/information.py:184 ../quodlibet/qltk/information.py:396 #, python-format msgid "Produced by %s" msgstr "Продюсер: %s" #: ../quodlibet/qltk/information.py:199 ../quodlibet/util/tags.py:76 msgid "artist" msgstr "артист" #: ../quodlibet/qltk/information.py:200 ../quodlibet/qltk/information.py:561 #: ../quodlibet/util/tags.py:76 msgid "artists" msgstr "виконавці" #. for backwards compat #: ../quodlibet/qltk/information.py:221 ../quodlibet/util/tags.py:86 #: ../quodlibet/util/tags.py:114 msgid "performers" msgstr "виконавці" #: ../quodlibet/qltk/information.py:235 ../quodlibet/qltk/information.py:248 #: ../quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "Ніколи" #: ../quodlibet/qltk/information.py:236 #, 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:254 ../quodlibet/util/tags.py:139 msgid "added" msgstr "доданий" #: ../quodlibet/qltk/information.py:255 ../quodlibet/util/tags.py:140 msgid "last played" msgstr "востаннє відтворено" #: ../quodlibet/qltk/information.py:256 ../quodlibet/util/tags.py:150 msgid "plays" msgstr "відтворень" #: ../quodlibet/qltk/information.py:257 ../quodlibet/util/tags.py:151 msgid "skips" msgstr "перервано" #: ../quodlibet/qltk/information.py:258 ../quodlibet/util/tags.py:156 msgid "rating" msgstr "рейтинг" #: ../quodlibet/qltk/information.py:287 msgid "path" msgstr "" #: ../quodlibet/qltk/information.py:288 ../quodlibet/util/tags.py:154 msgid "length" msgstr "тривалість" #: ../quodlibet/qltk/information.py:289 #, fuzzy msgid "format" msgstr "Інформація" #: ../quodlibet/qltk/information.py:290 ../quodlibet/util/tags.py:163 msgid "codec" msgstr "" #: ../quodlibet/qltk/information.py:291 ../quodlibet/util/tags.py:164 #, fuzzy msgid "encoding" msgstr "[Неправильне кодування]" #: ../quodlibet/qltk/information.py:292 ../quodlibet/util/tags.py:160 msgid "bitrate" msgstr "бітрейт" #: ../quodlibet/qltk/information.py:293 ../quodlibet/util/tags.py:161 msgid "file size" msgstr "розмір файлу" #: ../quodlibet/qltk/information.py:294 ../quodlibet/util/tags.py:149 msgid "modified" msgstr "змінено" #: ../quodlibet/qltk/information.py:331 msgid "Additional" msgstr "" #: ../quodlibet/qltk/information.py:383 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d вибрано" msgstr[1] "%d вибрано" msgstr[2] "%d вибрано" #: ../quodlibet/qltk/information.py:458 msgid "Track unavailable" msgstr "Трек недоступний" #: ../quodlibet/qltk/information.py:464 msgid "Track List" msgstr "Список треків" #: ../quodlibet/qltk/information.py:505 ../quodlibet/qltk/information.py:578 #, 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:508 msgid "Selected Discography" msgstr "Вибрані альбоми" #: ../quodlibet/qltk/information.py:558 #, 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:586 ../quodlibet/util/tags.py:74 msgid "albums" msgstr "альбоми" #: ../quodlibet/qltk/information.py:599 msgid "Total length:" msgstr "Загальна тривалість:" #: ../quodlibet/qltk/information.py:603 msgid "Total size:" msgstr "Загальний розмір:" #: ../quodlibet/qltk/information.py:606 msgid "Files" msgstr "Файли" #: ../quodlibet/qltk/lyrics.py:37 msgid "_Download" msgstr "_Завантажити" #: ../quodlibet/qltk/lyrics.py:40 #, fuzzy msgid "_Edit" msgstr "_Змінити зовнішній вигляд..." #. buffer.set_text(_("No lyrics found.\n\nYou can click the " #. "Download button to have Quod Libet search " #. "for lyrics online. You can also enter them " #. "yourself and click save.")) #: ../quodlibet/qltk/lyrics.py:73 ../quodlibet/qltk/lyrics.py:109 msgid "No lyrics found for this song." msgstr "Для цієї пісні текст не знайдено." #: ../quodlibet/qltk/lyrics.py:82 #, fuzzy msgid "Searching for lyrics…" 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/msg.py:41 msgid "Discard tag changes?" msgstr "Скасувати зміни в тегу?" #: ../quodlibet/qltk/msg.py:42 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "" "Теги було змінено, але зміни не були збережені. Зберегти їх чи повернути " "зміни?" #: ../quodlibet/qltk/msg.py:55 ../quodlibet/qltk/prefs.py:595 #: ../quodlibet/qltk/textedit.py:64 ../quodlibet/qltk/tracknumbers.py:117 #, fuzzy msgid "_Revert" msgstr "Ніколи" #: ../quodlibet/qltk/msg.py:86 msgid "File exists" msgstr "Файл існує" #: ../quodlibet/qltk/msg.py:88 #, python-format msgid "Replace %(file-name)s?" msgstr "" #: ../quodlibet/qltk/msg.py:94 #, fuzzy msgid "_Replace File" msgstr "Перейменувати файли" #: ../quodlibet/qltk/notif.py:182 msgid "Active tasks" msgstr "" #: ../quodlibet/qltk/notif.py:188 #, python-format msgid "%d tasks running" msgstr "" #: ../quodlibet/qltk/playorder.py:254 #, fuzzy msgid "Toggle shuffle mode" msgstr "Перемикнути режим програвання/паузи" #: ../quodlibet/qltk/playorder.py:270 #, fuzzy msgid "Toggle repeat mode" msgstr "Перемикнути режим програвання/паузи" #: ../quodlibet/qltk/pluginwin.py:44 msgid "Plugin Errors" msgstr "Помилки розширень" #: ../quodlibet/qltk/pluginwin.py:124 msgid "Enabled" msgstr "" #: ../quodlibet/qltk/pluginwin.py:125 #, fuzzy msgid "Disabled" msgstr "Вимкнути переглядач" #: ../quodlibet/qltk/pluginwin.py:131 msgid "No category" msgstr "" #: ../quodlibet/qltk/pluginwin.py:169 msgid "Events" msgstr "" #: ../quodlibet/qltk/pluginwin.py:170 #, fuzzy msgid "Play Order" msgstr "_Порядок:" #: ../quodlibet/qltk/pluginwin.py:171 #, fuzzy msgid "Editing" msgstr "Редагування тегів" #: ../quodlibet/qltk/pluginwin.py:173 #, fuzzy msgid "Covers" msgstr "Загальний розмір:" #: ../quodlibet/qltk/pluginwin.py:309 msgid "No plugins found." msgstr "Розширень не знайдено" #: ../quodlibet/qltk/pluginwin.py:358 #, fuzzy msgid "Plugins" msgstr "_Розширення" #: ../quodlibet/qltk/pluginwin.py:402 msgid "Show _Errors" msgstr "_Помилки" #: ../quodlibet/qltk/prefs.py:45 msgid "_Disc" msgstr "_Диск" #: ../quodlibet/qltk/prefs.py:46 msgid "_Track" msgstr "_Номер треку" #: ../quodlibet/qltk/prefs.py:47 #, fuzzy msgid "Grou_ping" msgstr "групування" #: ../quodlibet/qltk/prefs.py:50 msgid "Al_bum" msgstr "_Альбом" #: ../quodlibet/qltk/prefs.py:55 msgid "_Filename" msgstr "Назва _файлу" #: ../quodlibet/qltk/prefs.py:57 msgid "_Length" msgstr "_Тривалість" #: ../quodlibet/qltk/prefs.py:64 msgid "_Jump to playing song automatically" msgstr "" "Автоматично переходити _до відтворюваної \n" "пісні" #: ../quodlibet/qltk/prefs.py:66 msgid "When the playing song changes, scroll to it in the song list" msgstr "При зміні пісні переходити до неї в списку програвання" #: ../quodlibet/qltk/prefs.py:82 msgid "_Others:" msgstr "_Інші:" #: ../quodlibet/qltk/prefs.py:88 #, fuzzy msgid "_Edit…" msgstr "_Змінити зовнішній вигляд..." #: ../quodlibet/qltk/prefs.py:91 msgid "Add or remove additional column headers" msgstr "" #: ../quodlibet/qltk/prefs.py:101 msgid "Visible Columns" msgstr "Стовпець" #: ../quodlibet/qltk/prefs.py:104 msgid "Title includes _version" msgstr "Назва включає _версію" #: ../quodlibet/qltk/prefs.py:106 #, fuzzy msgid "Artist includes all _people" msgstr "Назва включає _версію" #: ../quodlibet/qltk/prefs.py:108 #, fuzzy msgid "Album includes _disc subtitle" msgstr "Альбом включає _частину" #: ../quodlibet/qltk/prefs.py:110 msgid "Filename includes _folder" msgstr "Назва файлу включає _каталог" #: ../quodlibet/qltk/prefs.py:123 #, fuzzy msgid "Column Preferences" msgstr "Налаштування" #: ../quodlibet/qltk/prefs.py:129 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "" #: ../quodlibet/qltk/prefs.py:142 ../quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "Список пісень" #: ../quodlibet/qltk/prefs.py:222 #, fuzzy msgid "Edit Columns" msgstr "Стовпець" #: ../quodlibet/qltk/prefs.py:259 msgid "Duration totals" msgstr "" #: ../quodlibet/qltk/prefs.py:271 msgid "_Global filter:" msgstr "_Загальний фільтр" #: ../quodlibet/qltk/prefs.py:277 msgid "Apply this query in addition to all others" msgstr "" #. Translators: The heading of the preference group, no action #: ../quodlibet/qltk/prefs.py:283 #, fuzzy msgctxt "heading" msgid "Search" msgstr "Пошук" #: ../quodlibet/qltk/prefs.py:287 ../quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "Вибір пісень" #: ../quodlibet/qltk/prefs.py:293 msgid "Confirm _multiple ratings" msgstr "" #: ../quodlibet/qltk/prefs.py:295 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "" #: ../quodlibet/qltk/prefs.py:298 msgid "Enable _one-click ratings" msgstr "" #: ../quodlibet/qltk/prefs.py:300 #, fuzzy msgid "Enable rating by clicking on the rating column in the song list" msgstr "При зміні пісні переходити до неї в списку програвання" #: ../quodlibet/qltk/prefs.py:306 ../quodlibet/qltk/prefs.py:616 #, fuzzy msgid "Ratings" msgstr "_Рейтинг" #. Filename choice algorithm config #: ../quodlibet/qltk/prefs.py:312 msgid "Prefer _embedded art" msgstr "" #: ../quodlibet/qltk/prefs.py:314 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" #: ../quodlibet/qltk/prefs.py:319 msgid "_Fixed image filename:" msgstr "" #: ../quodlibet/qltk/prefs.py:321 msgid "The single image filename to use if selected" msgstr "" #: ../quodlibet/qltk/prefs.py:327 msgid "The album art image file to use when forced" msgstr "" #: ../quodlibet/qltk/prefs.py:336 #, fuzzy msgid "Album Art" msgstr "Список альбомів" #: ../quodlibet/qltk/prefs.py:357 #, fuzzy msgid "Playback" msgstr "Призупинити програвання" #: ../quodlibet/qltk/prefs.py:362 msgid "Output Configuration" msgstr "" #: ../quodlibet/qltk/prefs.py:373 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" #: ../quodlibet/qltk/prefs.py:376 #, fuzzy msgid "_Fall-back gain (dB):" msgstr "Приріст гучності (дБ):" #: ../quodlibet/qltk/prefs.py:387 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "" #: ../quodlibet/qltk/prefs.py:390 #, fuzzy msgid "_Pre-amp gain (dB):" msgstr "Приріст гучності (дБ):" #: ../quodlibet/qltk/prefs.py:395 #, fuzzy msgid "_Enable Replay Gain volume adjustment" msgstr "Корегування гучності Replay Gain" #: ../quodlibet/qltk/prefs.py:420 #, fuzzy msgid "Replay Gain Volume Adjustment" msgstr "Корегування гучності Replay Gain" #: ../quodlibet/qltk/prefs.py:450 msgid "_Default rating:" msgstr "" #: ../quodlibet/qltk/prefs.py:493 #, fuzzy msgid "Rating _scale:" msgstr "_Рейтинг" #: ../quodlibet/qltk/prefs.py:542 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:547 msgid "_Bayesian averaging amount:" msgstr "" #: ../quodlibet/qltk/prefs.py:556 #, fuzzy msgid "Save ratings and play _counts" msgstr "Зберігати рейтинги та лічильники програвань" #: ../quodlibet/qltk/prefs.py:560 msgid "_Email:" msgstr "_Електронна пошта:" #: ../quodlibet/qltk/prefs.py:562 msgid "Ratings and play counts will be set for this email address" msgstr "Рейтинги та лічильники програвань будуть прив'язані до цієї адреси" #: ../quodlibet/qltk/prefs.py:577 #, fuzzy msgid "Auto-save tag changes" msgstr "Скасувати зміни в тегу?" #: ../quodlibet/qltk/prefs.py:579 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "" #: ../quodlibet/qltk/prefs.py:587 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:610 #, fuzzy msgid "Tags" msgstr "Редагувати теги" #: ../quodlibet/qltk/prefs.py:631 #, fuzzy msgid "Updating for new ratings" msgstr "_Нова станція" #: ../quodlibet/qltk/prefs.py:641 #, fuzzy msgid "Scan library _on start" msgstr "_Оновити бібліотеку" #: ../quodlibet/qltk/prefs.py:651 ../quodlibet/qltk/quodlibetwindow.py:1100 #, fuzzy msgid "_Scan Library" msgstr "_Пошук бібліотекою" #: ../quodlibet/qltk/prefs.py:653 ../quodlibet/qltk/quodlibetwindow.py:1162 msgid "Check for changes in your library" msgstr "Перевірити наявність змін в бібліотеці" #: ../quodlibet/qltk/prefs.py:658 #, fuzzy msgid "Re_build Library" msgstr "_Перезавантажити бібліотеку" #: ../quodlibet/qltk/prefs.py:661 #, fuzzy msgid "Reload all songs in your library. This can take a long time." msgstr "Перезавантажити всі пісні в бібліотеці (це може зайняти багато часу)" #: ../quodlibet/qltk/prefs.py:671 #, fuzzy msgid "Scan Directories" msgstr "_Сканувати каталоги" #: ../quodlibet/qltk/prefs.py:677 #, fuzzy msgid "Hidden Songs" msgstr "Немає пісень" #: ../quodlibet/qltk/properties.py:158 ../quodlibet/util/collection.py:398 #, 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:162 ../quodlibet/qltk/properties.py:164 msgid "Properties" msgstr "Властивості" #: ../quodlibet/qltk/queue.py:101 msgid "_Queue" msgstr "_Черга" #: ../quodlibet/qltk/queue.py:126 msgid "Stop Once Empty" msgstr "" #: ../quodlibet/qltk/queue.py:130 #, fuzzy msgid "_Clear Queue" msgstr "_Очистити помилки" #: ../quodlibet/qltk/queue.py:242 #, 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:198 msgid "_Browse Library" msgstr "_Переглянути бібліотеку" #: ../quodlibet/qltk/quodlibetwindow.py:395 #, fuzzy msgid "Toggle queue visibility" msgstr "Показати/сховати головне вікно" #: ../quodlibet/qltk/quodlibetwindow.py:516 #, fuzzy msgid "Playback Error" msgstr "Призупинити програвання" #: ../quodlibet/qltk/quodlibetwindow.py:524 #, fuzzy msgid "Set up library directories?" msgstr "Вибір каталогів" #: ../quodlibet/qltk/quodlibetwindow.py:525 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:531 msgid "_Not Now" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:532 msgid "_Set Up" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:956 msgid "Unable to add songs" msgstr "Не вдається додати пісні" #: ../quodlibet/qltk/quodlibetwindow.py:957 #: ../quodlibet/qltk/quodlibetwindow.py:1364 #, fuzzy, python-format msgid "%s uses an unsupported protocol." msgstr "<b>%s</b> використовує протокол, що не підтримується." #: ../quodlibet/qltk/quodlibetwindow.py:980 msgid "_Jump to Playing Song" msgstr "_Перейти до відтворюваної пісні" #: ../quodlibet/qltk/quodlibetwindow.py:986 #, fuzzy msgid "_File" msgstr "Файл" #: ../quodlibet/qltk/quodlibetwindow.py:987 #, fuzzy msgid "_Song" msgstr "Пісні" #: ../quodlibet/qltk/quodlibetwindow.py:988 msgid "_View" msgstr "_Вигляд" #: ../quodlibet/qltk/quodlibetwindow.py:989 #, fuzzy msgid "_Browse" msgstr "Вибір пісень" #: ../quodlibet/qltk/quodlibetwindow.py:990 msgid "_Control" msgstr "_Керування" #: ../quodlibet/qltk/quodlibetwindow.py:991 msgid "_Help" msgstr "_Довідка" #: ../quodlibet/qltk/quodlibetwindow.py:997 #, fuzzy msgid "_Add a Folder…" msgstr "_Додати каталог..." #: ../quodlibet/qltk/quodlibetwindow.py:1002 #, fuzzy msgid "_Add a File…" msgstr "_Додати файл..." #: ../quodlibet/qltk/quodlibetwindow.py:1007 #, fuzzy msgid "_Add a Location…" msgstr "Додати адресу" #: ../quodlibet/qltk/quodlibetwindow.py:1036 #, fuzzy msgid "Edit Bookmarks…" msgstr "_Редагувати закладки..." #: ../quodlibet/qltk/quodlibetwindow.py:1056 #, fuzzy msgid "Stop After This Song" msgstr "Зупинитись після цієї пісні" #: ../quodlibet/qltk/quodlibetwindow.py:1062 msgid "_Keyboard Shortcuts" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:1071 msgid "Online Help" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:1080 #, fuzzy msgid "Search Help" msgstr "Пошук" #: ../quodlibet/qltk/quodlibetwindow.py:1352 msgid "Add a Location" msgstr "Додати адресу" #: ../quodlibet/qltk/quodlibetwindow.py:1353 msgid "Enter the location of an audio file:" msgstr "Введіть адресу аудіо-файлу:" #: ../quodlibet/qltk/quodlibetwindow.py:1358 #: ../quodlibet/qltk/quodlibetwindow.py:1363 msgid "Unable to add location" msgstr "Не вдалося додати адресу" #: ../quodlibet/qltk/quodlibetwindow.py:1359 #, fuzzy, python-format msgid "%s is not a valid location." msgstr "<b>%s</b> не є правильною адресою." #: ../quodlibet/qltk/quodlibetwindow.py:1372 #: ../quodlibet/qltk/quodlibetwindow.py:1381 msgid "Add Music" msgstr "Додати музику" #: ../quodlibet/qltk/quodlibetwindow.py:1372 ../quodlibet/qltk/scanbox.py:99 #, fuzzy msgid "_Add Folders" msgstr "_Додати каталог..." #: ../quodlibet/qltk/quodlibetwindow.py:1379 #, fuzzy msgid "Music Files" msgstr "Музичний програвач" #: ../quodlibet/qltk/quodlibetwindow.py:1381 #, fuzzy msgid "_Add Files" msgstr "_Додати файл..." #: ../quodlibet/qltk/ratingsmenu.py:24 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "" #: ../quodlibet/qltk/ratingsmenu.py:26 msgid "The saved ratings will be removed" msgstr "" #: ../quodlibet/qltk/ratingsmenu.py:27 #, python-format msgid "The rating of all selected songs will be changed to '%s'" msgstr "" #: ../quodlibet/qltk/ratingsmenu.py:57 ../quodlibet/qltk/ratingsmenu.py:111 #, fuzzy msgid "_Remove Rating" msgstr "_Рейтинг" #: ../quodlibet/qltk/ratingsmenu.py:98 #, fuzzy msgid "Change _Rating" msgstr "_Рейтинг" #: ../quodlibet/qltk/renamefiles.py:46 msgid "Replace spaces with _underscores" msgstr "Замінити пробіли на підкреслення" #: ../quodlibet/qltk/renamefiles.py:56 msgid "Strip _Windows-incompatible characters" msgstr "Замінити _Windows-несумісні символи" #: ../quodlibet/qltk/renamefiles.py:74 msgid "Strip _diacritical marks" msgstr "Замінити _діакритичні знаки" #: ../quodlibet/qltk/renamefiles.py:85 msgid "Strip non-_ASCII characters" msgstr "Замінити не-_ASCII символи" #: ../quodlibet/qltk/renamefiles.py:95 msgid "Use only _lowercase characters" msgstr "" #: ../quodlibet/qltk/renamefiles.py:123 msgid "Rename Files" msgstr "Перейменувати файли" #: ../quodlibet/qltk/renamefiles.py:139 ../quodlibet/qltk/tagsfrompath.py:116 #, fuzzy msgid "Path Patterns" msgstr "шаблон" #: ../quodlibet/qltk/renamefiles.py:140 ../quodlibet/qltk/tagsfrompath.py:117 #, fuzzy msgid "Edit saved patterns…" msgstr "Редагувати збережені параметри..." #: ../quodlibet/qltk/renamefiles.py:143 ../quodlibet/qltk/tagsfrompath.py:120 #: ../quodlibet/qltk/tracknumbers.py:58 msgid "_Preview" msgstr "_Попередній перегляд" #: ../quodlibet/qltk/renamefiles.py:190 msgid "New Name" msgstr "Нова назва" #: ../quodlibet/qltk/renamefiles.py:255 msgid "Unable to rename file" msgstr "Не вдалося перейменувати файл" #: ../quodlibet/qltk/renamefiles.py:256 #, fuzzy, python-format msgid "" "Renaming <b>%(old-name)s</b> to <b>%(new-name)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." msgstr "" "Не вдалося перейменувати <b>%s</b> на <b>%s</b>. Можливо, цільовий файл вже " "існує, або ви не маєте прав для створення нового чи видалення старого файлу." #: ../quodlibet/qltk/renamefiles.py:264 #, fuzzy msgid "Ignore _All Errors" msgstr "_Помилки" #: ../quodlibet/qltk/renamefiles.py:267 msgid "_Continue" msgstr "_Продовжити" #: ../quodlibet/qltk/renamefiles.py:296 msgid "Path is not absolute" msgstr "Неабсолютний шлях" #: ../quodlibet/qltk/renamefiles.py:297 #, python-format msgid "" "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 ~/." msgstr "" "Шаблон\n" "\t<b>%s</b>\n" "містить /, але починається не з кореневого каталогу. Для запобігання помилок " "в назвах каталогів, почніть шаблон з кореневого каталогу." #: ../quodlibet/qltk/scanbox.py:47 #, fuzzy msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "" "Пісні, розташовані в цих каталогах (розділені ':'), будуть додані до " "бібліотеки" #: ../quodlibet/qltk/scanbox.py:99 msgid "Select Directories" msgstr "Вибір каталогів" #: ../quodlibet/qltk/searchbar.py:52 #, fuzzy msgid "Saved Searches" msgstr "Збережені значення" #: ../quodlibet/qltk/searchbar.py:53 #, fuzzy msgid "Edit saved searches…" msgstr "Редагувати збережені параметри..." #: ../quodlibet/qltk/searchbar.py:74 msgid "Search your library, using free text or QL queries" msgstr "" #: ../quodlibet/qltk/searchbar.py:129 #, fuzzy msgid "Search after _typing" msgstr "Зупинитись після цієї пісні" #: ../quodlibet/qltk/searchbar.py:132 msgid "Show search results after the user stops typing." msgstr "" #: ../quodlibet/qltk/searchbar.py:187 msgid "_Limit:" msgstr "_Обмеження:" #: ../quodlibet/qltk/searchbar.py:200 msgid "_Weight" 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 ../quodlibet/qltk/shortcuts.py:41 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: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:377 #, python-format msgid "_Filter on %s" msgstr "_Фільтрувати по %s" #: ../quodlibet/qltk/songlist.py:1094 #, fuzzy msgid "All _Headers" msgstr "_Альбом" #: ../quodlibet/qltk/songlist.py:1095 msgid "_Track Headers" msgstr "_Трек" #: ../quodlibet/qltk/songlist.py:1096 msgid "_Album Headers" msgstr "_Альбом" #: ../quodlibet/qltk/songlist.py:1097 msgid "_People Headers" msgstr "_Люди" #: ../quodlibet/qltk/songlist.py:1098 msgid "_Date Headers" msgstr "_Дата" #: ../quodlibet/qltk/songlist.py:1099 msgid "_File Headers" msgstr "_Файл" #: ../quodlibet/qltk/songlist.py:1100 msgid "_Production Headers" msgstr "_Виробництво" #: ../quodlibet/qltk/songlist.py:1115 #, fuzzy msgid "_Customize Headers…" msgstr "_Налаштувати заголовки..." #: ../quodlibet/qltk/songlist.py:1120 msgid "_Expand Column" msgstr "" #: ../quodlibet/qltk/songsmenu.py:36 #, 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:64 #, 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:149 #, fuzzy msgid "Configure Plugins…" msgstr "_Виділяти кольором критерій пошуку" #: ../quodlibet/qltk/songsmenu.py:345 msgid "Add to _Queue" msgstr "Додати до _черги" #: ../quodlibet/qltk/songsmenu.py:368 msgid "_Copy to Device" msgstr "_Копіювати до пристрою" #: ../quodlibet/qltk/songsmenu.py:379 #, fuzzy msgid "_Remove from Library" msgstr "_Вилучити зі cписку програвання" #: ../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:101 msgid "Tags From Path" msgstr "Теги з імен файлів" #: ../quodlibet/qltk/tagsfrompath.py:138 msgid "Tags replace existing ones" msgstr "Теги замінять існуючі" #: ../quodlibet/qltk/tagsfrompath.py:139 msgid "Tags are added to existing ones" msgstr "Теги будуть додані до існуючих" #. Save button #: ../quodlibet/qltk/tagsfrompath.py:153 msgid "Save" msgstr "" #: ../quodlibet/qltk/tagsfrompath.py:195 #, python-format msgid "" "The pattern\n" "\t<b>%s</b>\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" "Шаблон\n" "\t<b>%s</b>\n" "є недопустимим. Можливо, він містить незакриті лапки (< / >) або " "повторений двічі тег." #: ../quodlibet/qltk/tagsfrompath.py:216 msgid "Invalid tags" msgstr "Неправильні теги" #: ../quodlibet/qltk/tagsfrompath.py:217 #, 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" "Вибрані файли не підтримують редагування цих тегів." #: ../quodlibet/qltk/textedit.py:142 #, 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:158 msgid "Edit Display" msgstr "Змінити зовнішній вигляд" #: ../quodlibet/qltk/tracknumbers.py:39 msgid "Track Numbers" msgstr "Номери треків" #: ../quodlibet/qltk/tracknumbers.py:42 msgid "Start fro_m:" msgstr "Починати _з:" #: ../quodlibet/qltk/tracknumbers.py:51 msgid "_Total tracks:" msgstr "_Всього треків:" #: ../quodlibet/qltk/unity.py:52 #, fuzzy msgid "Play/Pause" msgstr "Програвач" #: ../quodlibet/qltk/unity.py:75 #, fuzzy msgid "Previous" msgstr "_Попередній перегляд" #: ../quodlibet/qltk/views.py:923 #, 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:89 #, fuzzy msgid "Checking for Updates" msgstr "Перевірка точок монтування" #: ../quodlibet/update.py:124 #, fuzzy msgid "Connection failed" msgstr "місце запису" #: ../quodlibet/update.py:133 #, python-format msgid "You are already using the newest version %(version)s" msgstr "" #: ../quodlibet/update.py:136 #, 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:420 msgid "Playlists must have a name" msgstr "" #: ../quodlibet/util/collection.py:603 #, python-format msgid "A playlist named %s already exists." msgstr "Список програвання %s вже існує." #: ../quodlibet/util/cover/built_in.py:26 #, fuzzy msgid "Embedded album covers" msgstr "Показувати _обкладинки альбомів" #: ../quodlibet/util/cover/built_in.py:27 msgid "Uses covers embedded into audio files." msgstr "" #: ../quodlibet/util/cover/built_in.py:49 #, fuzzy msgid "Filesystem cover" msgstr "Файлова система" #: ../quodlibet/util/cover/built_in.py:50 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "" #: ../quodlibet/util/__init__.py:93 msgid "Display brief usage information" msgstr "Вивести коротку інформацію з користування" #: ../quodlibet/util/__init__.py:95 msgid "Display version and copyright" msgstr "Вивести версію та інформацію про авторські права" #: ../quodlibet/util/__init__.py:135 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "" #: ../quodlibet/util/__init__.py:137 msgid "[options]" msgstr "[параметри]" #: ../quodlibet/util/__init__.py:182 #, fuzzy, python-format msgid "Option %r not recognized." msgstr "E: Невідомий параметр '%s'" #: ../quodlibet/util/__init__.py:185 #, fuzzy, python-format msgid "Option %r requires an argument." msgstr "E: Параметр '%s' вимагає аргументу." #: ../quodlibet/util/__init__.py:188 #, fuzzy, python-format msgid "%r is not a unique prefix." msgstr "E: '%s' неоднозначний" #: ../quodlibet/util/__init__.py:364 #, python-format msgid "%d kbps" msgstr "%d Кбіт/с" #: ../quodlibet/util/__init__.py:419 #, fuzzy, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%d секунда" msgstr[1] "%d секунди" msgstr[2] "%d секунд" #: ../quodlibet/util/__init__.py:432 msgid "No time information" msgstr "Немає інформації про час" #: ../quodlibet/util/__init__.py:435 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d секунда" msgstr[1] "%d секунди" msgstr[2] "%d секунд" #: ../quodlibet/util/__init__.py:436 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d хвилина" msgstr[1] "%d хвилини" msgstr[2] "%d хвилин" #: ../quodlibet/util/__init__.py:437 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d година" msgstr[1] "%d години" msgstr[2] "%d годин" #: ../quodlibet/util/__init__.py:438 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d день" msgstr[1] "%d дні" msgstr[2] "%d днів" #: ../quodlibet/util/__init__.py:439 #, 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:563 #, 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 msgid "Unable to edit song" msgstr "Не вдалося редагувати пісню" #: ../quodlibet/util/songwrapper.py:113 #, python-format msgid "" "Saving <b>%s</b> 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:34 #: ../quodlibet/util/string/__init__.py:44 msgid "[Invalid Encoding]" msgstr "[Неправильне кодування]" #: ../quodlibet/util/tags.py:74 msgid "album" msgstr "альбом" #: ../quodlibet/util/tags.py:75 msgid "arranger" msgstr "аранжувальник" #: ../quodlibet/util/tags.py:75 msgid "arrangers" msgstr "аранжувальники" #: ../quodlibet/util/tags.py:75 #, fuzzy msgid "arrangement" msgstr "аранжувальник" #: ../quodlibet/util/tags.py:77 msgid "author" msgstr "автор" #: ../quodlibet/util/tags.py:77 msgid "authors" msgstr "автори" #: ../quodlibet/util/tags.py:78 msgid "composer" msgstr "композитор" #: ../quodlibet/util/tags.py:78 msgid "composers" msgstr "композитори" #: ../quodlibet/util/tags.py:78 #, fuzzy msgid "composition" msgstr "композитор" #. Translators: conducting as in conducting a musical performance #: ../quodlibet/util/tags.py:80 msgid "conductor" msgstr "диригент" #: ../quodlibet/util/tags.py:80 msgid "conductors" msgstr "диригенти" #: ../quodlibet/util/tags.py:80 #, fuzzy msgid "conducting" msgstr "диригент" #: ../quodlibet/util/tags.py:81 msgid "contact" msgstr "зв'язок" #: ../quodlibet/util/tags.py:82 msgid "copyright" msgstr "авторське право" #: ../quodlibet/util/tags.py:83 msgid "date" msgstr "дата" #: ../quodlibet/util/tags.py:84 msgid "description" msgstr "опис" #: ../quodlibet/util/tags.py:85 msgid "genre" msgstr "жанр" #: ../quodlibet/util/tags.py:85 #, fuzzy msgid "genres" msgstr "жанр" #: ../quodlibet/util/tags.py:86 msgid "performer" msgstr "виконавець" #: ../quodlibet/util/tags.py:87 msgid "grouping" msgstr "групування" #: ../quodlibet/util/tags.py:88 msgid "language" msgstr "мова" #: ../quodlibet/util/tags.py:89 msgid "license" msgstr "ліцензія" #: ../quodlibet/util/tags.py:90 msgid "location" msgstr "місце запису" #: ../quodlibet/util/tags.py:91 msgid "lyricist" msgstr "автор слів" #: ../quodlibet/util/tags.py:91 msgid "lyricists" msgstr "автори слів" #: ../quodlibet/util/tags.py:91 #, fuzzy msgid "lyrics" msgstr "автор слів" #. Translators: Also e.g. "record label", "publisher" #: ../quodlibet/util/tags.py:93 msgid "organization" msgstr "організація" #: ../quodlibet/util/tags.py:94 msgid "title" msgstr "назва" #: ../quodlibet/util/tags.py:95 msgid "version" msgstr "версія" #: ../quodlibet/util/tags.py:96 msgid "website" msgstr "веб-сайт" #: ../quodlibet/util/tags.py:98 msgid "album artist" msgstr "автор альбому" #: ../quodlibet/util/tags.py:99 msgid "BPM" msgstr "ударів на хвилину" #. Translators: This used to be called "part". #: ../quodlibet/util/tags.py:102 ../quodlibet/util/tags.py:103 msgid "disc subtitle" msgstr "" #: ../quodlibet/util/tags.py:104 ../quodlibet/util/tags.py:141 msgid "disc" msgstr "диск" #: ../quodlibet/util/tags.py:105 ../quodlibet/util/tags.py:143 msgid "track" msgstr "трек" #: ../quodlibet/util/tags.py:106 msgid "label ID" msgstr "ID видавця" #: ../quodlibet/util/tags.py:107 msgid "original release date" msgstr "оригінальна дата випуску" #: ../quodlibet/util/tags.py:108 msgid "original album" msgstr "оригінальний альбом" #: ../quodlibet/util/tags.py:109 msgid "original artist" msgstr "оригінальний виконавець" #: ../quodlibet/util/tags.py:110 msgid "recording date" msgstr "дата запису" #: ../quodlibet/util/tags.py:111 msgid "release country" 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:120 #, fuzzy msgid "MusicBrainz recording ID" msgstr "Ідентифікатор треку MusicBrainz" #: ../quodlibet/util/tags.py:121 #, fuzzy msgid "MusicBrainz release track ID" msgstr "Ідентифікатор треку MusicBrainz" #: ../quodlibet/util/tags.py:122 #, fuzzy msgid "MusicBrainz release ID" msgstr "Ідентифікатор треку MusicBrainz" #: ../quodlibet/util/tags.py:123 #, fuzzy msgid "MusicBrainz artist ID" msgstr "Ідентифікатор виконавця MusicBrainz" #: ../quodlibet/util/tags.py:124 #, fuzzy msgid "MusicBrainz release artist ID" msgstr "Ідентифікатор треку MusicBrainz" #: ../quodlibet/util/tags.py:125 msgid "MusicBrainz TRM ID" msgstr "Ідентифікатор TRM MusicBrainz" #: ../quodlibet/util/tags.py:126 msgid "MusicIP PUID" msgstr "MusicIP PUID" #: ../quodlibet/util/tags.py:127 msgid "MusicBrainz album status" msgstr "Статус альбому MusicBrainz" #: ../quodlibet/util/tags.py:128 msgid "MusicBrainz album type" msgstr "Тип альбому MusicBrainz" #: ../quodlibet/util/tags.py:129 #, fuzzy msgid "MusicBrainz release group ID" msgstr "Ідентифікатор треку MusicBrainz" #. Translators: "gain" means a volume adjustment, not "to acquire". #: ../quodlibet/util/tags.py:132 msgid "track gain" msgstr "підсилення треку" #: ../quodlibet/util/tags.py:133 msgid "track peak" msgstr "пік треку" #. Translators: "gain" means a volume adjustment, not "to acquire". #: ../quodlibet/util/tags.py:135 msgid "album gain" msgstr "підсилення альбому" #: ../quodlibet/util/tags.py:136 msgid "album peak" msgstr "пік альбому" #: ../quodlibet/util/tags.py:137 #, fuzzy msgid "reference loudness" msgstr "Налаштування" #: ../quodlibet/util/tags.py:142 msgid "discs" msgstr "диски" #: ../quodlibet/util/tags.py:144 msgid "tracks" msgstr "треки" #: ../quodlibet/util/tags.py:145 msgid "last started" msgstr "востаннє запущено" #: ../quodlibet/util/tags.py:146 msgid "full name" msgstr "повна назва" #: ../quodlibet/util/tags.py:153 msgid "mount point" msgstr "точка монтування" #: ../quodlibet/util/tags.py:155 msgid "people" msgstr "люди" #: ../quodlibet/util/tags.py:157 msgid "year" msgstr "рік" #: ../quodlibet/util/tags.py:158 #, fuzzy msgid "original release year" msgstr "оригінальна дата випуску" #: ../quodlibet/util/tags.py:159 #, fuzzy msgid "bookmark" msgstr "Закладки" #: ../quodlibet/util/tags.py:162 #, fuzzy msgid "file format" msgstr "формат" #: ../quodlibet/util/tags.py:165 #, fuzzy msgid "playlists" msgstr "Списки програвання" #: ../quodlibet/util/tags.py:166 msgid "channel count" msgstr "" #. Translators: e.g. "artist (sort)" #: ../quodlibet/util/tags.py:256 msgid "sort" msgstr "" #. Translators: e.g. "performer (roles)" #: ../quodlibet/util/tags.py:264 msgid "roles" msgstr "" #, fuzzy #~ msgid "browsers" #~ msgstr "Вибір пісень" #~ msgid "Unable to download lyrics." #~ msgstr "Не вдалося завантажити текст пісні." #~ msgid "Remove all songs from the queue" #~ msgstr "Видалити всі пісні з черги" #~ msgid "Watch this folder for new songs" #~ 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 "Model:" #~ msgstr "Модель:" #~ msgid "Capacity:" #~ msgstr "Ємність:" #~ msgid "Firmware:" #~ msgstr "Мікропрограми:" #, fuzzy #~ msgid "Removing orphaned iPod track" #~ msgstr "W: видалення 'самотнього' треку iPod" #, 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 "_Select" #~ 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 "Choose New Stations" #~ msgstr "Виберіть нові станції" #~ msgid "Add" #~ msgstr "Додати" #, fuzzy #~ msgid "Bitrate" #~ msgstr "бітрейт" #~ msgid "_Stations..." #~ msgstr "_Станції..." #, fuzzy #~ msgid "Quod Libet" #~ msgstr "Вийти з Quod Libet" #~ 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9791858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/po/zh_CN.po�������������������������������������������������������������������������0000644�0001750�0001750�00000502413�00000000000�014462� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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: 2017-05-17 18:58+0200\n" "PO-Revision-Date: 2013-07-20 22:33+0100\n" "Last-Translator: Emfox Zhou <EmfoxZhou@gmail.com>\n" "Language-Team: Emfox Zhou <EmfoxZhou@gmail.com>\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: Poedit 1.5.4\n" #: ../data/exfalso.appdata.xml.in.h:1 ../data/exfalso.desktop.in.h:2 msgid "Edit tags in your audio files" msgstr "编辑您的音频文件里的标签" #: ../data/exfalso.appdata.xml.in.h:2 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/exfalso.appdata.xml.in.h:3 ../data/quodlibet.appdata.xml.in.h:3 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/exfalso.desktop.in.h:1 msgid "Audio tag editor" msgstr "音频标签编辑器" #: ../data/quodlibet.appdata.xml.in.h:1 ../data/quodlibet.desktop.in.h:2 msgid "Listen to, browse, or edit your audio collection" msgstr "听、浏览或者编辑您的音频收藏" #: ../data/quodlibet.appdata.xml.in.h:2 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 "" #: ../data/quodlibet.desktop.in.h:1 msgid "Music Player" msgstr "音乐播放器" #: ../quodlibet/browsers/albums/main.py:168 #: ../quodlibet/browsers/covergrid/main.py:54 #, fuzzy msgid "_Title" msgstr "标题" #: ../quodlibet/browsers/albums/main.py:169 #: ../quodlibet/browsers/covergrid/main.py:55 ../quodlibet/qltk/prefs.py:49 msgid "_Artist" msgstr "歌手(_A)" #: ../quodlibet/browsers/albums/main.py:170 #: ../quodlibet/browsers/covergrid/main.py:56 ../quodlibet/qltk/prefs.py:54 msgid "_Date" msgstr "日期(_D)" #: ../quodlibet/browsers/albums/main.py:171 #: ../quodlibet/browsers/covergrid/main.py:57 ../quodlibet/qltk/prefs.py:53 #, fuzzy msgid "_Genre" msgstr "流派" #: ../quodlibet/browsers/albums/main.py:172 #: ../quodlibet/browsers/covergrid/main.py:58 ../quodlibet/qltk/prefs.py:58 #: ../quodlibet/qltk/ratingsmenu.py:39 msgid "_Rating" msgstr "评分(_R)" #: ../quodlibet/browsers/albums/main.py:178 #: ../quodlibet/browsers/covergrid/main.py:64 #, fuzzy msgid "Sort _by…" msgstr "按日期排序" #: ../quodlibet/browsers/albums/main.py:199 #: ../quodlibet/browsers/covergrid/main.py:85 #: ../quodlibet/browsers/paned/prefs.py:166 #: ../quodlibet/browsers/playlists/main.py:629 #: ../quodlibet/qltk/exfalsowindow.py:109 ../quodlibet/qltk/pluginwin.py:341 #: ../quodlibet/qltk/quodlibetwindow.py:1016 #, fuzzy msgid "_Preferences" msgstr "Ex Falso 首选项" #: ../quodlibet/browsers/albums/main.py:361 msgid "Album List" msgstr "专辑列表" #: ../quodlibet/browsers/albums/main.py:362 msgid "_Album List" msgstr "专辑列表(_A)" #: ../quodlibet/browsers/albums/main.py:472 #: ../quodlibet/browsers/covergrid/main.py:279 #: ../quodlibet/browsers/covergrid/main.py:488 msgid "All Albums" msgstr "所有专辑" #: ../quodlibet/browsers/albums/main.py:473 #: ../quodlibet/browsers/covergrid/main.py:280 #: ../quodlibet/browsers/covergrid/main.py:489 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "" #: ../quodlibet/browsers/albums/main.py:650 #: ../quodlibet/browsers/covergrid/main.py:467 #, fuzzy 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:381 ../quodlibet/util/collection.py:245 #, 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:379 ../quodlibet/util/collection.py:249 #, python-format msgid "%d disc" msgid_plural "%d discs" msgstr[0] "%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 "显示专辑封面(_C)" #: ../quodlibet/browsers/albums/prefs.py:67 msgid "Inline _search includes people" msgstr "" #: ../quodlibet/browsers/albums/prefs.py:71 #: ../quodlibet/browsers/covergrid/prefs.py:120 #, fuzzy msgid "Options" msgstr "[选项]" #: ../quodlibet/browsers/albums/prefs.py:74 #: ../quodlibet/browsers/covergrid/prefs.py:123 msgid "Album Display" msgstr "专辑显示" #: ../quodlibet/browsers/albums/prefs.py:78 #: ../quodlibet/browsers/covergrid/prefs.py:127 #: ../quodlibet/browsers/media.py:39 #: ../quodlibet/browsers/playlists/prefs.py:56 #: ../quodlibet/ext/songsmenu/albumart.py:326 #: ../quodlibet/ext/songsmenu/duplicates.py:350 #: ../quodlibet/ext/songsmenu/filterall.py:48 #: ../quodlibet/qltk/bookmarks.py:101 ../quodlibet/qltk/cbes.py:93 #: ../quodlibet/qltk/data_editors.py:99 ../quodlibet/qltk/data_editors.py:324 #: ../quodlibet/qltk/exfalsowindow.py:297 ../quodlibet/qltk/pluginwin.py:79 #: ../quodlibet/qltk/pluginwin.py:427 ../quodlibet/qltk/prefs.py:707 #: ../quodlibet/qltk/textedit.py:164 ../quodlibet/update.py:148 msgid "_Close" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:55 #: ../quodlibet/browsers/audiofeeds.py:67 #: ../quodlibet/browsers/audiofeeds.py:69 #: ../quodlibet/browsers/audiofeeds.py:159 #: ../quodlibet/browsers/paned/models.py:86 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:46 #: ../quodlibet/formats/_audio.py:495 ../quodlibet/order/__init__.py:27 #: ../quodlibet/qltk/information.py:240 ../quodlibet/qltk/information.py:247 #: ../quodlibet/qltk/information.py:273 ../quodlibet/qltk/wlw.py:70 msgid "Unknown" msgstr "未知" #: ../quodlibet/browsers/audiofeeds.py:246 msgid "New Feed" msgstr "新的源" #: ../quodlibet/browsers/audiofeeds.py:247 msgid "Enter the location of an audio feed:" msgstr "输入音频源的位置:" #: ../quodlibet/browsers/audiofeeds.py:248 #: ../quodlibet/browsers/collection/prefs.py:90 #: ../quodlibet/browsers/iradio.py:341 ../quodlibet/browsers/paned/prefs.py:78 #: ../quodlibet/browsers/playlists/menu.py:96 #: ../quodlibet/browsers/playlists/util.py:52 ../quodlibet/qltk/bookmarks.py:62 #: ../quodlibet/qltk/cbes.py:55 ../quodlibet/qltk/data_editors.py:311 #: ../quodlibet/qltk/edittags.py:288 ../quodlibet/qltk/edittags.py:488 #: ../quodlibet/qltk/quodlibetwindow.py:1354 ../quodlibet/qltk/scanbox.py:61 msgid "_Add" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:265 #, fuzzy msgid "Audio Feeds" msgstr "音频设备:%s" #: ../quodlibet/browsers/audiofeeds.py:266 msgid "_Audio Feeds" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:345 #: ../quodlibet/browsers/audiofeeds.py:350 #, fuzzy msgid "_Download…" msgstr "下载(_D)" #: ../quodlibet/browsers/audiofeeds.py:359 msgid "Download Files" msgstr "下载文件" #. Save button #: ../quodlibet/browsers/audiofeeds.py:359 #: ../quodlibet/browsers/audiofeeds.py:371 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:81 #: ../quodlibet/ext/songsmenu/albumart.py:322 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:355 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:278 #: ../quodlibet/ext/songsmenu/html.py:76 #: ../quodlibet/ext/songsmenu/lastfmsync.py:216 #: ../quodlibet/ext/songsmenu/playlist.py:51 #: ../quodlibet/ext/songsmenu/replaygain.py:365 #: ../quodlibet/ext/songsmenu/tapbpm.py:182 ../quodlibet/qltk/_editutils.py:39 #: ../quodlibet/qltk/lyrics.py:38 ../quodlibet/qltk/msg.py:52 #: ../quodlibet/qltk/renamefiles.py:168 ../quodlibet/qltk/tracknumbers.py:113 msgid "_Save" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:371 msgid "Download File" msgstr "下载文件" #: ../quodlibet/browsers/audiofeeds.py:394 #: ../quodlibet/browsers/playlists/main.py:213 #: ../quodlibet/qltk/data_editors.py:96 msgid "_New" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:454 #: ../quodlibet/browsers/audiofeeds.py:513 msgid "Unable to add feed" msgstr "无法加入源" #: ../quodlibet/browsers/audiofeeds.py:455 #: ../quodlibet/browsers/audiofeeds.py:514 #, python-format msgid "" "%s could not be added. The server may be down, or the location may not be an " "audio feed." msgstr "" #. refresh button #: ../quodlibet/browsers/audiofeeds.py:462 ../quodlibet/browsers/media.py:217 #: ../quodlibet/browsers/media.py:386 ../quodlibet/qltk/filesel.py:259 #: ../quodlibet/qltk/pluginwin.py:413 #, fuzzy msgid "_Refresh" msgstr "刷新库(_F)" #: ../quodlibet/browsers/audiofeeds.py:463 #: ../quodlibet/browsers/playlists/main.py:457 #: ../quodlibet/browsers/playlists/util.py:43 ../quodlibet/qltk/delete.py:143 #: ../quodlibet/qltk/filesel.py:256 ../quodlibet/qltk/lyrics.py:39 #: ../quodlibet/qltk/maskedbox.py:28 ../quodlibet/qltk/songsmenu.py:392 #, fuzzy msgid "_Delete" msgstr "删除文件" #: ../quodlibet/browsers/audiofeeds.py:530 msgid "" "The current audio backend does not support URLs, Audio Feeds browser " "disabled." msgstr "" #: ../quodlibet/browsers/_base.py:147 ../quodlibet/browsers/_base.py:150 msgid "Library Browser" msgstr "库浏览器" #: ../quodlibet/browsers/_base.py:274 ../quodlibet/ext/songsmenu/refresh.py:30 #: ../quodlibet/qltk/exfalsowindow.py:241 ../quodlibet/qltk/information.py:542 #: ../quodlibet/qltk/maskedbox.py:68 ../quodlibet/util/collection.py:527 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "" #: ../quodlibet/browsers/_base.py:402 ../quodlibet/browsers/_base.py:407 #: ../quodlibet/qltk/tagsfrompath.py:194 ../quodlibet/qltk/textedit.py:141 #: ../quodlibet/util/__init__.py:622 msgid "Invalid pattern" msgstr "非法参数" #: ../quodlibet/browsers/collection/main.py:78 msgid "Album Collection" msgstr "" #: ../quodlibet/browsers/collection/main.py:79 msgid "Album _Collection" msgstr "" #: ../quodlibet/browsers/collection/models.py:24 #, fuzzy, python-format msgid "Unknown %s" msgstr "未知" #: ../quodlibet/browsers/collection/models.py:25 #, python-format msgid "Multiple %s Values" msgstr "" #: ../quodlibet/browsers/collection/prefs.py:66 #: ../quodlibet/browsers/paned/prefs.py:51 msgid "_Custom" msgstr "自定义(_C)" #. Remove button #: ../quodlibet/browsers/collection/prefs.py:94 #: ../quodlibet/browsers/paned/prefs.py:82 #: ../quodlibet/browsers/playlists/menu.py:97 #: ../quodlibet/ext/playlist/remove_duplicates.py:60 #: ../quodlibet/qltk/bookmarks.py:97 ../quodlibet/qltk/bookmarks.py:127 #: ../quodlibet/qltk/cbes.py:82 ../quodlibet/qltk/cbes.py:89 #: ../quodlibet/qltk/data_editors.py:81 ../quodlibet/qltk/data_editors.py:94 #: ../quodlibet/qltk/data_editors.py:301 ../quodlibet/qltk/data_editors.py:314 #: ../quodlibet/qltk/data_editors.py:322 ../quodlibet/qltk/edittags.py:494 #: ../quodlibet/qltk/edittags.py:634 ../quodlibet/qltk/maskedbox.py:48 #: ../quodlibet/qltk/maskedbox.py:88 ../quodlibet/qltk/queue.py:350 #: ../quodlibet/qltk/scanbox.py:36 ../quodlibet/qltk/scanbox.py:63 #, fuzzy msgid "_Remove" msgstr "删除站点(_R)" #: ../quodlibet/browsers/collection/prefs.py:122 #: ../quodlibet/ext/songsmenu/filterall.py:34 #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:92 #: ../quodlibet/qltk/edittags.py:431 msgid "Tag" msgstr "标签" #: ../quodlibet/browsers/collection/prefs.py:128 msgid "Merge" msgstr "" #: ../quodlibet/browsers/collection/prefs.py:188 #, fuzzy msgid "Album Collection Preferences" msgstr "专辑列表首选项" #: ../quodlibet/browsers/collection/prefs.py:195 #: ../quodlibet/browsers/paned/prefs.py:209 #: ../quodlibet/ext/songsmenu/editplaycount.py:45 #: ../quodlibet/ext/songsmenu/exact_rating.py:38 #: ../quodlibet/player/gstbe/prefs.py:40 ../quodlibet/qltk/prefs.py:127 #: ../quodlibet/qltk/textedit.py:65 msgid "_Apply" msgstr "" #: ../quodlibet/browsers/collection/prefs.py:198 #: ../quodlibet/browsers/paned/prefs.py:213 #: ../quodlibet/browsers/playlists/menu.py:95 #: ../quodlibet/browsers/playlists/util.py:42 #: ../quodlibet/errorreport/ui.py:108 #: ../quodlibet/ext/playlist/export_to_folder.py:37 #: ../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:44 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:281 #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:88 #: ../quodlibet/ext/songsmenu/importexport.py:35 #: ../quodlibet/ext/songsmenu/lastfmsync.py:215 #: ../quodlibet/ext/songsmenu/playlist.py:50 #: ../quodlibet/ext/songsmenu/replaygain.py:364 #: ../quodlibet/ext/songsmenu/tapbpm.py:181 ../quodlibet/plugins/playlist.py:39 #: ../quodlibet/qltk/chooser.py:184 ../quodlibet/qltk/chooser.py:205 #: ../quodlibet/qltk/chooser.py:229 ../quodlibet/qltk/chooser.py:253 #: ../quodlibet/qltk/delete.py:90 ../quodlibet/qltk/delete.py:133 #: ../quodlibet/qltk/edittags.py:287 ../quodlibet/qltk/_editutils.py:38 #: ../quodlibet/qltk/getstring.py:28 ../quodlibet/qltk/maskedbox.py:27 #: ../quodlibet/qltk/msg.py:54 ../quodlibet/qltk/msg.py:93 #: ../quodlibet/qltk/ratingsmenu.py:33 ../quodlibet/qltk/songsmenu.py:45 #: ../quodlibet/qltk/songsmenu.py:73 ../quodlibet/update.py:94 msgid "_Cancel" msgstr "" #: ../quodlibet/browsers/covergrid/main.py:125 #, fuzzy msgid "Cover Grid" msgstr "总大小:" #: ../quodlibet/browsers/covergrid/main.py:126 #, fuzzy msgid "_Cover Grid" msgstr "总大小:" #: ../quodlibet/browsers/covergrid/prefs.py:54 #, fuzzy msgid "Cover Grid Preferences" msgstr "Ex Falso 首选项" #: ../quodlibet/browsers/covergrid/prefs.py:64 #, fuzzy msgid "Show album _text" msgstr "显示专辑封面(_C)" #: ../quodlibet/browsers/covergrid/prefs.py:71 #, fuzzy msgid "Show \"All Albums\" Item" msgstr "所有专辑" #: ../quodlibet/browsers/covergrid/prefs.py:78 msgid "Vertical Split" msgstr "" #: ../quodlibet/browsers/covergrid/prefs.py:110 #: ../quodlibet/browsers/covergrid/prefs.py:111 #, fuzzy msgid "Cover Magnification" msgstr "没有新的站点" #: ../quodlibet/browsers/filesystem.py:40 msgid "File System" msgstr "文件系统" #: ../quodlibet/browsers/filesystem.py:41 msgid "_File System" msgstr "文件系统(_F)" #: ../quodlibet/browsers/filesystem.py:113 ../quodlibet/browsers/media.py:491 #: ../quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "无法复制曲目" #: ../quodlibet/browsers/filesystem.py:114 ../quodlibet/qltk/songlist.py:268 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "被选定的文件无法被复制到其它曲目列表或队列。" #: ../quodlibet/browsers/filesystem.py:189 msgid "_Add to Library" msgstr "加入到库(_A)" #: ../quodlibet/browsers/iradio.py:178 msgid "Unsupported file type" msgstr "不支持的文件类型" #: ../quodlibet/browsers/iradio.py:179 #, 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:219 ../quodlibet/browsers/iradio.py:232 #: ../quodlibet/browsers/iradio.py:810 msgid "Unable to add station" msgstr "无法加入站点" #: ../quodlibet/browsers/iradio.py:243 ../quodlibet/browsers/iradio.py:471 msgid "Internet Radio" msgstr "网上广播" #: ../quodlibet/browsers/iradio.py:243 #, fuzzy msgid "Downloading station list" msgstr "下载文件" #: ../quodlibet/browsers/iradio.py:339 msgid "New Station" msgstr "新站点" #: ../quodlibet/browsers/iradio.py:340 msgid "Enter the location of an Internet radio station:" msgstr "输入网上广播站点的位置:" #: ../quodlibet/browsers/iradio.py:358 msgid "Electronic" msgstr "" #: ../quodlibet/browsers/iradio.py:361 msgid "Hip Hop / Rap" msgstr "" #: ../quodlibet/browsers/iradio.py:362 msgid "Oldies" msgstr "" #: ../quodlibet/browsers/iradio.py:363 msgid "R&B" msgstr "" #: ../quodlibet/browsers/iradio.py:364 msgid "Japanese" msgstr "" #: ../quodlibet/browsers/iradio.py:365 msgid "Indian" msgstr "" #: ../quodlibet/browsers/iradio.py:367 msgid "Religious" msgstr "" #: ../quodlibet/browsers/iradio.py:369 msgid "Charts" msgstr "" #: ../quodlibet/browsers/iradio.py:370 msgid "Turkish" msgstr "" #: ../quodlibet/browsers/iradio.py:371 msgid "Reggae / Dancehall" msgstr "" #: ../quodlibet/browsers/iradio.py:372 #, fuzzy msgid "Latin" msgstr "评分" #: ../quodlibet/browsers/iradio.py:373 msgid "College Radio" msgstr "" #: ../quodlibet/browsers/iradio.py:374 msgid "Talk / News" msgstr "" #: ../quodlibet/browsers/iradio.py:375 msgid "Ambient" msgstr "" #: ../quodlibet/browsers/iradio.py:376 msgid "Jazz" msgstr "" #: ../quodlibet/browsers/iradio.py:377 ../quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "" #: ../quodlibet/browsers/iradio.py:378 ../quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "" #: ../quodlibet/browsers/iradio.py:379 msgid "Alternative" msgstr "" #: ../quodlibet/browsers/iradio.py:380 msgid "Metal" msgstr "" #: ../quodlibet/browsers/iradio.py:381 msgid "Country" msgstr "" #: ../quodlibet/browsers/iradio.py:382 msgid "News" msgstr "" #: ../quodlibet/browsers/iradio.py:383 msgid "Schlager" msgstr "" #: ../quodlibet/browsers/iradio.py:384 msgid "Funk" msgstr "" #: ../quodlibet/browsers/iradio.py:385 msgid "Indie" msgstr "" #: ../quodlibet/browsers/iradio.py:386 msgid "Blues" msgstr "" #: ../quodlibet/browsers/iradio.py:387 msgid "Soul" msgstr "" #: ../quodlibet/browsers/iradio.py:388 msgid "Lounge" msgstr "" #: ../quodlibet/browsers/iradio.py:389 msgid "Punk" msgstr "" #: ../quodlibet/browsers/iradio.py:390 msgid "Reggaeton" msgstr "" #: ../quodlibet/browsers/iradio.py:392 msgid "Slavic" msgstr "" #: ../quodlibet/browsers/iradio.py:394 msgid "Greek" msgstr "" #: ../quodlibet/browsers/iradio.py:395 msgid "Gothic" msgstr "" #: ../quodlibet/browsers/iradio.py:396 ../quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "" #: ../quodlibet/browsers/iradio.py:449 msgid "Would you like to load a list of popular radio stations?" msgstr "" #: ../quodlibet/browsers/iradio.py:455 #, fuzzy msgid "_Load Stations" msgstr "新站点(_N)" #: ../quodlibet/browsers/iradio.py:472 msgid "_Internet Radio" msgstr "网上广播(_I)" #: ../quodlibet/browsers/iradio.py:538 #, fuzzy msgid "_New Station…" msgstr "新站点" #: ../quodlibet/browsers/iradio.py:541 #, fuzzy msgid "_Update Stations" msgstr "新站点(_N)" #: ../quodlibet/browsers/iradio.py:568 #, fuzzy msgid "All Stations" msgstr "新站点" #. TODO: support for ~#rating=!None etc (#1940) #: ../quodlibet/browsers/iradio.py:572 #: ../quodlibet/browsers/soundcloud/main.py:64 msgid "Favorites" msgstr "" #: ../quodlibet/browsers/iradio.py:580 msgid "No Category" msgstr "" #: ../quodlibet/browsers/iradio.py:802 msgid "No stations found" msgstr "没有发现站点" #: ../quodlibet/browsers/iradio.py:803 #, python-format msgid "No Internet radio stations were found at %s." msgstr "没有发现网上广播站点 %s" #: ../quodlibet/browsers/iradio.py:811 msgid "All stations listed are already in your library." msgstr "所有列出的站点都已经在您的库里。" #: ../quodlibet/browsers/iradio.py:828 #, fuzzy msgid "Add to Favorites" msgstr "加入到播放列表(_A)" #: ../quodlibet/browsers/iradio.py:832 #, fuzzy msgid "Remove from Favorites" msgstr "从播放列表里删除(_R)" #: ../quodlibet/browsers/iradio.py:932 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "" #: ../quodlibet/browsers/media.py:36 #, fuzzy msgid "Device Properties" msgstr "属性" #: ../quodlibet/browsers/media.py:52 msgid "Device:" msgstr "" #: ../quodlibet/browsers/media.py:54 msgid "Not mounted" msgstr "" #: ../quodlibet/browsers/media.py:55 #, fuzzy msgid "Mount point:" msgstr "挂载点" #: ../quodlibet/browsers/media.py:61 ../quodlibet/qltk/cbes.py:40 msgid "_Name:" msgstr "名字(_N):" #: ../quodlibet/browsers/media.py:135 #, fuzzy msgid "Media Devices" msgstr "音频设备:%s" #: ../quodlibet/browsers/media.py:136 #, fuzzy msgid "_Media Devices" msgstr "音频设备:%s" #. eject button #: ../quodlibet/browsers/media.py:224 ../quodlibet/browsers/media.py:378 #, fuzzy msgid "_Eject" msgstr "选择(_S)" #: ../quodlibet/browsers/media.py:360 #, fuzzy msgid "_Properties" msgstr "属性" #: ../quodlibet/browsers/media.py:365 #: ../quodlibet/browsers/playlists/main.py:464 msgid "_Rename" msgstr "重命名(_R)" #: ../quodlibet/browsers/media.py:461 #, python-format msgid "%(used-size)s used, %(free-size)s available" msgstr "" #: ../quodlibet/browsers/media.py:479 #, fuzzy, python-format msgid "%s is not connected." msgstr "<b>%s</b> 不是合法的位置。" #: ../quodlibet/browsers/media.py:499 #, fuzzy, python-format msgid "Copying %(song)s" msgstr "删除 <b>%s</b> 失败。" #: ../quodlibet/browsers/media.py:513 ../quodlibet/browsers/media.py:529 #, fuzzy msgid "Unable to copy song" msgstr "无法复制曲目" #: ../quodlibet/browsers/media.py:514 msgid "There is not enough free space for this song." msgstr "" #: ../quodlibet/browsers/media.py:526 #, fuzzy, python-format msgid "%s could not be copied." msgstr "<b>%s</b> 不是合法的位置。" #: ../quodlibet/browsers/media.py:545 #, fuzzy msgid "Unable to delete songs" msgstr "无法添加曲目信息" #: ../quodlibet/browsers/media.py:557 #, fuzzy, python-format msgid "Deleting %(song)s" msgstr "删除 <b>%s</b> 失败。" #: ../quodlibet/browsers/media.py:575 #, fuzzy, python-format msgid "%s could not be deleted." msgstr "<b>%s</b> 不是合法的位置。" #: ../quodlibet/browsers/media.py:579 #, fuzzy msgid "Unable to delete song" msgstr "无法编辑曲目" #: ../quodlibet/browsers/media.py:594 #, fuzzy, python-format msgid "Ejecting %s failed." msgstr "删除 <b>%s</b> 失败。" #: ../quodlibet/browsers/media.py:597 #, fuzzy msgid "Unable to eject device" msgstr "无法删除文件" #: ../quodlibet/browsers/media.py:603 msgid "No device backend, Media Devices browser disabled." msgstr "" #: ../quodlibet/browsers/paned/main.py:40 ../quodlibet/qltk/shortcuts.py:44 #, fuzzy msgid "Paned Browser" msgstr "关掉浏览器" #: ../quodlibet/browsers/paned/main.py:41 msgid "_Paned Browser" msgstr "" #: ../quodlibet/browsers/paned/main.py:90 msgid "Select _All" msgstr "全选(_A)" #: ../quodlibet/browsers/paned/models.py:104 ../quodlibet/qltk/pluginwin.py:122 #: ../quodlibet/qltk/pluginwin.py:164 msgid "All" msgstr "所有" #: ../quodlibet/browsers/paned/prefs.py:67 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "<tt>%s</tt>" msgstr "" #: ../quodlibet/browsers/paned/prefs.py:162 msgid "_Wide Mode" msgstr "" #: ../quodlibet/browsers/paned/prefs.py:197 msgid "Paned Browser Preferences" msgstr "" #: ../quodlibet/browsers/paned/prefs.py:204 msgid "Equal pane width" msgstr "" #: ../quodlibet/browsers/playlists/main.py:48 #: ../quodlibet/browsers/playlists/main.py:575 #: ../quodlibet/qltk/pluginwin.py:168 msgid "Playlists" msgstr "播放列表" #: ../quodlibet/browsers/playlists/main.py:49 msgid "_Playlists" msgstr "播放列表(_P)" #: ../quodlibet/browsers/playlists/main.py:152 msgid "_Remove from Playlist" msgstr "从播放列表里删除(_R)" #: ../quodlibet/browsers/playlists/main.py:215 #: ../quodlibet/browsers/playlists/main.py:576 msgid "_Import" msgstr "导入(_I)" #: ../quodlibet/browsers/playlists/main.py:391 #: ../quodlibet/browsers/playlists/util.py:50 #: ../quodlibet/util/collection.py:570 msgid "New Playlist" msgstr "新播放列表" #: ../quodlibet/browsers/playlists/main.py:413 msgid "Unable to import playlist" msgstr "无法导入播放列表" #: ../quodlibet/browsers/playlists/main.py:414 msgid "Quod Libet can only import playlists in the M3U and PLS formats." msgstr "Quod Libet 只能导入 M3U 或者 PLS 格式的播放列表" #: ../quodlibet/browsers/playlists/main.py:565 msgid "Unable to rename playlist" msgstr "无法重命名播放列表" #: ../quodlibet/browsers/playlists/main.py:576 msgid "Import Playlist" msgstr "导入播放列表" #: ../quodlibet/browsers/playlists/menu.py:25 #, fuzzy msgid "_New Playlist…" msgstr "新播放列表(_N)" #: ../quodlibet/browsers/playlists/menu.py:86 #, 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:90 #, 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 "Ex Falso 首选项" #: ../quodlibet/browsers/playlists/prefs.py:52 #, fuzzy msgid "Playlist display" msgstr "播放列表" #: ../quodlibet/browsers/playlists/util.py:33 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "" #: ../quodlibet/browsers/playlists/util.py:35 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" #: ../quodlibet/browsers/playlists/util.py:51 #, fuzzy msgid "Enter a name for the new playlist:" msgstr "输入新文件夹的名字:" #: ../quodlibet/browsers/playlists/util.py:102 #, fuzzy, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" "正在导入播放列表。\n" "\n" "已经添加 %d/%d 首曲目。" #: ../quodlibet/browsers/search.py:33 msgid "_Limit Results" msgstr "限制结果(_L)" #: ../quodlibet/browsers/search.py:48 msgid "Search Library" msgstr "搜索库" #: ../quodlibet/browsers/search.py:49 msgid "_Search Library" msgstr "搜索库(_S)" #: ../quodlibet/browsers/soundcloud/main.py:38 #, fuzzy msgid "Soundcloud Browser" msgstr "关掉浏览器" #: ../quodlibet/browsers/soundcloud/main.py:39 msgid "Sound_cloud" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:59 #: ../quodlibet/qltk/searchbar.py:73 msgid "Search" msgstr "搜索" #: ../quodlibet/browsers/soundcloud/main.py:136 #, python-format msgid "Go to %s" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:380 #, fuzzy msgid "Connected" msgstr "位置" #: ../quodlibet/browsers/soundcloud/main.py:381 #, python-format msgid "Quod Libet is now connected, <b>%s</b>!" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:393 #, python-format msgid "Log out of %s" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:395 msgid "Enter code…" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:396 #, python-format msgid "Log in to %s" msgstr "" #: ../quodlibet/browsers/soundcloud/util.py:86 msgid "Soundcloud authorisation" msgstr "" #: ../quodlibet/browsers/soundcloud/util.py:87 msgid "Enter Soundcloud auth code:" msgstr "" #: ../quodlibet/cli.py:50 #, fuzzy msgid "Quod Libet is not running (add '--run' to start it)" msgstr "Quod Libet 没有在运行。" #: ../quodlibet/cli.py:85 msgid "a music library and player" msgstr "音乐库和播放器" #: ../quodlibet/cli.py:86 #, fuzzy msgid "[option]" msgstr "[选项]" #: ../quodlibet/cli.py:88 msgid "Print the playing song and exit" msgstr "显示正在播放的曲目并退出" #: ../quodlibet/cli.py:89 msgid "Begin playing immediately" msgstr "立即开始播放" #: ../quodlibet/cli.py:90 msgid "Don't show any windows on start" msgstr "" #: ../quodlibet/cli.py:93 msgid "Jump to next song" msgstr "跳到下一首曲目" #: ../quodlibet/cli.py:95 msgid "Jump to previous song or restart if near the beginning" msgstr "" #: ../quodlibet/cli.py:96 msgid "Jump to previous song" msgstr "跳到前一首曲目" #: ../quodlibet/cli.py:97 msgid "Start playback" msgstr "开放回放" #: ../quodlibet/cli.py:98 msgid "Pause playback" msgstr "暂停回放" #: ../quodlibet/cli.py:99 msgid "Toggle play/pause mode" msgstr "切换播放/暂停模式" #: ../quodlibet/cli.py:100 #, fuzzy msgid "Stop playback" msgstr "开放回放" #: ../quodlibet/cli.py:101 msgid "Turn up volume" msgstr "加大音量" #: ../quodlibet/cli.py:102 msgid "Turn down volume" msgstr "减小音量" #: ../quodlibet/cli.py:103 msgid "Print player status" msgstr "显示播放器状态" #: ../quodlibet/cli.py:104 msgid "Hide main window" msgstr "隐藏主窗口" #: ../quodlibet/cli.py:105 msgid "Show main window" msgstr "显示主窗口" #: ../quodlibet/cli.py:106 msgid "Toggle main window visibility" msgstr "切换主窗口可见性" #: ../quodlibet/cli.py:107 msgid "Focus the running player" msgstr "焦点移到运行中的播放器" #: ../quodlibet/cli.py:108 msgid "Remove active browser filters" msgstr "" #: ../quodlibet/cli.py:109 #, fuzzy msgid "Refresh and rescan library" msgstr "刷新库(_F)" #: ../quodlibet/cli.py:110 #, fuzzy msgid "List available browsers" msgstr "关掉浏览器" #: ../quodlibet/cli.py:111 msgid "Print the current playlist" msgstr "显示当前播放列表" #: ../quodlibet/cli.py:112 msgid "Print the contents of the queue" msgstr "显示队列内容" #: ../quodlibet/cli.py:113 #, fuzzy msgid "Print the active text query" msgstr "显示队列内容" #: ../quodlibet/cli.py:114 msgid "Start without plugins" msgstr "" #: ../quodlibet/cli.py:115 #, fuzzy msgid "Start Quod Libet if it isn't running" msgstr "Quod Libet 没有在运行。" #: ../quodlibet/cli.py:116 msgid "Exit Quod Libet" msgstr "退出 Quod Libet" #: ../quodlibet/cli.py:121 msgid "Seek within the playing song" msgstr "在正在播放的曲目中定位" #: ../quodlibet/cli.py:121 msgid "[+|-][HH:]MM:SS" msgstr "" #: ../quodlibet/cli.py:122 #, fuzzy msgid "Set or toggle shuffle mode" msgstr "切换播放/暂停模式" #: ../quodlibet/cli.py:123 msgid "Turn repeat off, on, or toggle it" msgstr "开、关或切换重复播放" #: ../quodlibet/cli.py:124 msgid "Set the volume" msgstr "设定音量" #: ../quodlibet/cli.py:125 msgid "Search your audio library" msgstr "搜索您的音频库" #: ../quodlibet/cli.py:125 ../quodlibet/cli.py:137 ../quodlibet/cli.py:141 #: ../quodlibet/cli.py:143 msgid "query" msgstr "查询" #: ../quodlibet/cli.py:126 msgid "Play a file" msgstr "播放文件" #: ../quodlibet/cli.py:126 ../quodlibet/cli.py:137 ../quodlibet/cli.py:143 #, fuzzy msgctxt "command" msgid "filename" msgstr "文件名" #: ../quodlibet/cli.py:127 msgid "Rate the playing song" msgstr "评估正在播放的曲目" #: ../quodlibet/cli.py:128 msgid "Set the current browser" msgstr "设定当前浏览器" #: ../quodlibet/cli.py:129 #, fuzzy msgid "Stop after the playing song" msgstr "评估正在播放的曲目" #: ../quodlibet/cli.py:130 msgid "Open a new browser" msgstr "打开新的浏览器" #: ../quodlibet/cli.py:131 msgid "Show or hide the queue" msgstr "显示或隐藏队列" #: ../quodlibet/cli.py:133 #, fuzzy msgid "Show or hide the main song list (deprecated)" msgstr "显示或隐藏主曲目列表" #: ../quodlibet/cli.py:134 msgid "Filter on a random value" msgstr "以随机值过滤" #: ../quodlibet/cli.py:134 #, fuzzy msgctxt "command" msgid "tag" msgstr "标签" #: ../quodlibet/cli.py:135 msgid "Filter on a tag value" msgstr "以标签值过滤" #: ../quodlibet/cli.py:135 msgid "tag=value" msgstr "" #: ../quodlibet/cli.py:136 msgid "Enqueue a file or query" msgstr "" #: ../quodlibet/cli.py:138 msgid "Enqueue comma-separated files" msgstr "" #: ../quodlibet/cli.py:139 ../quodlibet/util/tags.py:147 msgid "filename" msgstr "文件名" #: ../quodlibet/cli.py:140 msgid "Print filenames of results of query to stdout" msgstr "" #: ../quodlibet/cli.py:142 msgid "Unqueue a file or query" msgstr "" #: ../quodlibet/cli.py:203 #, fuzzy, python-format msgid "Invalid argument for '%s'." msgstr "错误:%s 的非法参数。" #: ../quodlibet/cli.py:204 ../quodlibet/util/__init__.py:190 #, fuzzy, python-format msgid "Try %s --help." msgstr "错误:试试 %s --help。" #: ../quodlibet/devices/_base.py:65 #, fuzzy msgid "Unknown Device" msgstr "未知" #: ../quodlibet/devices/__init__.py:32 #, python-format msgid "Could not import %s, which is needed for device support." msgstr "" #: ../quodlibet/devices/__init__.py:153 #, python-format msgid "%r is not a supported device." msgstr "" #: ../quodlibet/devices/__init__.py:245 ../quodlibet/devices/__init__.py:251 #, python-format msgid "Could not find '%s'." msgstr "" #: ../quodlibet/devices/__init__.py:450 #, fuzzy msgid "Initializing device backend." msgstr "非法的值" #: ../quodlibet/devices/__init__.py:451 #, python-format msgid "Trying '%s'" msgstr "" #: ../quodlibet/devices/__init__.py:461 msgid "Couldn't connect to a device backend." msgstr "" #: ../quodlibet/devices/__init__.py:463 msgid "Device backend initialized." msgstr "" #: ../quodlibet/devices/storage.py:57 #, fuzzy msgid "_Filename pattern:" msgstr "文件名(_F)" #: ../quodlibet/devices/storage.py:61 #, fuzzy msgid "Copy _album covers" msgstr "显示专辑封面(_C)" #: ../quodlibet/devices/storage.py:65 msgid "_Remove unused covers and directories" msgstr "" #: ../quodlibet/errorreport/ui.py:60 msgid "An Error Occurred" msgstr "" #: ../quodlibet/errorreport/ui.py:62 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:72 msgid "File Bug Report" msgstr "" #: ../quodlibet/errorreport/ui.py:74 ../quodlibet/errorreport/ui.py:90 msgid "Submit Error Report" msgstr "" #: ../quodlibet/errorreport/ui.py:75 msgid "Quit Program" msgstr "" #: ../quodlibet/errorreport/ui.py:76 #, fuzzy msgid "Ignore Error" msgstr "显示错误(_E)" #: ../quodlibet/errorreport/ui.py:80 msgid "Error details:" msgstr "" #: ../quodlibet/errorreport/ui.py:92 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:100 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "" #: ../quodlibet/errorreport/ui.py:109 msgid "_Send" msgstr "" #: ../quodlibet/errorreport/ui.py:115 #, fuzzy msgid "Short description…" msgstr "描述" #: ../quodlibet/errorreport/ui.py:118 msgid "Data to be sent:" msgstr "" #: ../quodlibet/exfalso.py:34 msgid "an audio tag editor" msgstr "音频标签编辑器" #: ../quodlibet/exfalso.py:34 ../quodlibet/util/tags.py:148 msgid "directory" msgstr "目录" #: ../quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "" #: ../quodlibet/ext/covers/artwork_url.py:20 msgid "" "Downloads covers linked to by the artwork_url tag.This works with the " "Soundcloud browser." msgstr "" #: ../quodlibet/ext/covers/discogs.py:25 #, fuzzy msgid "Discogs Cover Source" msgstr "MusicBrainz 音轨 ID" #: ../quodlibet/ext/covers/discogs.py:26 msgid "Downloads covers from Discogs." msgstr "" #: ../quodlibet/ext/covers/lastfm.py:22 msgid "Last.fm Cover Source" msgstr "" #: ../quodlibet/ext/covers/lastfm.py:23 msgid "Downloads covers from Last.fm's cover art archive." msgstr "" #: ../quodlibet/ext/covers/musicbrainz.py:19 #, fuzzy msgid "MusicBrainz Cover Source" msgstr "MusicBrainz 音轨 ID" #: ../quodlibet/ext/covers/musicbrainz.py:20 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:25 msgid "Kana/Kanji Simple Inverter" msgstr "" #: ../quodlibet/ext/editing/kakasi.py:26 msgid "Converts kana/kanji to romaji before renaming." msgstr "" #: ../quodlibet/ext/editing/kakasi.py:35 msgid "Romanize _Japanese text" msgstr "" #: ../quodlibet/ext/editing/kakasi.py:63 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:19 msgid "" "Allows arbitrary regex substitutions (s///) 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 "标题大小写标签(_T)" #: ../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:69 #, fuzzy msgid "Advanced Preferences" msgstr "Ex Falso 首选项" #: ../quodlibet/ext/events/advanced_preferences.py:70 msgid "Allow editing of advanced config settings." msgstr "" #: ../quodlibet/ext/events/advanced_preferences.py:162 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:153 msgid "Top of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:154 msgid "Middle of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:155 msgid "Bottom of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:158 msgid "_Position:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:171 #, fuzzy msgid "_Cover size:" msgstr "总大小:" #: ../quodlibet/ext/events/animosd/prefs.py:177 #: ../quodlibet/ext/events/lyricswindow.py:334 ../quodlibet/qltk/prefs.py:266 #, fuzzy msgid "Display" msgstr "编辑显示" #: ../quodlibet/ext/events/animosd/prefs.py:190 msgid "_Font:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:195 msgid "Left" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:196 msgid "Center" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:197 #, fuzzy msgid "Right" msgstr "权重(_W)" #: ../quodlibet/ext/events/animosd/prefs.py:200 msgid "_Align text:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:206 msgid "Text" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:217 msgid "_Text:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:227 msgid "_Fill:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:232 #: ../quodlibet/ext/events/synchronizedlyrics.py:63 msgid "Colors" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:240 msgid "_Shadows" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:241 msgid "_Outline" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:242 msgid "Rou_nded Corners" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:258 msgid "_Delay:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:264 #: ../quodlibet/qltk/pluginwin.py:172 msgid "Effects" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:270 #, fuzzy msgid "Ed_it Display Pattern…" msgstr "编辑显示" #: ../quodlibet/ext/events/animosd/prefs.py:274 #: ../quodlibet/ext/events/trayicon/prefs.py:78 #, fuzzy msgid "Preview" msgstr "预览(_P)" #: ../quodlibet/ext/events/auto_library_update.py:136 msgid "Automatic Library Update" msgstr "" #: ../quodlibet/ext/events/auto_library_update.py:137 #, python-format msgid "Keeps your library up to date with inotify. Requires %s." 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 by Brian Nelson." 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/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:97 msgid "Equalizer" msgstr "" #: ../quodlibet/ext/events/equalizer.py:98 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:132 msgid "The current backend does not support equalization." msgstr "" #: ../quodlibet/ext/events/equalizer.py:138 #, python-format msgid "%.1f kHz" msgstr "" #: ../quodlibet/ext/events/equalizer.py:139 #: ../quodlibet/ext/gstreamer/crossfeed.py:93 #: ../quodlibet/ext/gstreamer/karaoke.py:95 #, python-format msgid "%d Hz" msgstr "" #: ../quodlibet/ext/events/equalizer.py:173 #: ../quodlibet/ext/gstreamer/crossfeed.py:112 #, fuzzy, python-format msgid "%.1f dB" msgstr "%d 秒" #: ../quodlibet/ext/events/equalizer.py:192 #: ../quodlibet/ext/gstreamer/crossfeed.py:31 #, fuzzy msgid "Custom" msgstr "自定义(_C)" #: ../quodlibet/ext/events/equalizer.py:199 #, fuzzy msgid "_Clear" msgstr "插件错误" #. Translators: statuses relating to Instant Messenger apps #: ../quodlibet/ext/events/gajim_status.py:27 msgid "online" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:28 msgid "offline" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:29 msgid "chat" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:30 msgid "away" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:31 msgid "xa" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:32 msgid "invisible" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:37 msgid "Gajim Status Message" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:38 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:45 #: ../quodlibet/ext/events/telepathy_status.py:69 msgid "paused" 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:160 msgid "Add '[paused]'" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:163 msgid "If checked, '[paused]' will be added to status message on pause." msgstr "" #: ../quodlibet/ext/events/gajim_status.py:187 msgid "Statuses for which message will be changed" msgstr "" #: ../quodlibet/ext/events/headphonemon.py:156 msgid "Pause on Headphone Unplug" msgstr "" #: ../quodlibet/ext/events/headphonemon.py:157 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" #: ../quodlibet/ext/events/inhibit.py:41 msgid "Inhibit Screensaver" msgstr "" #: ../quodlibet/ext/events/inhibit.py:42 msgid "Prevents the GNOME screensaver from activating while a song is playing." msgstr "" #: ../quodlibet/ext/events/inhibit.py:51 #, fuzzy msgid "Music is playing" msgstr "音乐播放器" #: ../quodlibet/ext/events/iradiolog.py:16 #, fuzzy msgid "Internet Radio Log" msgstr "网上广播" #: ../quodlibet/ext/events/iradiolog.py:17 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" #: ../quodlibet/ext/events/jep118.py:29 msgid "JEP-118" msgstr "" #: ../quodlibet/ext/events/jep118.py:30 msgid "Outputs a Jabber User Tunes file to ~/.quodlibet/jabber." msgstr "" #: ../quodlibet/ext/events/language.py:21 #, fuzzy msgid "Change Language" msgstr "评分(_R)" #: ../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 msgid "A restart is required for any changes to take effect" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:199 #, fuzzy msgid "No active song" msgstr "无法保存曲目" #: ../quodlibet/ext/events/lyricswindow.py:215 #, fuzzy msgid "No lyrics found" msgstr "没有找到插件。" #: ../quodlibet/ext/events/lyricswindow.py:227 #, fuzzy msgid "Lyrics:" msgstr "歌词" #: ../quodlibet/ext/events/lyricswindow.py:284 msgid "_Zoom level:" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:302 msgid "URL:" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:307 msgid "Revert to default" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:322 msgid "Search via above URL if the lyrics couldn't be found in LyricsWikia." msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:339 #, fuzzy msgid "Alternate search" msgstr "清空搜索" #: ../quodlibet/ext/events/lyricswindow.py:347 #, fuzzy msgid "Lyrics Window" msgstr "歌词" #: ../quodlibet/ext/events/lyricswindow.py:348 msgid "Shows a window containing lyrics of the playing song." msgstr "" #: ../quodlibet/ext/events/mediaserver.py:38 msgid "UPnP AV Media Server" msgstr "" #: ../quodlibet/ext/events/mediaserver.py:39 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." 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:39 msgid "" "Allows control of Quod Libet using the MPRIS 1.0/2.0 D-Bus Interface " "Specification." msgstr "" #: ../quodlibet/ext/events/mpris/__init__.py:45 #: ../quodlibet/ext/events/trayicon/prefs.py:30 #, fuzzy msgid "Hide main window on close" msgstr "隐藏主窗口" #: ../quodlibet/ext/events/mpris/__init__.py:48 #: ../quodlibet/ext/events/themeswitcher.py:84 #: ../quodlibet/ext/gstreamer/compressor.py:99 #: ../quodlibet/ext/gstreamer/crossfeed.py:136 #: ../quodlibet/ext/gstreamer/karaoke.py:99 #: ../quodlibet/ext/gstreamer/pitch.py:83 ../quodlibet/qltk/prefs.py:688 #, fuzzy msgid "Preferences" msgstr "Ex Falso 首选项" #: ../quodlibet/ext/events/mqtt.py:50 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/mqtt.py:56 msgid "MQTT Publisher" msgstr "" #: ../quodlibet/ext/events/mqtt.py:57 msgid "Publishes status messages to an MQTT topic." msgstr "" #: ../quodlibet/ext/events/mqtt.py:122 msgid "Broker hostname" msgstr "" #: ../quodlibet/ext/events/mqtt.py:122 msgid "broker hostname / IP" msgstr "" #: ../quodlibet/ext/events/mqtt.py:124 msgid "Broker port" msgstr "" #: ../quodlibet/ext/events/mqtt.py:124 msgid "broker port" msgstr "" #: ../quodlibet/ext/events/mqtt.py:126 msgid "Topic" msgstr "" #: ../quodlibet/ext/events/mqtt.py:128 #, fuzzy msgid "Playing Pattern" msgstr "参数" #: ../quodlibet/ext/events/mqtt.py:130 msgid "Status text when a song is started." msgstr "" #: ../quodlibet/ext/events/mqtt.py:132 #, fuzzy msgid "Paused Pattern" msgstr "参数" #: ../quodlibet/ext/events/mqtt.py:134 msgid "Text when a song is paused." msgstr "" #: ../quodlibet/ext/events/mqtt.py:136 msgid "No-song Text" msgstr "" #: ../quodlibet/ext/events/mqtt.py:138 msgid "Plain text for when there is no current song" msgstr "" #: ../quodlibet/ext/events/mqtt.py:149 #, fuzzy msgid "MQTT Configuration" msgstr "信息" #: ../quodlibet/ext/events/mqtt.py:153 #, fuzzy msgid "Status Text" msgstr "参数" #: ../quodlibet/ext/events/mqtt.py:185 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "" #: ../quodlibet/ext/events/mqtt.py:189 #, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s" msgstr "" #: ../quodlibet/ext/events/mqtt.py:192 #, fuzzy msgid "Connection error" msgstr "位置" #: ../quodlibet/ext/events/notify.py:80 msgid "Notification text" msgstr "" #: ../quodlibet/ext/events/notify.py:88 #, fuzzy msgid "_Title:" msgstr "标题" #: ../quodlibet/ext/events/notify.py:99 ../quodlibet/ext/events/notify.py:128 msgid "Revert to default pattern" msgstr "" #: ../quodlibet/ext/events/notify.py:118 msgid "_Body:" msgstr "" #: ../quodlibet/ext/events/notify.py:138 msgid "_Show notification" msgstr "" #: ../quodlibet/ext/events/notify.py:156 #, fuzzy msgid "Show notifications" msgstr "没有新的站点" #: ../quodlibet/ext/events/notify.py:162 msgid "Only on <i>_manual</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:170 msgid "Only on <i>_automatic</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:178 msgid "On <i>a_ll</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:196 msgid "Only when the main window is not _focused" msgstr "" #: ../quodlibet/ext/events/notify.py:204 msgid "Show \"_Next\" button" msgstr "" #: ../quodlibet/ext/events/notify.py:236 msgid "Connection Error" msgstr "" #: ../quodlibet/ext/events/notify.py:237 ../quodlibet/ext/events/notify.py:391 #: ../quodlibet/ext/events/notify.py:433 msgid "Couldn't connect to notification daemon." msgstr "" #: ../quodlibet/ext/events/notify.py:251 #, fuzzy msgid "Song Notifications" msgstr "没有新的站点" #: ../quodlibet/ext/events/notify.py:252 msgid "Displays a notification when the song changes." msgstr "" #: ../quodlibet/ext/events/notify.py:415 ../quodlibet/qltk/unity.py:65 msgid "Next" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:178 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:254 #, python-format msgid "Could not contact service '%s'." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:260 msgid "Authentication failed: invalid URL." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:277 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:282 msgid "Client is banned. Contact the author." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:286 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:351 msgid "AudioScrobbler Submission" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:352 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:450 msgid "Authentication successful." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:462 msgid "_Service:" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:462 msgid "_URL:" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:462 #, fuzzy msgid "User_name:" msgstr "名字(_N):" #: ../quodlibet/ext/events/qlscrobbler.py:463 msgid "_Password:" msgstr "" #. Translators: Other service #: ../quodlibet/ext/events/qlscrobbler.py:479 #, fuzzy msgid "Other…" msgstr "其它(_O):" #. verify data #: ../quodlibet/ext/events/qlscrobbler.py:517 msgid "_Verify account data" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:522 #: ../quodlibet/ext/songsmenu/lastfmsync.py:304 msgid "Account" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:530 #, fuzzy msgid "_Artist pattern:" msgstr "歌手(_A)" #: ../quodlibet/ext/events/qlscrobbler.py:530 #, fuzzy msgid "_Title pattern:" msgstr "文件名(_F)" #: ../quodlibet/ext/events/qlscrobbler.py:531 msgid "Exclude _filter:" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:549 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:559 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:568 msgid "Songs matching this filter will not be submitted." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:576 msgid "_Offline mode (don't submit anything)" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:580 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:27 #, fuzzy msgid "Random Album Playback" msgstr "随机专辑(_B)" #: ../quodlibet/ext/events/randomalbum.py:28 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:38 msgid "Rated higher" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:39 msgid "Played more often" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:40 msgid "Skipped more often" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:41 msgid "Played more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:42 msgid "Started more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:43 msgid "Added more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:44 #, fuzzy msgid "Longer albums" msgstr "专辑" #: ../quodlibet/ext/events/randomalbum.py:83 msgid "seconds before starting next album" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:87 #, fuzzy msgid "Weights" msgstr "权重(_W)" #: ../quodlibet/ext/events/randomalbum.py:89 msgid "Play some albums more than others" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:103 msgid "avoid" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:114 msgid "prefer" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:201 #, fuzzy msgid "Random Album" msgstr "随机专辑(_B)" #: ../quodlibet/ext/events/randomalbum.py:202 #, python-format msgid "Waiting to start %s" msgstr "" #: ../quodlibet/ext/events/rbimport.py:114 #, fuzzy msgid "Import Failed" msgstr "导入播放列表" #: ../quodlibet/ext/events/rbimport.py:119 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "" #: ../quodlibet/ext/events/rbimport.py:127 msgid "Rhythmbox Import" msgstr "" #: ../quodlibet/ext/events/rbimport.py:128 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "" #: ../quodlibet/ext/events/rbimport.py:132 #, fuzzy msgid "Start Import" msgstr "导入(_I)" #: ../quodlibet/ext/events/screensaver.py:25 msgid "Screensaver Pause" msgstr "" #: ../quodlibet/ext/events/screensaver.py:26 msgid "Pauses playback while the GNOME screensaver is active." msgstr "" #: ../quodlibet/ext/events/searchprovider.py:73 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "" #: ../quodlibet/ext/events/searchprovider.py:79 msgid "GNOME Search Provider" msgstr "" #: ../quodlibet/ext/events/searchprovider.py:80 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/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:29 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:57 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:58 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:34 #, fuzzy msgid "Synchronized Lyrics" msgstr "歌词" #: ../quodlibet/ext/events/synchronizedlyrics.py:35 msgid "Shows synchronized lyrics from .lrc file with same name as the track." msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:66 msgid "Text:" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:76 msgid "Background:" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:87 msgid "Font" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:90 msgid "Size (px):" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:62 msgid "Telepathy Status Messages" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:63 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:122 msgid "Playing:" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:123 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:139 msgid "Paused:" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:140 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:156 msgid "Plain text for status when there is no current song" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:157 msgid "No song:" msgstr "" #. Frame #: ../quodlibet/ext/events/telepathy_status.py:164 #, 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/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:77 #: ../quodlibet/ext/events/trayicon/prefs.py:98 #: ../quodlibet/ext/events/trayicon/systemtray.py:177 #: ../quodlibet/qltk/info.py:47 msgid "Not playing" msgstr "" #: ../quodlibet/ext/events/trayicon/__init__.py:53 #, fuzzy msgid "Tray Icon" msgstr "系统托盘图标首选项" #: ../quodlibet/ext/events/trayicon/__init__.py:54 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:183 #: ../quodlibet/qltk/quodlibetwindow.py:1046 #: ../quodlibet/qltk/quodlibetwindow.py:1238 #, fuzzy msgid "_Play" msgstr "播放列表(_P)" #: ../quodlibet/ext/events/trayicon/menu.py:63 #: ../quodlibet/qltk/quodlibetwindow.py:185 #: ../quodlibet/qltk/quodlibetwindow.py:1240 ../quodlibet/qltk/wlw.py:51 #, fuzzy msgid "P_ause" msgstr "播放器" #: ../quodlibet/ext/events/trayicon/menu.py:68 #: ../quodlibet/qltk/quodlibetwindow.py:190 #: ../quodlibet/qltk/quodlibetwindow.py:1041 #, fuzzy msgid "Pre_vious" msgstr "预览(_P)" #: ../quodlibet/ext/events/trayicon/menu.py:71 #: ../quodlibet/qltk/quodlibetwindow.py:194 #: ../quodlibet/qltk/quodlibetwindow.py:1051 msgid "_Next" msgstr "" #: ../quodlibet/ext/events/trayicon/menu.py:76 msgid "_Shuffle" msgstr "" #: ../quodlibet/ext/events/trayicon/menu.py:81 msgid "_Repeat" msgstr "重复(_R)" #: ../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:1012 #, fuzzy msgid "Open _Browser" msgstr "打开新的浏览器" #: ../quodlibet/ext/events/trayicon/menu.py:103 #: ../quodlibet/qltk/quodlibetwindow.py:1031 ../quodlibet/qltk/songsmenu.py:411 msgid "Edit _Tags" msgstr "编辑标签(_T)" #: ../quodlibet/ext/events/trayicon/menu.py:112 #: ../quodlibet/qltk/quodlibetwindow.py:975 ../quodlibet/qltk/songsmenu.py:424 msgid "_Information" msgstr "信息(_I)" #: ../quodlibet/ext/events/trayicon/menu.py:114 #: ../quodlibet/qltk/songsmenu.py:340 #, fuzzy msgid "Play_lists" msgstr "播放列表" #: ../quodlibet/ext/events/trayicon/menu.py:132 #: ../quodlibet/qltk/quodlibetwindow.py:1026 msgid "_Quit" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:32 ../quodlibet/qltk/prefs.py:69 msgid "Behavior" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:42 msgid "Scroll wheel adjusts volume" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel changes song" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll _Wheel" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:84 #, fuzzy msgid "Tooltip Display" msgstr "编辑显示" #: ../quodlibet/ext/events/viewlyrics.py:23 #, fuzzy msgid "View Lyrics" msgstr "歌词" #: ../quodlibet/ext/events/viewlyrics.py:24 msgid "Automatically displays lyrics beneath the song list in the main window." msgstr "" #: ../quodlibet/ext/events/viewlyrics.py:29 #, fuzzy msgid "_Lyrics" 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 "显示错误(_E)" #: ../quodlibet/ext/events/visualisations.py:76 msgid "Visualiser executable:" msgstr "" #: ../quodlibet/ext/events/visualisations.py:91 msgid "Reload" msgstr "" #: ../quodlibet/ext/events/waveformseekbar.py:406 msgid "Waveform Seek Bar" msgstr "" #: ../quodlibet/ext/events/waveformseekbar.py:410 msgid "A seekbar in the shape of the waveform of the current song." msgstr "" #: ../quodlibet/ext/events/waveformseekbar.py:443 msgid "Override foreground color:" msgstr "" #: ../quodlibet/ext/events/write_cover.py:32 msgid "Picture Saver" msgstr "" #: ../quodlibet/ext/events/write_cover.py:33 msgid "Saves the cover image of the current song to a file." msgstr "" #: ../quodlibet/ext/events/write_cover.py:66 #, fuzzy msgid "File:" msgstr "文件" #: ../quodlibet/ext/gstreamer/compressor.py:20 msgid "_Threshold:" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:21 msgid "Threshold until the filter is activated" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:22 msgid "R_atio:" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:22 msgid "Compression ratio" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:74 #: ../quodlibet/ext/gstreamer/karaoke.py:91 #, python-format msgid "%d %%" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:105 msgid "Audio Compressor" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:106 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:19 #, fuzzy msgid "_Preset:" msgstr "预览(_P)" #: ../quodlibet/ext/gstreamer/crossfeed.py:19 #, fuzzy msgid "Filter preset" msgstr "以歌手过滤(_A)" #: ../quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Frequency cut:" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Low-pass filter cut frequency" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed _level:" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed level" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:25 msgid "Default" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Chu Moy" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Jan Meier" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:31 #, fuzzy msgid "Custom settings" msgstr "自定义(_C)" #: ../quodlibet/ext/gstreamer/crossfeed.py:152 msgid "Crossfeed" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:153 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:20 #, fuzzy msgid "Filter _band:" msgstr "以流派过滤(_G)" #: ../quodlibet/ext/gstreamer/karaoke.py:21 msgid "The Frequency band of the filter" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:22 #, fuzzy msgid "Filter _width:" msgstr "以歌手过滤(_A)" #: ../quodlibet/ext/gstreamer/karaoke.py:23 msgid "The Frequency width of the filter" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:24 msgid "_Level:" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:24 msgid "Level of the effect" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:105 msgid "Karaoke" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:106 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:20 msgid "R_ate:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:21 msgid "_Tempo:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:22 msgid "_Pitch:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:89 #, fuzzy msgid "Audio Pitch / Speed" msgstr "音频设备:%s" #: ../quodlibet/ext/gstreamer/pitch.py:90 #, fuzzy msgid "Controls the pitch of an audio stream." msgstr "输入音频源的位置:" #: ../quodlibet/ext/playlist/export_to_folder.py:29 #: ../quodlibet/ext/playlist/export_to_folder.py:97 #: ../quodlibet/ext/playlist/export_to_folder.py:138 #, fuzzy msgid "Export Playlist to Folder" msgstr "导入播放列表" #: ../quodlibet/ext/playlist/export_to_folder.py:38 #, fuzzy msgid "_Export" msgstr "导入(_I)" #: ../quodlibet/ext/playlist/export_to_folder.py:43 #, fuzzy msgid "Destination folder:" msgstr "没有发现站点" #: ../quodlibet/ext/playlist/export_to_folder.py:58 #, fuzzy msgid "Filename pattern:" msgstr "文件名(_F)" #: ../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:156 #, fuzzy msgid "Default filename pattern:" msgstr "文件名(_F)" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:23 msgid "Export to Squeezebox" msgstr "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:25 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 "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Export playlist to Squeezebox" msgstr "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:80 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 "从播放列表里删除(_R)" #: ../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 "" "Playback follows your selection, or the next song in the list once exhausted." msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:22 msgid "Playcount Equalizer" msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:23 msgid "Shuffle, preferring songs with fewer total plays." msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:25 #, fuzzy msgid "Prefer less played" msgstr "最近一次播放" #: ../quodlibet/ext/playorder/queue.py:19 #, fuzzy msgid "Queue Only" msgstr "队列(_Q)" #: ../quodlibet/ext/playorder/queue.py:21 msgid "" "Limits playing of songs to the queue. Select this play order in the main " "window, then double-clicking any song will enqueue it instead of playing." msgstr "" #: ../quodlibet/ext/playorder/reverse.py:14 #, fuzzy msgid "Reverse" msgstr "从来没有" #: ../quodlibet/ext/playorder/reverse.py:16 msgid "Reverses the play order of songs." msgstr "" #: ../quodlibet/ext/playorder/skip_songs.py:25 #, fuzzy msgid "Skip Songs" msgstr "没有曲目" #: ../quodlibet/ext/playorder/skip_songs.py:27 msgid "" "Playback skips over songs with a rating equal or below a given threshold." msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:30 msgid "Repeat Each Track" msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:32 msgid "Shuffle songs, but repeat every track a set number of times." msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:51 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. Syntax is '@(if: " "condition, then, else)'." msgstr "" #: ../quodlibet/ext/query/pythonexpression.py:14 msgid "Python Query" msgstr "" #: ../quodlibet/ext/query/pythonexpression.py:15 msgid "" "Use Python expressions in queries. Syntax is '@(python: expression)'. The " "variable 's' is the song being matched." msgstr "" #: ../quodlibet/ext/query/savedsearch.py:19 #, fuzzy msgid "Include Saved Search" msgstr "已保存值" #: ../quodlibet/ext/query/savedsearch.py:20 msgid "" "Include the results of a saved search as part of another query. Syntax is " "'@(saved: search name)'." 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:116 msgid "Port:" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:121 #, fuzzy msgid "Username:" msgstr "重命名(_R)" #: ../quodlibet/ext/_shared/squeezebox/base.py:126 msgid "Password:" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:130 msgid "Library directory the server connects to." msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:132 #, fuzzy msgid "Library path:" msgstr "库" #. Add verify button #: ../quodlibet/ext/_shared/squeezebox/base.py:141 msgid "_Verify settings" msgstr "" #. Server settings Frame #: ../quodlibet/ext/_shared/squeezebox/base.py:147 msgid "Squeezebox Server" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:150 msgid "Debug" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:26 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:28 msgid "unidentified Squeezebox server" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:37 #, 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:20 #: ../quodlibet/ext/songsmenu/importexport.py:34 #: ../quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:329 #, fuzzy msgid "Fit image to _window" msgstr "隐藏主窗口" #. Both labels #: ../quodlibet/ext/songsmenu/albumart.py:338 msgid "_Program:" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:343 msgid "_Edit image after saving" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:345 #, fuzzy msgid "File_name:" msgstr "文件名" #: ../quodlibet/ext/songsmenu/albumart.py:457 msgid "Saving failed" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:458 #, fuzzy, python-format msgid "Unable to save \"%s\"." msgstr "无法保存曲目" #: ../quodlibet/ext/songsmenu/albumart.py:556 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:613 #, fuzzy msgid "Album Art Downloader" msgstr "专辑列表" #: ../quodlibet/ext/songsmenu/albumart.py:666 #, python-format msgid "from %(source)s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:669 #, python-format msgid "Resolution: %s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:672 #, fuzzy, python-format msgid "Size: %s" msgstr "大小" #: ../quodlibet/ext/songsmenu/albumart.py:690 #, fuzzy msgid "_Search" msgstr "搜索(_S):" #: ../quodlibet/ext/songsmenu/albumart.py:741 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:451 #, fuzzy msgid "Searching…" msgstr "搜索" #: ../quodlibet/ext/songsmenu/albumart.py:804 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:922 #, fuzzy msgid "Download Album Art" msgstr "专辑列表" #: ../quodlibet/ext/songsmenu/albumart.py:923 msgid "Downloads album covers from various websites." msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:936 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 "编辑书签(_E)..." #: ../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 "编辑书签(_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 专辑 ID" #: ../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 #: ../quodlibet/qltk/downloader.py:52 msgid "Filename" msgstr "文件名" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:130 #, fuzzy msgid "Disc" msgstr "唱片(_D)" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:131 #: ../quodlibet/ext/songsmenu/replaygain.py:404 #: ../quodlibet/qltk/tracknumbers.py:92 msgid "Track" msgstr "音轨" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:132 #, fuzzy msgid "Title" msgstr "标题" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:133 #, fuzzy msgid "Artist" msgstr "歌手(_A)" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:352 #, fuzzy msgid "MusicBrainz lookup" msgstr "MusicBrainz 专辑 ID" #: ../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:447 msgid "Please enter a query." msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:465 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:496 msgid "Error encountered. Please retry." msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:472 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:488 msgid "Loading result…" msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:475 #, fuzzy msgid "No results found." msgstr "没有找到插件。" #: ../quodlibet/ext/songsmenu/browsefolders.py:159 #, fuzzy msgid "Browse Folders" msgstr "浏览器" #: ../quodlibet/ext/songsmenu/browsefolders.py:160 msgid "Opens the songs' folders in a file manager." msgstr "" #: ../quodlibet/ext/songsmenu/browsefolders.py:172 #, fuzzy msgid "Unable to open folders" msgstr "无法创建文件夹" #: ../quodlibet/ext/songsmenu/browsefolders.py:173 msgid "No program available to open folders." msgstr "" #: ../quodlibet/ext/songsmenu/console.py:40 msgid "Python Console" msgstr "" #: ../quodlibet/ext/songsmenu/console.py:41 msgid "Interactive Python console." msgstr "" #: ../quodlibet/ext/songsmenu/console.py:72 msgid "You can access the following objects by default:" msgstr "" #: ../quodlibet/ext/songsmenu/console.py:82 msgid "Your current working directory is:" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:41 msgid "Command" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:44 #, fuzzy msgid "name" msgstr "重命名(_R)" #: ../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:55 #, fuzzy msgid "pattern" 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:91 #, fuzzy msgid "Input value" msgstr "非法的值" #: ../quodlibet/ext/songsmenu/custom_commands.py:92 #, python-format msgid "Value for %s?" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:136 #, fuzzy msgid "Custom Commands" msgstr "自定义(_C)" #: ../quodlibet/ext/songsmenu/custom_commands.py:137 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:188 #: ../quodlibet/ext/songsmenu/custom_commands.py:198 #: ../quodlibet/ext/songsmenu/custom_commands.py:252 msgid "Edit Custom Commands" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:199 msgid "" "Supports QL patterns\n" "eg <tt><~artist~title></tt>" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:283 #, fuzzy, python-format msgid "Unable to run custom command %s" msgstr "无法复制曲目" #: ../quodlibet/ext/songsmenu/duplicates.py:290 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "" #: ../quodlibet/ext/songsmenu/duplicates.py:343 msgid "Collapse / Expand all" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:347 #, python-format msgid "Duplicate key expression is '%s'" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:363 #, fuzzy msgid "Duplicates Browser" msgstr "关掉浏览器" #: ../quodlibet/ext/songsmenu/duplicates.py:364 msgid "Finds and displays similarly tagged versions of songs." msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:407 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:409 msgid "_Group duplicates by:" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:414 msgid "Duplicate Key" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:419 #, fuzzy msgid "Remove _Whitespace" msgstr "删除站点(_R)" #: ../quodlibet/ext/songsmenu/duplicates.py:420 #, fuzzy msgid "Remove _Diacritics" msgstr "删除站点(_R)" #: ../quodlibet/ext/songsmenu/duplicates.py:421 #, fuzzy msgid "Remove _Punctuation" msgstr "删除站点(_R)" #: ../quodlibet/ext/songsmenu/duplicates.py:422 msgid "Case _Insensitive" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:430 msgid "Matching options" msgstr "" #. Create a dialog. #: ../quodlibet/ext/songsmenu/editplaycount.py:19 #: ../quodlibet/ext/songsmenu/editplaycount.py:41 #, fuzzy msgid "Edit Playcount" msgstr "编辑显示" #: ../quodlibet/ext/songsmenu/editplaycount.py:20 msgid "" "Edit a song's ~#playcount and ~#skipcount.\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's ~#playcount to 0, the ~#lastplayed and ~#laststarted " "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:68 msgid "Play Count" msgstr "" #: ../quodlibet/ext/songsmenu/editplaycount.py:69 msgid "Skip Count" msgstr "" #: ../quodlibet/ext/songsmenu/embedded.py:24 #, fuzzy msgid "Edit Embedded Images" msgstr "删除站点(_R)" #: ../quodlibet/ext/songsmenu/embedded.py:25 #, fuzzy msgid "Removes or replaces embedded images." msgstr "删除站点(_R)" #: ../quodlibet/ext/songsmenu/embedded.py:78 #, fuzzy msgid "_Remove all Images" msgstr "删除站点(_R)" #: ../quodlibet/ext/songsmenu/embedded.py:82 #, fuzzy msgid "_Embed Current Image" msgstr "删除站点(_R)" #: ../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 "以流派过滤(_G)" #: ../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:41 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 #: ../quodlibet/qltk/downloader.py:67 #, fuzzy msgid "Queued" msgstr "队列(_Q)" #: ../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 "写入" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" 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 音轨 ID" #: ../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 "专辑列表(_A)" #: ../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:49 msgid "Generating fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:63 msgid "_Details" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:85 msgid "_Submit" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:115 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:118 msgid "Fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Songs with MBIDs:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with sufficient tags:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs to submit:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:162 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:178 msgid "Submitting fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:186 msgid "Submitting…" msgstr "" #: ../quodlibet/ext/songsmenu/forcewrite.py:17 #, fuzzy msgid "Update Tags in Files" msgstr "新站点(_N)" #: ../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/id3tlen.py:21 msgid "Fix MP3 Duration" msgstr "" #: ../quodlibet/ext/songsmenu/id3tlen.py:22 msgid "" "Removes TLEN frames from ID3 tags which can be the cause for invalid song " "durations." msgstr "" #: ../quodlibet/ext/songsmenu/ifp.py:20 msgid "Send to iFP" msgstr "" #: ../quodlibet/ext/songsmenu/ifp.py:21 msgid "Uploads songs to an iRiver iFP device." msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:51 msgid "Export Metadata" msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:52 msgid "Exports metadata of selected songs as a .tags file." msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:92 #, fuzzy msgid "Import Metadata" msgstr "导入播放列表" #: ../quodlibet/ext/songsmenu/importexport.py:93 msgid "Imports metadata for selected songs from a .tags file." msgstr "" #: ../quodlibet/ext/songsmenu/k3b.py:23 msgid "Burn CD" msgstr "" #: ../quodlibet/ext/songsmenu/k3b.py:24 msgid "Burns CDs with K3b, Brasero or xfburn." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:96 msgid "Updating chart list." msgstr "" #. No charts to fetch, no update scheduled. #: ../quodlibet/ext/songsmenu/lastfmsync.py:114 msgid "Already up-to-date." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:121 #, python-format msgid "Fetching chart for week of %s." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:143 msgid "Sync complete." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:149 msgid "Error during sync" msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:214 #: ../quodlibet/ext/songsmenu/lastfmsync.py:244 msgid "Last.fm Sync" msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:245 msgid "Updates your library's statistics from your Last.fm profile." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:293 #, fuzzy msgid "_Username:" msgstr "重命名(_R)" #: ../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 "" #. Create a dialog. #: ../quodlibet/ext/songsmenu/migratemetadata.py:29 #: ../quodlibet/ext/songsmenu/migratemetadata.py:38 #, fuzzy msgid "Migrate Metadata" msgstr "导入播放列表" #: ../quodlibet/ext/songsmenu/migratemetadata.py:32 msgid "Copies the quodlibet-specific metadata between songs." msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:45 msgid "_Copy" msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:47 msgid "_Paste" msgstr "" #. Create the tag table. #: ../quodlibet/ext/songsmenu/migratemetadata.py:57 #, fuzzy msgid "Information to copy/paste" msgstr "信息" #. Create the indexing box. #: ../quodlibet/ext/songsmenu/migratemetadata.py:79 msgid "Map tracks by disc and track number" msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:80 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 "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:96 #, python-format msgid "There is %d stored track." msgid_plural "There are %d stored tracks." msgstr[0] "" #: ../quodlibet/ext/songsmenu/playlist.py:31 #, fuzzy msgid "Export as Playlist" msgstr "导入播放列表" #: ../quodlibet/ext/songsmenu/playlist.py:32 msgid "Exports songs to an M3U or PLS playlist." msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:77 msgid "Use relative paths" msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:77 msgid "Use absolute paths" msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:132 #, fuzzy msgid "Unable to export playlist" msgstr "无法导入播放列表" #: ../quodlibet/ext/songsmenu/playlist.py:133 #, fuzzy, python-format msgid "Writing to <b>%s</b> failed." msgstr "删除 <b>%s</b> 失败。" #. Translators: Plugin name #: ../quodlibet/ext/songsmenu/refresh.py:22 #, fuzzy msgid "Rescan Songs" msgstr "刷新库(_F)" #: ../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 "刷新库(_F)" #: ../quodlibet/ext/songsmenu/replaygain.py:362 msgid "ReplayGain Analyzer" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:418 msgid "Progress" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:433 msgid "Gain" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:448 msgid "Peak" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:463 #, python-format msgid "There is <b>%(to-process)s</b> album to update (of %(all)s)" msgid_plural "There are <b>%(to-process)s</b> albums to update (of %(all)s)" msgstr[0] "" #: ../quodlibet/ext/songsmenu/replaygain.py:578 msgid "Replay Gain" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:579 msgid "" "Analyzes and updates ReplayGain information, using GStreamer. Results are " "grouped by album." msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:617 msgid "always" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:618 msgid "if <b>any</b> RG tags are missing" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:620 msgid "if <b>album</b> RG tags are missing" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:637 msgid "_Process albums:" msgstr "" #. Server settings Frame #: ../quodlibet/ext/songsmenu/replaygain.py:649 #, 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 "" #. TRANSLATORS: BPM mean "beats per minute" #: ../quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "" #: ../quodlibet/ext/songsmenu/tapbpm.py:32 #: ../quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" msgstr "" #: ../quodlibet/ext/songsmenu/tapbpm.py:36 #, fuzzy msgid "Reset" msgstr "预览(_P)" #: ../quodlibet/ext/songsmenu/tapbpm.py:42 #, fuzzy msgid "Tap" msgstr "标签" #: ../quodlibet/ext/songsmenu/tapbpm.py:172 #: ../quodlibet/ext/songsmenu/tapbpm.py:179 msgid "Tap BPM" msgstr "" #: ../quodlibet/ext/songsmenu/tapbpm.py:173 #, fuzzy msgid "Tap BPM for the selected song." msgstr "无法添加曲目信息" #: ../quodlibet/ext/songsmenu/website_search.py:35 #, fuzzy msgid "Website Search" msgstr "搜索" #: ../quodlibet/ext/songsmenu/website_search.py:36 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern-example)s." msgstr "" #: ../quodlibet/ext/songsmenu/website_search.py:78 #, fuzzy msgid "Search URL patterns" msgstr "参数" #: ../quodlibet/ext/songsmenu/website_search.py:88 #, fuzzy msgid "Edit search URLs" msgstr "编辑已保存的值..." #. Add link to editor #: ../quodlibet/ext/songsmenu/website_search.py:114 #, fuzzy msgid "Configure Searches…" msgstr "给搜索条件着色(_S)" #: ../quodlibet/ext/songsmenu/wikipedia.py:46 #, python-format msgid "Search at %(website)s" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:63 msgid "Search Artist in Wikipedia" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:64 msgid "" "Opens a browser window with Wikipedia article on the playing song artist." msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:71 msgid "Search Album in Wikipedia" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:72 msgid "" "Opens a browser window with Wikipedia article on the playing song album." msgstr "" #. then (try to) load all new files #: ../quodlibet/library/libraries.py:650 ../quodlibet/library/libraries.py:660 #: ../quodlibet/library/libraries.py:726 ../quodlibet/library/libraries.py:745 #: ../quodlibet/qltk/information.py:268 ../quodlibet/qltk/prefs.py:639 #: ../quodlibet/util/library.py:124 msgid "Library" msgstr "库" #: ../quodlibet/library/libraries.py:650 #, fuzzy msgid "Checking mount points" msgstr "挂载点" #: ../quodlibet/library/libraries.py:660 #, fuzzy msgid "Scanning library" msgstr "已导入曲目库。" #: ../quodlibet/library/libraries.py:725 #, fuzzy, python-format msgid "Scanning %s" msgstr "正在检查 %s" #: ../quodlibet/library/libraries.py:745 msgid "Loading files" msgstr "" #: ../quodlibet/operon/base.py:70 #, python-format msgid "Failed to load file: %r" msgstr "" #: ../quodlibet/operon/commands.py:37 msgid "List tags" msgstr "" #: ../quodlibet/operon/commands.py:42 ../quodlibet/operon/commands.py:81 #: ../quodlibet/operon/commands.py:461 msgid "Print terse output" msgstr "" #: ../quodlibet/operon/commands.py:44 ../quodlibet/operon/commands.py:83 #: ../quodlibet/operon/commands.py:463 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "" #: ../quodlibet/operon/commands.py:47 ../quodlibet/operon/commands.py:86 msgid "Also list programmatic tags" msgstr "" #: ../quodlibet/operon/commands.py:51 ../quodlibet/operon/commands.py:129 #: ../quodlibet/operon/commands.py:220 ../quodlibet/operon/commands.py:293 #: ../quodlibet/operon/commands.py:336 ../quodlibet/operon/commands.py:340 #: ../quodlibet/operon/commands.py:391 ../quodlibet/operon/commands.py:394 #: ../quodlibet/operon/commands.py:433 ../quodlibet/operon/commands.py:468 #: ../quodlibet/operon/commands.py:508 ../quodlibet/operon/commands.py:543 #: ../quodlibet/operon/commands.py:585 msgid "Not enough arguments" msgstr "" #: ../quodlibet/operon/commands.py:53 ../quodlibet/operon/commands.py:90 #: ../quodlibet/operon/commands.py:131 ../quodlibet/operon/commands.py:222 #: ../quodlibet/operon/commands.py:470 msgid "Too many arguments" msgstr "" #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:92 #: ../quodlibet/operon/commands.py:475 ../quodlibet/qltk/data_editors.py:363 #, fuzzy msgid "Description" msgstr "描述" #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:475 #: ../quodlibet/qltk/edittags.py:454 msgid "Value" msgstr "值" #: ../quodlibet/operon/commands.py:76 msgid "List all common tags" msgstr "" #: ../quodlibet/operon/commands.py:118 msgid "Copy tags from one file to another" msgstr "" #: ../quodlibet/operon/commands.py:123 ../quodlibet/operon/commands.py:164 #: ../quodlibet/operon/commands.py:289 ../quodlibet/operon/commands.py:324 #: ../quodlibet/operon/commands.py:384 msgid "Show changes, don't apply them" msgstr "" #: ../quodlibet/operon/commands.py:125 msgid "Skip tags that can't be written" msgstr "" #: ../quodlibet/operon/commands.py:145 #, python-format msgid "Can't copy tag %r to file: %r" 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:304 ../quodlibet/operon/commands.py:444 #: ../quodlibet/operon/commands.py:676 #, python-format msgid "Can not set %r" msgstr "" #: ../quodlibet/operon/commands.py:319 #, fuzzy msgid "Remove tags" msgstr "删除站点(_R)" #: ../quodlibet/operon/commands.py:326 ../quodlibet/operon/commands.py:386 msgid "Value is a regular expression" msgstr "" #: ../quodlibet/operon/commands.py:328 #, fuzzy msgid "Remove all tags" msgstr "删除站点(_R)" #: ../quodlibet/operon/commands.py:332 msgid "Can't combine '--all' with '--regexp'" msgstr "" #: ../quodlibet/operon/commands.py:366 #, python-format msgid "Can't remove %r from %r" msgstr "" #: ../quodlibet/operon/commands.py:379 #, fuzzy msgid "Remove a tag value" msgstr "以标签值过滤" #: ../quodlibet/operon/commands.py:428 #, fuzzy msgid "Add a tag value" msgstr "以标签值过滤" #: ../quodlibet/operon/commands.py:456 #, fuzzy msgid "List file information" msgstr "没有时间信息" #: ../quodlibet/operon/commands.py:502 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" #: ../quodlibet/operon/commands.py:515 #, fuzzy, python-format msgid "Failed to load image file: %r" msgstr "无法重命名文件" #: ../quodlibet/operon/commands.py:522 ../quodlibet/operon/commands.py:551 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" #: ../quodlibet/operon/commands.py:538 #, fuzzy msgid "Remove all embedded images" msgstr "删除站点(_R)" #: ../quodlibet/operon/commands.py:568 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "" #: ../quodlibet/operon/commands.py:580 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" #: ../quodlibet/operon/commands.py:639 msgid "Rename files based on tags" msgstr "" #: ../quodlibet/operon/commands.py:654 msgid "Fill tags based on the file path" msgstr "" #: ../quodlibet/operon/commands.py:704 ../quodlibet/qltk/information.py:305 #: ../quodlibet/qltk/properties.py:84 ../quodlibet/qltk/renamefiles.py:176 #: ../quodlibet/qltk/tagsfrompath.py:229 ../quodlibet/qltk/tracknumbers.py:79 msgid "File" msgstr "文件" #: ../quodlibet/operon/commands.py:712 msgid "Fill tracknumbers for all files" msgstr "" #: ../quodlibet/operon/commands.py:731 msgid "Print tags based on the given pattern" msgstr "" #: ../quodlibet/operon/commands.py:768 #, fuzzy msgid "Display help information" msgstr "没有时间信息" #: ../quodlibet/operon/util.py:40 #, 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:30 #, fuzzy msgid "_Unknown" msgstr "未知" #: ../quodlibet/order/__init__.py:142 msgid "In Order" msgstr "顺序" #: ../quodlibet/order/__init__.py:143 msgid "_In Order" msgstr "顺序(_I)" #: ../quodlibet/order/reorder.py:23 #, fuzzy msgid "Random" msgstr "随机(_R)" #: ../quodlibet/order/reorder.py:24 ../quodlibet/qltk/queue.py:119 msgid "_Random" msgstr "随机(_R)" #: ../quodlibet/order/reorder.py:39 ../quodlibet/order/reorder.py:40 msgid "Prefer higher rated" msgstr "" #: ../quodlibet/order/repeat.py:43 ../quodlibet/order/repeat.py:44 msgid "Repeat this track" msgstr "" #: ../quodlibet/order/repeat.py:57 ../quodlibet/order/repeat.py:58 #, fuzzy msgid "Repeat all" msgstr "重复(_R)" #: ../quodlibet/order/repeat.py:73 ../quodlibet/order/repeat.py:74 msgid "One Song" msgstr "单曲" #: ../quodlibet/player/gstbe/player.py:98 msgid "Stream" msgstr "" #: ../quodlibet/player/gstbe/player.py:98 msgid "Buffering" msgstr "" #: ../quodlibet/player/gstbe/player.py:319 msgid "Could not create GStreamer pipeline" msgstr "" #: ../quodlibet/player/gstbe/player.py:560 msgid "No GStreamer element found to handle media format" msgstr "" #: ../quodlibet/player/gstbe/player.py:561 #, 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:25 msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. In case the pipeline contains a sink, it will be used instead of " "the default one." msgstr "" #: ../quodlibet/player/gstbe/prefs.py:36 msgid "_Output pipeline:" msgstr "" #: ../quodlibet/player/gstbe/prefs.py:43 #, fuzzy, python-format msgid "%.1f seconds" msgstr "%d 秒" #: ../quodlibet/player/gstbe/prefs.py:57 msgid "_Buffer duration:" msgstr "" #: ../quodlibet/player/gstbe/prefs.py:66 msgid "Disable _gapless playback" msgstr "" #: ../quodlibet/player/gstbe/prefs.py:70 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions." msgstr "" #: ../quodlibet/player/gstbe/util.py:93 #, fuzzy msgid "No GStreamer audio sink found" msgstr "没有发现站点" #: ../quodlibet/player/gstbe/util.py:112 msgid "Invalid GStreamer output pipeline" msgstr "" #: ../quodlibet/player/xinebe/player.py:90 #, fuzzy msgid "Unable to create audio output" msgstr "无法创建文件夹" #: ../quodlibet/player/xinebe/player.py:91 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "" #: ../quodlibet/plugins/__init__.py:62 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" #: ../quodlibet/plugins/__init__.py:71 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "" #: ../quodlibet/plugins/playlist.py:30 #, 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:41 ../quodlibet/qltk/songsmenu.py:46 #: ../quodlibet/qltk/songsmenu.py:74 #, fuzzy msgid "_Run Plugin" msgstr "插件(_P)" #: ../quodlibet/qltk/about.py:40 #, python-format msgid "Supported formats: %s" msgstr "支持的格式: %s" #: ../quodlibet/qltk/about.py:43 #, python-format msgid "Audio device: %s" msgstr "音频设备:%s" #. 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:207 ../quodlibet/qltk/information.py:131 msgid "Bookmarks" msgstr "书签" #: ../quodlibet/qltk/browser.py:56 msgid "_Filters" msgstr "过滤器(_F)" #: ../quodlibet/qltk/browser.py:57 #, fuzzy msgid "Recently _Played" msgstr "从来没有播放过(_N)" #: ../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 #, 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 "随机流派(_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:48 ../quodlibet/qltk/edittags.py:311 msgid "_Value:" msgstr "值(_V):" #: ../quodlibet/qltk/cbes.py:262 msgid "Saved Values" msgstr "已保存值" #: ../quodlibet/qltk/cbes.py:263 #, fuzzy msgid "Edit saved values…" msgstr "编辑已保存的值..." #: ../quodlibet/qltk/controls.py:111 msgid "Auto_matic" msgstr "" #: ../quodlibet/qltk/controls.py:112 #, fuzzy msgid "_Track Mode" msgstr "音轨号" #: ../quodlibet/qltk/controls.py:113 #, fuzzy msgid "_Album Mode" msgstr "专辑列表(_A)" #. Translators: player state, no action #: ../quodlibet/qltk/controls.py:122 msgid "_Mute" msgstr "" #: ../quodlibet/qltk/controls.py:128 #, fuzzy msgid "_Replay Gain Mode" msgstr "无音量调整" #. Translators: New Command/Entry/Item/... #: ../quodlibet/qltk/data_editors.py:119 #, python-format msgid "New %s" msgstr "" #: ../quodlibet/qltk/data_editors.py:218 #, fuzzy msgid "(unknown)" msgstr "未知" #: ../quodlibet/qltk/data_editors.py:355 msgid "Tag expression" msgstr "" #: ../quodlibet/qltk/data_editors.py:382 msgid "Tag expression e.g. people:real or ~album~year." msgstr "" #: ../quodlibet/qltk/data_editors.py:383 #, fuzzy msgid "Enter new tag" 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] "" #: ../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] "" #: ../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 #, 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/downloader.py:38 msgid "Downloads" msgstr "下载" #: ../quodlibet/qltk/downloader.py:62 msgid "Size" msgstr "大小" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: ../quodlibet/qltk/downloader.py:94 ../quodlibet/qltk/renamefiles.py:265 #: ../quodlibet/qltk/wlw.py:50 msgid "_Stop" msgstr "" #: ../quodlibet/qltk/edittags.py:63 ../quodlibet/qltk/edittags.py:74 #, python-format msgid "missing from %d song" msgid_plural "missing from %d songs" msgstr[0] "" #: ../quodlibet/qltk/edittags.py:67 ../quodlibet/qltk/edittags.py:71 #, python-format msgid "different across %d song" msgid_plural "different across %d songs" msgstr[0] "" #: ../quodlibet/qltk/edittags.py:193 msgid "Split into _Multiple Values" msgstr "" #: ../quodlibet/qltk/edittags.py:211 msgid "Split Disc out of _Album" msgstr "" #: ../quodlibet/qltk/edittags.py:228 msgid "Split _Version out of Title" msgstr "" #: ../quodlibet/qltk/edittags.py:259 msgid "Split Arranger out of Ar_tist" msgstr "" #: ../quodlibet/qltk/edittags.py:264 msgid "Split _Performer out of Artist" msgstr "" #: ../quodlibet/qltk/edittags.py:270 msgid "Split _Performer out of Title" msgstr "" #: ../quodlibet/qltk/edittags.py:276 msgid "Split _Originalartist out of Title" msgstr "" #: ../quodlibet/qltk/edittags.py:283 msgid "Add a Tag" msgstr "增加一个标签" #: ../quodlibet/qltk/edittags.py:302 msgid "_Tag:" msgstr "标签(_T):" #: ../quodlibet/qltk/edittags.py:404 msgid "Edit Tags" msgstr "编辑标签" #: ../quodlibet/qltk/edittags.py:477 msgid "Show _programmatic tags" msgstr "" #: ../quodlibet/qltk/edittags.py:478 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" #. Translators: Revert button in the tag editor #: ../quodlibet/qltk/edittags.py:508 #, fuzzy msgctxt "edittags" msgid "_Revert" msgstr "从来没有" #. Translators: Save button in the tag editor #: ../quodlibet/qltk/edittags.py:513 msgctxt "edittags" msgid "_Save" msgstr "" #: ../quodlibet/qltk/edittags.py:659 msgid "Unable to add tag" msgstr "无法增加标签" #: ../quodlibet/qltk/edittags.py:660 #, fuzzy, python-format msgid "Unable to add <b>%s</b>" msgstr "无法添加曲目" #: ../quodlibet/qltk/edittags.py:662 #, fuzzy, python-format msgid "" "The files currently selected do not support multiple values for <b>%s</b>." msgstr "" "非法标签<b>%s</b>\n" "当前被选定的文件不支持编辑这个标签。" #. Can't add the new tag. #: ../quodlibet/qltk/edittags.py:689 ../quodlibet/qltk/edittags.py:856 #: ../quodlibet/qltk/tagsfrompath.py:212 ../quodlibet/util/__init__.py:554 #: ../quodlibet/util/tags.py:231 msgid "Invalid tag" msgstr "非法标签" #: ../quodlibet/qltk/edittags.py:690 ../quodlibet/qltk/edittags.py:857 #: ../quodlibet/qltk/tagsfrompath.py:213 #, python-format msgid "" "Invalid tag <b>%s</b>\n" "\n" "The files currently selected do not support editing this tag." msgstr "" "非法标签<b>%s</b>\n" "当前被选定的文件不支持编辑这个标签。" #: ../quodlibet/qltk/edittags.py:828 ../quodlibet/qltk/edittags.py:868 msgid "Invalid value" msgstr "非法的值" #: ../quodlibet/qltk/edittags.py:829 ../quodlibet/qltk/edittags.py:869 #, python-format msgid "" "Invalid value: <b>%(value)s</b>\n" "\n" "%(error)s" msgstr "" #: ../quodlibet/qltk/_editutils.py:28 msgid "Tag may not be accurate" msgstr "标签可能不准确" #: ../quodlibet/qltk/_editutils.py:31 #, 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:47 msgid "Unable to save song" msgstr "无法保存曲目" #: ../quodlibet/qltk/_editutils.py:50 #, 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:142 #, fuzzy 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:95 #: ../quodlibet/qltk/quodlibetwindow.py:1066 msgid "_About" msgstr "" #: ../quodlibet/qltk/exfalsowindow.py:99 #: ../quodlibet/qltk/quodlibetwindow.py:1088 msgid "_Check for Updates…" msgstr "" #: ../quodlibet/qltk/exfalsowindow.py:105 #: ../quodlibet/qltk/quodlibetwindow.py:1021 ../quodlibet/qltk/songsmenu.py:304 msgid "_Plugins" msgstr "插件(_P)" #: ../quodlibet/qltk/exfalsowindow.py:267 #, python-format msgid "%(title)s and %(count)s more" msgid_plural "%(title)s and %(count)s more" msgstr[0] "" #: ../quodlibet/qltk/exfalsowindow.py:279 msgid "Ex Falso Preferences" msgstr "Ex Falso 首选项" #: ../quodlibet/qltk/exfalsowindow.py:289 ../quodlibet/qltk/prefs.py:598 msgid "Split _on:" msgstr "" #: ../quodlibet/qltk/exfalsowindow.py:295 ../quodlibet/qltk/prefs.py:613 msgid "Tag Editing" msgstr "标签编辑" #: ../quodlibet/qltk/filesel.py:210 msgid "Folders" msgstr "文件夹" #: ../quodlibet/qltk/filesel.py:253 #, fuzzy msgid "_New Folder…" msgstr "新文件夹" #: ../quodlibet/qltk/filesel.py:262 #, fuzzy msgid "_Select all Sub-Folders" msgstr "全选(_A)" #: ../quodlibet/qltk/filesel.py:374 msgid "New Folder" msgstr "新文件夹" #: ../quodlibet/qltk/filesel.py:374 msgid "Enter a name for the new folder:" msgstr "输入新文件夹的名字:" #: ../quodlibet/qltk/filesel.py:387 msgid "Unable to create folder" msgstr "无法创建文件夹" #: ../quodlibet/qltk/filesel.py:404 msgid "Unable to delete folder" msgstr "无法删除文件夹" #: ../quodlibet/qltk/filesel.py:519 ../quodlibet/qltk/pluginwin.py:167 msgid "Songs" msgstr "曲目" #. Translators: As in "by Artist Name" #: ../quodlibet/qltk/info.py:42 #, python-format msgid "by %s" msgstr "" #: ../quodlibet/qltk/info.py:43 ../quodlibet/qltk/information.py:167 #: ../quodlibet/qltk/information.py:448 #, python-format msgid "Disc %s" msgstr "唱片 %s" #: ../quodlibet/qltk/info.py:44 ../quodlibet/qltk/information.py:172 #, python-format msgid "Track %s" msgstr "音轨 %s" #: ../quodlibet/qltk/info.py:108 #, fuzzy msgid "_Edit Display…" msgstr "编辑显示" #: ../quodlibet/qltk/information.py:105 msgid "No songs are selected." msgstr "没有选中曲目。" #: ../quodlibet/qltk/information.py:106 msgid "No Songs" msgstr "没有曲目" #: ../quodlibet/qltk/information.py:121 ../quodlibet/qltk/information.py:338 #: ../quodlibet/qltk/information.py:471 ../quodlibet/qltk/information.py:531 msgid "Information" msgstr "信息" #: ../quodlibet/qltk/information.py:126 msgid "Lyrics" msgstr "歌词" #: ../quodlibet/qltk/information.py:184 ../quodlibet/qltk/information.py:396 #, python-format msgid "Produced by %s" msgstr "%s 制造" #: ../quodlibet/qltk/information.py:199 ../quodlibet/util/tags.py:76 msgid "artist" msgstr "歌手" #: ../quodlibet/qltk/information.py:200 ../quodlibet/qltk/information.py:561 #: ../quodlibet/util/tags.py:76 msgid "artists" msgstr "歌手" #. for backwards compat #: ../quodlibet/qltk/information.py:221 ../quodlibet/util/tags.py:86 #: ../quodlibet/util/tags.py:114 msgid "performers" msgstr "演员" #: ../quodlibet/qltk/information.py:235 ../quodlibet/qltk/information.py:248 #: ../quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "从来没有" #: ../quodlibet/qltk/information.py:236 #, fuzzy, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "%d 时间" #: ../quodlibet/qltk/information.py:254 ../quodlibet/util/tags.py:139 msgid "added" msgstr "加入" #: ../quodlibet/qltk/information.py:255 ../quodlibet/util/tags.py:140 msgid "last played" msgstr "最近一次播放" #: ../quodlibet/qltk/information.py:256 ../quodlibet/util/tags.py:150 msgid "plays" msgstr "" #: ../quodlibet/qltk/information.py:257 ../quodlibet/util/tags.py:151 msgid "skips" msgstr "" #: ../quodlibet/qltk/information.py:258 ../quodlibet/util/tags.py:156 msgid "rating" msgstr "评分" #: ../quodlibet/qltk/information.py:287 msgid "path" msgstr "" #: ../quodlibet/qltk/information.py:288 ../quodlibet/util/tags.py:154 msgid "length" msgstr "长度" #: ../quodlibet/qltk/information.py:289 #, fuzzy msgid "format" msgstr "信息" #: ../quodlibet/qltk/information.py:290 ../quodlibet/util/tags.py:163 msgid "codec" msgstr "" #: ../quodlibet/qltk/information.py:291 ../quodlibet/util/tags.py:164 #, fuzzy msgid "encoding" msgstr "[非法编码]" #: ../quodlibet/qltk/information.py:292 ../quodlibet/util/tags.py:160 msgid "bitrate" msgstr "比特率" #: ../quodlibet/qltk/information.py:293 ../quodlibet/util/tags.py:161 msgid "file size" msgstr "文件大小" #: ../quodlibet/qltk/information.py:294 ../quodlibet/util/tags.py:149 msgid "modified" msgstr "修改" #: ../quodlibet/qltk/information.py:331 msgid "Additional" msgstr "" #: ../quodlibet/qltk/information.py:383 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d 选中" #: ../quodlibet/qltk/information.py:458 msgid "Track unavailable" msgstr "音轨不可用" #: ../quodlibet/qltk/information.py:464 msgid "Track List" msgstr "音轨列表" #: ../quodlibet/qltk/information.py:505 ../quodlibet/qltk/information.py:578 #, python-format msgid "%d song with no album" msgid_plural "%d songs with no album" msgstr[0] "%d 首曲目没有专辑信息" #: ../quodlibet/qltk/information.py:508 msgid "Selected Discography" msgstr "" #: ../quodlibet/qltk/information.py:558 #, python-format msgid "%d song with no artist" msgid_plural "%d songs with no artist" msgstr[0] "" #: ../quodlibet/qltk/information.py:586 ../quodlibet/util/tags.py:74 msgid "albums" msgstr "专辑" #: ../quodlibet/qltk/information.py:599 msgid "Total length:" msgstr "总长度:" #: ../quodlibet/qltk/information.py:603 msgid "Total size:" msgstr "总大小:" #: ../quodlibet/qltk/information.py:606 msgid "Files" msgstr "文件" #: ../quodlibet/qltk/lyrics.py:37 msgid "_Download" msgstr "下载(_D)" #: ../quodlibet/qltk/lyrics.py:40 #, fuzzy msgid "_Edit" msgstr "编辑书签(_E)..." #. buffer.set_text(_("No lyrics found.\n\nYou can click the " #. "Download button to have Quod Libet search " #. "for lyrics online. You can also enter them " #. "yourself and click save.")) #: ../quodlibet/qltk/lyrics.py:73 ../quodlibet/qltk/lyrics.py:109 msgid "No lyrics found for this song." msgstr "" #: ../quodlibet/qltk/lyrics.py:82 msgid "Searching for lyrics…" 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/msg.py:41 msgid "Discard tag changes?" msgstr "" #: ../quodlibet/qltk/msg.py:42 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "" #: ../quodlibet/qltk/msg.py:55 ../quodlibet/qltk/prefs.py:595 #: ../quodlibet/qltk/textedit.py:64 ../quodlibet/qltk/tracknumbers.py:117 #, fuzzy msgid "_Revert" msgstr "从来没有" #: ../quodlibet/qltk/msg.py:86 #, fuzzy msgid "File exists" msgstr "文件系统" #: ../quodlibet/qltk/msg.py:88 #, python-format msgid "Replace %(file-name)s?" msgstr "" #: ../quodlibet/qltk/msg.py:94 #, fuzzy msgid "_Replace File" msgstr "重命名文件" #: ../quodlibet/qltk/notif.py:182 msgid "Active tasks" msgstr "" #: ../quodlibet/qltk/notif.py:188 #, python-format msgid "%d tasks running" msgstr "" #: ../quodlibet/qltk/playorder.py:254 #, fuzzy msgid "Toggle shuffle mode" msgstr "切换播放/暂停模式" #: ../quodlibet/qltk/playorder.py:270 #, fuzzy msgid "Toggle repeat mode" msgstr "切换播放/暂停模式" #: ../quodlibet/qltk/pluginwin.py:44 msgid "Plugin Errors" msgstr "插件错误" #: ../quodlibet/qltk/pluginwin.py:124 msgid "Enabled" msgstr "" #: ../quodlibet/qltk/pluginwin.py:125 #, fuzzy msgid "Disabled" msgstr "关掉浏览器" #: ../quodlibet/qltk/pluginwin.py:131 msgid "No category" msgstr "" #: ../quodlibet/qltk/pluginwin.py:169 msgid "Events" msgstr "" #: ../quodlibet/qltk/pluginwin.py:170 #, fuzzy msgid "Play Order" msgstr "播放次序(_O)" #: ../quodlibet/qltk/pluginwin.py:171 #, fuzzy msgid "Editing" msgstr "标签编辑" #: ../quodlibet/qltk/pluginwin.py:173 #, fuzzy msgid "Covers" msgstr "总大小:" #: ../quodlibet/qltk/pluginwin.py:309 msgid "No plugins found." msgstr "没有找到插件。" #: ../quodlibet/qltk/pluginwin.py:358 #, fuzzy msgid "Plugins" msgstr "插件(_P)" #: ../quodlibet/qltk/pluginwin.py:402 msgid "Show _Errors" msgstr "显示错误(_E)" #: ../quodlibet/qltk/prefs.py:45 msgid "_Disc" msgstr "唱片(_D)" #: ../quodlibet/qltk/prefs.py:46 msgid "_Track" msgstr "音轨(_T)" #: ../quodlibet/qltk/prefs.py:47 #, fuzzy msgid "Grou_ping" msgstr "组合" #: ../quodlibet/qltk/prefs.py:50 msgid "Al_bum" msgstr "专辑(_B)" #: ../quodlibet/qltk/prefs.py:55 msgid "_Filename" msgstr "文件名(_F)" #: ../quodlibet/qltk/prefs.py:57 msgid "_Length" msgstr "长度(_L)" #: ../quodlibet/qltk/prefs.py:64 msgid "_Jump to playing song automatically" msgstr "自动跳到正在播放的曲目" #: ../quodlibet/qltk/prefs.py:66 msgid "When the playing song changes, scroll to it in the song list" msgstr "当正在播放的曲目改变的时候,在曲目列表里相应跳过去" #: ../quodlibet/qltk/prefs.py:82 msgid "_Others:" msgstr "其它(_O):" #: ../quodlibet/qltk/prefs.py:88 #, fuzzy msgid "_Edit…" msgstr "编辑书签(_E)..." #: ../quodlibet/qltk/prefs.py:91 msgid "Add or remove additional column headers" msgstr "" #: ../quodlibet/qltk/prefs.py:101 msgid "Visible Columns" msgstr "可见的栏" #: ../quodlibet/qltk/prefs.py:104 msgid "Title includes _version" msgstr "标题包含版本(_V)" #: ../quodlibet/qltk/prefs.py:106 #, fuzzy msgid "Artist includes all _people" msgstr "标题包含版本(_V)" #: ../quodlibet/qltk/prefs.py:108 #, fuzzy msgid "Album includes _disc subtitle" msgstr "专辑包含部分(_P)" #: ../quodlibet/qltk/prefs.py:110 msgid "Filename includes _folder" msgstr "文件名包含文件夹(_F)" #: ../quodlibet/qltk/prefs.py:123 #, fuzzy msgid "Column Preferences" msgstr "Ex Falso 首选项" #: ../quodlibet/qltk/prefs.py:129 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "" #: ../quodlibet/qltk/prefs.py:142 ../quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "曲目列表" #: ../quodlibet/qltk/prefs.py:222 #, fuzzy msgid "Edit Columns" msgstr "可见的栏" #: ../quodlibet/qltk/prefs.py:259 msgid "Duration totals" msgstr "" #: ../quodlibet/qltk/prefs.py:271 msgid "_Global filter:" msgstr "全局过滤器:" #: ../quodlibet/qltk/prefs.py:277 msgid "Apply this query in addition to all others" msgstr "" #. Translators: The heading of the preference group, no action #: ../quodlibet/qltk/prefs.py:283 #, fuzzy msgctxt "heading" msgid "Search" msgstr "搜索" #: ../quodlibet/qltk/prefs.py:287 ../quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "浏览器" #: ../quodlibet/qltk/prefs.py:293 msgid "Confirm _multiple ratings" msgstr "" #: ../quodlibet/qltk/prefs.py:295 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "" #: ../quodlibet/qltk/prefs.py:298 msgid "Enable _one-click ratings" msgstr "" #: ../quodlibet/qltk/prefs.py:300 #, fuzzy msgid "Enable rating by clicking on the rating column in the song list" msgstr "当正在播放的曲目改变的时候,在曲目列表里相应跳过去" #: ../quodlibet/qltk/prefs.py:306 ../quodlibet/qltk/prefs.py:616 #, fuzzy msgid "Ratings" msgstr "评分(_R)" #. Filename choice algorithm config #: ../quodlibet/qltk/prefs.py:312 msgid "Prefer _embedded art" msgstr "" #: ../quodlibet/qltk/prefs.py:314 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" #: ../quodlibet/qltk/prefs.py:319 msgid "_Fixed image filename:" msgstr "" #: ../quodlibet/qltk/prefs.py:321 msgid "The single image filename to use if selected" msgstr "" #: ../quodlibet/qltk/prefs.py:327 msgid "The album art image file to use when forced" msgstr "" #: ../quodlibet/qltk/prefs.py:336 #, fuzzy msgid "Album Art" msgstr "专辑列表" #: ../quodlibet/qltk/prefs.py:357 #, fuzzy msgid "Playback" msgstr "暂停回放" #: ../quodlibet/qltk/prefs.py:362 msgid "Output Configuration" msgstr "" #: ../quodlibet/qltk/prefs.py:373 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" #: ../quodlibet/qltk/prefs.py:376 msgid "_Fall-back gain (dB):" msgstr "" #: ../quodlibet/qltk/prefs.py:387 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "" #: ../quodlibet/qltk/prefs.py:390 msgid "_Pre-amp gain (dB):" msgstr "" #: ../quodlibet/qltk/prefs.py:395 #, fuzzy msgid "_Enable Replay Gain volume adjustment" msgstr "无音量调整" #: ../quodlibet/qltk/prefs.py:420 #, fuzzy msgid "Replay Gain Volume Adjustment" msgstr "无音量调整" #: ../quodlibet/qltk/prefs.py:450 msgid "_Default rating:" msgstr "" #: ../quodlibet/qltk/prefs.py:493 #, fuzzy msgid "Rating _scale:" msgstr "评分(_R)" #: ../quodlibet/qltk/prefs.py:542 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:547 msgid "_Bayesian averaging amount:" msgstr "" #: ../quodlibet/qltk/prefs.py:556 msgid "Save ratings and play _counts" msgstr "" #: ../quodlibet/qltk/prefs.py:560 msgid "_Email:" msgstr "" #: ../quodlibet/qltk/prefs.py:562 msgid "Ratings and play counts will be set for this email address" msgstr "" #: ../quodlibet/qltk/prefs.py:577 msgid "Auto-save tag changes" msgstr "" #: ../quodlibet/qltk/prefs.py:579 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "" #: ../quodlibet/qltk/prefs.py:587 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:610 #, fuzzy msgid "Tags" msgstr "编辑标签" #: ../quodlibet/qltk/prefs.py:631 #, fuzzy msgid "Updating for new ratings" msgstr "新站点(_N)" #: ../quodlibet/qltk/prefs.py:641 #, fuzzy msgid "Scan library _on start" msgstr "刷新库(_F)" #: ../quodlibet/qltk/prefs.py:651 ../quodlibet/qltk/quodlibetwindow.py:1100 #, fuzzy msgid "_Scan Library" msgstr "搜索库(_S)" #: ../quodlibet/qltk/prefs.py:653 ../quodlibet/qltk/quodlibetwindow.py:1162 msgid "Check for changes in your library" msgstr "检查您的库的更改" #: ../quodlibet/qltk/prefs.py:658 #, fuzzy msgid "Re_build Library" msgstr "重新导入库(_L)" #: ../quodlibet/qltk/prefs.py:661 #, fuzzy msgid "Reload all songs in your library. This can take a long time." msgstr "重新导入您的库里的所有曲目(可能会花费较长时间)" #: ../quodlibet/qltk/prefs.py:671 #, fuzzy msgid "Scan Directories" msgstr "扫描目录(_D)" #: ../quodlibet/qltk/prefs.py:677 #, fuzzy msgid "Hidden Songs" msgstr "没有曲目" #: ../quodlibet/qltk/properties.py:158 ../quodlibet/util/collection.py:398 #, python-format msgid "%(title)s and %(count)d more" msgid_plural "%(title)s and %(count)d more" msgstr[0] "" #: ../quodlibet/qltk/properties.py:162 ../quodlibet/qltk/properties.py:164 msgid "Properties" msgstr "属性" #: ../quodlibet/qltk/queue.py:101 msgid "_Queue" msgstr "队列(_Q)" #: ../quodlibet/qltk/queue.py:126 msgid "Stop Once Empty" msgstr "" #: ../quodlibet/qltk/queue.py:130 #, fuzzy msgid "_Clear Queue" msgstr "插件错误" #: ../quodlibet/qltk/queue.py:242 #, python-format msgid "%(count)d song (%(time)s)" msgid_plural "%(count)d songs (%(time)s)" msgstr[0] "" #: ../quodlibet/qltk/quodlibetwindow.py:198 msgid "_Browse Library" msgstr "浏览库(_B)" #: ../quodlibet/qltk/quodlibetwindow.py:395 #, fuzzy msgid "Toggle queue visibility" msgstr "切换主窗口可见性" #: ../quodlibet/qltk/quodlibetwindow.py:516 #, fuzzy msgid "Playback Error" msgstr "暂停回放" #: ../quodlibet/qltk/quodlibetwindow.py:524 #, fuzzy msgid "Set up library directories?" msgstr "选择目录" #: ../quodlibet/qltk/quodlibetwindow.py:525 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:531 msgid "_Not Now" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:532 msgid "_Set Up" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:956 msgid "Unable to add songs" msgstr "无法添加曲目信息" #: ../quodlibet/qltk/quodlibetwindow.py:957 #: ../quodlibet/qltk/quodlibetwindow.py:1364 #, fuzzy, python-format msgid "%s uses an unsupported protocol." msgstr "<b>%s</b>使用不支持的协议。" #: ../quodlibet/qltk/quodlibetwindow.py:980 msgid "_Jump to Playing Song" msgstr "跳到正在播放的曲目(_J)" #: ../quodlibet/qltk/quodlibetwindow.py:986 #, fuzzy msgid "_File" msgstr "文件" #: ../quodlibet/qltk/quodlibetwindow.py:987 #, fuzzy msgid "_Song" msgstr "曲目" #: ../quodlibet/qltk/quodlibetwindow.py:988 msgid "_View" msgstr "查看(_V)" #: ../quodlibet/qltk/quodlibetwindow.py:989 #, fuzzy msgid "_Browse" msgstr "浏览器" #: ../quodlibet/qltk/quodlibetwindow.py:990 msgid "_Control" msgstr "控制(_C)" #: ../quodlibet/qltk/quodlibetwindow.py:991 msgid "_Help" msgstr "帮助(_H)" #: ../quodlibet/qltk/quodlibetwindow.py:997 #, fuzzy msgid "_Add a Folder…" msgstr "加入文件夹(_A)..." #: ../quodlibet/qltk/quodlibetwindow.py:1002 #, fuzzy msgid "_Add a File…" msgstr "加入文件(_A)..." #: ../quodlibet/qltk/quodlibetwindow.py:1007 #, fuzzy msgid "_Add a Location…" msgstr "加入位置" #: ../quodlibet/qltk/quodlibetwindow.py:1036 #, fuzzy msgid "Edit Bookmarks…" msgstr "编辑书签(_E)..." #: ../quodlibet/qltk/quodlibetwindow.py:1056 #, fuzzy msgid "Stop After This Song" msgstr "这首曲目放完后就停止" #: ../quodlibet/qltk/quodlibetwindow.py:1062 msgid "_Keyboard Shortcuts" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:1071 msgid "Online Help" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:1080 #, fuzzy msgid "Search Help" msgstr "搜索" #: ../quodlibet/qltk/quodlibetwindow.py:1352 msgid "Add a Location" msgstr "加入位置" #: ../quodlibet/qltk/quodlibetwindow.py:1353 msgid "Enter the location of an audio file:" msgstr "输入音频文件的位置:" #: ../quodlibet/qltk/quodlibetwindow.py:1358 #: ../quodlibet/qltk/quodlibetwindow.py:1363 msgid "Unable to add location" msgstr "无法添加位置" #: ../quodlibet/qltk/quodlibetwindow.py:1359 #, fuzzy, python-format msgid "%s is not a valid location." msgstr "<b>%s</b> 不是合法的位置。" #: ../quodlibet/qltk/quodlibetwindow.py:1372 #: ../quodlibet/qltk/quodlibetwindow.py:1381 msgid "Add Music" msgstr "添加音乐" #: ../quodlibet/qltk/quodlibetwindow.py:1372 ../quodlibet/qltk/scanbox.py:99 #, fuzzy msgid "_Add Folders" msgstr "加入文件夹(_A)..." #: ../quodlibet/qltk/quodlibetwindow.py:1379 #, fuzzy msgid "Music Files" msgstr "音乐播放器" #: ../quodlibet/qltk/quodlibetwindow.py:1381 #, fuzzy msgid "_Add Files" msgstr "加入文件(_A)..." #: ../quodlibet/qltk/ratingsmenu.py:24 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "" #: ../quodlibet/qltk/ratingsmenu.py:26 msgid "The saved ratings will be removed" msgstr "" #: ../quodlibet/qltk/ratingsmenu.py:27 #, python-format msgid "The rating of all selected songs will be changed to '%s'" msgstr "" #: ../quodlibet/qltk/ratingsmenu.py:57 ../quodlibet/qltk/ratingsmenu.py:111 #, fuzzy msgid "_Remove Rating" msgstr "删除站点(_R)" #: ../quodlibet/qltk/ratingsmenu.py:98 #, fuzzy msgid "Change _Rating" msgstr "评分(_R)" #: ../quodlibet/qltk/renamefiles.py:46 msgid "Replace spaces with _underscores" msgstr "" #: ../quodlibet/qltk/renamefiles.py:56 msgid "Strip _Windows-incompatible characters" msgstr "" #: ../quodlibet/qltk/renamefiles.py:74 msgid "Strip _diacritical marks" msgstr "" #: ../quodlibet/qltk/renamefiles.py:85 msgid "Strip non-_ASCII characters" msgstr "" #: ../quodlibet/qltk/renamefiles.py:95 msgid "Use only _lowercase characters" msgstr "" #: ../quodlibet/qltk/renamefiles.py:123 msgid "Rename Files" msgstr "重命名文件" #: ../quodlibet/qltk/renamefiles.py:139 ../quodlibet/qltk/tagsfrompath.py:116 #, fuzzy msgid "Path Patterns" msgstr "参数" #: ../quodlibet/qltk/renamefiles.py:140 ../quodlibet/qltk/tagsfrompath.py:117 #, fuzzy msgid "Edit saved patterns…" msgstr "编辑已保存的值..." #: ../quodlibet/qltk/renamefiles.py:143 ../quodlibet/qltk/tagsfrompath.py:120 #: ../quodlibet/qltk/tracknumbers.py:58 msgid "_Preview" msgstr "预览(_P)" #: ../quodlibet/qltk/renamefiles.py:190 msgid "New Name" msgstr "新的名字" #: ../quodlibet/qltk/renamefiles.py:255 msgid "Unable to rename file" msgstr "无法重命名文件" #: ../quodlibet/qltk/renamefiles.py:256 #, python-format msgid "" "Renaming <b>%(old-name)s</b> to <b>%(new-name)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." msgstr "" #: ../quodlibet/qltk/renamefiles.py:264 #, fuzzy msgid "Ignore _All Errors" msgstr "显示错误(_E)" #: ../quodlibet/qltk/renamefiles.py:267 msgid "_Continue" msgstr "继续(_C)" #: ../quodlibet/qltk/renamefiles.py:296 msgid "Path is not absolute" msgstr "路径不是绝对的" #: ../quodlibet/qltk/renamefiles.py:297 #, python-format msgid "" "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 ~/." msgstr "" #: ../quodlibet/qltk/scanbox.py:47 #, fuzzy msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "这些文件夹里的曲目(由“:”分隔)将会被加入到您的库里" #: ../quodlibet/qltk/scanbox.py:99 msgid "Select Directories" msgstr "选择目录" #: ../quodlibet/qltk/searchbar.py:52 #, fuzzy msgid "Saved Searches" msgstr "已保存值" #: ../quodlibet/qltk/searchbar.py:53 #, fuzzy msgid "Edit saved searches…" msgstr "编辑已保存的值..." #: ../quodlibet/qltk/searchbar.py:74 msgid "Search your library, using free text or QL queries" msgstr "" #: ../quodlibet/qltk/searchbar.py:129 #, fuzzy msgid "Search after _typing" msgstr "这首曲目放完后就停止" #: ../quodlibet/qltk/searchbar.py:132 msgid "Show search results after the user stops typing." msgstr "" #: ../quodlibet/qltk/searchbar.py:187 msgid "_Limit:" msgstr "限制(_L):" #: ../quodlibet/qltk/searchbar.py:200 msgid "_Weight" msgstr "权重(_W)" #: ../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 ../quodlibet/qltk/shortcuts.py:41 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: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:377 #, python-format msgid "_Filter on %s" msgstr "以 %s 过滤(_F)" #: ../quodlibet/qltk/songlist.py:1094 #, fuzzy msgid "All _Headers" msgstr "专辑列表(_A)" #: ../quodlibet/qltk/songlist.py:1095 #, fuzzy msgid "_Track Headers" msgstr "音轨号" #: ../quodlibet/qltk/songlist.py:1096 #, fuzzy msgid "_Album Headers" msgstr "专辑列表(_A)" #: ../quodlibet/qltk/songlist.py:1097 msgid "_People Headers" msgstr "" #: ../quodlibet/qltk/songlist.py:1098 msgid "_Date Headers" msgstr "" #: ../quodlibet/qltk/songlist.py:1099 #, fuzzy msgid "_File Headers" msgstr "过滤器(_F)" #: ../quodlibet/qltk/songlist.py:1100 msgid "_Production Headers" msgstr "" #: ../quodlibet/qltk/songlist.py:1115 #, fuzzy msgid "_Customize Headers…" msgstr "过滤器(_F)" #: ../quodlibet/qltk/songlist.py:1120 msgid "_Expand Column" msgstr "" #: ../quodlibet/qltk/songsmenu.py:36 #, 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:64 #, 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:149 #, fuzzy msgid "Configure Plugins…" msgstr "给搜索条件着色(_S)" #: ../quodlibet/qltk/songsmenu.py:345 msgid "Add to _Queue" msgstr "加入到队列(_Q)" #: ../quodlibet/qltk/songsmenu.py:368 msgid "_Copy to Device" msgstr "" #: ../quodlibet/qltk/songsmenu.py:379 #, fuzzy msgid "_Remove from Library" msgstr "从播放列表里删除(_R)" #: ../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:101 msgid "Tags From Path" msgstr "" #: ../quodlibet/qltk/tagsfrompath.py:138 msgid "Tags replace existing ones" msgstr "" #: ../quodlibet/qltk/tagsfrompath.py:139 msgid "Tags are added to existing ones" msgstr "" #. Save button #: ../quodlibet/qltk/tagsfrompath.py:153 msgid "Save" msgstr "" #: ../quodlibet/qltk/tagsfrompath.py:195 #, python-format msgid "" "The pattern\n" "\t<b>%s</b>\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" #: ../quodlibet/qltk/tagsfrompath.py:216 msgid "Invalid tags" msgstr "非法标签" #: ../quodlibet/qltk/tagsfrompath.py:217 #, python-format msgid "" "Invalid tags <b>%s</b>\n" "\n" "The files currently selected do not support editing these tags." msgstr "" #: ../quodlibet/qltk/textedit.py:142 #, 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:158 msgid "Edit Display" msgstr "编辑显示" #: ../quodlibet/qltk/tracknumbers.py:39 msgid "Track Numbers" msgstr "音轨号" #: ../quodlibet/qltk/tracknumbers.py:42 msgid "Start fro_m:" msgstr "开始于(_M):" #: ../quodlibet/qltk/tracknumbers.py:51 msgid "_Total tracks:" msgstr "总音轨数:" #: ../quodlibet/qltk/unity.py:52 #, fuzzy msgid "Play/Pause" msgstr "播放器" #: ../quodlibet/qltk/unity.py:75 #, fuzzy msgid "Previous" msgstr "预览(_P)" #: ../quodlibet/qltk/views.py:923 #, 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 #, fuzzy, python-format msgid "%(current)s of %(all)s" msgstr "正在移动 %d/%d" #: ../quodlibet/update.py:89 #, fuzzy msgid "Checking for Updates" msgstr "挂载点" #: ../quodlibet/update.py:124 #, fuzzy msgid "Connection failed" msgstr "位置" #: ../quodlibet/update.py:133 #, python-format msgid "You are already using the newest version %(version)s" msgstr "" #: ../quodlibet/update.py:136 #, 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:420 msgid "Playlists must have a name" msgstr "" #: ../quodlibet/util/collection.py:603 #, python-format msgid "A playlist named %s already exists." msgstr "名为 %s 的播放列表已经存在" #: ../quodlibet/util/cover/built_in.py:26 #, fuzzy msgid "Embedded album covers" msgstr "显示专辑封面(_C)" #: ../quodlibet/util/cover/built_in.py:27 msgid "Uses covers embedded into audio files." msgstr "" #: ../quodlibet/util/cover/built_in.py:49 #, fuzzy msgid "Filesystem cover" msgstr "文件系统" #: ../quodlibet/util/cover/built_in.py:50 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "" #: ../quodlibet/util/__init__.py:93 msgid "Display brief usage information" msgstr "" #: ../quodlibet/util/__init__.py:95 msgid "Display version and copyright" msgstr "显示版本和版权" #: ../quodlibet/util/__init__.py:135 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "" #: ../quodlibet/util/__init__.py:137 msgid "[options]" msgstr "[选项]" #: ../quodlibet/util/__init__.py:182 #, python-format msgid "Option %r not recognized." msgstr "" #: ../quodlibet/util/__init__.py:185 #, python-format msgid "Option %r requires an argument." msgstr "" #: ../quodlibet/util/__init__.py:188 #, python-format msgid "%r is not a unique prefix." msgstr "" #: ../quodlibet/util/__init__.py:364 #, python-format msgid "%d kbps" msgstr "%d kbps" #: ../quodlibet/util/__init__.py:419 #, fuzzy, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%d 秒" #: ../quodlibet/util/__init__.py:432 msgid "No time information" msgstr "没有时间信息" #: ../quodlibet/util/__init__.py:435 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d 秒" #: ../quodlibet/util/__init__.py:436 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d 分" #: ../quodlibet/util/__init__.py:437 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d 小时" #: ../quodlibet/util/__init__.py:438 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d 天" #: ../quodlibet/util/__init__.py:439 #, 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:563 #, 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 "" #. 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 msgid "Unable to edit song" msgstr "无法编辑曲目" #: ../quodlibet/util/songwrapper.py:113 #, python-format msgid "" "Saving <b>%s</b> 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:34 #: ../quodlibet/util/string/__init__.py:44 msgid "[Invalid Encoding]" msgstr "[非法编码]" #: ../quodlibet/util/tags.py:74 msgid "album" msgstr "专辑" #: ../quodlibet/util/tags.py:75 msgid "arranger" msgstr "" #: ../quodlibet/util/tags.py:75 msgid "arrangers" msgstr "" #: ../quodlibet/util/tags.py:75 msgid "arrangement" msgstr "" #: ../quodlibet/util/tags.py:77 msgid "author" msgstr "作者" #: ../quodlibet/util/tags.py:77 msgid "authors" msgstr "作者" #: ../quodlibet/util/tags.py:78 msgid "composer" msgstr "作曲" #: ../quodlibet/util/tags.py:78 msgid "composers" msgstr "作曲" #: ../quodlibet/util/tags.py:78 #, fuzzy msgid "composition" msgstr "作曲" #. Translators: conducting as in conducting a musical performance #: ../quodlibet/util/tags.py:80 msgid "conductor" msgstr "执导" #: ../quodlibet/util/tags.py:80 msgid "conductors" msgstr "执导" #: ../quodlibet/util/tags.py:80 #, fuzzy msgid "conducting" msgstr "执导" #: ../quodlibet/util/tags.py:81 msgid "contact" msgstr "" #: ../quodlibet/util/tags.py:82 msgid "copyright" msgstr "版权" #: ../quodlibet/util/tags.py:83 msgid "date" msgstr "日期" #: ../quodlibet/util/tags.py:84 msgid "description" msgstr "描述" #: ../quodlibet/util/tags.py:85 msgid "genre" msgstr "流派" #: ../quodlibet/util/tags.py:85 #, fuzzy msgid "genres" msgstr "流派" #: ../quodlibet/util/tags.py:86 msgid "performer" msgstr "表演" #: ../quodlibet/util/tags.py:87 msgid "grouping" msgstr "组合" #: ../quodlibet/util/tags.py:88 msgid "language" msgstr "语言" #: ../quodlibet/util/tags.py:89 msgid "license" msgstr "许可" #: ../quodlibet/util/tags.py:90 msgid "location" msgstr "位置" #: ../quodlibet/util/tags.py:91 msgid "lyricist" msgstr "作词" #: ../quodlibet/util/tags.py:91 msgid "lyricists" msgstr "作词" #: ../quodlibet/util/tags.py:91 #, fuzzy msgid "lyrics" msgstr "作词" #. Translators: Also e.g. "record label", "publisher" #: ../quodlibet/util/tags.py:93 msgid "organization" msgstr "组织" #: ../quodlibet/util/tags.py:94 msgid "title" msgstr "标题" #: ../quodlibet/util/tags.py:95 msgid "version" msgstr "版本" #: ../quodlibet/util/tags.py:96 msgid "website" msgstr "网站" #: ../quodlibet/util/tags.py:98 msgid "album artist" msgstr "专辑歌手" #: ../quodlibet/util/tags.py:99 msgid "BPM" msgstr "" #. Translators: This used to be called "part". #: ../quodlibet/util/tags.py:102 ../quodlibet/util/tags.py:103 msgid "disc subtitle" msgstr "" #: ../quodlibet/util/tags.py:104 ../quodlibet/util/tags.py:141 msgid "disc" msgstr "唱片" #: ../quodlibet/util/tags.py:105 ../quodlibet/util/tags.py:143 msgid "track" msgstr "音轨" #: ../quodlibet/util/tags.py:106 msgid "label ID" msgstr "" #: ../quodlibet/util/tags.py:107 msgid "original release date" msgstr "原始发行日期" #: ../quodlibet/util/tags.py:108 msgid "original album" msgstr "原始专辑" #: ../quodlibet/util/tags.py:109 msgid "original artist" msgstr "原始歌手" #: ../quodlibet/util/tags.py:110 msgid "recording date" msgstr "录制日期" #: ../quodlibet/util/tags.py:111 msgid "release country" 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:120 #, fuzzy msgid "MusicBrainz recording ID" msgstr "MusicBrainz 音轨 ID" #: ../quodlibet/util/tags.py:121 #, fuzzy msgid "MusicBrainz release track ID" msgstr "MusicBrainz 音轨 ID" #: ../quodlibet/util/tags.py:122 #, fuzzy msgid "MusicBrainz release ID" msgstr "MusicBrainz 音轨 ID" #: ../quodlibet/util/tags.py:123 #, fuzzy msgid "MusicBrainz artist ID" msgstr "MusicBrainz 歌手 ID" #: ../quodlibet/util/tags.py:124 #, fuzzy msgid "MusicBrainz release artist ID" msgstr "MusicBrainz 音轨 ID" #: ../quodlibet/util/tags.py:125 msgid "MusicBrainz TRM ID" msgstr "" #: ../quodlibet/util/tags.py:126 msgid "MusicIP PUID" msgstr "" #: ../quodlibet/util/tags.py:127 #, fuzzy msgid "MusicBrainz album status" msgstr "MusicBrainz 专辑歌手 ID" #: ../quodlibet/util/tags.py:128 #, fuzzy msgid "MusicBrainz album type" msgstr "MusicBrainz 专辑 ID" #: ../quodlibet/util/tags.py:129 #, fuzzy msgid "MusicBrainz release group ID" msgstr "MusicBrainz 音轨 ID" #. Translators: "gain" means a volume adjustment, not "to acquire". #: ../quodlibet/util/tags.py:132 msgid "track gain" msgstr "音轨调整" #: ../quodlibet/util/tags.py:133 msgid "track peak" msgstr "" #. Translators: "gain" means a volume adjustment, not "to acquire". #: ../quodlibet/util/tags.py:135 msgid "album gain" msgstr "专辑调整" #: ../quodlibet/util/tags.py:136 msgid "album peak" msgstr "" #: ../quodlibet/util/tags.py:137 msgid "reference loudness" msgstr "" #: ../quodlibet/util/tags.py:142 msgid "discs" msgstr "唱片" #: ../quodlibet/util/tags.py:144 msgid "tracks" msgstr "音轨" #: ../quodlibet/util/tags.py:145 #, fuzzy msgid "last started" msgstr "最近一次播放" #: ../quodlibet/util/tags.py:146 msgid "full name" msgstr "全名" #: ../quodlibet/util/tags.py:153 msgid "mount point" msgstr "挂载点" #: ../quodlibet/util/tags.py:155 msgid "people" msgstr "" #: ../quodlibet/util/tags.py:157 msgid "year" msgstr "年份" #: ../quodlibet/util/tags.py:158 #, fuzzy msgid "original release year" msgstr "原始发行日期" #: ../quodlibet/util/tags.py:159 #, fuzzy msgid "bookmark" msgstr "书签" #: ../quodlibet/util/tags.py:162 #, fuzzy msgid "file format" msgstr "格式" #: ../quodlibet/util/tags.py:165 #, fuzzy msgid "playlists" msgstr "播放列表" #: ../quodlibet/util/tags.py:166 msgid "channel count" msgstr "" #. Translators: e.g. "artist (sort)" #: ../quodlibet/util/tags.py:256 msgid "sort" msgstr "" #. Translators: e.g. "performer (roles)" #: ../quodlibet/util/tags.py:264 msgid "roles" msgstr "" #, fuzzy #~ msgid "browsers" #~ msgstr "浏览器" #~ msgid "Remove all songs from the queue" #~ msgstr "删除队列里的所有曲目" #~ msgid "Watch this folder for new songs" #~ 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 "Unable to open input files" #~ msgstr "无法打开文件" #, 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 "_Select" #~ msgstr "选择(_S)" #~ 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 "Choose New Stations" #~ msgstr "选择新的站点" #~ msgid "Add" #~ msgstr "加入" #, fuzzy #~ msgid "Bitrate" #~ msgstr "比特率" #~ msgid "_Stations..." #~ msgstr "站点(_S)..." #, fuzzy #~ msgid "Quod Libet" #~ msgstr "退出 Quod Libet" #~ 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9791858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/po/zh_TW.po�������������������������������������������������������������������������0000644�0001750�0001750�00000516770�00000000000�014527� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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: 2017-05-17 18:58+0200\n" "PO-Revision-Date: 2013-07-20 22:36+0100\n" "Last-Translator: Hsin-lin Cheng <lancetw@gmail.com>\n" "Language-Team: Hsin-lin Cheng <lancetw@gmail.com>\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: Poedit 1.5.4\n" #: ../data/exfalso.appdata.xml.in.h:1 ../data/exfalso.desktop.in.h:2 msgid "Edit tags in your audio files" msgstr "編輯您的音訊標籤" #: ../data/exfalso.appdata.xml.in.h:2 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/exfalso.appdata.xml.in.h:3 ../data/quodlibet.appdata.xml.in.h:3 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/exfalso.desktop.in.h:1 msgid "Audio tag editor" msgstr "音效標籤編輯器" #: ../data/quodlibet.appdata.xml.in.h:1 ../data/quodlibet.desktop.in.h:2 msgid "Listen to, browse, or edit your audio collection" msgstr "收聽、瀏覽,或編輯您的音訊收藏" #: ../data/quodlibet.appdata.xml.in.h:2 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 "" #: ../data/quodlibet.desktop.in.h:1 msgid "Music Player" msgstr "音樂播放器" #: ../quodlibet/browsers/albums/main.py:168 #: ../quodlibet/browsers/covergrid/main.py:54 #, fuzzy msgid "_Title" msgstr "標題" #: ../quodlibet/browsers/albums/main.py:169 #: ../quodlibet/browsers/covergrid/main.py:55 ../quodlibet/qltk/prefs.py:49 msgid "_Artist" msgstr "演出者 (_A)" #: ../quodlibet/browsers/albums/main.py:170 #: ../quodlibet/browsers/covergrid/main.py:56 ../quodlibet/qltk/prefs.py:54 msgid "_Date" msgstr "日期 (_D)" #: ../quodlibet/browsers/albums/main.py:171 #: ../quodlibet/browsers/covergrid/main.py:57 ../quodlibet/qltk/prefs.py:53 #, fuzzy msgid "_Genre" msgstr "風格" #: ../quodlibet/browsers/albums/main.py:172 #: ../quodlibet/browsers/covergrid/main.py:58 ../quodlibet/qltk/prefs.py:58 #: ../quodlibet/qltk/ratingsmenu.py:39 msgid "_Rating" msgstr "評等 (_R)" #: ../quodlibet/browsers/albums/main.py:178 #: ../quodlibet/browsers/covergrid/main.py:64 #, fuzzy msgid "Sort _by…" msgstr "依日期排序" #: ../quodlibet/browsers/albums/main.py:199 #: ../quodlibet/browsers/covergrid/main.py:85 #: ../quodlibet/browsers/paned/prefs.py:166 #: ../quodlibet/browsers/playlists/main.py:629 #: ../quodlibet/qltk/exfalsowindow.py:109 ../quodlibet/qltk/pluginwin.py:341 #: ../quodlibet/qltk/quodlibetwindow.py:1016 #, fuzzy msgid "_Preferences" msgstr "偏好設定" #: ../quodlibet/browsers/albums/main.py:361 msgid "Album List" msgstr "專輯清單" #: ../quodlibet/browsers/albums/main.py:362 msgid "_Album List" msgstr "專輯清單 (_A)" #: ../quodlibet/browsers/albums/main.py:472 #: ../quodlibet/browsers/covergrid/main.py:279 #: ../quodlibet/browsers/covergrid/main.py:488 msgid "All Albums" msgstr "所有專輯" #: ../quodlibet/browsers/albums/main.py:473 #: ../quodlibet/browsers/covergrid/main.py:280 #: ../quodlibet/browsers/covergrid/main.py:489 #, python-format msgid "%d album" msgid_plural "%d albums" msgstr[0] "%d 專輯" #: ../quodlibet/browsers/albums/main.py:650 #: ../quodlibet/browsers/covergrid/main.py:467 #, fuzzy 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:381 ../quodlibet/util/collection.py:245 #, 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:379 ../quodlibet/util/collection.py:249 #, python-format msgid "%d disc" msgid_plural "%d discs" msgstr[0] "%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 "顯示專輯封面 (_C)" #: ../quodlibet/browsers/albums/prefs.py:67 msgid "Inline _search includes people" msgstr "" #: ../quodlibet/browsers/albums/prefs.py:71 #: ../quodlibet/browsers/covergrid/prefs.py:120 #, fuzzy msgid "Options" msgstr "[選項]" #: ../quodlibet/browsers/albums/prefs.py:74 #: ../quodlibet/browsers/covergrid/prefs.py:123 msgid "Album Display" msgstr "專輯顯示" #: ../quodlibet/browsers/albums/prefs.py:78 #: ../quodlibet/browsers/covergrid/prefs.py:127 #: ../quodlibet/browsers/media.py:39 #: ../quodlibet/browsers/playlists/prefs.py:56 #: ../quodlibet/ext/songsmenu/albumart.py:326 #: ../quodlibet/ext/songsmenu/duplicates.py:350 #: ../quodlibet/ext/songsmenu/filterall.py:48 #: ../quodlibet/qltk/bookmarks.py:101 ../quodlibet/qltk/cbes.py:93 #: ../quodlibet/qltk/data_editors.py:99 ../quodlibet/qltk/data_editors.py:324 #: ../quodlibet/qltk/exfalsowindow.py:297 ../quodlibet/qltk/pluginwin.py:79 #: ../quodlibet/qltk/pluginwin.py:427 ../quodlibet/qltk/prefs.py:707 #: ../quodlibet/qltk/textedit.py:164 ../quodlibet/update.py:148 msgid "_Close" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:55 #: ../quodlibet/browsers/audiofeeds.py:67 #: ../quodlibet/browsers/audiofeeds.py:69 #: ../quodlibet/browsers/audiofeeds.py:159 #: ../quodlibet/browsers/paned/models.py:86 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:46 #: ../quodlibet/formats/_audio.py:495 ../quodlibet/order/__init__.py:27 #: ../quodlibet/qltk/information.py:240 ../quodlibet/qltk/information.py:247 #: ../quodlibet/qltk/information.py:273 ../quodlibet/qltk/wlw.py:70 msgid "Unknown" msgstr "未知" #: ../quodlibet/browsers/audiofeeds.py:246 msgid "New Feed" msgstr "新的饋流" #: ../quodlibet/browsers/audiofeeds.py:247 msgid "Enter the location of an audio feed:" msgstr "輸入音訊檔案饋流位置:" #: ../quodlibet/browsers/audiofeeds.py:248 #: ../quodlibet/browsers/collection/prefs.py:90 #: ../quodlibet/browsers/iradio.py:341 ../quodlibet/browsers/paned/prefs.py:78 #: ../quodlibet/browsers/playlists/menu.py:96 #: ../quodlibet/browsers/playlists/util.py:52 ../quodlibet/qltk/bookmarks.py:62 #: ../quodlibet/qltk/cbes.py:55 ../quodlibet/qltk/data_editors.py:311 #: ../quodlibet/qltk/edittags.py:288 ../quodlibet/qltk/edittags.py:488 #: ../quodlibet/qltk/quodlibetwindow.py:1354 ../quodlibet/qltk/scanbox.py:61 msgid "_Add" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:265 msgid "Audio Feeds" msgstr "音訊饋流" #: ../quodlibet/browsers/audiofeeds.py:266 msgid "_Audio Feeds" msgstr "音訊饋流 (_A)" #: ../quodlibet/browsers/audiofeeds.py:345 #: ../quodlibet/browsers/audiofeeds.py:350 #, fuzzy msgid "_Download…" msgstr "下載 (_D)" #: ../quodlibet/browsers/audiofeeds.py:359 msgid "Download Files" msgstr "下載檔案" #. Save button #: ../quodlibet/browsers/audiofeeds.py:359 #: ../quodlibet/browsers/audiofeeds.py:371 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:81 #: ../quodlibet/ext/songsmenu/albumart.py:322 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:355 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:278 #: ../quodlibet/ext/songsmenu/html.py:76 #: ../quodlibet/ext/songsmenu/lastfmsync.py:216 #: ../quodlibet/ext/songsmenu/playlist.py:51 #: ../quodlibet/ext/songsmenu/replaygain.py:365 #: ../quodlibet/ext/songsmenu/tapbpm.py:182 ../quodlibet/qltk/_editutils.py:39 #: ../quodlibet/qltk/lyrics.py:38 ../quodlibet/qltk/msg.py:52 #: ../quodlibet/qltk/renamefiles.py:168 ../quodlibet/qltk/tracknumbers.py:113 msgid "_Save" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:371 msgid "Download File" msgstr "下載檔案" #: ../quodlibet/browsers/audiofeeds.py:394 #: ../quodlibet/browsers/playlists/main.py:213 #: ../quodlibet/qltk/data_editors.py:96 msgid "_New" msgstr "" #: ../quodlibet/browsers/audiofeeds.py:454 #: ../quodlibet/browsers/audiofeeds.py:513 msgid "Unable to add feed" msgstr "無法加入饋流" #: ../quodlibet/browsers/audiofeeds.py:455 #: ../quodlibet/browsers/audiofeeds.py:514 #, fuzzy, python-format msgid "" "%s could not be added. The server may be down, or the location may not be an " "audio feed." msgstr "<b>%s</b> 不能被加入。伺服器可能關機中,或者這位置可能不是音訊饋流。" #. refresh button #: ../quodlibet/browsers/audiofeeds.py:462 ../quodlibet/browsers/media.py:217 #: ../quodlibet/browsers/media.py:386 ../quodlibet/qltk/filesel.py:259 #: ../quodlibet/qltk/pluginwin.py:413 #, fuzzy msgid "_Refresh" msgstr "重新整理資料庫 (_F)" #: ../quodlibet/browsers/audiofeeds.py:463 #: ../quodlibet/browsers/playlists/main.py:457 #: ../quodlibet/browsers/playlists/util.py:43 ../quodlibet/qltk/delete.py:143 #: ../quodlibet/qltk/filesel.py:256 ../quodlibet/qltk/lyrics.py:39 #: ../quodlibet/qltk/maskedbox.py:28 ../quodlibet/qltk/songsmenu.py:392 #, fuzzy msgid "_Delete" msgstr "刪除檔案" #: ../quodlibet/browsers/audiofeeds.py:530 msgid "" "The current audio backend does not support URLs, Audio Feeds browser " "disabled." msgstr "" #: ../quodlibet/browsers/_base.py:147 ../quodlibet/browsers/_base.py:150 msgid "Library Browser" msgstr "資料庫瀏覽器" #: ../quodlibet/browsers/_base.py:274 ../quodlibet/ext/songsmenu/refresh.py:30 #: ../quodlibet/qltk/exfalsowindow.py:241 ../quodlibet/qltk/information.py:542 #: ../quodlibet/qltk/maskedbox.py:68 ../quodlibet/util/collection.py:527 #, python-format msgid "%d song" msgid_plural "%d songs" msgstr[0] "%d 曲目" #: ../quodlibet/browsers/_base.py:402 ../quodlibet/browsers/_base.py:407 #: ../quodlibet/qltk/tagsfrompath.py:194 ../quodlibet/qltk/textedit.py:141 #: ../quodlibet/util/__init__.py:622 msgid "Invalid pattern" msgstr "無效的格式" #: ../quodlibet/browsers/collection/main.py:78 msgid "Album Collection" msgstr "" #: ../quodlibet/browsers/collection/main.py:79 msgid "Album _Collection" msgstr "" #: ../quodlibet/browsers/collection/models.py:24 #, fuzzy, python-format msgid "Unknown %s" msgstr "未知" #: ../quodlibet/browsers/collection/models.py:25 #, fuzzy, python-format msgid "Multiple %s Values" msgstr "多重設定值分割 (_M)" #: ../quodlibet/browsers/collection/prefs.py:66 #: ../quodlibet/browsers/paned/prefs.py:51 msgid "_Custom" msgstr "自訂 (_C)" #. Remove button #: ../quodlibet/browsers/collection/prefs.py:94 #: ../quodlibet/browsers/paned/prefs.py:82 #: ../quodlibet/browsers/playlists/menu.py:97 #: ../quodlibet/ext/playlist/remove_duplicates.py:60 #: ../quodlibet/qltk/bookmarks.py:97 ../quodlibet/qltk/bookmarks.py:127 #: ../quodlibet/qltk/cbes.py:82 ../quodlibet/qltk/cbes.py:89 #: ../quodlibet/qltk/data_editors.py:81 ../quodlibet/qltk/data_editors.py:94 #: ../quodlibet/qltk/data_editors.py:301 ../quodlibet/qltk/data_editors.py:314 #: ../quodlibet/qltk/data_editors.py:322 ../quodlibet/qltk/edittags.py:494 #: ../quodlibet/qltk/edittags.py:634 ../quodlibet/qltk/maskedbox.py:48 #: ../quodlibet/qltk/maskedbox.py:88 ../quodlibet/qltk/queue.py:350 #: ../quodlibet/qltk/scanbox.py:36 ../quodlibet/qltk/scanbox.py:63 #, fuzzy msgid "_Remove" msgstr "評等 (_R)" #: ../quodlibet/browsers/collection/prefs.py:122 #: ../quodlibet/ext/songsmenu/filterall.py:34 #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:92 #: ../quodlibet/qltk/edittags.py:431 msgid "Tag" msgstr "標籤" #: ../quodlibet/browsers/collection/prefs.py:128 msgid "Merge" msgstr "" #: ../quodlibet/browsers/collection/prefs.py:188 #, fuzzy msgid "Album Collection Preferences" msgstr "專輯清單偏好設定" #: ../quodlibet/browsers/collection/prefs.py:195 #: ../quodlibet/browsers/paned/prefs.py:209 #: ../quodlibet/ext/songsmenu/editplaycount.py:45 #: ../quodlibet/ext/songsmenu/exact_rating.py:38 #: ../quodlibet/player/gstbe/prefs.py:40 ../quodlibet/qltk/prefs.py:127 #: ../quodlibet/qltk/textedit.py:65 msgid "_Apply" msgstr "" #: ../quodlibet/browsers/collection/prefs.py:198 #: ../quodlibet/browsers/paned/prefs.py:213 #: ../quodlibet/browsers/playlists/menu.py:95 #: ../quodlibet/browsers/playlists/util.py:42 #: ../quodlibet/errorreport/ui.py:108 #: ../quodlibet/ext/playlist/export_to_folder.py:37 #: ../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:44 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:281 #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:88 #: ../quodlibet/ext/songsmenu/importexport.py:35 #: ../quodlibet/ext/songsmenu/lastfmsync.py:215 #: ../quodlibet/ext/songsmenu/playlist.py:50 #: ../quodlibet/ext/songsmenu/replaygain.py:364 #: ../quodlibet/ext/songsmenu/tapbpm.py:181 ../quodlibet/plugins/playlist.py:39 #: ../quodlibet/qltk/chooser.py:184 ../quodlibet/qltk/chooser.py:205 #: ../quodlibet/qltk/chooser.py:229 ../quodlibet/qltk/chooser.py:253 #: ../quodlibet/qltk/delete.py:90 ../quodlibet/qltk/delete.py:133 #: ../quodlibet/qltk/edittags.py:287 ../quodlibet/qltk/_editutils.py:38 #: ../quodlibet/qltk/getstring.py:28 ../quodlibet/qltk/maskedbox.py:27 #: ../quodlibet/qltk/msg.py:54 ../quodlibet/qltk/msg.py:93 #: ../quodlibet/qltk/ratingsmenu.py:33 ../quodlibet/qltk/songsmenu.py:45 #: ../quodlibet/qltk/songsmenu.py:73 ../quodlibet/update.py:94 msgid "_Cancel" msgstr "" #: ../quodlibet/browsers/covergrid/main.py:125 #, fuzzy msgid "Cover Grid" msgstr "合計大小:" #: ../quodlibet/browsers/covergrid/main.py:126 #, 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 "顯示專輯封面 (_C)" #: ../quodlibet/browsers/covergrid/prefs.py:71 #, fuzzy msgid "Show \"All Albums\" Item" msgstr "所有專輯" #: ../quodlibet/browsers/covergrid/prefs.py:78 msgid "Vertical Split" msgstr "" #: ../quodlibet/browsers/covergrid/prefs.py:110 #: ../quodlibet/browsers/covergrid/prefs.py:111 #, fuzzy msgid "Cover Magnification" msgstr "團體" #: ../quodlibet/browsers/filesystem.py:40 msgid "File System" msgstr "檔案系統" #: ../quodlibet/browsers/filesystem.py:41 msgid "_File System" msgstr "檔案系統 (_F)" #: ../quodlibet/browsers/filesystem.py:113 ../quodlibet/browsers/media.py:491 #: ../quodlibet/qltk/songlist.py:267 msgid "Unable to copy songs" msgstr "無法複製曲目" #: ../quodlibet/browsers/filesystem.py:114 ../quodlibet/qltk/songlist.py:268 msgid "The files selected cannot be copied to other song lists or the queue." msgstr "選取的檔案不能被複製到其他曲目清單或佇列。" #: ../quodlibet/browsers/filesystem.py:189 msgid "_Add to Library" msgstr "加入資料庫 (_A)" #: ../quodlibet/browsers/iradio.py:178 msgid "Unsupported file type" msgstr "未支援的檔案格式" #: ../quodlibet/browsers/iradio.py:179 #, 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:219 ../quodlibet/browsers/iradio.py:232 #: ../quodlibet/browsers/iradio.py:810 msgid "Unable to add station" msgstr "無法加入站台" #: ../quodlibet/browsers/iradio.py:243 ../quodlibet/browsers/iradio.py:471 msgid "Internet Radio" msgstr "網路電台" #: ../quodlibet/browsers/iradio.py:243 #, fuzzy msgid "Downloading station list" msgstr "下載檔案" #: ../quodlibet/browsers/iradio.py:339 msgid "New Station" msgstr "新站台" #: ../quodlibet/browsers/iradio.py:340 msgid "Enter the location of an Internet radio station:" msgstr "輸入網路電台位置:" #: ../quodlibet/browsers/iradio.py:358 msgid "Electronic" msgstr "" #: ../quodlibet/browsers/iradio.py:361 msgid "Hip Hop / Rap" msgstr "" #: ../quodlibet/browsers/iradio.py:362 msgid "Oldies" msgstr "" #: ../quodlibet/browsers/iradio.py:363 msgid "R&B" msgstr "" #: ../quodlibet/browsers/iradio.py:364 msgid "Japanese" msgstr "" #: ../quodlibet/browsers/iradio.py:365 msgid "Indian" msgstr "" #: ../quodlibet/browsers/iradio.py:367 msgid "Religious" msgstr "" #: ../quodlibet/browsers/iradio.py:369 msgid "Charts" msgstr "" #: ../quodlibet/browsers/iradio.py:370 msgid "Turkish" msgstr "" #: ../quodlibet/browsers/iradio.py:371 msgid "Reggae / Dancehall" msgstr "" #: ../quodlibet/browsers/iradio.py:372 #, fuzzy msgid "Latin" msgstr "曲目評等" #: ../quodlibet/browsers/iradio.py:373 msgid "College Radio" msgstr "" #: ../quodlibet/browsers/iradio.py:374 msgid "Talk / News" msgstr "" #: ../quodlibet/browsers/iradio.py:375 msgid "Ambient" msgstr "" #: ../quodlibet/browsers/iradio.py:376 msgid "Jazz" msgstr "" #: ../quodlibet/browsers/iradio.py:377 ../quodlibet/ext/events/equalizer.py:45 msgid "Classical" msgstr "" #: ../quodlibet/browsers/iradio.py:378 ../quodlibet/ext/events/equalizer.py:60 msgid "Pop" msgstr "" #: ../quodlibet/browsers/iradio.py:379 msgid "Alternative" msgstr "" #: ../quodlibet/browsers/iradio.py:380 msgid "Metal" msgstr "" #: ../quodlibet/browsers/iradio.py:381 msgid "Country" msgstr "" #: ../quodlibet/browsers/iradio.py:382 msgid "News" msgstr "" #: ../quodlibet/browsers/iradio.py:383 msgid "Schlager" msgstr "" #: ../quodlibet/browsers/iradio.py:384 msgid "Funk" msgstr "" #: ../quodlibet/browsers/iradio.py:385 msgid "Indie" msgstr "" #: ../quodlibet/browsers/iradio.py:386 msgid "Blues" msgstr "" #: ../quodlibet/browsers/iradio.py:387 msgid "Soul" msgstr "" #: ../quodlibet/browsers/iradio.py:388 msgid "Lounge" msgstr "" #: ../quodlibet/browsers/iradio.py:389 msgid "Punk" msgstr "" #: ../quodlibet/browsers/iradio.py:390 msgid "Reggaeton" msgstr "" #: ../quodlibet/browsers/iradio.py:392 msgid "Slavic" msgstr "" #: ../quodlibet/browsers/iradio.py:394 msgid "Greek" msgstr "" #: ../quodlibet/browsers/iradio.py:395 msgid "Gothic" msgstr "" #: ../quodlibet/browsers/iradio.py:396 ../quodlibet/ext/events/equalizer.py:38 msgid "Rock" msgstr "" #: ../quodlibet/browsers/iradio.py:449 msgid "Would you like to load a list of popular radio stations?" msgstr "" #: ../quodlibet/browsers/iradio.py:455 #, fuzzy msgid "_Load Stations" msgstr "新的站台 (_N)" #: ../quodlibet/browsers/iradio.py:472 msgid "_Internet Radio" msgstr "網路電台 (_I)" #: ../quodlibet/browsers/iradio.py:538 #, fuzzy msgid "_New Station…" msgstr "新站台" #: ../quodlibet/browsers/iradio.py:541 #, fuzzy msgid "_Update Stations" msgstr "新的站台 (_N)" #: ../quodlibet/browsers/iradio.py:568 #, fuzzy msgid "All Stations" msgstr "新站台" #. TODO: support for ~#rating=!None etc (#1940) #: ../quodlibet/browsers/iradio.py:572 #: ../quodlibet/browsers/soundcloud/main.py:64 msgid "Favorites" msgstr "" #: ../quodlibet/browsers/iradio.py:580 msgid "No Category" msgstr "" #: ../quodlibet/browsers/iradio.py:802 msgid "No stations found" msgstr "未發現站台" #: ../quodlibet/browsers/iradio.py:803 #, python-format msgid "No Internet radio stations were found at %s." msgstr "%s 沒有網路電台被發現。" #: ../quodlibet/browsers/iradio.py:811 msgid "All stations listed are already in your library." msgstr "所有列出的站台已經在您的資料庫當中了。" #: ../quodlibet/browsers/iradio.py:828 #, fuzzy msgid "Add to Favorites" msgstr "加入播放清單 (_A)" #: ../quodlibet/browsers/iradio.py:832 #, fuzzy msgid "Remove from Favorites" msgstr "從播放清單中移除 (_R)" #: ../quodlibet/browsers/iradio.py:932 #, python-format msgid "%(count)d station" msgid_plural "%(count)d stations" msgstr[0] "%(count)d 站台" #: ../quodlibet/browsers/media.py:36 msgid "Device Properties" msgstr "裝置屬性" #: ../quodlibet/browsers/media.py:52 msgid "Device:" msgstr "裝置:" #: ../quodlibet/browsers/media.py:54 msgid "Not mounted" msgstr "未掛載" #: ../quodlibet/browsers/media.py:55 #, fuzzy msgid "Mount point:" msgstr "掛載點:" #: ../quodlibet/browsers/media.py:61 ../quodlibet/qltk/cbes.py:40 msgid "_Name:" msgstr "名稱:(_N)" #: ../quodlibet/browsers/media.py:135 msgid "Media Devices" msgstr "媒體裝置" #: ../quodlibet/browsers/media.py:136 msgid "_Media Devices" msgstr "媒體裝置 (_M)" #. eject button #: ../quodlibet/browsers/media.py:224 ../quodlibet/browsers/media.py:378 msgid "_Eject" msgstr "退出 (_E)" #: ../quodlibet/browsers/media.py:360 #, fuzzy msgid "_Properties" msgstr "屬性" #: ../quodlibet/browsers/media.py:365 #: ../quodlibet/browsers/playlists/main.py:464 msgid "_Rename" msgstr "重新命名 (_R)" #: ../quodlibet/browsers/media.py:461 #, fuzzy, python-format msgid "%(used-size)s used, %(free-size)s available" msgstr "<b>%s</b> 已使用,<b>%s</b> 可用" #: ../quodlibet/browsers/media.py:479 #, fuzzy, python-format msgid "%s is not connected." msgstr "<b>%s</b> 未連線。" #: ../quodlibet/browsers/media.py:499 #, fuzzy, python-format msgid "Copying %(song)s" msgstr "正在複製 <b>%s</b>" #: ../quodlibet/browsers/media.py:513 ../quodlibet/browsers/media.py:529 msgid "Unable to copy song" msgstr "無法複製曲目" #: ../quodlibet/browsers/media.py:514 msgid "There is not enough free space for this song." msgstr "沒有足夠的空間給這首曲目。" #: ../quodlibet/browsers/media.py:526 #, fuzzy, python-format msgid "%s could not be copied." msgstr "無法複製 <b>%s</b>。" #: ../quodlibet/browsers/media.py:545 msgid "Unable to delete songs" msgstr "無法刪除曲目" #: ../quodlibet/browsers/media.py:557 #, fuzzy, python-format msgid "Deleting %(song)s" msgstr "正在刪除 <b>%s</b>" #: ../quodlibet/browsers/media.py:575 #, fuzzy, python-format msgid "%s could not be deleted." msgstr "無法刪除 <b>%s</b>。" #: ../quodlibet/browsers/media.py:579 msgid "Unable to delete song" msgstr "無法刪除曲目" #: ../quodlibet/browsers/media.py:594 #, fuzzy, python-format msgid "Ejecting %s failed." msgstr "退出 <b>%s</b> 失敗。" #: ../quodlibet/browsers/media.py:597 msgid "Unable to eject device" msgstr "無法退出裝置" #: ../quodlibet/browsers/media.py:603 msgid "No device backend, Media Devices browser disabled." msgstr "" #: ../quodlibet/browsers/paned/main.py:40 ../quodlibet/qltk/shortcuts.py:44 msgid "Paned Browser" msgstr "窗格瀏覽器" #: ../quodlibet/browsers/paned/main.py:41 msgid "_Paned Browser" msgstr "窗格瀏覽器 (_P)" #: ../quodlibet/browsers/paned/main.py:90 msgid "Select _All" msgstr "全選 (_A)" #: ../quodlibet/browsers/paned/models.py:104 ../quodlibet/qltk/pluginwin.py:122 #: ../quodlibet/qltk/pluginwin.py:164 msgid "All" msgstr "全部" #: ../quodlibet/browsers/paned/prefs.py:67 #, python-format msgid "" "Tag pattern with optional markup e.g. <tt>composer</tt> or\n" "<tt>%s</tt>" msgstr "" #: ../quodlibet/browsers/paned/prefs.py:162 msgid "_Wide Mode" msgstr "" #: ../quodlibet/browsers/paned/prefs.py:197 msgid "Paned Browser Preferences" msgstr "窗格瀏覽器偏好設定" #: ../quodlibet/browsers/paned/prefs.py:204 msgid "Equal pane width" msgstr "" #: ../quodlibet/browsers/playlists/main.py:48 #: ../quodlibet/browsers/playlists/main.py:575 #: ../quodlibet/qltk/pluginwin.py:168 msgid "Playlists" msgstr "播放清單" #: ../quodlibet/browsers/playlists/main.py:49 msgid "_Playlists" msgstr "播放清單 (_P)" #: ../quodlibet/browsers/playlists/main.py:152 msgid "_Remove from Playlist" msgstr "從播放清單中移除 (_R)" #: ../quodlibet/browsers/playlists/main.py:215 #: ../quodlibet/browsers/playlists/main.py:576 msgid "_Import" msgstr "匯入 (_I)" #: ../quodlibet/browsers/playlists/main.py:391 #: ../quodlibet/browsers/playlists/util.py:50 #: ../quodlibet/util/collection.py:570 msgid "New Playlist" msgstr "新的播放清單" #: ../quodlibet/browsers/playlists/main.py:413 msgid "Unable to import playlist" msgstr "無法匯入播放清單" #: ../quodlibet/browsers/playlists/main.py:414 msgid "Quod Libet can only import playlists in the M3U and PLS formats." msgstr "Quod Libet 僅不能匯入 M3U 或 PLS 格式的播放清單。" #: ../quodlibet/browsers/playlists/main.py:565 msgid "Unable to rename playlist" msgstr "無法重新命名播放清單" #: ../quodlibet/browsers/playlists/main.py:576 msgid "Import Playlist" msgstr "匯入播放清單" #: ../quodlibet/browsers/playlists/menu.py:25 #, fuzzy msgid "_New Playlist…" msgstr "新的播放清單 (_N)" #: ../quodlibet/browsers/playlists/menu.py:86 #, 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:90 #, 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:33 #, python-format msgid "Are you sure you want to delete the playlist '%s'?" msgstr "" #: ../quodlibet/browsers/playlists/util.py:35 msgid "" "All information about the selected playlist will be deleted and can not be " "restored." msgstr "" #: ../quodlibet/browsers/playlists/util.py:51 #, fuzzy msgid "Enter a name for the new playlist:" msgstr "輸入新資料夾的名稱:" #: ../quodlibet/browsers/playlists/util.py:102 #, fuzzy, python-format msgid "" "Importing playlist.\n" "\n" "%(current)d/%(total)d songs added." msgstr "" "正在匯入播放清單。\n" "\n" "%d/%d 曲目已加入。" #: ../quodlibet/browsers/search.py:33 msgid "_Limit Results" msgstr "設定搜尋結果上限 (_L)" #: ../quodlibet/browsers/search.py:48 msgid "Search Library" msgstr "搜尋資料庫" #: ../quodlibet/browsers/search.py:49 msgid "_Search Library" msgstr "搜尋資料庫 (_S)" #: ../quodlibet/browsers/soundcloud/main.py:38 #, fuzzy msgid "Soundcloud Browser" msgstr "窗格瀏覽器" #: ../quodlibet/browsers/soundcloud/main.py:39 msgid "Sound_cloud" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:59 #: ../quodlibet/qltk/searchbar.py:73 msgid "Search" msgstr "搜尋" #: ../quodlibet/browsers/soundcloud/main.py:136 #, python-format msgid "Go to %s" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:380 #, fuzzy msgid "Connected" msgstr "位置" #: ../quodlibet/browsers/soundcloud/main.py:381 #, python-format msgid "Quod Libet is now connected, <b>%s</b>!" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:393 #, python-format msgid "Log out of %s" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:395 msgid "Enter code…" msgstr "" #: ../quodlibet/browsers/soundcloud/main.py:396 #, python-format msgid "Log in to %s" msgstr "" #: ../quodlibet/browsers/soundcloud/util.py:86 msgid "Soundcloud authorisation" msgstr "" #: ../quodlibet/browsers/soundcloud/util.py:87 msgid "Enter Soundcloud auth code:" msgstr "" #: ../quodlibet/cli.py:50 #, fuzzy msgid "Quod Libet is not running (add '--run' to start it)" msgstr "Quod Libet 並未執行。" #: ../quodlibet/cli.py:85 msgid "a music library and player" msgstr "一個音樂資料庫與播放器" #: ../quodlibet/cli.py:86 #, fuzzy msgid "[option]" msgstr "[選項]" #: ../quodlibet/cli.py:88 msgid "Print the playing song and exit" msgstr "顯示播放中的曲目並離開" #: ../quodlibet/cli.py:89 msgid "Begin playing immediately" msgstr "立即開始播放" #: ../quodlibet/cli.py:90 msgid "Don't show any windows on start" msgstr "" #: ../quodlibet/cli.py:93 msgid "Jump to next song" msgstr "跳到下一個曲目" #: ../quodlibet/cli.py:95 msgid "Jump to previous song or restart if near the beginning" msgstr "" #: ../quodlibet/cli.py:96 msgid "Jump to previous song" msgstr "跳到上一個曲目" #: ../quodlibet/cli.py:97 msgid "Start playback" msgstr "開始播放" #: ../quodlibet/cli.py:98 msgid "Pause playback" msgstr "暫停播放" #: ../quodlibet/cli.py:99 msgid "Toggle play/pause mode" msgstr "切換 播放/暫停 模式" #: ../quodlibet/cli.py:100 #, fuzzy msgid "Stop playback" msgstr "開始播放" #: ../quodlibet/cli.py:101 msgid "Turn up volume" msgstr "調高音量" #: ../quodlibet/cli.py:102 msgid "Turn down volume" msgstr "調低音量" #: ../quodlibet/cli.py:103 msgid "Print player status" msgstr "顯示播放器狀態" #: ../quodlibet/cli.py:104 msgid "Hide main window" msgstr "隱藏主視窗" #: ../quodlibet/cli.py:105 msgid "Show main window" msgstr "顯示主視窗" #: ../quodlibet/cli.py:106 msgid "Toggle main window visibility" msgstr "切換主視窗可見性" #: ../quodlibet/cli.py:107 msgid "Focus the running player" msgstr "焦點移到執行中的播放器" #: ../quodlibet/cli.py:108 msgid "Remove active browser filters" msgstr "" #: ../quodlibet/cli.py:109 #, fuzzy msgid "Refresh and rescan library" msgstr "重新整理資料庫 (_F)" #: ../quodlibet/cli.py:110 #, fuzzy msgid "List available browsers" msgstr "停用瀏覽器" #: ../quodlibet/cli.py:111 msgid "Print the current playlist" msgstr "顯示當前的播放清單" #: ../quodlibet/cli.py:112 msgid "Print the contents of the queue" msgstr "顯示佇列的內容" #: ../quodlibet/cli.py:113 #, fuzzy msgid "Print the active text query" msgstr "顯示佇列的內容" #: ../quodlibet/cli.py:114 msgid "Start without plugins" msgstr "" #: ../quodlibet/cli.py:115 #, fuzzy msgid "Start Quod Libet if it isn't running" msgstr "Quod Libet 並未執行。" #: ../quodlibet/cli.py:116 msgid "Exit Quod Libet" msgstr "離開 Quod Libet" #: ../quodlibet/cli.py:121 msgid "Seek within the playing song" msgstr "在其中找尋播放中的曲目" #: ../quodlibet/cli.py:121 msgid "[+|-][HH:]MM:SS" msgstr "[+|-][HH:]MM:SS" #: ../quodlibet/cli.py:122 #, fuzzy msgid "Set or toggle shuffle mode" msgstr "切換 播放/暫停 模式" #: ../quodlibet/cli.py:123 msgid "Turn repeat off, on, or toggle it" msgstr "關掉、打開或切換重新播放" #: ../quodlibet/cli.py:124 msgid "Set the volume" msgstr "設定音量" #: ../quodlibet/cli.py:125 msgid "Search your audio library" msgstr "搜尋您的音訊資料庫" #: ../quodlibet/cli.py:125 ../quodlibet/cli.py:137 ../quodlibet/cli.py:141 #: ../quodlibet/cli.py:143 msgid "query" msgstr "查詢" #: ../quodlibet/cli.py:126 msgid "Play a file" msgstr "播放檔案" #: ../quodlibet/cli.py:126 ../quodlibet/cli.py:137 ../quodlibet/cli.py:143 #, fuzzy msgctxt "command" msgid "filename" msgstr "檔名" #: ../quodlibet/cli.py:127 msgid "Rate the playing song" msgstr "評等播放中的曲目" #: ../quodlibet/cli.py:128 msgid "Set the current browser" msgstr "設定當前的瀏覽器" #: ../quodlibet/cli.py:129 #, fuzzy msgid "Stop after the playing song" msgstr "評等播放中的曲目" #: ../quodlibet/cli.py:130 msgid "Open a new browser" msgstr "開啟新的瀏覽器" #: ../quodlibet/cli.py:131 msgid "Show or hide the queue" msgstr "顯示或隱藏佇列" #: ../quodlibet/cli.py:133 #, fuzzy msgid "Show or hide the main song list (deprecated)" msgstr "顯示或隱藏主要曲目清單" #: ../quodlibet/cli.py:134 msgid "Filter on a random value" msgstr "以亂數篩選" #: ../quodlibet/cli.py:134 #, fuzzy msgctxt "command" msgid "tag" msgstr "標籤" #: ../quodlibet/cli.py:135 msgid "Filter on a tag value" msgstr "以標籤值篩選" #: ../quodlibet/cli.py:135 msgid "tag=value" msgstr "tag=value" #: ../quodlibet/cli.py:136 msgid "Enqueue a file or query" msgstr "佇列檔案或查詢" #: ../quodlibet/cli.py:138 msgid "Enqueue comma-separated files" msgstr "" #: ../quodlibet/cli.py:139 ../quodlibet/util/tags.py:147 msgid "filename" msgstr "檔名" #: ../quodlibet/cli.py:140 msgid "Print filenames of results of query to stdout" msgstr "" #: ../quodlibet/cli.py:142 #, fuzzy msgid "Unqueue a file or query" msgstr "佇列檔案或查詢" #: ../quodlibet/cli.py:203 #, fuzzy, python-format msgid "Invalid argument for '%s'." msgstr "錯誤:無效的參數:「%s」。" #: ../quodlibet/cli.py:204 ../quodlibet/util/__init__.py:190 #, fuzzy, python-format msgid "Try %s --help." msgstr "錯誤:試試 %s --help。" #: ../quodlibet/devices/_base.py:65 msgid "Unknown Device" msgstr "未知的裝置" #: ../quodlibet/devices/__init__.py:32 #, python-format msgid "Could not import %s, which is needed for device support." msgstr "" #: ../quodlibet/devices/__init__.py:153 #, fuzzy, python-format msgid "%r is not a supported device." msgstr "錯誤:「%s」不是一個獨特的前綴 (prefix)。" #: ../quodlibet/devices/__init__.py:245 ../quodlibet/devices/__init__.py:251 #, python-format msgid "Could not find '%s'." msgstr "" #: ../quodlibet/devices/__init__.py:450 #, fuzzy msgid "Initializing device backend." msgstr "無效的設定值" #: ../quodlibet/devices/__init__.py:451 #, python-format msgid "Trying '%s'" msgstr "" #: ../quodlibet/devices/__init__.py:461 msgid "Couldn't connect to a device backend." msgstr "" #: ../quodlibet/devices/__init__.py:463 msgid "Device backend initialized." msgstr "" #: ../quodlibet/devices/storage.py:57 #, fuzzy msgid "_Filename pattern:" msgstr "檔名型態 (_F)" #: ../quodlibet/devices/storage.py:61 msgid "Copy _album covers" msgstr "複製專輯封面 (_A)" #: ../quodlibet/devices/storage.py:65 msgid "_Remove unused covers and directories" msgstr "移除不在使用的專輯封面與目錄 (_R)" #: ../quodlibet/errorreport/ui.py:60 msgid "An Error Occurred" msgstr "" #: ../quodlibet/errorreport/ui.py:62 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:72 msgid "File Bug Report" msgstr "" #: ../quodlibet/errorreport/ui.py:74 ../quodlibet/errorreport/ui.py:90 msgid "Submit Error Report" msgstr "" #: ../quodlibet/errorreport/ui.py:75 msgid "Quit Program" msgstr "" #: ../quodlibet/errorreport/ui.py:76 #, fuzzy msgid "Ignore Error" msgstr "顯示錯誤 (_E)" #: ../quodlibet/errorreport/ui.py:80 msgid "Error details:" msgstr "" #: ../quodlibet/errorreport/ui.py:92 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:100 msgid "" "(optional) Please provide a short description of what happened when the " "error occurred:" msgstr "" #: ../quodlibet/errorreport/ui.py:109 msgid "_Send" msgstr "" #: ../quodlibet/errorreport/ui.py:115 #, fuzzy msgid "Short description…" msgstr "描述" #: ../quodlibet/errorreport/ui.py:118 msgid "Data to be sent:" msgstr "" #: ../quodlibet/exfalso.py:34 msgid "an audio tag editor" msgstr "一個音訊標籤編輯器" #: ../quodlibet/exfalso.py:34 ../quodlibet/util/tags.py:148 msgid "directory" msgstr "目錄" #: ../quodlibet/ext/covers/artwork_url.py:19 msgid "Artwork URL Cover Source" msgstr "" #: ../quodlibet/ext/covers/artwork_url.py:20 msgid "" "Downloads covers linked to by the artwork_url tag.This works with the " "Soundcloud browser." msgstr "" #: ../quodlibet/ext/covers/discogs.py:25 #, fuzzy msgid "Discogs Cover Source" msgstr "MusicBrainz 音軌 ID" #: ../quodlibet/ext/covers/discogs.py:26 msgid "Downloads covers from Discogs." msgstr "" #: ../quodlibet/ext/covers/lastfm.py:22 msgid "Last.fm Cover Source" msgstr "" #: ../quodlibet/ext/covers/lastfm.py:23 msgid "Downloads covers from Last.fm's cover art archive." msgstr "" #: ../quodlibet/ext/covers/musicbrainz.py:19 #, fuzzy msgid "MusicBrainz Cover Source" msgstr "MusicBrainz 音軌 ID" #: ../quodlibet/ext/covers/musicbrainz.py:20 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:25 msgid "Kana/Kanji Simple Inverter" msgstr "" #: ../quodlibet/ext/editing/kakasi.py:26 msgid "Converts kana/kanji to romaji before renaming." msgstr "" #: ../quodlibet/ext/editing/kakasi.py:35 msgid "Romanize _Japanese text" msgstr "" #: ../quodlibet/ext/editing/kakasi.py:63 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:19 msgid "" "Allows arbitrary regex substitutions (s///) 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 "標籤英文首字大寫 (_T)" #: ../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:69 #, fuzzy msgid "Advanced Preferences" msgstr "窗格瀏覽器偏好設定" #: ../quodlibet/ext/events/advanced_preferences.py:70 msgid "Allow editing of advanced config settings." msgstr "" #: ../quodlibet/ext/events/advanced_preferences.py:162 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:153 msgid "Top of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:154 msgid "Middle of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:155 msgid "Bottom of screen" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:158 msgid "_Position:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:171 #, fuzzy msgid "_Cover size:" msgstr "合計大小:" #: ../quodlibet/ext/events/animosd/prefs.py:177 #: ../quodlibet/ext/events/lyricswindow.py:334 ../quodlibet/qltk/prefs.py:266 #, fuzzy msgid "Display" msgstr "編輯顯示" #: ../quodlibet/ext/events/animosd/prefs.py:190 msgid "_Font:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:195 msgid "Left" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:196 msgid "Center" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:197 #, fuzzy msgid "Right" msgstr "加權 (_W)" #: ../quodlibet/ext/events/animosd/prefs.py:200 msgid "_Align text:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:206 msgid "Text" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:217 msgid "_Text:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:227 msgid "_Fill:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:232 #: ../quodlibet/ext/events/synchronizedlyrics.py:63 msgid "Colors" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:240 msgid "_Shadows" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:241 msgid "_Outline" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:242 msgid "Rou_nded Corners" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:258 msgid "_Delay:" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:264 #: ../quodlibet/qltk/pluginwin.py:172 msgid "Effects" msgstr "" #: ../quodlibet/ext/events/animosd/prefs.py:270 #, fuzzy msgid "Ed_it Display Pattern…" msgstr "編輯顯示" #: ../quodlibet/ext/events/animosd/prefs.py:274 #: ../quodlibet/ext/events/trayicon/prefs.py:78 #, fuzzy msgid "Preview" msgstr "預覽 (_P)" #: ../quodlibet/ext/events/auto_library_update.py:136 msgid "Automatic Library Update" msgstr "" #: ../quodlibet/ext/events/auto_library_update.py:137 #, python-format msgid "Keeps your library up to date with inotify. Requires %s." 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 by Brian Nelson." 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/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:97 msgid "Equalizer" msgstr "" #: ../quodlibet/ext/events/equalizer.py:98 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:132 msgid "The current backend does not support equalization." msgstr "" #: ../quodlibet/ext/events/equalizer.py:138 #, python-format msgid "%.1f kHz" msgstr "" #: ../quodlibet/ext/events/equalizer.py:139 #: ../quodlibet/ext/gstreamer/crossfeed.py:93 #: ../quodlibet/ext/gstreamer/karaoke.py:95 #, python-format msgid "%d Hz" msgstr "" #: ../quodlibet/ext/events/equalizer.py:173 #: ../quodlibet/ext/gstreamer/crossfeed.py:112 #, fuzzy, python-format msgid "%.1f dB" msgstr "%d 秒" #: ../quodlibet/ext/events/equalizer.py:192 #: ../quodlibet/ext/gstreamer/crossfeed.py:31 #, fuzzy msgid "Custom" msgstr "自訂 (_C)" #: ../quodlibet/ext/events/equalizer.py:199 #, fuzzy msgid "_Clear" msgstr "外掛程式錯誤" #. Translators: statuses relating to Instant Messenger apps #: ../quodlibet/ext/events/gajim_status.py:27 msgid "online" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:28 msgid "offline" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:29 msgid "chat" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:30 msgid "away" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:31 msgid "xa" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:32 msgid "invisible" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:37 msgid "Gajim Status Message" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:38 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:45 #: ../quodlibet/ext/events/telepathy_status.py:69 msgid "paused" 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:160 msgid "Add '[paused]'" msgstr "" #: ../quodlibet/ext/events/gajim_status.py:163 msgid "If checked, '[paused]' will be added to status message on pause." msgstr "" #: ../quodlibet/ext/events/gajim_status.py:187 msgid "Statuses for which message will be changed" msgstr "" #: ../quodlibet/ext/events/headphonemon.py:156 msgid "Pause on Headphone Unplug" msgstr "" #: ../quodlibet/ext/events/headphonemon.py:157 msgid "" "Pauses in case headphones get unplugged and unpauses in case they get " "plugged in again." msgstr "" #: ../quodlibet/ext/events/inhibit.py:41 msgid "Inhibit Screensaver" msgstr "" #: ../quodlibet/ext/events/inhibit.py:42 msgid "Prevents the GNOME screensaver from activating while a song is playing." msgstr "" #: ../quodlibet/ext/events/inhibit.py:51 #, fuzzy msgid "Music is playing" msgstr "音樂播放器" #: ../quodlibet/ext/events/iradiolog.py:16 #, fuzzy msgid "Internet Radio Log" msgstr "網路電台" #: ../quodlibet/ext/events/iradiolog.py:17 msgid "" "Records the last 10 songs played on radio stations, and lists them in the " "seek context menu." msgstr "" #: ../quodlibet/ext/events/jep118.py:29 msgid "JEP-118" msgstr "" #: ../quodlibet/ext/events/jep118.py:30 msgid "Outputs a Jabber User Tunes file to ~/.quodlibet/jabber." msgstr "" #: ../quodlibet/ext/events/language.py:21 #, fuzzy msgid "Change Language" msgstr "評等 (_R)" #: ../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 msgid "A restart is required for any changes to take effect" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:199 #, fuzzy msgid "No active song" msgstr "無法儲存曲目" #: ../quodlibet/ext/events/lyricswindow.py:215 #, fuzzy msgid "No lyrics found" msgstr "找不到外掛。" #: ../quodlibet/ext/events/lyricswindow.py:227 #, fuzzy msgid "Lyrics:" msgstr "歌詞" #: ../quodlibet/ext/events/lyricswindow.py:284 msgid "_Zoom level:" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:302 msgid "URL:" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:307 msgid "Revert to default" msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:322 msgid "Search via above URL if the lyrics couldn't be found in LyricsWikia." msgstr "" #: ../quodlibet/ext/events/lyricswindow.py:339 #, fuzzy msgid "Alternate search" msgstr "清除搜尋紀錄" #: ../quodlibet/ext/events/lyricswindow.py:347 #, fuzzy msgid "Lyrics Window" msgstr "歌詞" #: ../quodlibet/ext/events/lyricswindow.py:348 msgid "Shows a window containing lyrics of the playing song." msgstr "" #: ../quodlibet/ext/events/mediaserver.py:38 msgid "UPnP AV Media Server" msgstr "" #: ../quodlibet/ext/events/mediaserver.py:39 msgid "" "Exposes all albums to the Rygel UPnP Media Server through the MediaServer2 D-" "Bus interface." 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:39 msgid "" "Allows control of Quod Libet using the MPRIS 1.0/2.0 D-Bus Interface " "Specification." msgstr "" #: ../quodlibet/ext/events/mpris/__init__.py:45 #: ../quodlibet/ext/events/trayicon/prefs.py:30 #, fuzzy msgid "Hide main window on close" msgstr "隱藏主視窗" #: ../quodlibet/ext/events/mpris/__init__.py:48 #: ../quodlibet/ext/events/themeswitcher.py:84 #: ../quodlibet/ext/gstreamer/compressor.py:99 #: ../quodlibet/ext/gstreamer/crossfeed.py:136 #: ../quodlibet/ext/gstreamer/karaoke.py:99 #: ../quodlibet/ext/gstreamer/pitch.py:83 ../quodlibet/qltk/prefs.py:688 #, fuzzy msgid "Preferences" msgstr "偏好設定" #: ../quodlibet/ext/events/mqtt.py:50 #, python-format msgid "Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/mqtt.py:56 msgid "MQTT Publisher" msgstr "" #: ../quodlibet/ext/events/mqtt.py:57 msgid "Publishes status messages to an MQTT topic." msgstr "" #: ../quodlibet/ext/events/mqtt.py:122 msgid "Broker hostname" msgstr "" #: ../quodlibet/ext/events/mqtt.py:122 msgid "broker hostname / IP" msgstr "" #: ../quodlibet/ext/events/mqtt.py:124 msgid "Broker port" msgstr "" #: ../quodlibet/ext/events/mqtt.py:124 msgid "broker port" msgstr "" #: ../quodlibet/ext/events/mqtt.py:126 msgid "Topic" msgstr "" #: ../quodlibet/ext/events/mqtt.py:128 #, fuzzy msgid "Playing Pattern" msgstr "模式" #: ../quodlibet/ext/events/mqtt.py:130 msgid "Status text when a song is started." msgstr "" #: ../quodlibet/ext/events/mqtt.py:132 #, fuzzy msgid "Paused Pattern" msgstr "模式" #: ../quodlibet/ext/events/mqtt.py:134 msgid "Text when a song is paused." msgstr "" #: ../quodlibet/ext/events/mqtt.py:136 #, fuzzy msgid "No-song Text" msgstr "%d 曲目" #: ../quodlibet/ext/events/mqtt.py:138 msgid "Plain text for when there is no current song" msgstr "" #: ../quodlibet/ext/events/mqtt.py:149 #, fuzzy msgid "MQTT Configuration" msgstr "資訊" #: ../quodlibet/ext/events/mqtt.py:153 #, fuzzy msgid "Status Text" msgstr "模式" #: ../quodlibet/ext/events/mqtt.py:185 #, python-format msgid "Connected to broker at %(host)s:%(port)d" msgstr "" #: ../quodlibet/ext/events/mqtt.py:189 #, python-format msgid "Couldn't connect to %(host)s:%(port)d (%(msg)s" msgstr "" #: ../quodlibet/ext/events/mqtt.py:192 #, fuzzy msgid "Connection error" msgstr "位置" #: ../quodlibet/ext/events/notify.py:80 msgid "Notification text" msgstr "" #: ../quodlibet/ext/events/notify.py:88 #, fuzzy msgid "_Title:" msgstr "標題" #: ../quodlibet/ext/events/notify.py:99 ../quodlibet/ext/events/notify.py:128 msgid "Revert to default pattern" msgstr "" #: ../quodlibet/ext/events/notify.py:118 msgid "_Body:" msgstr "" #: ../quodlibet/ext/events/notify.py:138 msgid "_Show notification" msgstr "" #: ../quodlibet/ext/events/notify.py:156 msgid "Show notifications" msgstr "" #: ../quodlibet/ext/events/notify.py:162 msgid "Only on <i>_manual</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:170 msgid "Only on <i>_automatic</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:178 msgid "On <i>a_ll</i> song changes" msgstr "" #: ../quodlibet/ext/events/notify.py:196 msgid "Only when the main window is not _focused" msgstr "" #: ../quodlibet/ext/events/notify.py:204 msgid "Show \"_Next\" button" msgstr "" #: ../quodlibet/ext/events/notify.py:236 msgid "Connection Error" msgstr "" #: ../quodlibet/ext/events/notify.py:237 ../quodlibet/ext/events/notify.py:391 #: ../quodlibet/ext/events/notify.py:433 msgid "Couldn't connect to notification daemon." msgstr "" #: ../quodlibet/ext/events/notify.py:251 msgid "Song Notifications" msgstr "" #: ../quodlibet/ext/events/notify.py:252 msgid "Displays a notification when the song changes." msgstr "" #: ../quodlibet/ext/events/notify.py:415 ../quodlibet/qltk/unity.py:65 msgid "Next" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:178 msgid "" "Please visit the Plugins window to set QLScrobbler up. Until then, songs " "will not be submitted." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:254 #, python-format msgid "Could not contact service '%s'." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:260 msgid "Authentication failed: invalid URL." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:277 #, python-format msgid "Authentication failed: Invalid username '%s' or bad password." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:282 msgid "Client is banned. Contact the author." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:286 msgid "Wrong system time. Submissions may fail until it is corrected." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:351 msgid "AudioScrobbler Submission" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:352 msgid "" "Audioscrobbler client for Last.fm, Libre.fm and other Audioscrobbler " "services." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:450 msgid "Authentication successful." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:462 #, fuzzy msgid "_Service:" msgstr "裝置:" #: ../quodlibet/ext/events/qlscrobbler.py:462 msgid "_URL:" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:462 #, fuzzy msgid "User_name:" msgstr "名稱:(_N)" #: ../quodlibet/ext/events/qlscrobbler.py:463 msgid "_Password:" msgstr "" #. Translators: Other service #: ../quodlibet/ext/events/qlscrobbler.py:479 #, fuzzy msgid "Other…" msgstr "其他:(_O)" #. verify data #: ../quodlibet/ext/events/qlscrobbler.py:517 msgid "_Verify account data" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:522 #: ../quodlibet/ext/songsmenu/lastfmsync.py:304 msgid "Account" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:530 #, fuzzy msgid "_Artist pattern:" msgstr "演出者 (_A)" #: ../quodlibet/ext/events/qlscrobbler.py:530 #, fuzzy msgid "_Title pattern:" msgstr "檔名型態 (_F)" #: ../quodlibet/ext/events/qlscrobbler.py:531 msgid "Exclude _filter:" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:549 msgid "" "The pattern used to format the artist name for submission. Leave blank for " "default." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:559 msgid "" "The pattern used to format the title for submission. Leave blank for default." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:568 msgid "Songs matching this filter will not be submitted." msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:576 msgid "_Offline mode (don't submit anything)" msgstr "" #: ../quodlibet/ext/events/qlscrobbler.py:580 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:27 #, fuzzy msgid "Random Album Playback" msgstr "隨機專輯 (_B)" #: ../quodlibet/ext/events/randomalbum.py:28 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:38 msgid "Rated higher" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:39 msgid "Played more often" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:40 msgid "Skipped more often" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:41 msgid "Played more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:42 msgid "Started more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:43 msgid "Added more recently" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:44 #, fuzzy msgid "Longer albums" msgstr "專輯" #: ../quodlibet/ext/events/randomalbum.py:83 msgid "seconds before starting next album" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:87 #, fuzzy msgid "Weights" msgstr "加權 (_W)" #: ../quodlibet/ext/events/randomalbum.py:89 msgid "Play some albums more than others" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:103 msgid "avoid" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:114 msgid "prefer" msgstr "" #: ../quodlibet/ext/events/randomalbum.py:201 #, fuzzy msgid "Random Album" msgstr "隨機專輯 (_B)" #: ../quodlibet/ext/events/randomalbum.py:202 #, python-format msgid "Waiting to start %s" msgstr "" #: ../quodlibet/ext/events/rbimport.py:114 #, fuzzy msgid "Import Failed" msgstr "匯入播放清單" #: ../quodlibet/ext/events/rbimport.py:119 #, python-format msgid "Successfully imported ratings and statistics for %d songs" msgstr "" #: ../quodlibet/ext/events/rbimport.py:127 msgid "Rhythmbox Import" msgstr "" #: ../quodlibet/ext/events/rbimport.py:128 msgid "Imports ratings and song statistics from Rhythmbox." msgstr "" #: ../quodlibet/ext/events/rbimport.py:132 #, fuzzy msgid "Start Import" msgstr "匯入 (_I)" #: ../quodlibet/ext/events/screensaver.py:25 msgid "Screensaver Pause" msgstr "" #: ../quodlibet/ext/events/screensaver.py:26 msgid "Pauses playback while the GNOME screensaver is active." msgstr "" #: ../quodlibet/ext/events/searchprovider.py:73 msgid "No GNOME Shell search provider for Quod Libet installed." msgstr "" #: ../quodlibet/ext/events/searchprovider.py:79 msgid "GNOME Search Provider" msgstr "" #: ../quodlibet/ext/events/searchprovider.py:80 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/squeezebox_sync.py:28 msgid "Squeezebox Sync" msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:29 msgid "" "Makes Logitech Squeezebox mirror Quod Libet output, provided both read from " "an identical library." msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:57 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:90 msgid "Error finding Squeezebox server" msgstr "" #: ../quodlibet/ext/events/squeezebox_sync.py:58 #: ../quodlibet/ext/playlist/export_to_squeezebox.py:91 #, python-format msgid "Error finding %s. Please check settings" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:34 #, fuzzy msgid "Synchronized Lyrics" msgstr "歌詞" #: ../quodlibet/ext/events/synchronizedlyrics.py:35 msgid "Shows synchronized lyrics from .lrc file with same name as the track." msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:66 msgid "Text:" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:76 msgid "Background:" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:87 msgid "Font" msgstr "" #: ../quodlibet/ext/events/synchronizedlyrics.py:90 msgid "Size (px):" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:62 msgid "Telepathy Status Messages" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:63 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:122 #, fuzzy msgid "Playing:" msgstr "尚未播放" #: ../quodlibet/ext/events/telepathy_status.py:123 #, python-format msgid "Status text when a song is started. Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:139 msgid "Paused:" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:140 #, python-format msgid "Status text when a song is paused. Accepts QL Patterns e.g. %s" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:156 msgid "Plain text for status when there is no current song" msgstr "" #: ../quodlibet/ext/events/telepathy_status.py:157 #, fuzzy msgid "No song:" msgstr "%d 曲目" #. Frame #: ../quodlibet/ext/events/telepathy_status.py:164 #, 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/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:77 #: ../quodlibet/ext/events/trayicon/prefs.py:98 #: ../quodlibet/ext/events/trayicon/systemtray.py:177 #: ../quodlibet/qltk/info.py:47 msgid "Not playing" msgstr "尚未播放" #: ../quodlibet/ext/events/trayicon/__init__.py:53 msgid "Tray Icon" msgstr "" #: ../quodlibet/ext/events/trayicon/__init__.py:54 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:183 #: ../quodlibet/qltk/quodlibetwindow.py:1046 #: ../quodlibet/qltk/quodlibetwindow.py:1238 #, fuzzy msgid "_Play" msgstr "播放清單 (_P)" #: ../quodlibet/ext/events/trayicon/menu.py:63 #: ../quodlibet/qltk/quodlibetwindow.py:185 #: ../quodlibet/qltk/quodlibetwindow.py:1240 ../quodlibet/qltk/wlw.py:51 #, fuzzy msgid "P_ause" msgstr "播放器" #: ../quodlibet/ext/events/trayicon/menu.py:68 #: ../quodlibet/qltk/quodlibetwindow.py:190 #: ../quodlibet/qltk/quodlibetwindow.py:1041 #, fuzzy msgid "Pre_vious" msgstr "預覽 (_P)" #: ../quodlibet/ext/events/trayicon/menu.py:71 #: ../quodlibet/qltk/quodlibetwindow.py:194 #: ../quodlibet/qltk/quodlibetwindow.py:1051 msgid "_Next" msgstr "" #: ../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 #, fuzzy msgid "Stop _After This Song" msgstr "在這首歌之後停止" #: ../quodlibet/ext/events/trayicon/menu.py:92 #: ../quodlibet/qltk/quodlibetwindow.py:1012 #, fuzzy msgid "Open _Browser" msgstr "開啟新的瀏覽器" #: ../quodlibet/ext/events/trayicon/menu.py:103 #: ../quodlibet/qltk/quodlibetwindow.py:1031 ../quodlibet/qltk/songsmenu.py:411 msgid "Edit _Tags" msgstr "編輯標籤 (_T)" #: ../quodlibet/ext/events/trayicon/menu.py:112 #: ../quodlibet/qltk/quodlibetwindow.py:975 ../quodlibet/qltk/songsmenu.py:424 msgid "_Information" msgstr "資訊 (_I)" #: ../quodlibet/ext/events/trayicon/menu.py:114 #: ../quodlibet/qltk/songsmenu.py:340 #, fuzzy msgid "Play_lists" msgstr "播放清單" #: ../quodlibet/ext/events/trayicon/menu.py:132 #: ../quodlibet/qltk/quodlibetwindow.py:1026 msgid "_Quit" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:32 ../quodlibet/qltk/prefs.py:69 msgid "Behavior" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:42 msgid "Scroll wheel adjusts volume" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:48 msgid "Scroll wheel changes song" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:54 msgid "Scroll _Wheel" msgstr "" #: ../quodlibet/ext/events/trayicon/prefs.py:84 #, fuzzy msgid "Tooltip Display" msgstr "編輯顯示" #: ../quodlibet/ext/events/viewlyrics.py:23 #, fuzzy msgid "View Lyrics" msgstr "歌詞" #: ../quodlibet/ext/events/viewlyrics.py:24 msgid "Automatically displays lyrics beneath the song list in the main window." msgstr "" #: ../quodlibet/ext/events/viewlyrics.py:29 #, fuzzy msgid "_Lyrics" 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 "顯示錯誤 (_E)" #: ../quodlibet/ext/events/visualisations.py:76 msgid "Visualiser executable:" msgstr "" #: ../quodlibet/ext/events/visualisations.py:91 msgid "Reload" msgstr "" #: ../quodlibet/ext/events/waveformseekbar.py:406 msgid "Waveform Seek Bar" msgstr "" #: ../quodlibet/ext/events/waveformseekbar.py:410 msgid "A seekbar in the shape of the waveform of the current song." msgstr "" #: ../quodlibet/ext/events/waveformseekbar.py:443 msgid "Override foreground color:" msgstr "" #: ../quodlibet/ext/events/write_cover.py:32 msgid "Picture Saver" msgstr "" #: ../quodlibet/ext/events/write_cover.py:33 msgid "Saves the cover image of the current song to a file." msgstr "" #: ../quodlibet/ext/events/write_cover.py:66 #, fuzzy msgid "File:" msgstr "檔案" #: ../quodlibet/ext/gstreamer/compressor.py:20 msgid "_Threshold:" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:21 msgid "Threshold until the filter is activated" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:22 msgid "R_atio:" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:22 msgid "Compression ratio" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:74 #: ../quodlibet/ext/gstreamer/karaoke.py:91 #, python-format msgid "%d %%" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:105 msgid "Audio Compressor" msgstr "" #: ../quodlibet/ext/gstreamer/compressor.py:106 msgid "" "Changes the amplitude of all samples above a specific threshold with a " "specific ratio." msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:19 #, fuzzy msgid "_Preset:" msgstr "預覽 (_P)" #: ../quodlibet/ext/gstreamer/crossfeed.py:19 #, fuzzy msgid "Filter preset" msgstr "依演出者篩選 (_A)" #: ../quodlibet/ext/gstreamer/crossfeed.py:20 msgid "_Frequency cut:" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:20 msgid "Low-pass filter cut frequency" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed _level:" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:21 msgid "Feed level" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:25 msgid "Default" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:26 msgid "Closest to virtual speaker placement (30°, 3 meter)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:27 msgid "Chu Moy" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:28 msgid "Close to Chu Moy's crossfeeder (popular)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:29 msgid "Jan Meier" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:30 msgid "Close to Jan Meier's CORDA amplifiers (little change)" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:31 #, fuzzy msgid "Custom settings" msgstr "自訂 (_C)" #: ../quodlibet/ext/gstreamer/crossfeed.py:152 msgid "Crossfeed" msgstr "" #: ../quodlibet/ext/gstreamer/crossfeed.py:153 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:20 #, fuzzy msgid "Filter _band:" msgstr "依風格篩選 (_G)" #: ../quodlibet/ext/gstreamer/karaoke.py:21 msgid "The Frequency band of the filter" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:22 #, fuzzy msgid "Filter _width:" msgstr "依演出者篩選 (_A)" #: ../quodlibet/ext/gstreamer/karaoke.py:23 msgid "The Frequency width of the filter" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:24 msgid "_Level:" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:24 msgid "Level of the effect" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:105 msgid "Karaoke" msgstr "" #: ../quodlibet/ext/gstreamer/karaoke.py:106 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:20 msgid "R_ate:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:21 msgid "_Tempo:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:22 msgid "_Pitch:" msgstr "" #: ../quodlibet/ext/gstreamer/pitch.py:89 #, fuzzy msgid "Audio Pitch / Speed" msgstr "音訊饋流" #: ../quodlibet/ext/gstreamer/pitch.py:90 #, fuzzy msgid "Controls the pitch of an audio stream." msgstr "輸入音訊檔案饋流位置:" #: ../quodlibet/ext/playlist/export_to_folder.py:29 #: ../quodlibet/ext/playlist/export_to_folder.py:97 #: ../quodlibet/ext/playlist/export_to_folder.py:138 #, fuzzy msgid "Export Playlist to Folder" msgstr "匯入播放清單" #: ../quodlibet/ext/playlist/export_to_folder.py:38 #, fuzzy msgid "_Export" msgstr "匯入 (_I)" #: ../quodlibet/ext/playlist/export_to_folder.py:43 #, fuzzy msgid "Destination folder:" msgstr "未發現站台" #: ../quodlibet/ext/playlist/export_to_folder.py:58 #, fuzzy msgid "Filename pattern:" msgstr "檔名型態 (_F)" #: ../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:156 #, fuzzy msgid "Default filename pattern:" msgstr "檔名型態 (_F)" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:23 msgid "Export to Squeezebox" msgstr "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:25 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 "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:79 msgid "Export playlist to Squeezebox" msgstr "" #: ../quodlibet/ext/playlist/export_to_squeezebox.py:80 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 "從播放清單中移除 (_R)" #: ../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 "" "Playback follows your selection, or the next song in the list once exhausted." msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:22 msgid "Playcount Equalizer" msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:23 msgid "Shuffle, preferring songs with fewer total plays." msgstr "" #: ../quodlibet/ext/playorder/playcounteq.py:25 #, fuzzy msgid "Prefer less played" msgstr "上次播放" #: ../quodlibet/ext/playorder/queue.py:19 #, fuzzy msgid "Queue Only" msgstr "佇列 (_Q)" #: ../quodlibet/ext/playorder/queue.py:21 msgid "" "Limits playing of songs to the queue. Select this play order in the main " "window, then double-clicking any song will enqueue it instead of playing." msgstr "" #: ../quodlibet/ext/playorder/reverse.py:14 #, fuzzy msgid "Reverse" msgstr "從未" #: ../quodlibet/ext/playorder/reverse.py:16 msgid "Reverses the play order of songs." msgstr "" #: ../quodlibet/ext/playorder/skip_songs.py:25 #, fuzzy msgid "Skip Songs" msgstr "無曲目" #: ../quodlibet/ext/playorder/skip_songs.py:27 msgid "" "Playback skips over songs with a rating equal or below a given threshold." msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:30 msgid "Repeat Each Track" msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:32 msgid "Shuffle songs, but repeat every track a set number of times." msgstr "" #: ../quodlibet/ext/playorder/track_repeat.py:51 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. Syntax is '@(if: " "condition, then, else)'." msgstr "" #: ../quodlibet/ext/query/pythonexpression.py:14 msgid "Python Query" msgstr "" #: ../quodlibet/ext/query/pythonexpression.py:15 msgid "" "Use Python expressions in queries. Syntax is '@(python: expression)'. The " "variable 's' is the song being matched." msgstr "" #: ../quodlibet/ext/query/savedsearch.py:19 #, fuzzy msgid "Include Saved Search" msgstr "已儲存設定值" #: ../quodlibet/ext/query/savedsearch.py:20 msgid "" "Include the results of a saved search as part of another query. Syntax is " "'@(saved: search name)'." 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:116 msgid "Port:" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:121 #, fuzzy msgid "Username:" msgstr "重新命名 (_R)" #: ../quodlibet/ext/_shared/squeezebox/base.py:126 msgid "Password:" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:130 msgid "Library directory the server connects to." msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:132 #, fuzzy msgid "Library path:" msgstr "資料庫" #. Add verify button #: ../quodlibet/ext/_shared/squeezebox/base.py:141 msgid "_Verify settings" msgstr "" #. Server settings Frame #: ../quodlibet/ext/_shared/squeezebox/base.py:147 msgid "Squeezebox Server" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/base.py:150 msgid "Debug" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:26 #, python-brace-format msgid "Squeezebox server at {hostname}:{port}" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:28 msgid "unidentified Squeezebox server" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/server.py:37 #, 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:20 #: ../quodlibet/ext/songsmenu/importexport.py:34 #: ../quodlibet/qltk/getstring.py:21 msgid "_OK" msgstr "" #: ../quodlibet/ext/_shared/squeezebox/util.py:26 msgid "" "Found Squeezebox server.\n" "Please choose the player" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:329 #, fuzzy msgid "Fit image to _window" msgstr "隱藏主視窗" #. Both labels #: ../quodlibet/ext/songsmenu/albumart.py:338 msgid "_Program:" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:343 msgid "_Edit image after saving" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:345 #, fuzzy msgid "File_name:" msgstr "檔案名稱" #: ../quodlibet/ext/songsmenu/albumart.py:457 msgid "Saving failed" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:458 #, fuzzy, python-format msgid "Unable to save \"%s\"." msgstr "無法儲存曲目" #: ../quodlibet/ext/songsmenu/albumart.py:556 #, python-format msgid "[albumart] HTTP Error: %s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:613 #, fuzzy msgid "Album Art Downloader" msgstr "專輯清單" #: ../quodlibet/ext/songsmenu/albumart.py:666 #, python-format msgid "from %(source)s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:669 #, python-format msgid "Resolution: %s" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:672 #, fuzzy, python-format msgid "Size: %s" msgstr "大小" #: ../quodlibet/ext/songsmenu/albumart.py:690 #, fuzzy msgid "_Search" msgstr "搜尋:(_S)" #: ../quodlibet/ext/songsmenu/albumart.py:741 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:451 #, fuzzy msgid "Searching…" msgstr "搜尋" #: ../quodlibet/ext/songsmenu/albumart.py:804 #: ../quodlibet/ext/songsmenu/fingerprint/search.py:42 msgid "Done" msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:922 #, fuzzy msgid "Download Album Art" msgstr "專輯清單" #: ../quodlibet/ext/songsmenu/albumart.py:923 msgid "Downloads album covers from various websites." msgstr "" #: ../quodlibet/ext/songsmenu/albumart.py:936 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 "編輯書籤... (_E)" #: ../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 "編輯書籤... (_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 專輯類型" #: ../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 #: ../quodlibet/qltk/downloader.py:52 msgid "Filename" msgstr "檔案名稱" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:130 #, fuzzy msgid "Disc" msgstr "唱片 (_D)" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:131 #: ../quodlibet/ext/songsmenu/replaygain.py:404 #: ../quodlibet/qltk/tracknumbers.py:92 msgid "Track" msgstr "音軌" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:132 #, fuzzy msgid "Title" msgstr "標題" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:133 #, fuzzy msgid "Artist" msgstr "演出者 (_A)" #: ../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:447 msgid "Please enter a query." msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:465 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:496 msgid "Error encountered. Please retry." msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:472 #: ../quodlibet/ext/songsmenu/brainz/widgets.py:488 msgid "Loading result…" msgstr "" #: ../quodlibet/ext/songsmenu/brainz/widgets.py:475 #, fuzzy msgid "No results found." msgstr "找不到外掛。" #: ../quodlibet/ext/songsmenu/browsefolders.py:159 #, fuzzy msgid "Browse Folders" msgstr "瀏覽器" #: ../quodlibet/ext/songsmenu/browsefolders.py:160 msgid "Opens the songs' folders in a file manager." msgstr "" #: ../quodlibet/ext/songsmenu/browsefolders.py:172 #, fuzzy msgid "Unable to open folders" msgstr "無法建立資料夾" #: ../quodlibet/ext/songsmenu/browsefolders.py:173 msgid "No program available to open folders." msgstr "" #: ../quodlibet/ext/songsmenu/console.py:40 msgid "Python Console" msgstr "" #: ../quodlibet/ext/songsmenu/console.py:41 msgid "Interactive Python console." msgstr "" #: ../quodlibet/ext/songsmenu/console.py:72 msgid "You can access the following objects by default:" msgstr "" #: ../quodlibet/ext/songsmenu/console.py:82 msgid "Your current working directory is:" 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 "重新命名 (_R)" #: ../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:55 #, fuzzy msgid "pattern" 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:91 #, fuzzy msgid "Input value" msgstr "無效的設定值" #: ../quodlibet/ext/songsmenu/custom_commands.py:92 #, python-format msgid "Value for %s?" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:136 #, fuzzy msgid "Custom Commands" msgstr "自訂 (_C)" #: ../quodlibet/ext/songsmenu/custom_commands.py:137 msgid "" "Runs custom commands (in batches if required) on songs using any of their " "tags." msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:188 #: ../quodlibet/ext/songsmenu/custom_commands.py:198 #: ../quodlibet/ext/songsmenu/custom_commands.py:252 msgid "Edit Custom Commands" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:199 msgid "" "Supports QL patterns\n" "eg <tt><~artist~title></tt>" msgstr "" #: ../quodlibet/ext/songsmenu/custom_commands.py:283 #, fuzzy, python-format msgid "Unable to run custom command %s" msgstr "無法複製曲目" #: ../quodlibet/ext/songsmenu/duplicates.py:290 #, python-format msgid "%d duplicate group" msgid_plural "%d duplicate groups" msgstr[0] "" #: ../quodlibet/ext/songsmenu/duplicates.py:343 msgid "Collapse / Expand all" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:347 #, python-format msgid "Duplicate key expression is '%s'" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:363 #, fuzzy msgid "Duplicates Browser" msgstr "停用瀏覽器" #: ../quodlibet/ext/songsmenu/duplicates.py:364 msgid "Finds and displays similarly tagged versions of songs." msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:407 msgid "" "Accepts QL tag expressions like <tt>~artist~title</tt> or " "<tt>musicbrainz_track_id</tt>" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:409 msgid "_Group duplicates by:" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:414 msgid "Duplicate Key" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:419 msgid "Remove _Whitespace" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:420 #, fuzzy msgid "Remove _Diacritics" msgstr "評等 (_R)" #: ../quodlibet/ext/songsmenu/duplicates.py:421 #, fuzzy msgid "Remove _Punctuation" msgstr "評等 (_R)" #: ../quodlibet/ext/songsmenu/duplicates.py:422 msgid "Case _Insensitive" msgstr "" #: ../quodlibet/ext/songsmenu/duplicates.py:430 msgid "Matching options" msgstr "" #. Create a dialog. #: ../quodlibet/ext/songsmenu/editplaycount.py:19 #: ../quodlibet/ext/songsmenu/editplaycount.py:41 #, fuzzy msgid "Edit Playcount" msgstr "編輯顯示" #: ../quodlibet/ext/songsmenu/editplaycount.py:20 msgid "" "Edit a song's ~#playcount and ~#skipcount.\n" "\n" "When multiple songs are selected, counts will be incremented, rather than " "set.\n" "\n" "When setting a song's ~#playcount to 0, the ~#lastplayed and ~#laststarted " "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:68 msgid "Play Count" msgstr "" #: ../quodlibet/ext/songsmenu/editplaycount.py:69 msgid "Skip Count" msgstr "" #: ../quodlibet/ext/songsmenu/embedded.py:24 msgid "Edit Embedded Images" msgstr "" #: ../quodlibet/ext/songsmenu/embedded.py:25 msgid "Removes or replaces embedded images." msgstr "" #: ../quodlibet/ext/songsmenu/embedded.py:78 #, fuzzy msgid "_Remove all Images" msgstr "評等 (_R)" #: ../quodlibet/ext/songsmenu/embedded.py:82 msgid "_Embed Current 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 "依風格篩選 (_G)" #: ../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:41 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 #: ../quodlibet/qltk/downloader.py:67 #, fuzzy msgid "Queued" msgstr "佇列 (_Q)" #: ../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 "寫入" #: ../quodlibet/ext/songsmenu/fingerprint/search.py:144 msgid "Status" 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 音軌 ID" #: ../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 "專輯檔頭 (_A)" #: ../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:49 msgid "Generating fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:63 msgid "_Details" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:85 msgid "_Submit" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:115 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:118 msgid "Fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:120 msgid "Songs with MBIDs:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:122 msgid "Songs with sufficient tags:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:124 msgid "Songs to submit:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:162 #, python-format msgid "Done. %(to-send)d/%(all)d songs to submit." msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:178 msgid "Submitting fingerprints:" msgstr "" #: ../quodlibet/ext/songsmenu/fingerprint/submit.py:186 msgid "Submitting…" msgstr "" #: ../quodlibet/ext/songsmenu/forcewrite.py:17 #, fuzzy msgid "Update Tags in Files" msgstr "新的站台 (_N)" #: ../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/id3tlen.py:21 msgid "Fix MP3 Duration" msgstr "" #: ../quodlibet/ext/songsmenu/id3tlen.py:22 msgid "" "Removes TLEN frames from ID3 tags which can be the cause for invalid song " "durations." msgstr "" #: ../quodlibet/ext/songsmenu/ifp.py:20 msgid "Send to iFP" msgstr "" #: ../quodlibet/ext/songsmenu/ifp.py:21 msgid "Uploads songs to an iRiver iFP device." msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:51 msgid "Export Metadata" msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:52 msgid "Exports metadata of selected songs as a .tags file." msgstr "" #: ../quodlibet/ext/songsmenu/importexport.py:92 #, fuzzy msgid "Import Metadata" msgstr "匯入播放清單" #: ../quodlibet/ext/songsmenu/importexport.py:93 msgid "Imports metadata for selected songs from a .tags file." msgstr "" #: ../quodlibet/ext/songsmenu/k3b.py:23 msgid "Burn CD" msgstr "" #: ../quodlibet/ext/songsmenu/k3b.py:24 msgid "Burns CDs with K3b, Brasero or xfburn." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:96 msgid "Updating chart list." msgstr "" #. No charts to fetch, no update scheduled. #: ../quodlibet/ext/songsmenu/lastfmsync.py:114 msgid "Already up-to-date." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:121 #, python-format msgid "Fetching chart for week of %s." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:143 msgid "Sync complete." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:149 msgid "Error during sync" msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:214 #: ../quodlibet/ext/songsmenu/lastfmsync.py:244 msgid "Last.fm Sync" msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:245 msgid "Updates your library's statistics from your Last.fm profile." msgstr "" #: ../quodlibet/ext/songsmenu/lastfmsync.py:293 #, fuzzy msgid "_Username:" msgstr "重新命名 (_R)" #: ../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 "" #. Create a dialog. #: ../quodlibet/ext/songsmenu/migratemetadata.py:29 #: ../quodlibet/ext/songsmenu/migratemetadata.py:38 #, fuzzy msgid "Migrate Metadata" msgstr "匯入播放清單" #: ../quodlibet/ext/songsmenu/migratemetadata.py:32 msgid "Copies the quodlibet-specific metadata between songs." msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:45 msgid "_Copy" msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:47 msgid "_Paste" msgstr "" #. Create the tag table. #: ../quodlibet/ext/songsmenu/migratemetadata.py:57 #, fuzzy msgid "Information to copy/paste" msgstr "資訊" #. Create the indexing box. #: ../quodlibet/ext/songsmenu/migratemetadata.py:79 msgid "Map tracks by disc and track number" msgstr "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:80 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 "" #: ../quodlibet/ext/songsmenu/migratemetadata.py:96 #, python-format msgid "There is %d stored track." msgid_plural "There are %d stored tracks." msgstr[0] "" #: ../quodlibet/ext/songsmenu/playlist.py:31 #, fuzzy msgid "Export as Playlist" msgstr "匯入播放清單" #: ../quodlibet/ext/songsmenu/playlist.py:32 msgid "Exports songs to an M3U or PLS playlist." msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:77 msgid "Use relative paths" msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:77 msgid "Use absolute paths" msgstr "" #: ../quodlibet/ext/songsmenu/playlist.py:132 #, fuzzy msgid "Unable to export playlist" msgstr "無法匯入播放清單" #: ../quodlibet/ext/songsmenu/playlist.py:133 #, fuzzy, python-format msgid "Writing to <b>%s</b> failed." msgstr "退出 <b>%s</b> 失敗。" #. Translators: Plugin name #: ../quodlibet/ext/songsmenu/refresh.py:22 #, fuzzy msgid "Rescan Songs" msgstr "重新整理資料庫 (_F)" #: ../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 "重新整理資料庫 (_F)" #: ../quodlibet/ext/songsmenu/replaygain.py:362 msgid "ReplayGain Analyzer" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:418 msgid "Progress" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:433 msgid "Gain" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:448 msgid "Peak" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:463 #, python-format msgid "There is <b>%(to-process)s</b> album to update (of %(all)s)" msgid_plural "There are <b>%(to-process)s</b> albums to update (of %(all)s)" msgstr[0] "" #: ../quodlibet/ext/songsmenu/replaygain.py:578 msgid "Replay Gain" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:579 msgid "" "Analyzes and updates ReplayGain information, using GStreamer. Results are " "grouped by album." msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:617 msgid "always" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:618 msgid "if <b>any</b> RG tags are missing" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:620 msgid "if <b>album</b> RG tags are missing" msgstr "" #: ../quodlibet/ext/songsmenu/replaygain.py:637 msgid "_Process albums:" msgstr "" #. Server settings Frame #: ../quodlibet/ext/songsmenu/replaygain.py:649 #, 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 "" #. TRANSLATORS: BPM mean "beats per minute" #: ../quodlibet/ext/songsmenu/tapbpm.py:31 msgid "BPM:" msgstr "" #: ../quodlibet/ext/songsmenu/tapbpm.py:32 #: ../quodlibet/ext/songsmenu/tapbpm.py:61 msgid "n/a" msgstr "" #: ../quodlibet/ext/songsmenu/tapbpm.py:36 #, fuzzy msgid "Reset" msgstr "預覽 (_P)" #: ../quodlibet/ext/songsmenu/tapbpm.py:42 #, fuzzy msgid "Tap" msgstr "標籤" #: ../quodlibet/ext/songsmenu/tapbpm.py:172 #: ../quodlibet/ext/songsmenu/tapbpm.py:179 msgid "Tap BPM" msgstr "" #: ../quodlibet/ext/songsmenu/tapbpm.py:173 #, fuzzy msgid "Tap BPM for the selected song." msgstr "無法刪除曲目" #: ../quodlibet/ext/songsmenu/website_search.py:35 #, fuzzy msgid "Website Search" msgstr "搜尋" #: ../quodlibet/ext/songsmenu/website_search.py:36 #, python-format msgid "" "Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern-example)s." msgstr "" #: ../quodlibet/ext/songsmenu/website_search.py:78 #, fuzzy msgid "Search URL patterns" msgstr "模式" #: ../quodlibet/ext/songsmenu/website_search.py:88 #, fuzzy msgid "Edit search URLs" msgstr "編輯儲存設定值..." #. Add link to editor #: ../quodlibet/ext/songsmenu/website_search.py:114 #, fuzzy msgid "Configure Searches…" msgstr "以顏色標示搜尋項目 (_S)" #: ../quodlibet/ext/songsmenu/wikipedia.py:46 #, python-format msgid "Search at %(website)s" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:63 msgid "Search Artist in Wikipedia" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:64 msgid "" "Opens a browser window with Wikipedia article on the playing song artist." msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:71 msgid "Search Album in Wikipedia" msgstr "" #: ../quodlibet/ext/songsmenu/wikipedia.py:72 msgid "" "Opens a browser window with Wikipedia article on the playing song album." msgstr "" #. then (try to) load all new files #: ../quodlibet/library/libraries.py:650 ../quodlibet/library/libraries.py:660 #: ../quodlibet/library/libraries.py:726 ../quodlibet/library/libraries.py:745 #: ../quodlibet/qltk/information.py:268 ../quodlibet/qltk/prefs.py:639 #: ../quodlibet/util/library.py:124 msgid "Library" msgstr "資料庫" #: ../quodlibet/library/libraries.py:650 msgid "Checking mount points" msgstr "正在檢查掛載點" #: ../quodlibet/library/libraries.py:660 msgid "Scanning library" msgstr "正在掃瞄資料庫" #: ../quodlibet/library/libraries.py:725 #, python-format msgid "Scanning %s" msgstr "正在掃瞄 %s" #: ../quodlibet/library/libraries.py:745 msgid "Loading files" msgstr "" #: ../quodlibet/operon/base.py:70 #, python-format msgid "Failed to load file: %r" msgstr "" #: ../quodlibet/operon/commands.py:37 msgid "List tags" msgstr "" #: ../quodlibet/operon/commands.py:42 ../quodlibet/operon/commands.py:81 #: ../quodlibet/operon/commands.py:461 msgid "Print terse output" msgstr "" #: ../quodlibet/operon/commands.py:44 ../quodlibet/operon/commands.py:83 #: ../quodlibet/operon/commands.py:463 #, python-format msgid "Columns to display and order in terse mode (%s)" msgstr "" #: ../quodlibet/operon/commands.py:47 ../quodlibet/operon/commands.py:86 #, fuzzy msgid "Also list programmatic tags" msgstr "顯示標題音樂 (programmatic) 標籤 (_p)" #: ../quodlibet/operon/commands.py:51 ../quodlibet/operon/commands.py:129 #: ../quodlibet/operon/commands.py:220 ../quodlibet/operon/commands.py:293 #: ../quodlibet/operon/commands.py:336 ../quodlibet/operon/commands.py:340 #: ../quodlibet/operon/commands.py:391 ../quodlibet/operon/commands.py:394 #: ../quodlibet/operon/commands.py:433 ../quodlibet/operon/commands.py:468 #: ../quodlibet/operon/commands.py:508 ../quodlibet/operon/commands.py:543 #: ../quodlibet/operon/commands.py:585 msgid "Not enough arguments" msgstr "" #: ../quodlibet/operon/commands.py:53 ../quodlibet/operon/commands.py:90 #: ../quodlibet/operon/commands.py:131 ../quodlibet/operon/commands.py:222 #: ../quodlibet/operon/commands.py:470 msgid "Too many arguments" msgstr "" #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:92 #: ../quodlibet/operon/commands.py:475 ../quodlibet/qltk/data_editors.py:363 #, fuzzy msgid "Description" msgstr "描述" #: ../quodlibet/operon/commands.py:56 ../quodlibet/operon/commands.py:475 #: ../quodlibet/qltk/edittags.py:454 msgid "Value" msgstr "設定值" #: ../quodlibet/operon/commands.py:76 msgid "List all common tags" msgstr "" #: ../quodlibet/operon/commands.py:118 msgid "Copy tags from one file to another" msgstr "" #: ../quodlibet/operon/commands.py:123 ../quodlibet/operon/commands.py:164 #: ../quodlibet/operon/commands.py:289 ../quodlibet/operon/commands.py:324 #: ../quodlibet/operon/commands.py:384 msgid "Show changes, don't apply them" msgstr "" #: ../quodlibet/operon/commands.py:125 msgid "Skip tags that can't be written" msgstr "" #: ../quodlibet/operon/commands.py:145 #, python-format msgid "Can't copy tag %r to file: %r" 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:304 ../quodlibet/operon/commands.py:444 #: ../quodlibet/operon/commands.py:676 #, python-format msgid "Can not set %r" msgstr "" #: ../quodlibet/operon/commands.py:319 msgid "Remove tags" msgstr "" #: ../quodlibet/operon/commands.py:326 ../quodlibet/operon/commands.py:386 msgid "Value is a regular expression" msgstr "" #: ../quodlibet/operon/commands.py:328 msgid "Remove all tags" msgstr "" #: ../quodlibet/operon/commands.py:332 msgid "Can't combine '--all' with '--regexp'" msgstr "" #: ../quodlibet/operon/commands.py:366 #, python-format msgid "Can't remove %r from %r" msgstr "" #: ../quodlibet/operon/commands.py:379 #, fuzzy msgid "Remove a tag value" msgstr "以標籤值篩選" #: ../quodlibet/operon/commands.py:428 #, fuzzy msgid "Add a tag value" msgstr "以標籤值篩選" #: ../quodlibet/operon/commands.py:456 #, fuzzy msgid "List file information" msgstr "無時間資訊" #: ../quodlibet/operon/commands.py:502 msgid "" "Set the provided image as primary embedded image and remove all other " "embedded images" msgstr "" #: ../quodlibet/operon/commands.py:515 #, fuzzy, python-format msgid "Failed to load image file: %r" msgstr "無法重新命名檔案" #: ../quodlibet/operon/commands.py:522 ../quodlibet/operon/commands.py:551 #, python-format msgid "Image editing not supported for %(file_name)s (%(file_format)s)" msgstr "" #: ../quodlibet/operon/commands.py:538 msgid "Remove all embedded images" msgstr "" #: ../quodlibet/operon/commands.py:568 #, python-format msgid "Extract embedded images to %(filepath)s" msgstr "" #: ../quodlibet/operon/commands.py:580 msgid "" "Path to where the images will be saved to (defaults to the working directory)" msgstr "" #: ../quodlibet/operon/commands.py:639 msgid "Rename files based on tags" msgstr "" #: ../quodlibet/operon/commands.py:654 msgid "Fill tags based on the file path" msgstr "" #: ../quodlibet/operon/commands.py:704 ../quodlibet/qltk/information.py:305 #: ../quodlibet/qltk/properties.py:84 ../quodlibet/qltk/renamefiles.py:176 #: ../quodlibet/qltk/tagsfrompath.py:229 ../quodlibet/qltk/tracknumbers.py:79 msgid "File" msgstr "檔案" #: ../quodlibet/operon/commands.py:712 msgid "Fill tracknumbers for all files" msgstr "" #: ../quodlibet/operon/commands.py:731 msgid "Print tags based on the given pattern" msgstr "" #: ../quodlibet/operon/commands.py:768 #, fuzzy msgid "Display help information" msgstr "顯示基本的使用方法" #: ../quodlibet/operon/util.py:40 #, 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:30 #, fuzzy msgid "_Unknown" msgstr "未知" #: ../quodlibet/order/__init__.py:142 msgid "In Order" msgstr "順序" #: ../quodlibet/order/__init__.py:143 msgid "_In Order" msgstr "順序 (_I)" #: ../quodlibet/order/reorder.py:23 #, fuzzy msgid "Random" msgstr "隨機 (_R)" #: ../quodlibet/order/reorder.py:24 ../quodlibet/qltk/queue.py:119 msgid "_Random" msgstr "隨機 (_R)" #: ../quodlibet/order/reorder.py:39 ../quodlibet/order/reorder.py:40 msgid "Prefer higher rated" msgstr "" #: ../quodlibet/order/repeat.py:43 ../quodlibet/order/repeat.py:44 msgid "Repeat this track" msgstr "" #: ../quodlibet/order/repeat.py:57 ../quodlibet/order/repeat.py:58 #, fuzzy msgid "Repeat all" msgstr "重覆播放 (_R)" #: ../quodlibet/order/repeat.py:73 ../quodlibet/order/repeat.py:74 msgid "One Song" msgstr "單曲" #: ../quodlibet/player/gstbe/player.py:98 msgid "Stream" msgstr "" #: ../quodlibet/player/gstbe/player.py:98 msgid "Buffering" msgstr "" #: ../quodlibet/player/gstbe/player.py:319 msgid "Could not create GStreamer pipeline" msgstr "" #: ../quodlibet/player/gstbe/player.py:560 msgid "No GStreamer element found to handle media format" msgstr "" #: ../quodlibet/player/gstbe/player.py:561 #, 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:25 msgid "" "The GStreamer output pipeline used for playback. Leave blank for the default " "pipeline. In case the pipeline contains a sink, it will be used instead of " "the default one." msgstr "" #: ../quodlibet/player/gstbe/prefs.py:36 msgid "_Output pipeline:" msgstr "" #: ../quodlibet/player/gstbe/prefs.py:43 #, fuzzy, python-format msgid "%.1f seconds" msgstr "%d 秒" #: ../quodlibet/player/gstbe/prefs.py:57 msgid "_Buffer duration:" msgstr "" #: ../quodlibet/player/gstbe/prefs.py:66 msgid "Disable _gapless playback" msgstr "" #: ../quodlibet/player/gstbe/prefs.py:70 msgid "" "Disabling gapless playback can avoid track changing problems with some " "GStreamer versions." msgstr "" #: ../quodlibet/player/gstbe/util.py:93 #, fuzzy msgid "No GStreamer audio sink found" msgstr "未發現站台" #: ../quodlibet/player/gstbe/util.py:112 msgid "Invalid GStreamer output pipeline" msgstr "" #: ../quodlibet/player/xinebe/player.py:90 #, fuzzy msgid "Unable to create audio output" msgstr "無法建立資料夾" #: ../quodlibet/player/xinebe/player.py:91 #, python-format msgid "" "The audio device %r was not found. Check your Xine settings in ~/.quodlibet/" "config." msgstr "" #: ../quodlibet/plugins/__init__.py:62 #, python-brace-format msgid "" "Couldn't find module '{module}'. Perhaps you need to install the package?" msgstr "" #: ../quodlibet/plugins/__init__.py:71 #, python-brace-format msgid "Couldn't find GStreamer element '{element}'." msgstr "" #: ../quodlibet/plugins/playlist.py:30 #, 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:41 ../quodlibet/qltk/songsmenu.py:46 #: ../quodlibet/qltk/songsmenu.py:74 #, fuzzy msgid "_Run Plugin" msgstr "外掛 (_P)" #: ../quodlibet/qltk/about.py:40 #, python-format msgid "Supported formats: %s" msgstr "支援格式:%s" #: ../quodlibet/qltk/about.py:43 #, python-format msgid "Audio device: %s" msgstr "音訊裝置:%s" #. 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:207 ../quodlibet/qltk/information.py:131 msgid "Bookmarks" msgstr "書籤" #: ../quodlibet/qltk/browser.py:56 msgid "_Filters" msgstr "篩選 (_F)" #: ../quodlibet/qltk/browser.py:57 #, fuzzy msgid "Recently _Played" msgstr "從未播放過 (_N)" #: ../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 #, 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 "隨機風格 (_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:48 ../quodlibet/qltk/edittags.py:311 msgid "_Value:" msgstr "設定值:(_V)" #: ../quodlibet/qltk/cbes.py:262 msgid "Saved Values" msgstr "已儲存設定值" #: ../quodlibet/qltk/cbes.py:263 #, fuzzy msgid "Edit saved values…" msgstr "編輯儲存設定值..." #: ../quodlibet/qltk/controls.py:111 msgid "Auto_matic" msgstr "" #: ../quodlibet/qltk/controls.py:112 #, fuzzy msgid "_Track Mode" msgstr "音軌檔頭 (_T)" #: ../quodlibet/qltk/controls.py:113 #, fuzzy msgid "_Album Mode" msgstr "專輯檔頭 (_A)" #. Translators: player state, no action #: ../quodlibet/qltk/controls.py:122 msgid "_Mute" msgstr "" #: ../quodlibet/qltk/controls.py:128 #, fuzzy msgid "_Replay Gain Mode" msgstr "回放增益音量修正 (_R)" #. Translators: New Command/Entry/Item/... #: ../quodlibet/qltk/data_editors.py:119 #, python-format msgid "New %s" msgstr "" #: ../quodlibet/qltk/data_editors.py:218 #, fuzzy msgid "(unknown)" msgstr "未知" #: ../quodlibet/qltk/data_editors.py:355 msgid "Tag expression" msgstr "" #: ../quodlibet/qltk/data_editors.py:382 msgid "Tag expression e.g. people:real or ~album~year." msgstr "" #: ../quodlibet/qltk/data_editors.py:383 #, fuzzy msgid "Enter new tag" 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] "" #: ../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] "" #: ../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 #, 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/downloader.py:38 msgid "Downloads" msgstr "下載" #: ../quodlibet/qltk/downloader.py:62 msgid "Size" msgstr "大小" #. Add stop/pause buttons. count = 0 means an indefinite #. number of steps. #: ../quodlibet/qltk/downloader.py:94 ../quodlibet/qltk/renamefiles.py:265 #: ../quodlibet/qltk/wlw.py:50 msgid "_Stop" msgstr "" #: ../quodlibet/qltk/edittags.py:63 ../quodlibet/qltk/edittags.py:74 #, python-format msgid "missing from %d song" msgid_plural "missing from %d songs" msgstr[0] "%d 曲目遺失" #: ../quodlibet/qltk/edittags.py:67 ../quodlibet/qltk/edittags.py:71 #, python-format msgid "different across %d song" msgid_plural "different across %d songs" msgstr[0] "%d 首曲目有差異" #: ../quodlibet/qltk/edittags.py:193 msgid "Split into _Multiple Values" msgstr "多重設定值分割 (_M)" #: ../quodlibet/qltk/edittags.py:211 msgid "Split Disc out of _Album" msgstr "從專輯分離唱片 (_A)" #: ../quodlibet/qltk/edittags.py:228 msgid "Split _Version out of Title" msgstr "從標題分離版本 (_V)" #: ../quodlibet/qltk/edittags.py:259 msgid "Split Arranger out of Ar_tist" msgstr "從演出者分離組織者 (_T)" #: ../quodlibet/qltk/edittags.py:264 msgid "Split _Performer out of Artist" msgstr "從演出者分離演奏者 (_P)" #: ../quodlibet/qltk/edittags.py:270 #, fuzzy msgid "Split _Performer out of Title" msgstr "從演出者分離演奏者 (_P)" #: ../quodlibet/qltk/edittags.py:276 #, fuzzy msgid "Split _Originalartist out of Title" msgstr "從標題分離版本 (_V)" #: ../quodlibet/qltk/edittags.py:283 msgid "Add a Tag" msgstr "加入標籤" #: ../quodlibet/qltk/edittags.py:302 msgid "_Tag:" msgstr "標籤:(_T)" #: ../quodlibet/qltk/edittags.py:404 msgid "Edit Tags" msgstr "編輯標籤" #: ../quodlibet/qltk/edittags.py:477 msgid "Show _programmatic tags" msgstr "顯示標題音樂 (programmatic) 標籤 (_p)" #: ../quodlibet/qltk/edittags.py:478 msgid "" "Access all tags, including machine-generated ones e.g. MusicBrainz or Replay " "Gain tags" msgstr "" #. Translators: Revert button in the tag editor #: ../quodlibet/qltk/edittags.py:508 #, fuzzy msgctxt "edittags" msgid "_Revert" msgstr "從未" #. Translators: Save button in the tag editor #: ../quodlibet/qltk/edittags.py:513 msgctxt "edittags" msgid "_Save" msgstr "" #: ../quodlibet/qltk/edittags.py:659 msgid "Unable to add tag" msgstr "無法加入標籤" #: ../quodlibet/qltk/edittags.py:660 #, fuzzy, python-format msgid "Unable to add <b>%s</b>" msgstr "無法加入曲目" #: ../quodlibet/qltk/edittags.py:662 #, fuzzy, python-format msgid "" "The files currently selected do not support multiple values for <b>%s</b>." msgstr "" "無法加入 <b>%s</b>\n" "\n" "當前選取的檔案不支援多重設定值。" #. Can't add the new tag. #: ../quodlibet/qltk/edittags.py:689 ../quodlibet/qltk/edittags.py:856 #: ../quodlibet/qltk/tagsfrompath.py:212 ../quodlibet/util/__init__.py:554 #: ../quodlibet/util/tags.py:231 msgid "Invalid tag" msgstr "無效的標籤" #: ../quodlibet/qltk/edittags.py:690 ../quodlibet/qltk/edittags.py:857 #: ../quodlibet/qltk/tagsfrompath.py:213 #, python-format msgid "" "Invalid tag <b>%s</b>\n" "\n" "The files currently selected do not support editing this tag." msgstr "" "無效的標籤 <b>%s</b>\n" "\n" "當前選取的檔案不支援標籤編輯。" #: ../quodlibet/qltk/edittags.py:828 ../quodlibet/qltk/edittags.py:868 msgid "Invalid value" msgstr "無效的設定值" #: ../quodlibet/qltk/edittags.py:829 ../quodlibet/qltk/edittags.py:869 #, python-format msgid "" "Invalid value: <b>%(value)s</b>\n" "\n" "%(error)s" msgstr "" "無效的設定值:<b>%(value)s</b>\n" "\n" "%(error)s" #: ../quodlibet/qltk/_editutils.py:28 msgid "Tag may not be accurate" msgstr "標籤可能不正確" #: ../quodlibet/qltk/_editutils.py:31 #, 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:47 msgid "Unable to save song" msgstr "無法儲存曲目" #: ../quodlibet/qltk/_editutils.py:50 #, 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:142 #, fuzzy 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:95 #: ../quodlibet/qltk/quodlibetwindow.py:1066 msgid "_About" msgstr "" #: ../quodlibet/qltk/exfalsowindow.py:99 #: ../quodlibet/qltk/quodlibetwindow.py:1088 msgid "_Check for Updates…" msgstr "" #: ../quodlibet/qltk/exfalsowindow.py:105 #: ../quodlibet/qltk/quodlibetwindow.py:1021 ../quodlibet/qltk/songsmenu.py:304 msgid "_Plugins" msgstr "外掛 (_P)" #: ../quodlibet/qltk/exfalsowindow.py:267 #, fuzzy, python-format msgid "%(title)s and %(count)s more" msgid_plural "%(title)s and %(count)s more" msgstr[0] "%(title)s 與其他 %(count)d 首..." #: ../quodlibet/qltk/exfalsowindow.py:279 msgid "Ex Falso Preferences" msgstr "Ex Falso 偏好設定" #: ../quodlibet/qltk/exfalsowindow.py:289 ../quodlibet/qltk/prefs.py:598 msgid "Split _on:" msgstr "分隔標記 (_O)" #: ../quodlibet/qltk/exfalsowindow.py:295 ../quodlibet/qltk/prefs.py:613 msgid "Tag Editing" msgstr "標籤編輯" #: ../quodlibet/qltk/filesel.py:210 msgid "Folders" msgstr "資料夾" #: ../quodlibet/qltk/filesel.py:253 #, fuzzy msgid "_New Folder…" msgstr "新資料夾" #: ../quodlibet/qltk/filesel.py:262 #, fuzzy msgid "_Select all Sub-Folders" msgstr "選取所有子資料夾 (_S)" #: ../quodlibet/qltk/filesel.py:374 msgid "New Folder" msgstr "新資料夾" #: ../quodlibet/qltk/filesel.py:374 msgid "Enter a name for the new folder:" msgstr "輸入新資料夾的名稱:" #: ../quodlibet/qltk/filesel.py:387 msgid "Unable to create folder" msgstr "無法建立資料夾" #: ../quodlibet/qltk/filesel.py:404 msgid "Unable to delete folder" msgstr "無法刪除資料夾" #: ../quodlibet/qltk/filesel.py:519 ../quodlibet/qltk/pluginwin.py:167 msgid "Songs" msgstr "曲目" #. Translators: As in "by Artist Name" #: ../quodlibet/qltk/info.py:42 #, python-format msgid "by %s" msgstr "演出者:%s" #: ../quodlibet/qltk/info.py:43 ../quodlibet/qltk/information.py:167 #: ../quodlibet/qltk/information.py:448 #, python-format msgid "Disc %s" msgstr "唱片 %s" #: ../quodlibet/qltk/info.py:44 ../quodlibet/qltk/information.py:172 #, python-format msgid "Track %s" msgstr "音軌 %s" #: ../quodlibet/qltk/info.py:108 #, fuzzy msgid "_Edit Display…" msgstr "編輯顯示" #: ../quodlibet/qltk/information.py:105 msgid "No songs are selected." msgstr "無曲目被選取。" #: ../quodlibet/qltk/information.py:106 msgid "No Songs" msgstr "無曲目" #: ../quodlibet/qltk/information.py:121 ../quodlibet/qltk/information.py:338 #: ../quodlibet/qltk/information.py:471 ../quodlibet/qltk/information.py:531 msgid "Information" msgstr "資訊" #: ../quodlibet/qltk/information.py:126 msgid "Lyrics" msgstr "歌詞" #: ../quodlibet/qltk/information.py:184 ../quodlibet/qltk/information.py:396 #, python-format msgid "Produced by %s" msgstr "由 %s 創作" #: ../quodlibet/qltk/information.py:199 ../quodlibet/util/tags.py:76 msgid "artist" msgstr "演出者" #: ../quodlibet/qltk/information.py:200 ../quodlibet/qltk/information.py:561 #: ../quodlibet/util/tags.py:76 msgid "artists" msgstr "演出者" #. for backwards compat #: ../quodlibet/qltk/information.py:221 ../quodlibet/util/tags.py:86 #: ../quodlibet/util/tags.py:114 msgid "performers" msgstr "表演者" #: ../quodlibet/qltk/information.py:235 ../quodlibet/qltk/information.py:248 #: ../quodlibet/qltk/songlistcolumns.py:275 msgid "Never" msgstr "從未" #: ../quodlibet/qltk/information.py:236 #, fuzzy, python-format msgid "%(n)d time" msgid_plural "%(n)d times" msgstr[0] "%d 次" #: ../quodlibet/qltk/information.py:254 ../quodlibet/util/tags.py:139 msgid "added" msgstr "加入時間" #: ../quodlibet/qltk/information.py:255 ../quodlibet/util/tags.py:140 msgid "last played" msgstr "上次播放" #: ../quodlibet/qltk/information.py:256 ../quodlibet/util/tags.py:150 msgid "plays" msgstr "播放次數" #: ../quodlibet/qltk/information.py:257 ../quodlibet/util/tags.py:151 msgid "skips" msgstr "跳過次數" #: ../quodlibet/qltk/information.py:258 ../quodlibet/util/tags.py:156 msgid "rating" msgstr "曲目評等" #: ../quodlibet/qltk/information.py:287 msgid "path" msgstr "" #: ../quodlibet/qltk/information.py:288 ../quodlibet/util/tags.py:154 msgid "length" msgstr "長度" #: ../quodlibet/qltk/information.py:289 #, fuzzy msgid "format" msgstr "資訊" #: ../quodlibet/qltk/information.py:290 ../quodlibet/util/tags.py:163 msgid "codec" msgstr "" #: ../quodlibet/qltk/information.py:291 ../quodlibet/util/tags.py:164 #, fuzzy msgid "encoding" msgstr "[無效的編碼]" #: ../quodlibet/qltk/information.py:292 ../quodlibet/util/tags.py:160 msgid "bitrate" msgstr "位元率" #: ../quodlibet/qltk/information.py:293 ../quodlibet/util/tags.py:161 msgid "file size" msgstr "檔案大小" #: ../quodlibet/qltk/information.py:294 ../quodlibet/util/tags.py:149 msgid "modified" msgstr "修改時間" #: ../quodlibet/qltk/information.py:331 msgid "Additional" msgstr "" #: ../quodlibet/qltk/information.py:383 #, python-format msgid "%d selected" msgid_plural "%d selected" msgstr[0] "%d 已選取" #: ../quodlibet/qltk/information.py:458 msgid "Track unavailable" msgstr "無效的音軌" #: ../quodlibet/qltk/information.py:464 msgid "Track List" msgstr "音軌清單" #: ../quodlibet/qltk/information.py:505 ../quodlibet/qltk/information.py:578 #, python-format msgid "%d song with no album" msgid_plural "%d songs with no album" msgstr[0] "%d 曲目沒有專輯資訊" #: ../quodlibet/qltk/information.py:508 msgid "Selected Discography" msgstr "已選擇音樂唱片分類" #: ../quodlibet/qltk/information.py:558 #, python-format msgid "%d song with no artist" msgid_plural "%d songs with no artist" msgstr[0] "%d 曲目沒有演出者資訊" #: ../quodlibet/qltk/information.py:586 ../quodlibet/util/tags.py:74 msgid "albums" msgstr "專輯" #: ../quodlibet/qltk/information.py:599 msgid "Total length:" msgstr "總計長度:" #: ../quodlibet/qltk/information.py:603 msgid "Total size:" msgstr "合計大小:" #: ../quodlibet/qltk/information.py:606 msgid "Files" msgstr "檔案" #: ../quodlibet/qltk/lyrics.py:37 msgid "_Download" msgstr "下載 (_D)" #: ../quodlibet/qltk/lyrics.py:40 #, fuzzy msgid "_Edit" msgstr "編輯顯示... (_E)" #. buffer.set_text(_("No lyrics found.\n\nYou can click the " #. "Download button to have Quod Libet search " #. "for lyrics online. You can also enter them " #. "yourself and click save.")) #: ../quodlibet/qltk/lyrics.py:73 ../quodlibet/qltk/lyrics.py:109 msgid "No lyrics found for this song." msgstr "找不到這首曲目的歌詞。" #: ../quodlibet/qltk/lyrics.py:82 #, fuzzy msgid "Searching for lyrics…" 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/msg.py:41 msgid "Discard tag changes?" msgstr "要放棄標籤的變更?" #: ../quodlibet/qltk/msg.py:42 msgid "" "Tags have been changed but not saved. Save these files, or revert and " "discard changes?" msgstr "標籤已被改變但尚未儲存。要儲存這些檔案或者是放棄變更?" #: ../quodlibet/qltk/msg.py:55 ../quodlibet/qltk/prefs.py:595 #: ../quodlibet/qltk/textedit.py:64 ../quodlibet/qltk/tracknumbers.py:117 #, fuzzy msgid "_Revert" msgstr "從未" #: ../quodlibet/qltk/msg.py:86 msgid "File exists" msgstr "檔案已存在" #: ../quodlibet/qltk/msg.py:88 #, python-format msgid "Replace %(file-name)s?" msgstr "" #: ../quodlibet/qltk/msg.py:94 #, fuzzy msgid "_Replace File" msgstr "重新命名檔案" #: ../quodlibet/qltk/notif.py:182 msgid "Active tasks" msgstr "" #: ../quodlibet/qltk/notif.py:188 #, python-format msgid "%d tasks running" msgstr "" #: ../quodlibet/qltk/playorder.py:254 #, fuzzy msgid "Toggle shuffle mode" msgstr "切換 播放/暫停 模式" #: ../quodlibet/qltk/playorder.py:270 #, fuzzy msgid "Toggle repeat mode" msgstr "切換 播放/暫停 模式" #: ../quodlibet/qltk/pluginwin.py:44 msgid "Plugin Errors" msgstr "外掛程式錯誤" #: ../quodlibet/qltk/pluginwin.py:124 msgid "Enabled" msgstr "" #: ../quodlibet/qltk/pluginwin.py:125 #, fuzzy msgid "Disabled" msgstr "停用瀏覽器" #: ../quodlibet/qltk/pluginwin.py:131 msgid "No category" msgstr "" #: ../quodlibet/qltk/pluginwin.py:169 msgid "Events" msgstr "" #: ../quodlibet/qltk/pluginwin.py:170 #, fuzzy msgid "Play Order" msgstr "排序:(_O)" #: ../quodlibet/qltk/pluginwin.py:171 #, fuzzy msgid "Editing" msgstr "標籤編輯" #: ../quodlibet/qltk/pluginwin.py:173 #, fuzzy msgid "Covers" msgstr "合計大小:" #: ../quodlibet/qltk/pluginwin.py:309 msgid "No plugins found." msgstr "找不到外掛。" #: ../quodlibet/qltk/pluginwin.py:358 #, fuzzy msgid "Plugins" msgstr "外掛 (_P)" #: ../quodlibet/qltk/pluginwin.py:402 msgid "Show _Errors" msgstr "顯示錯誤 (_E)" #: ../quodlibet/qltk/prefs.py:45 msgid "_Disc" msgstr "唱片 (_D)" #: ../quodlibet/qltk/prefs.py:46 msgid "_Track" msgstr "音軌 (_T)" #: ../quodlibet/qltk/prefs.py:47 #, fuzzy msgid "Grou_ping" msgstr "組合" #: ../quodlibet/qltk/prefs.py:50 msgid "Al_bum" msgstr "專輯 (_B)" #: ../quodlibet/qltk/prefs.py:55 msgid "_Filename" msgstr "檔名 (_F)" #: ../quodlibet/qltk/prefs.py:57 msgid "_Length" msgstr "長度 (_L)" #: ../quodlibet/qltk/prefs.py:64 msgid "_Jump to playing song automatically" msgstr "自動跳到播放中的曲目 (_J)" #: ../quodlibet/qltk/prefs.py:66 msgid "When the playing song changes, scroll to it in the song list" msgstr "當變更播放中的曲目時,捲動清單到該曲目位置" #: ../quodlibet/qltk/prefs.py:82 msgid "_Others:" msgstr "其他:(_O)" #: ../quodlibet/qltk/prefs.py:88 #, fuzzy msgid "_Edit…" msgstr "編輯顯示... (_E)" #: ../quodlibet/qltk/prefs.py:91 msgid "Add or remove additional column headers" msgstr "" #: ../quodlibet/qltk/prefs.py:101 msgid "Visible Columns" msgstr "可視欄位" #: ../quodlibet/qltk/prefs.py:104 msgid "Title includes _version" msgstr "標題包含版本 (_V)" #: ../quodlibet/qltk/prefs.py:106 #, fuzzy msgid "Artist includes all _people" msgstr "標題包含版本 (_V)" #: ../quodlibet/qltk/prefs.py:108 #, fuzzy msgid "Album includes _disc subtitle" msgstr "專輯包含部份 (_P)" #: ../quodlibet/qltk/prefs.py:110 msgid "Filename includes _folder" msgstr "檔名包含資料夾 (_F)" #: ../quodlibet/qltk/prefs.py:123 #, fuzzy msgid "Column Preferences" msgstr "偏好設定" #: ../quodlibet/qltk/prefs.py:129 msgid "Apply current configuration to song list, adding new columns to the end" msgstr "" #: ../quodlibet/qltk/prefs.py:142 ../quodlibet/qltk/shortcuts.py:24 msgid "Song List" msgstr "曲目清單" #: ../quodlibet/qltk/prefs.py:222 #, fuzzy msgid "Edit Columns" msgstr "可視欄位" #: ../quodlibet/qltk/prefs.py:259 msgid "Duration totals" msgstr "" #: ../quodlibet/qltk/prefs.py:271 msgid "_Global filter:" msgstr "通用篩選:(_G)" #: ../quodlibet/qltk/prefs.py:277 msgid "Apply this query in addition to all others" msgstr "" #. Translators: The heading of the preference group, no action #: ../quodlibet/qltk/prefs.py:283 #, fuzzy msgctxt "heading" msgid "Search" msgstr "搜尋" #: ../quodlibet/qltk/prefs.py:287 ../quodlibet/qltk/shortcuts.py:21 msgid "Browsers" msgstr "瀏覽器" #: ../quodlibet/qltk/prefs.py:293 msgid "Confirm _multiple ratings" msgstr "" #: ../quodlibet/qltk/prefs.py:295 msgid "" "Ask for confirmation before changing the rating of multiple songs at once" msgstr "" #: ../quodlibet/qltk/prefs.py:298 msgid "Enable _one-click ratings" msgstr "" #: ../quodlibet/qltk/prefs.py:300 #, fuzzy msgid "Enable rating by clicking on the rating column in the song list" msgstr "當變更播放中的曲目時,捲動清單到該曲目位置" #: ../quodlibet/qltk/prefs.py:306 ../quodlibet/qltk/prefs.py:616 #, fuzzy msgid "Ratings" msgstr "評等 (_R)" #. Filename choice algorithm config #: ../quodlibet/qltk/prefs.py:312 msgid "Prefer _embedded art" msgstr "" #: ../quodlibet/qltk/prefs.py:314 msgid "" "Choose to use artwork embedded in the audio (where available) over other " "sources" msgstr "" #: ../quodlibet/qltk/prefs.py:319 msgid "_Fixed image filename:" msgstr "" #: ../quodlibet/qltk/prefs.py:321 msgid "The single image filename to use if selected" msgstr "" #: ../quodlibet/qltk/prefs.py:327 msgid "The album art image file to use when forced" msgstr "" #: ../quodlibet/qltk/prefs.py:336 #, fuzzy msgid "Album Art" msgstr "專輯清單" #: ../quodlibet/qltk/prefs.py:357 #, fuzzy msgid "Playback" msgstr "暫停播放" #: ../quodlibet/qltk/prefs.py:362 msgid "Output Configuration" msgstr "" #: ../quodlibet/qltk/prefs.py:373 msgid "" "If no Replay Gain information is available for a song, scale the volume by " "this value" msgstr "" #: ../quodlibet/qltk/prefs.py:376 #, fuzzy msgid "_Fall-back gain (dB):" msgstr "音量增益 (dB):(_V)" #: ../quodlibet/qltk/prefs.py:387 msgid "" "Scale volume for all songs by this value, as long as the result will not clip" msgstr "" #: ../quodlibet/qltk/prefs.py:390 #, fuzzy msgid "_Pre-amp gain (dB):" msgstr "音量增益 (dB):(_V)" #: ../quodlibet/qltk/prefs.py:395 #, fuzzy msgid "_Enable Replay Gain volume adjustment" msgstr "回放增益音量修正 (_R)" #: ../quodlibet/qltk/prefs.py:420 #, fuzzy msgid "Replay Gain Volume Adjustment" msgstr "回放增益音量修正 (_R)" #: ../quodlibet/qltk/prefs.py:450 msgid "_Default rating:" msgstr "" #: ../quodlibet/qltk/prefs.py:493 #, fuzzy msgid "Rating _scale:" msgstr "評等 (_R)" #: ../quodlibet/qltk/prefs.py:542 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:547 msgid "_Bayesian averaging amount:" msgstr "" #: ../quodlibet/qltk/prefs.py:556 #, fuzzy msgid "Save ratings and play _counts" msgstr "儲存評等與播放次數" #: ../quodlibet/qltk/prefs.py:560 msgid "_Email:" msgstr "電子郵件:(_E)" #: ../quodlibet/qltk/prefs.py:562 msgid "Ratings and play counts will be set for this email address" msgstr "評等和播放次數將會被設定到這個電子郵件地址" #: ../quodlibet/qltk/prefs.py:577 #, fuzzy msgid "Auto-save tag changes" msgstr "要放棄標籤的變更?" #: ../quodlibet/qltk/prefs.py:579 msgid "Save changes to tags without confirmation when editing multiple files" msgstr "" #: ../quodlibet/qltk/prefs.py:587 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:610 #, fuzzy msgid "Tags" msgstr "編輯標籤" #: ../quodlibet/qltk/prefs.py:631 #, fuzzy msgid "Updating for new ratings" msgstr "新的站台 (_N)" #: ../quodlibet/qltk/prefs.py:641 #, fuzzy msgid "Scan library _on start" msgstr "重新整理資料庫 (_F)" #: ../quodlibet/qltk/prefs.py:651 ../quodlibet/qltk/quodlibetwindow.py:1100 #, fuzzy msgid "_Scan Library" msgstr "搜尋資料庫 (_S)" #: ../quodlibet/qltk/prefs.py:653 ../quodlibet/qltk/quodlibetwindow.py:1162 msgid "Check for changes in your library" msgstr "檢查您的資料庫變動" #: ../quodlibet/qltk/prefs.py:658 #, fuzzy msgid "Re_build Library" msgstr "重新載入資料庫 (_L)" #: ../quodlibet/qltk/prefs.py:661 #, fuzzy msgid "Reload all songs in your library. This can take a long time." msgstr "重新載入您的資料庫中所有曲目 (這可能會花一些時間)" #: ../quodlibet/qltk/prefs.py:671 #, fuzzy msgid "Scan Directories" msgstr "掃瞄目錄 (_D)" #: ../quodlibet/qltk/prefs.py:677 #, fuzzy msgid "Hidden Songs" msgstr "無曲目" #: ../quodlibet/qltk/properties.py:158 ../quodlibet/util/collection.py:398 #, fuzzy, 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:162 ../quodlibet/qltk/properties.py:164 msgid "Properties" msgstr "屬性" #: ../quodlibet/qltk/queue.py:101 msgid "_Queue" msgstr "佇列 (_Q)" #: ../quodlibet/qltk/queue.py:126 msgid "Stop Once Empty" msgstr "" #: ../quodlibet/qltk/queue.py:130 #, fuzzy msgid "_Clear Queue" msgstr "外掛程式錯誤" #: ../quodlibet/qltk/queue.py:242 #, 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:198 msgid "_Browse Library" msgstr "瀏覽資料庫 (_B)" #: ../quodlibet/qltk/quodlibetwindow.py:395 #, fuzzy msgid "Toggle queue visibility" msgstr "切換主視窗可見性" #: ../quodlibet/qltk/quodlibetwindow.py:516 #, fuzzy msgid "Playback Error" msgstr "暫停播放" #: ../quodlibet/qltk/quodlibetwindow.py:524 #, fuzzy msgid "Set up library directories?" msgstr "選取目錄" #: ../quodlibet/qltk/quodlibetwindow.py:525 msgid "You don't have any music library set up. Would you like to do that now?" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:531 msgid "_Not Now" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:532 msgid "_Set Up" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:956 msgid "Unable to add songs" msgstr "無法加入曲目" #: ../quodlibet/qltk/quodlibetwindow.py:957 #: ../quodlibet/qltk/quodlibetwindow.py:1364 #, fuzzy, python-format msgid "%s uses an unsupported protocol." msgstr "<b>%s</b> 使用了未支援的通訊協定。" #: ../quodlibet/qltk/quodlibetwindow.py:980 msgid "_Jump to Playing Song" msgstr "跳到播放中的曲目 (_J)" #: ../quodlibet/qltk/quodlibetwindow.py:986 #, fuzzy msgid "_File" msgstr "檔案" #: ../quodlibet/qltk/quodlibetwindow.py:987 #, fuzzy msgid "_Song" msgstr "曲目" #: ../quodlibet/qltk/quodlibetwindow.py:988 msgid "_View" msgstr "檢視 (_V)" #: ../quodlibet/qltk/quodlibetwindow.py:989 #, fuzzy msgid "_Browse" msgstr "瀏覽器" #: ../quodlibet/qltk/quodlibetwindow.py:990 msgid "_Control" msgstr "控制 (_C)" #: ../quodlibet/qltk/quodlibetwindow.py:991 msgid "_Help" msgstr "說明 (_H)" #: ../quodlibet/qltk/quodlibetwindow.py:997 #, fuzzy msgid "_Add a Folder…" msgstr "加入資料夾... (_A)" #: ../quodlibet/qltk/quodlibetwindow.py:1002 #, fuzzy msgid "_Add a File…" msgstr "加入檔案... (_A)" #: ../quodlibet/qltk/quodlibetwindow.py:1007 #, fuzzy msgid "_Add a Location…" msgstr "加入位置" #: ../quodlibet/qltk/quodlibetwindow.py:1036 #, fuzzy msgid "Edit Bookmarks…" msgstr "編輯書籤... (_E)" #: ../quodlibet/qltk/quodlibetwindow.py:1056 #, fuzzy msgid "Stop After This Song" msgstr "在這首歌之後停止" #: ../quodlibet/qltk/quodlibetwindow.py:1062 msgid "_Keyboard Shortcuts" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:1071 msgid "Online Help" msgstr "" #: ../quodlibet/qltk/quodlibetwindow.py:1080 #, fuzzy msgid "Search Help" msgstr "搜尋" #: ../quodlibet/qltk/quodlibetwindow.py:1352 msgid "Add a Location" msgstr "加入位置" #: ../quodlibet/qltk/quodlibetwindow.py:1353 msgid "Enter the location of an audio file:" msgstr "輸入音訊檔案位置:" #: ../quodlibet/qltk/quodlibetwindow.py:1358 #: ../quodlibet/qltk/quodlibetwindow.py:1363 msgid "Unable to add location" msgstr "無法加入位置" #: ../quodlibet/qltk/quodlibetwindow.py:1359 #, fuzzy, python-format msgid "%s is not a valid location." msgstr "<b>%s</b> 不是有效的位置。" #: ../quodlibet/qltk/quodlibetwindow.py:1372 #: ../quodlibet/qltk/quodlibetwindow.py:1381 msgid "Add Music" msgstr "加入音樂" #: ../quodlibet/qltk/quodlibetwindow.py:1372 ../quodlibet/qltk/scanbox.py:99 #, fuzzy msgid "_Add Folders" msgstr "加入資料夾... (_A)" #: ../quodlibet/qltk/quodlibetwindow.py:1379 #, fuzzy msgid "Music Files" msgstr "音樂播放器" #: ../quodlibet/qltk/quodlibetwindow.py:1381 #, fuzzy msgid "_Add Files" msgstr "加入檔案... (_A)" #: ../quodlibet/qltk/ratingsmenu.py:24 #, python-format msgid "Are you sure you want to change the rating of all %d songs?" msgstr "" #: ../quodlibet/qltk/ratingsmenu.py:26 msgid "The saved ratings will be removed" msgstr "" #: ../quodlibet/qltk/ratingsmenu.py:27 #, python-format msgid "The rating of all selected songs will be changed to '%s'" msgstr "" #: ../quodlibet/qltk/ratingsmenu.py:57 ../quodlibet/qltk/ratingsmenu.py:111 #, fuzzy msgid "_Remove Rating" msgstr "評等 (_R)" #: ../quodlibet/qltk/ratingsmenu.py:98 #, fuzzy msgid "Change _Rating" msgstr "評等 (_R)" #: ../quodlibet/qltk/renamefiles.py:46 msgid "Replace spaces with _underscores" msgstr "以底線替換空白 (_U)" #: ../quodlibet/qltk/renamefiles.py:56 msgid "Strip _Windows-incompatible characters" msgstr "刪除不相容 Windows 的字元 (_W)" #: ../quodlibet/qltk/renamefiles.py:74 msgid "Strip _diacritical marks" msgstr "刪除發音標記 (_D)" #: ../quodlibet/qltk/renamefiles.py:85 msgid "Strip non-_ASCII characters" msgstr "刪除非 ASCII 字元 (_A)" #: ../quodlibet/qltk/renamefiles.py:95 msgid "Use only _lowercase characters" msgstr "" #: ../quodlibet/qltk/renamefiles.py:123 msgid "Rename Files" msgstr "重新命名檔案" #: ../quodlibet/qltk/renamefiles.py:139 ../quodlibet/qltk/tagsfrompath.py:116 #, fuzzy msgid "Path Patterns" msgstr "模式" #: ../quodlibet/qltk/renamefiles.py:140 ../quodlibet/qltk/tagsfrompath.py:117 #, fuzzy msgid "Edit saved patterns…" msgstr "編輯儲存設定值..." #: ../quodlibet/qltk/renamefiles.py:143 ../quodlibet/qltk/tagsfrompath.py:120 #: ../quodlibet/qltk/tracknumbers.py:58 msgid "_Preview" msgstr "預覽 (_P)" #: ../quodlibet/qltk/renamefiles.py:190 msgid "New Name" msgstr "新的名稱" #: ../quodlibet/qltk/renamefiles.py:255 msgid "Unable to rename file" msgstr "無法重新命名檔案" #: ../quodlibet/qltk/renamefiles.py:256 #, fuzzy, python-format msgid "" "Renaming <b>%(old-name)s</b> to <b>%(new-name)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." msgstr "" "重新命名 <b>%s</b> 成 <b>%s</b> 時失敗。可能目標檔案已存在,或者是您沒有足夠" "的權限來建立新檔案或移除舊檔案。" #: ../quodlibet/qltk/renamefiles.py:264 #, fuzzy msgid "Ignore _All Errors" msgstr "顯示錯誤 (_E)" #: ../quodlibet/qltk/renamefiles.py:267 msgid "_Continue" msgstr "繼續 (_C)" #: ../quodlibet/qltk/renamefiles.py:296 msgid "Path is not absolute" msgstr "不是絕對路徑" #: ../quodlibet/qltk/renamefiles.py:297 #, python-format msgid "" "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 ~/." msgstr "" "這個模式\n" "\t<b>%s</b>\n" "包含 / 但不是以根目錄為起始。要避免呼叫錯誤的資料夾,您的起始目錄格式應為 / " "或 ~/。" #: ../quodlibet/qltk/scanbox.py:47 #, fuzzy msgid "" "Songs in the listed folders will be added to the library during a library " "refresh" msgstr "這些資料夾 (以「:」隔開) 中所放置的曲目將會被加入到您的資料庫中" #: ../quodlibet/qltk/scanbox.py:99 msgid "Select Directories" msgstr "選取目錄" #: ../quodlibet/qltk/searchbar.py:52 #, fuzzy msgid "Saved Searches" msgstr "已儲存設定值" #: ../quodlibet/qltk/searchbar.py:53 #, fuzzy msgid "Edit saved searches…" msgstr "編輯儲存設定值..." #: ../quodlibet/qltk/searchbar.py:74 msgid "Search your library, using free text or QL queries" msgstr "" #: ../quodlibet/qltk/searchbar.py:129 #, fuzzy msgid "Search after _typing" msgstr "在這首歌之後停止" #: ../quodlibet/qltk/searchbar.py:132 msgid "Show search results after the user stops typing." msgstr "" #: ../quodlibet/qltk/searchbar.py:187 msgid "_Limit:" msgstr "限制 (_L):" #: ../quodlibet/qltk/searchbar.py:200 msgid "_Weight" msgstr "加權 (_W)" #: ../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 ../quodlibet/qltk/shortcuts.py:41 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: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:377 #, python-format msgid "_Filter on %s" msgstr "以 %s 篩選 (_F)" #: ../quodlibet/qltk/songlist.py:1094 #, fuzzy msgid "All _Headers" msgstr "專輯檔頭 (_A)" #: ../quodlibet/qltk/songlist.py:1095 msgid "_Track Headers" msgstr "音軌檔頭 (_T)" #: ../quodlibet/qltk/songlist.py:1096 msgid "_Album Headers" msgstr "專輯檔頭 (_A)" #: ../quodlibet/qltk/songlist.py:1097 msgid "_People Headers" msgstr "個人或團體檔頭 (_P)" #: ../quodlibet/qltk/songlist.py:1098 msgid "_Date Headers" msgstr "日期檔頭 (_D)" #: ../quodlibet/qltk/songlist.py:1099 msgid "_File Headers" msgstr "檔案檔頭 (_F)" #: ../quodlibet/qltk/songlist.py:1100 msgid "_Production Headers" msgstr "出版檔頭 (_P)" #: ../quodlibet/qltk/songlist.py:1115 #, fuzzy msgid "_Customize Headers…" msgstr "設置檔頭... (_C)" #: ../quodlibet/qltk/songlist.py:1120 msgid "_Expand Column" msgstr "" #: ../quodlibet/qltk/songsmenu.py:36 #, 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:64 #, 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:149 #, fuzzy msgid "Configure Plugins…" msgstr "以顏色標示搜尋項目 (_S)" #: ../quodlibet/qltk/songsmenu.py:345 msgid "Add to _Queue" msgstr "加入佇列 (_A)" #: ../quodlibet/qltk/songsmenu.py:368 msgid "_Copy to Device" msgstr "複製到裝置 (_C)" #: ../quodlibet/qltk/songsmenu.py:379 #, fuzzy msgid "_Remove from Library" msgstr "從播放清單中移除 (_R)" #: ../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:101 msgid "Tags From Path" msgstr "從路徑名設定標籤" #: ../quodlibet/qltk/tagsfrompath.py:138 msgid "Tags replace existing ones" msgstr "替換現存的標籤" #: ../quodlibet/qltk/tagsfrompath.py:139 msgid "Tags are added to existing ones" msgstr "加入現存的標籤" #. Save button #: ../quodlibet/qltk/tagsfrompath.py:153 msgid "Save" msgstr "" #: ../quodlibet/qltk/tagsfrompath.py:195 #, python-format msgid "" "The pattern\n" "\t<b>%s</b>\n" "is invalid. Possibly it contains the same tag twice or it has unbalanced " "brackets (< / >)." msgstr "" "格式\n" "\t<b>%s</b>\n" "無效。可能是包含兩次同樣的標籤或是括號不平衡 (< / >)。" #: ../quodlibet/qltk/tagsfrompath.py:216 msgid "Invalid tags" msgstr "無效的標籤" #: ../quodlibet/qltk/tagsfrompath.py:217 #, 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" "當前選取的檔案不支援標籤編輯。" #: ../quodlibet/qltk/textedit.py:142 #, 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:158 msgid "Edit Display" msgstr "編輯顯示" #: ../quodlibet/qltk/tracknumbers.py:39 msgid "Track Numbers" msgstr "音軌編號" #: ../quodlibet/qltk/tracknumbers.py:42 msgid "Start fro_m:" msgstr "起始編號:(_m)" #: ../quodlibet/qltk/tracknumbers.py:51 msgid "_Total tracks:" msgstr "總計音軌數:(_T)" #: ../quodlibet/qltk/unity.py:52 #, fuzzy msgid "Play/Pause" msgstr "播放器" #: ../quodlibet/qltk/unity.py:75 #, fuzzy msgid "Previous" msgstr "預覽 (_P)" #: ../quodlibet/qltk/views.py:923 #, 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:89 #, fuzzy msgid "Checking for Updates" msgstr "正在檢查掛載點" #: ../quodlibet/update.py:124 #, fuzzy msgid "Connection failed" msgstr "位置" #: ../quodlibet/update.py:133 #, python-format msgid "You are already using the newest version %(version)s" msgstr "" #: ../quodlibet/update.py:136 #, 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:420 msgid "Playlists must have a name" msgstr "" #: ../quodlibet/util/collection.py:603 #, python-format msgid "A playlist named %s already exists." msgstr "叫作 %s 的播放清單已經存在了。" #: ../quodlibet/util/cover/built_in.py:26 #, fuzzy msgid "Embedded album covers" msgstr "顯示專輯封面 (_C)" #: ../quodlibet/util/cover/built_in.py:27 msgid "Uses covers embedded into audio files." msgstr "" #: ../quodlibet/util/cover/built_in.py:49 #, fuzzy msgid "Filesystem cover" msgstr "檔案系統" #: ../quodlibet/util/cover/built_in.py:50 msgid "" "Uses commonly named images found in common directories alongside the song." msgstr "" #: ../quodlibet/util/__init__.py:93 msgid "Display brief usage information" msgstr "顯示基本的使用方法" #: ../quodlibet/util/__init__.py:95 msgid "Display version and copyright" msgstr "顯示版本與著作權" #: ../quodlibet/util/__init__.py:135 #, python-format msgid "Usage: %(program)s %(usage)s" msgstr "" #: ../quodlibet/util/__init__.py:137 msgid "[options]" msgstr "[選項]" #: ../quodlibet/util/__init__.py:182 #, fuzzy, python-format msgid "Option %r not recognized." msgstr "錯誤:選項「%s」未被辨識。" #: ../quodlibet/util/__init__.py:185 #, fuzzy, python-format msgid "Option %r requires an argument." msgstr "錯誤:選項「%s」需要一個參數。" #: ../quodlibet/util/__init__.py:188 #, fuzzy, python-format msgid "%r is not a unique prefix." msgstr "錯誤:「%s」不是一個獨特的前綴 (prefix)。" #: ../quodlibet/util/__init__.py:364 #, python-format msgid "%d kbps" msgstr "%d kbps" #: ../quodlibet/util/__init__.py:419 #, fuzzy, python-format msgid "%s second" msgid_plural "%s seconds" msgstr[0] "%d 秒" #: ../quodlibet/util/__init__.py:432 msgid "No time information" msgstr "無時間資訊" #: ../quodlibet/util/__init__.py:435 #, python-format msgid "%d second" msgid_plural "%d seconds" msgstr[0] "%d 秒" #: ../quodlibet/util/__init__.py:436 #, python-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "%d 分" #: ../quodlibet/util/__init__.py:437 #, python-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "%d 時" #: ../quodlibet/util/__init__.py:438 #, python-format msgid "%d day" msgid_plural "%d days" msgstr[0] "%d 日" #: ../quodlibet/util/__init__.py:439 #, 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:563 #, 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 "回放增益增益必須以「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」或者是「bootleg」。" #: ../quodlibet/util/massagers.py:208 msgid "Language must be an ISO 639-2 three-letter code" msgstr "" #: ../quodlibet/util/songwrapper.py:112 msgid "Unable to edit song" msgstr "無法編輯曲目" #: ../quodlibet/util/songwrapper.py:113 #, python-format msgid "" "Saving <b>%s</b> 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:34 #: ../quodlibet/util/string/__init__.py:44 msgid "[Invalid Encoding]" msgstr "[無效的編碼]" #: ../quodlibet/util/tags.py:74 msgid "album" msgstr "專輯" #: ../quodlibet/util/tags.py:75 msgid "arranger" msgstr "組織者" #: ../quodlibet/util/tags.py:75 msgid "arrangers" msgstr "組織者" #: ../quodlibet/util/tags.py:75 #, fuzzy msgid "arrangement" msgstr "組織者" #: ../quodlibet/util/tags.py:77 msgid "author" msgstr "作者" #: ../quodlibet/util/tags.py:77 msgid "authors" msgstr "作者" #: ../quodlibet/util/tags.py:78 msgid "composer" msgstr "作曲" #: ../quodlibet/util/tags.py:78 msgid "composers" msgstr "作曲" #: ../quodlibet/util/tags.py:78 #, fuzzy msgid "composition" msgstr "作曲" #. Translators: conducting as in conducting a musical performance #: ../quodlibet/util/tags.py:80 msgid "conductor" msgstr "指揮" #: ../quodlibet/util/tags.py:80 msgid "conductors" msgstr "指揮" #: ../quodlibet/util/tags.py:80 #, fuzzy msgid "conducting" msgstr "指揮" #: ../quodlibet/util/tags.py:81 msgid "contact" msgstr "聯絡" #: ../quodlibet/util/tags.py:82 msgid "copyright" msgstr "著作權" #: ../quodlibet/util/tags.py:83 msgid "date" msgstr "日期" #: ../quodlibet/util/tags.py:84 msgid "description" msgstr "描述" #: ../quodlibet/util/tags.py:85 msgid "genre" msgstr "風格" #: ../quodlibet/util/tags.py:85 #, fuzzy msgid "genres" msgstr "風格" #: ../quodlibet/util/tags.py:86 msgid "performer" msgstr "表演者" #: ../quodlibet/util/tags.py:87 msgid "grouping" msgstr "組合" #: ../quodlibet/util/tags.py:88 msgid "language" msgstr "語言" #: ../quodlibet/util/tags.py:89 msgid "license" msgstr "許可" #: ../quodlibet/util/tags.py:90 msgid "location" msgstr "位置" #: ../quodlibet/util/tags.py:91 msgid "lyricist" msgstr "作詞" #: ../quodlibet/util/tags.py:91 msgid "lyricists" msgstr "作詞" #: ../quodlibet/util/tags.py:91 #, fuzzy msgid "lyrics" msgstr "作詞" #. Translators: Also e.g. "record label", "publisher" #: ../quodlibet/util/tags.py:93 msgid "organization" msgstr "團體" #: ../quodlibet/util/tags.py:94 msgid "title" msgstr "標題" #: ../quodlibet/util/tags.py:95 msgid "version" msgstr "版本" #: ../quodlibet/util/tags.py:96 msgid "website" msgstr "網站" #: ../quodlibet/util/tags.py:98 msgid "album artist" msgstr "專輯演出者" #: ../quodlibet/util/tags.py:99 msgid "BPM" msgstr "BPM" #. Translators: This used to be called "part". #: ../quodlibet/util/tags.py:102 ../quodlibet/util/tags.py:103 msgid "disc subtitle" msgstr "" #: ../quodlibet/util/tags.py:104 ../quodlibet/util/tags.py:141 msgid "disc" msgstr "唱片" #: ../quodlibet/util/tags.py:105 ../quodlibet/util/tags.py:143 msgid "track" msgstr "音軌" #: ../quodlibet/util/tags.py:106 msgid "label ID" msgstr "標籤 ID" #: ../quodlibet/util/tags.py:107 msgid "original release date" msgstr "最初發行日期" #: ../quodlibet/util/tags.py:108 msgid "original album" msgstr "原作專輯" #: ../quodlibet/util/tags.py:109 msgid "original artist" msgstr "原作" #: ../quodlibet/util/tags.py:110 msgid "recording date" msgstr "錄製日期" #: ../quodlibet/util/tags.py:111 msgid "release country" 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:120 #, fuzzy msgid "MusicBrainz recording ID" msgstr "MusicBrainz 音軌 ID" #: ../quodlibet/util/tags.py:121 #, fuzzy msgid "MusicBrainz release track ID" msgstr "MusicBrainz 音軌 ID" #: ../quodlibet/util/tags.py:122 #, fuzzy msgid "MusicBrainz release ID" msgstr "MusicBrainz 音軌 ID" #: ../quodlibet/util/tags.py:123 #, fuzzy msgid "MusicBrainz artist ID" msgstr "MusicBrainz 演出者 ID" #: ../quodlibet/util/tags.py:124 #, fuzzy msgid "MusicBrainz release artist ID" msgstr "MusicBrainz 音軌 ID" #: ../quodlibet/util/tags.py:125 msgid "MusicBrainz TRM ID" msgstr "MusicBrainz TRM ID" #: ../quodlibet/util/tags.py:126 msgid "MusicIP PUID" msgstr "MusicIP PUID" #: ../quodlibet/util/tags.py:127 msgid "MusicBrainz album status" msgstr "MusicBrainz 專輯狀態" #: ../quodlibet/util/tags.py:128 msgid "MusicBrainz album type" msgstr "MusicBrainz 專輯類型" #: ../quodlibet/util/tags.py:129 #, fuzzy msgid "MusicBrainz release group ID" msgstr "MusicBrainz 音軌 ID" #. Translators: "gain" means a volume adjustment, not "to acquire". #: ../quodlibet/util/tags.py:132 msgid "track gain" msgstr "音軌增益" #: ../quodlibet/util/tags.py:133 msgid "track peak" msgstr "音軌高峰值" #. Translators: "gain" means a volume adjustment, not "to acquire". #: ../quodlibet/util/tags.py:135 msgid "album gain" msgstr "專輯增益" #: ../quodlibet/util/tags.py:136 msgid "album peak" msgstr "專輯高峰值" #: ../quodlibet/util/tags.py:137 #, fuzzy msgid "reference loudness" msgstr "偏好設定" #: ../quodlibet/util/tags.py:142 msgid "discs" msgstr "唱片" #: ../quodlibet/util/tags.py:144 msgid "tracks" msgstr "音軌" #: ../quodlibet/util/tags.py:145 msgid "last started" msgstr "上次開始" #: ../quodlibet/util/tags.py:146 msgid "full name" msgstr "全名" #: ../quodlibet/util/tags.py:153 msgid "mount point" msgstr "掛載點" #: ../quodlibet/util/tags.py:155 msgid "people" msgstr "個人或團體" #: ../quodlibet/util/tags.py:157 msgid "year" msgstr "年份" #: ../quodlibet/util/tags.py:158 #, fuzzy msgid "original release year" msgstr "最初發行日期" #: ../quodlibet/util/tags.py:159 #, fuzzy msgid "bookmark" msgstr "書籤" #: ../quodlibet/util/tags.py:162 #, fuzzy msgid "file format" msgstr "格式" #: ../quodlibet/util/tags.py:165 #, fuzzy msgid "playlists" msgstr "播放清單" #: ../quodlibet/util/tags.py:166 msgid "channel count" msgstr "" #. Translators: e.g. "artist (sort)" #: ../quodlibet/util/tags.py:256 msgid "sort" msgstr "" #. Translators: e.g. "performer (roles)" #: ../quodlibet/util/tags.py:264 msgid "roles" msgstr "" #, fuzzy #~ msgid "browsers" #~ msgstr "瀏覽器" #~ msgid "Unable to download lyrics." #~ msgstr "無法下載歌詞。" #~ msgid "Remove all songs from the queue" #~ msgstr "移除佇列中所有曲目" #~ msgid "Watch this folder for new songs" #~ 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 "Model:" #~ msgstr "模式;" #~ msgid "Capacity:" #~ msgstr "容量:" #~ msgid "Firmware:" #~ msgstr "韌體" #, fuzzy #~ msgid "Removing orphaned iPod track" #~ msgstr "警告:正在移除孤立的 iPod 音軌" #, 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 "Unable to open input files" #~ 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 "搜尋" #~ 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 "_Select" #~ msgstr "選取 (_S)" #~ 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 "Choose New Stations" #~ msgstr "選擇新站台" #~ msgid "Add" #~ msgstr "加入" #, fuzzy #~ msgid "Bitrate" #~ msgstr "位元率" #~ msgid "_Stations..." #~ msgstr "站台... (_S)" #, fuzzy #~ msgid "Quod Libet" #~ msgstr "離開 Quod Libet" #~ 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9791858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/poetry.lock�������������������������������������������������������������������������0000644�0001750�0001750�00000135342�00000000000�014702� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������[[package]] name = "alabaster" version = "0.7.12" description = "A configurable sidebar-enabled Sphinx theme" category = "dev" optional = false python-versions = "*" [[package]] name = "atomicwrites" version = "1.4.0" description = "Atomic file writes." category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "attrs" version = "20.3.0" description = "Classes Without Boilerplate" category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [package.extras] dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "furo", "sphinx", "pre-commit"] docs = ["furo", "sphinx", "zope.interface"] tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"] tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six"] [[package]] name = "babel" version = "2.9.0" description = "Internationalization utilities" category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [package.dependencies] pytz = ">=2015.7" [[package]] name = "certifi" version = "2020.12.5" description = "Python package for providing Mozilla's CA Bundle." category = "main" optional = false python-versions = "*" [[package]] name = "chardet" version = "4.0.0" description = "Universal encoding detector for Python 2 and 3" category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [[package]] name = "colorama" version = "0.4.4" description = "Cross-platform colored terminal text." category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [[package]] name = "coverage" version = "5.4" description = "Code coverage measurement for Python" category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" [package.dependencies] toml = {version = "*", optional = true, markers = "extra == \"toml\""} [package.extras] toml = ["toml"] [[package]] name = "dbus-python" version = "1.2.16" description = "Python bindings for libdbus" category = "main" optional = true python-versions = "*" [[package]] name = "docutils" version = "0.16" description = "Docutils -- Python Documentation Utilities" category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [[package]] name = "feedparser" version = "6.0.2" description = "Universal feed parser, handles RSS 0.9x, RSS 1.0, RSS 2.0, CDF, Atom 0.3, and Atom 1.0 feeds" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] sgmllib3k = "*" [[package]] name = "flake8" version = "3.8.4" description = "the modular source code checker: pep8 pyflakes and co" category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" [package.dependencies] importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} mccabe = ">=0.6.0,<0.7.0" pycodestyle = ">=2.6.0a1,<2.7.0" pyflakes = ">=2.2.0,<2.3.0" [[package]] name = "idna" version = "2.10" description = "Internationalized Domain Names in Applications (IDNA)" category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "ifaddr" version = "0.1.7" description = "Cross-platform network interface and IP address enumeration library" category = "main" optional = true python-versions = "*" [[package]] name = "imagesize" version = "1.2.0" description = "Getting image size from png/jpeg/jpeg2000/gif file" category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "importlib-metadata" version = "3.4.0" description = "Read metadata from Python packages" category = "dev" optional = false python-versions = ">=3.6" [package.dependencies] typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""} zipp = ">=0.5" [package.extras] docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] testing = ["pytest (>=3.5,!=3.7.3)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pytest-cov", "pytest-enabler", "packaging", "pep517", "pyfakefs", "flufl.flake8", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"] [[package]] name = "iniconfig" version = "1.1.1" description = "iniconfig: brain-dead simple config-ini parsing" category = "dev" optional = false python-versions = "*" [[package]] name = "jinja2" version = "2.11.2" description = "A very fast and expressive template engine." category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [package.dependencies] MarkupSafe = ">=0.23" [package.extras] i18n = ["Babel (>=0.8)"] [[package]] name = "markupsafe" version = "1.1.1" description = "Safely add untrusted strings to HTML/XML markup." category = "dev" optional = false python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" [[package]] name = "mccabe" version = "0.6.1" description = "McCabe checker, plugin for flake8" category = "dev" optional = false python-versions = "*" [[package]] name = "musicbrainzngs" version = "0.7.1" description = "Python bindings for the MusicBrainz NGS and the Cover Art Archive webservices" category = "main" optional = true python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "mutagen" version = "1.45.1" description = "read and write audio tags for many formats" category = "main" optional = false python-versions = ">=3.5, <4" [[package]] name = "mypy" version = "0.790" description = "Optional static typing for Python" category = "dev" optional = false python-versions = ">=3.5" [package.dependencies] mypy-extensions = ">=0.4.3,<0.5.0" typed-ast = ">=1.4.0,<1.5.0" typing-extensions = ">=3.7.4" [package.extras] dmypy = ["psutil (>=4.0)"] [[package]] name = "mypy-extensions" version = "0.4.3" description = "Experimental type system extensions for programs checked with the mypy typechecker." category = "dev" optional = false python-versions = "*" [[package]] name = "packaging" version = "20.8" description = "Core utilities for Python packages" category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [package.dependencies] pyparsing = ">=2.0.2" [[package]] name = "pluggy" version = "0.13.1" description = "plugin and hook calling mechanisms for python" category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [package.dependencies] importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} [package.extras] dev = ["pre-commit", "tox"] [[package]] name = "polib" version = "1.1.0" description = "A library to manipulate gettext files (po and mo files)." category = "dev" optional = false python-versions = "*" [[package]] name = "py" version = "1.10.0" description = "library with cross-python path, ini-parsing, io, code, log facilities" category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "pycairo" version = "1.20.0" description = "Python interface for cairo" category = "main" optional = false python-versions = ">=3.6, <4" [[package]] name = "pycodestyle" version = "2.6.0" description = "Python style guide checker" category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "pyflakes" version = "2.2.0" description = "passive checker of Python programs" category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "pygments" version = "2.7.4" description = "Pygments is a syntax highlighting package written in Python." category = "dev" optional = false python-versions = ">=3.5" [[package]] name = "pygobject" version = "3.38.0" description = "Python bindings for GObject Introspection" category = "main" optional = false python-versions = ">=3.5, <4" [package.dependencies] pycairo = ">=1.11.1" [[package]] name = "pyinotify" version = "0.9.6" description = "Linux filesystem events monitoring" category = "main" optional = true python-versions = "*" [[package]] name = "pyparsing" version = "2.4.7" description = "Python parsing module" category = "dev" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" [[package]] name = "pytest" version = "6.2.2" description = "pytest: simple powerful testing with Python" category = "dev" optional = false python-versions = ">=3.6" [package.dependencies] atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} attrs = ">=19.2.0" colorama = {version = "*", markers = "sys_platform == \"win32\""} importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} iniconfig = "*" packaging = "*" pluggy = ">=0.12,<1.0.0a1" py = ">=1.8.2" toml = "*" [package.extras] testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] [[package]] name = "pytz" version = "2020.5" description = "World timezone definitions, modern and historical" category = "dev" optional = false python-versions = "*" [[package]] name = "requests" version = "2.25.1" description = "Python HTTP for Humans." category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [package.dependencies] certifi = ">=2017.4.17" chardet = ">=3.0.2,<5" idna = ">=2.5,<3" urllib3 = ">=1.21.1,<1.27" [package.extras] security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)"] socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"] [[package]] name = "sgmllib3k" version = "1.0.0" description = "Py3k port of sgmllib." category = "main" optional = false python-versions = "*" [[package]] name = "snowballstemmer" version = "2.1.0" description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." category = "dev" optional = false python-versions = "*" [[package]] name = "soco" version = "0.21.1" description = "SoCo (Sonos Controller) is a simple library to control Sonos speakers." category = "main" optional = true python-versions = ">=3.5" [package.dependencies] ifaddr = "*" requests = "*" xmltodict = "*" [[package]] name = "sphinx" version = "3.4.3" description = "Python documentation generator" category = "dev" optional = false python-versions = ">=3.5" [package.dependencies] alabaster = ">=0.7,<0.8" babel = ">=1.3" colorama = {version = ">=0.3.5", markers = "sys_platform == \"win32\""} docutils = ">=0.12" imagesize = "*" Jinja2 = ">=2.3" packaging = "*" Pygments = ">=2.0" requests = ">=2.5.0" snowballstemmer = ">=1.1" sphinxcontrib-applehelp = "*" sphinxcontrib-devhelp = "*" sphinxcontrib-htmlhelp = "*" sphinxcontrib-jsmath = "*" sphinxcontrib-qthelp = "*" sphinxcontrib-serializinghtml = "*" [package.extras] docs = ["sphinxcontrib-websupport"] lint = ["flake8 (>=3.5.0)", "isort", "mypy (>=0.790)", "docutils-stubs"] test = ["pytest", "pytest-cov", "html5lib", "cython", "typed-ast"] [[package]] name = "sphinx-rtd-theme" version = "0.5.1" description = "Read the Docs theme for Sphinx" category = "dev" optional = false python-versions = "*" [package.dependencies] sphinx = "*" [package.extras] dev = ["transifex-client", "sphinxcontrib-httpdomain", "bump2version"] [[package]] name = "sphinxcontrib-applehelp" version = "1.0.2" description = "sphinxcontrib-applehelp is a sphinx extension which outputs Apple help books" category = "dev" optional = false python-versions = ">=3.5" [package.extras] lint = ["flake8", "mypy", "docutils-stubs"] test = ["pytest"] [[package]] name = "sphinxcontrib-devhelp" version = "1.0.2" description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document." category = "dev" optional = false python-versions = ">=3.5" [package.extras] lint = ["flake8", "mypy", "docutils-stubs"] test = ["pytest"] [[package]] name = "sphinxcontrib-htmlhelp" version = "1.0.3" description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" category = "dev" optional = false python-versions = ">=3.5" [package.extras] lint = ["flake8", "mypy", "docutils-stubs"] test = ["pytest", "html5lib"] [[package]] name = "sphinxcontrib-jsmath" version = "1.0.1" description = "A sphinx extension which renders display math in HTML via JavaScript" category = "dev" optional = false python-versions = ">=3.5" [package.extras] test = ["pytest", "flake8", "mypy"] [[package]] name = "sphinxcontrib-qthelp" version = "1.0.3" description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document." category = "dev" optional = false python-versions = ">=3.5" [package.extras] lint = ["flake8", "mypy", "docutils-stubs"] test = ["pytest"] [[package]] name = "sphinxcontrib-serializinghtml" version = "1.1.4" description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)." category = "dev" optional = false python-versions = ">=3.5" [package.extras] lint = ["flake8", "mypy", "docutils-stubs"] test = ["pytest"] [[package]] name = "toml" version = "0.10.2" description = "Python Library for Tom's Obvious, Minimal Language" category = "dev" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" [[package]] name = "typed-ast" version = "1.4.2" description = "a fork of Python 2 and 3 ast modules with type comment support" category = "dev" optional = false python-versions = "*" [[package]] name = "typing-extensions" version = "3.7.4.3" description = "Backported and Experimental Type Hints for Python 3.5+" category = "dev" optional = false python-versions = "*" [[package]] name = "urllib3" version = "1.26.3" description = "HTTP library with thread-safe connection pooling, file post, and more." category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" [package.extras] brotli = ["brotlipy (>=0.6.0)"] secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] [[package]] name = "xmltodict" version = "0.12.0" description = "Makes working with XML feel like you are working with JSON" category = "main" optional = true python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "xvfbwrapper" version = "0.2.9" description = "run headless display inside X virtual framebuffer (Xvfb)" category = "dev" optional = false python-versions = "*" [[package]] name = "zipp" version = "3.4.0" description = "Backport of pathlib-compatible object wrapper for zip files" category = "dev" optional = false python-versions = ">=3.6" [package.extras] docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"] testing = ["pytest (>=3.5,!=3.7.3)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pytest-cov", "jaraco.test (>=3.2.0)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy"] [extras] plugins = ["musicbrainzngs", "pyinotify", "dbus-python", "soco"] [metadata] lock-version = "1.1" python-versions = "^3.7" content-hash = "3e2417ddb0218a3190c9be42cace507bb416fb6cf76c99c35433f50a5a2db4e5" [metadata.files] alabaster = [ {file = "alabaster-0.7.12-py2.py3-none-any.whl", hash = "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359"}, {file = "alabaster-0.7.12.tar.gz", hash = "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02"}, ] atomicwrites = [ {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, ] attrs = [ {file = "attrs-20.3.0-py2.py3-none-any.whl", hash = "sha256:31b2eced602aa8423c2aea9c76a724617ed67cf9513173fd3a4f03e3a929c7e6"}, {file = "attrs-20.3.0.tar.gz", hash = "sha256:832aa3cde19744e49938b91fea06d69ecb9e649c93ba974535d08ad92164f700"}, ] babel = [ {file = "Babel-2.9.0-py2.py3-none-any.whl", hash = "sha256:9d35c22fcc79893c3ecc85ac4a56cde1ecf3f19c540bba0922308a6c06ca6fa5"}, {file = "Babel-2.9.0.tar.gz", hash = "sha256:da031ab54472314f210b0adcff1588ee5d1d1d0ba4dbd07b94dba82bde791e05"}, ] certifi = [ {file = "certifi-2020.12.5-py2.py3-none-any.whl", hash = "sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830"}, {file = "certifi-2020.12.5.tar.gz", hash = "sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c"}, ] chardet = [ {file = "chardet-4.0.0-py2.py3-none-any.whl", hash = "sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5"}, {file = "chardet-4.0.0.tar.gz", hash = "sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa"}, ] colorama = [ {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, ] coverage = [ {file = "coverage-5.4-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:6d9c88b787638a451f41f97446a1c9fd416e669b4d9717ae4615bd29de1ac135"}, {file = "coverage-5.4-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:66a5aae8233d766a877c5ef293ec5ab9520929c2578fd2069308a98b7374ea8c"}, {file = "coverage-5.4-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:9754a5c265f991317de2bac0c70a746efc2b695cf4d49f5d2cddeac36544fb44"}, {file = "coverage-5.4-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:fbb17c0d0822684b7d6c09915677a32319f16ff1115df5ec05bdcaaee40b35f3"}, {file = "coverage-5.4-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:b7f7421841f8db443855d2854e25914a79a1ff48ae92f70d0a5c2f8907ab98c9"}, {file = "coverage-5.4-cp27-cp27m-win32.whl", hash = "sha256:4a780807e80479f281d47ee4af2eb2df3e4ccf4723484f77da0bb49d027e40a1"}, {file = "coverage-5.4-cp27-cp27m-win_amd64.whl", hash = "sha256:87c4b38288f71acd2106f5d94f575bc2136ea2887fdb5dfe18003c881fa6b370"}, {file = "coverage-5.4-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:c6809ebcbf6c1049002b9ac09c127ae43929042ec1f1dbd8bb1615f7cd9f70a0"}, {file = "coverage-5.4-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:ba7ca81b6d60a9f7a0b4b4e175dcc38e8fef4992673d9d6e6879fd6de00dd9b8"}, {file = "coverage-5.4-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:89fc12c6371bf963809abc46cced4a01ca4f99cba17be5e7d416ed7ef1245d19"}, {file = "coverage-5.4-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:4a8eb7785bd23565b542b01fb39115a975fefb4a82f23d407503eee2c0106247"}, {file = "coverage-5.4-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:7e40d3f8eb472c1509b12ac2a7e24158ec352fc8567b77ab02c0db053927e339"}, {file = "coverage-5.4-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:1ccae21a076d3d5f471700f6d30eb486da1626c380b23c70ae32ab823e453337"}, {file = "coverage-5.4-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:755c56beeacac6a24c8e1074f89f34f4373abce8b662470d3aa719ae304931f3"}, {file = "coverage-5.4-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:322549b880b2d746a7672bf6ff9ed3f895e9c9f108b714e7360292aa5c5d7cf4"}, {file = "coverage-5.4-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:60a3307a84ec60578accd35d7f0c71a3a971430ed7eca6567399d2b50ef37b8c"}, {file = "coverage-5.4-cp35-cp35m-win32.whl", hash = "sha256:1375bb8b88cb050a2d4e0da901001347a44302aeadb8ceb4b6e5aa373b8ea68f"}, {file = "coverage-5.4-cp35-cp35m-win_amd64.whl", hash = "sha256:16baa799ec09cc0dcb43a10680573269d407c159325972dd7114ee7649e56c66"}, {file = "coverage-5.4-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:2f2cf7a42d4b7654c9a67b9d091ec24374f7c58794858bff632a2039cb15984d"}, {file = "coverage-5.4-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:b62046592b44263fa7570f1117d372ae3f310222af1fc1407416f037fb3af21b"}, {file = "coverage-5.4-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:812eaf4939ef2284d29653bcfee9665f11f013724f07258928f849a2306ea9f9"}, {file = "coverage-5.4-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:859f0add98707b182b4867359e12bde806b82483fb12a9ae868a77880fc3b7af"}, {file = "coverage-5.4-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:04b14e45d6a8e159c9767ae57ecb34563ad93440fc1b26516a89ceb5b33c1ad5"}, {file = "coverage-5.4-cp36-cp36m-win32.whl", hash = "sha256:ebfa374067af240d079ef97b8064478f3bf71038b78b017eb6ec93ede1b6bcec"}, {file = "coverage-5.4-cp36-cp36m-win_amd64.whl", hash = "sha256:84df004223fd0550d0ea7a37882e5c889f3c6d45535c639ce9802293b39cd5c9"}, {file = "coverage-5.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:1b811662ecf72eb2d08872731636aee6559cae21862c36f74703be727b45df90"}, {file = "coverage-5.4-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:6b588b5cf51dc0fd1c9e19f622457cc74b7d26fe295432e434525f1c0fae02bc"}, {file = "coverage-5.4-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:3fe50f1cac369b02d34ad904dfe0771acc483f82a1b54c5e93632916ba847b37"}, {file = "coverage-5.4-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:32ab83016c24c5cf3db2943286b85b0a172dae08c58d0f53875235219b676409"}, {file = "coverage-5.4-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:68fb816a5dd901c6aff352ce49e2a0ffadacdf9b6fae282a69e7a16a02dad5fb"}, {file = "coverage-5.4-cp37-cp37m-win32.whl", hash = "sha256:a636160680c6e526b84f85d304e2f0bb4e94f8284dd765a1911de9a40450b10a"}, {file = "coverage-5.4-cp37-cp37m-win_amd64.whl", hash = "sha256:bb32ca14b4d04e172c541c69eec5f385f9a075b38fb22d765d8b0ce3af3a0c22"}, {file = "coverage-5.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4d7165a4e8f41eca6b990c12ee7f44fef3932fac48ca32cecb3a1b2223c21f"}, {file = "coverage-5.4-cp38-cp38-manylinux1_i686.whl", hash = "sha256:a565f48c4aae72d1d3d3f8e8fb7218f5609c964e9c6f68604608e5958b9c60c3"}, {file = "coverage-5.4-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:fff1f3a586246110f34dc762098b5afd2de88de507559e63553d7da643053786"}, {file = "coverage-5.4-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:a839e25f07e428a87d17d857d9935dd743130e77ff46524abb992b962eb2076c"}, {file = "coverage-5.4-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:6625e52b6f346a283c3d563d1fd8bae8956daafc64bb5bbd2b8f8a07608e3994"}, {file = "coverage-5.4-cp38-cp38-win32.whl", hash = "sha256:5bee3970617b3d74759b2d2df2f6a327d372f9732f9ccbf03fa591b5f7581e39"}, {file = "coverage-5.4-cp38-cp38-win_amd64.whl", hash = "sha256:03ed2a641e412e42cc35c244508cf186015c217f0e4d496bf6d7078ebe837ae7"}, {file = "coverage-5.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:14a9f1887591684fb59fdba8feef7123a0da2424b0652e1b58dd5b9a7bb1188c"}, {file = "coverage-5.4-cp39-cp39-manylinux1_i686.whl", hash = "sha256:9564ac7eb1652c3701ac691ca72934dd3009997c81266807aef924012df2f4b3"}, {file = "coverage-5.4-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:0f48fc7dc82ee14aeaedb986e175a429d24129b7eada1b7e94a864e4f0644dde"}, {file = "coverage-5.4-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:107d327071061fd4f4a2587d14c389a27e4e5c93c7cba5f1f59987181903902f"}, {file = "coverage-5.4-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:0cdde51bfcf6b6bd862ee9be324521ec619b20590787d1655d005c3fb175005f"}, {file = "coverage-5.4-cp39-cp39-win32.whl", hash = "sha256:c67734cff78383a1f23ceba3b3239c7deefc62ac2b05fa6a47bcd565771e5880"}, {file = "coverage-5.4-cp39-cp39-win_amd64.whl", hash = "sha256:c669b440ce46ae3abe9b2d44a913b5fd86bb19eb14a8701e88e3918902ecd345"}, {file = "coverage-5.4-pp36-none-any.whl", hash = "sha256:c0ff1c1b4d13e2240821ef23c1efb1f009207cb3f56e16986f713c2b0e7cd37f"}, {file = "coverage-5.4-pp37-none-any.whl", hash = "sha256:cd601187476c6bed26a0398353212684c427e10a903aeafa6da40c63309d438b"}, {file = "coverage-5.4.tar.gz", hash = "sha256:6d2e262e5e8da6fa56e774fb8e2643417351427604c2b177f8e8c5f75fc928ca"}, ] dbus-python = [ {file = "dbus-python-1.2.16.tar.gz", hash = "sha256:11238f1d86c995d8aed2e22f04a1e3779f0d70e587caffeab4857f3c662ed5a4"}, ] docutils = [ {file = "docutils-0.16-py2.py3-none-any.whl", hash = "sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af"}, {file = "docutils-0.16.tar.gz", hash = "sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc"}, ] feedparser = [ {file = "feedparser-6.0.2-py3-none-any.whl", hash = "sha256:f596c4b34fb3e2dc7e6ac3a8191603841e8d5d267210064e94d4238737452ddd"}, {file = "feedparser-6.0.2.tar.gz", hash = "sha256:1b00a105425f492f3954fd346e5b524ca9cef3a4bbf95b8809470e9857aa1074"}, ] flake8 = [ {file = "flake8-3.8.4-py2.py3-none-any.whl", hash = "sha256:749dbbd6bfd0cf1318af27bf97a14e28e5ff548ef8e5b1566ccfb25a11e7c839"}, {file = "flake8-3.8.4.tar.gz", hash = "sha256:aadae8761ec651813c24be05c6f7b4680857ef6afaae4651a4eccaef97ce6c3b"}, ] idna = [ {file = "idna-2.10-py2.py3-none-any.whl", hash = "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"}, {file = "idna-2.10.tar.gz", hash = "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6"}, ] ifaddr = [ {file = "ifaddr-0.1.7-py2.py3-none-any.whl", hash = "sha256:d1f603952f0a71c9ab4e705754511e4e03b02565bc4cec7188ad6415ff534cd3"}, {file = "ifaddr-0.1.7.tar.gz", hash = "sha256:1f9e8a6ca6f16db5a37d3356f07b6e52344f6f9f7e806d618537731669eb1a94"}, ] imagesize = [ {file = "imagesize-1.2.0-py2.py3-none-any.whl", hash = "sha256:6965f19a6a2039c7d48bca7dba2473069ff854c36ae6f19d2cde309d998228a1"}, {file = "imagesize-1.2.0.tar.gz", hash = "sha256:b1f6b5a4eab1f73479a50fb79fcf729514a900c341d8503d62a62dbc4127a2b1"}, ] importlib-metadata = [ {file = "importlib_metadata-3.4.0-py3-none-any.whl", hash = "sha256:ace61d5fc652dc280e7b6b4ff732a9c2d40db2c0f92bc6cb74e07b73d53a1771"}, {file = "importlib_metadata-3.4.0.tar.gz", hash = "sha256:fa5daa4477a7414ae34e95942e4dd07f62adf589143c875c133c1e53c4eff38d"}, ] iniconfig = [ {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, ] jinja2 = [ {file = "Jinja2-2.11.2-py2.py3-none-any.whl", hash = "sha256:f0a4641d3cf955324a89c04f3d94663aa4d638abe8f733ecd3582848e1c37035"}, {file = "Jinja2-2.11.2.tar.gz", hash = "sha256:89aab215427ef59c34ad58735269eb58b1a5808103067f7bb9d5836c651b3bb0"}, ] markupsafe = [ {file = "MarkupSafe-1.1.1-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161"}, {file = "MarkupSafe-1.1.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7"}, {file = "MarkupSafe-1.1.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183"}, {file = "MarkupSafe-1.1.1-cp27-cp27m-win32.whl", hash = "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b"}, {file = "MarkupSafe-1.1.1-cp27-cp27m-win_amd64.whl", hash = "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e"}, {file = "MarkupSafe-1.1.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f"}, {file = "MarkupSafe-1.1.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1"}, {file = "MarkupSafe-1.1.1-cp34-cp34m-macosx_10_6_intel.whl", hash = "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5"}, {file = "MarkupSafe-1.1.1-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1"}, {file = "MarkupSafe-1.1.1-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735"}, {file = "MarkupSafe-1.1.1-cp34-cp34m-win32.whl", hash = "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21"}, {file = "MarkupSafe-1.1.1-cp34-cp34m-win_amd64.whl", hash = "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235"}, {file = "MarkupSafe-1.1.1-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b"}, {file = "MarkupSafe-1.1.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f"}, {file = "MarkupSafe-1.1.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905"}, {file = "MarkupSafe-1.1.1-cp35-cp35m-win32.whl", hash = "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1"}, {file = "MarkupSafe-1.1.1-cp35-cp35m-win_amd64.whl", hash = "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d"}, {file = "MarkupSafe-1.1.1-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff"}, {file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473"}, {file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e"}, {file = "MarkupSafe-1.1.1-cp36-cp36m-win32.whl", hash = "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66"}, {file = "MarkupSafe-1.1.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5"}, {file = "MarkupSafe-1.1.1-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d"}, {file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e"}, {file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6"}, {file = "MarkupSafe-1.1.1-cp37-cp37m-win32.whl", hash = "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2"}, {file = "MarkupSafe-1.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c"}, {file = "MarkupSafe-1.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15"}, {file = "MarkupSafe-1.1.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2"}, {file = "MarkupSafe-1.1.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42"}, {file = "MarkupSafe-1.1.1-cp38-cp38-win32.whl", hash = "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b"}, {file = "MarkupSafe-1.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be"}, {file = "MarkupSafe-1.1.1.tar.gz", hash = "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b"}, ] mccabe = [ {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, ] musicbrainzngs = [ {file = "musicbrainzngs-0.7.1-py2.py3-none-any.whl", hash = "sha256:e841a8f975104c0a72290b09f59326050194081a5ae62ee512f41915090e1a10"}, {file = "musicbrainzngs-0.7.1.tar.gz", hash = "sha256:ab1c0100fd0b305852e65f2ed4113c6de12e68afd55186987b8ed97e0f98e627"}, ] mutagen = [ {file = "mutagen-1.45.1-py3-none-any.whl", hash = "sha256:9c9f243fcec7f410f138cb12c21c84c64fde4195481a30c9bfb05b5f003adfed"}, {file = "mutagen-1.45.1.tar.gz", hash = "sha256:6397602efb3c2d7baebd2166ed85731ae1c1d475abca22090b7141ff5034b3e1"}, ] mypy = [ {file = "mypy-0.790-cp35-cp35m-macosx_10_6_x86_64.whl", hash = "sha256:bd03b3cf666bff8d710d633d1c56ab7facbdc204d567715cb3b9f85c6e94f669"}, {file = "mypy-0.790-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:2170492030f6faa537647d29945786d297e4862765f0b4ac5930ff62e300d802"}, {file = "mypy-0.790-cp35-cp35m-win_amd64.whl", hash = "sha256:e86bdace26c5fe9cf8cb735e7cedfe7850ad92b327ac5d797c656717d2ca66de"}, {file = "mypy-0.790-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:e97e9c13d67fbe524be17e4d8025d51a7dca38f90de2e462243ab8ed8a9178d1"}, {file = "mypy-0.790-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0d34d6b122597d48a36d6c59e35341f410d4abfa771d96d04ae2c468dd201abc"}, {file = "mypy-0.790-cp36-cp36m-win_amd64.whl", hash = "sha256:72060bf64f290fb629bd4a67c707a66fd88ca26e413a91384b18db3876e57ed7"}, {file = "mypy-0.790-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:eea260feb1830a627fb526d22fbb426b750d9f5a47b624e8d5e7e004359b219c"}, {file = "mypy-0.790-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:c614194e01c85bb2e551c421397e49afb2872c88b5830e3554f0519f9fb1c178"}, {file = "mypy-0.790-cp37-cp37m-win_amd64.whl", hash = "sha256:0a0d102247c16ce93c97066443d11e2d36e6cc2a32d8ccc1f705268970479324"}, {file = "mypy-0.790-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cf4e7bf7f1214826cf7333627cb2547c0db7e3078723227820d0a2490f117a01"}, {file = "mypy-0.790-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:af4e9ff1834e565f1baa74ccf7ae2564ae38c8df2a85b057af1dbbc958eb6666"}, {file = "mypy-0.790-cp38-cp38-win_amd64.whl", hash = "sha256:da56dedcd7cd502ccd3c5dddc656cb36113dd793ad466e894574125945653cea"}, {file = "mypy-0.790-py3-none-any.whl", hash = "sha256:2842d4fbd1b12ab422346376aad03ff5d0805b706102e475e962370f874a5122"}, {file = "mypy-0.790.tar.gz", hash = "sha256:2b21ba45ad9ef2e2eb88ce4aeadd0112d0f5026418324176fd494a6824b74975"}, ] mypy-extensions = [ {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, ] packaging = [ {file = "packaging-20.8-py2.py3-none-any.whl", hash = "sha256:24e0da08660a87484d1602c30bb4902d74816b6985b93de36926f5bc95741858"}, {file = "packaging-20.8.tar.gz", hash = "sha256:78598185a7008a470d64526a8059de9aaa449238f280fc9eb6b13ba6c4109093"}, ] pluggy = [ {file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"}, {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"}, ] polib = [ {file = "polib-1.1.0-py2.py3-none-any.whl", hash = "sha256:93b730477c16380c9a96726c54016822ff81acfa553977fdd131f2b90ba858d7"}, {file = "polib-1.1.0.tar.gz", hash = "sha256:fad87d13696127ffb27ea0882d6182f1a9cf8a5e2b37a587751166c51e5a332a"}, ] py = [ {file = "py-1.10.0-py2.py3-none-any.whl", hash = "sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a"}, {file = "py-1.10.0.tar.gz", hash = "sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3"}, ] pycairo = [ {file = "pycairo-1.20.0-cp36-cp36m-win32.whl", hash = "sha256:e5a3433690c473e073a9917dc8f1fc7dc8b9af7b201bf372894b8ad70d960c6d"}, {file = "pycairo-1.20.0-cp36-cp36m-win_amd64.whl", hash = "sha256:a942614923b88ae75c794506d5c426fba9c46a055d3fdd3b8db7046b75c079cc"}, {file = "pycairo-1.20.0-cp37-cp37m-win32.whl", hash = "sha256:8cfa9578b745fb9cf2915ec580c2c50ebc2da00eac2cf4c4b54b63aa19da4b77"}, {file = "pycairo-1.20.0-cp37-cp37m-win_amd64.whl", hash = "sha256:273a33c56aba724ec42fe1d8f94c86c2e2660c1277470be9b04e5113d7c5b72d"}, {file = "pycairo-1.20.0-cp38-cp38-win32.whl", hash = "sha256:2088100a099c09c5e90bf247409ce6c98f51766b53bd13f96d6aac7addaa3e66"}, {file = "pycairo-1.20.0-cp38-cp38-win_amd64.whl", hash = "sha256:ceb1edcbeb48dabd5fbbdff2e4b429aa88ddc493d6ebafe78d94b050ac0749e2"}, {file = "pycairo-1.20.0-cp39-cp39-win32.whl", hash = "sha256:57a768f4edc8a9890d98070dd473a812ac3d046cef4bc1c817d68024dab9a9b4"}, {file = "pycairo-1.20.0-cp39-cp39-win_amd64.whl", hash = "sha256:57166119e424d71eccdba6b318bd731bdabd17188e2ba10d4f315f7bf16ace3f"}, {file = "pycairo-1.20.0.tar.gz", hash = "sha256:5695a10cb7f9ae0d01f665b56602a845b0a8cb17e2123bfece10c2e58552468c"}, ] pycodestyle = [ {file = "pycodestyle-2.6.0-py2.py3-none-any.whl", hash = "sha256:2295e7b2f6b5bd100585ebcb1f616591b652db8a741695b3d8f5d28bdc934367"}, {file = "pycodestyle-2.6.0.tar.gz", hash = "sha256:c58a7d2815e0e8d7972bf1803331fb0152f867bd89adf8a01dfd55085434192e"}, ] pyflakes = [ {file = "pyflakes-2.2.0-py2.py3-none-any.whl", hash = "sha256:0d94e0e05a19e57a99444b6ddcf9a6eb2e5c68d3ca1e98e90707af8152c90a92"}, {file = "pyflakes-2.2.0.tar.gz", hash = "sha256:35b2d75ee967ea93b55750aa9edbbf72813e06a66ba54438df2cfac9e3c27fc8"}, ] pygments = [ {file = "Pygments-2.7.4-py3-none-any.whl", hash = "sha256:bc9591213a8f0e0ca1a5e68a479b4887fdc3e75d0774e5c71c31920c427de435"}, {file = "Pygments-2.7.4.tar.gz", hash = "sha256:df49d09b498e83c1a73128295860250b0b7edd4c723a32e9bc0d295c7c2ec337"}, ] pygobject = [ {file = "PyGObject-3.38.0.tar.gz", hash = "sha256:051b950f509f2e9f125add96c1493bde987c527f7a0c15a1f7b69d6d1c3cd8e6"}, ] pyinotify = [ {file = "pyinotify-0.9.6.tar.gz", hash = "sha256:9c998a5d7606ca835065cdabc013ae6c66eb9ea76a00a1e3bc6e0cfe2b4f71f4"}, ] pyparsing = [ {file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"}, {file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"}, ] pytest = [ {file = "pytest-6.2.2-py3-none-any.whl", hash = "sha256:b574b57423e818210672e07ca1fa90aaf194a4f63f3ab909a2c67ebb22913839"}, {file = "pytest-6.2.2.tar.gz", hash = "sha256:9d1edf9e7d0b84d72ea3dbcdfd22b35fb543a5e8f2a60092dd578936bf63d7f9"}, ] pytz = [ {file = "pytz-2020.5-py2.py3-none-any.whl", hash = "sha256:16962c5fb8db4a8f63a26646d8886e9d769b6c511543557bc84e9569fb9a9cb4"}, {file = "pytz-2020.5.tar.gz", hash = "sha256:180befebb1927b16f6b57101720075a984c019ac16b1b7575673bea42c6c3da5"}, ] requests = [ {file = "requests-2.25.1-py2.py3-none-any.whl", hash = "sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e"}, {file = "requests-2.25.1.tar.gz", hash = "sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804"}, ] sgmllib3k = [ {file = "sgmllib3k-1.0.0.tar.gz", hash = "sha256:7868fb1c8bfa764c1ac563d3cf369c381d1325d36124933a726f29fcdaa812e9"}, ] snowballstemmer = [ {file = "snowballstemmer-2.1.0-py2.py3-none-any.whl", hash = "sha256:b51b447bea85f9968c13b650126a888aabd4cb4463fca868ec596826325dedc2"}, {file = "snowballstemmer-2.1.0.tar.gz", hash = "sha256:e997baa4f2e9139951b6f4c631bad912dfd3c792467e2f03d7239464af90e914"}, ] soco = [ {file = "soco-0.21.1-py2.py3-none-any.whl", hash = "sha256:cc03b5d6df84ab8a71c311a4e3cea81a25e8c47ce530fbdad8a0a66c927bce63"}, {file = "soco-0.21.1.tar.gz", hash = "sha256:d17b9e4cd34f133122711618db28e28678489ca879a4a749dafddc640faf2994"}, ] sphinx = [ {file = "Sphinx-3.4.3-py3-none-any.whl", hash = "sha256:c314c857e7cd47c856d2c5adff514ac2e6495f8b8e0f886a8a37e9305dfea0d8"}, {file = "Sphinx-3.4.3.tar.gz", hash = "sha256:41cad293f954f7d37f803d97eb184158cfd90f51195131e94875bc07cd08b93c"}, ] sphinx-rtd-theme = [ {file = "sphinx_rtd_theme-0.5.1-py2.py3-none-any.whl", hash = "sha256:fa6bebd5ab9a73da8e102509a86f3fcc36dec04a0b52ea80e5a033b2aba00113"}, {file = "sphinx_rtd_theme-0.5.1.tar.gz", hash = "sha256:eda689eda0c7301a80cf122dad28b1861e5605cbf455558f3775e1e8200e83a5"}, ] sphinxcontrib-applehelp = [ {file = "sphinxcontrib-applehelp-1.0.2.tar.gz", hash = "sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58"}, {file = "sphinxcontrib_applehelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a"}, ] sphinxcontrib-devhelp = [ {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"}, ] sphinxcontrib-htmlhelp = [ {file = "sphinxcontrib-htmlhelp-1.0.3.tar.gz", hash = "sha256:e8f5bb7e31b2dbb25b9cc435c8ab7a79787ebf7f906155729338f3156d93659b"}, {file = "sphinxcontrib_htmlhelp-1.0.3-py2.py3-none-any.whl", hash = "sha256:3c0bc24a2c41e340ac37c85ced6dafc879ab485c095b1d65d2461ac2f7cca86f"}, ] sphinxcontrib-jsmath = [ {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"}, ] sphinxcontrib-qthelp = [ {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"}, ] sphinxcontrib-serializinghtml = [ {file = "sphinxcontrib-serializinghtml-1.1.4.tar.gz", hash = "sha256:eaa0eccc86e982a9b939b2b82d12cc5d013385ba5eadcc7e4fed23f4405f77bc"}, {file = "sphinxcontrib_serializinghtml-1.1.4-py2.py3-none-any.whl", hash = "sha256:f242a81d423f59617a8e5cf16f5d4d74e28ee9a66f9e5b637a18082991db5a9a"}, ] toml = [ {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, ] typed-ast = [ {file = "typed_ast-1.4.2-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:7703620125e4fb79b64aa52427ec192822e9f45d37d4b6625ab37ef403e1df70"}, {file = "typed_ast-1.4.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:c9aadc4924d4b5799112837b226160428524a9a45f830e0d0f184b19e4090487"}, {file = "typed_ast-1.4.2-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:9ec45db0c766f196ae629e509f059ff05fc3148f9ffd28f3cfe75d4afb485412"}, {file = "typed_ast-1.4.2-cp35-cp35m-win32.whl", hash = "sha256:85f95aa97a35bdb2f2f7d10ec5bbdac0aeb9dafdaf88e17492da0504de2e6400"}, {file = "typed_ast-1.4.2-cp35-cp35m-win_amd64.whl", hash = "sha256:9044ef2df88d7f33692ae3f18d3be63dec69c4fb1b5a4a9ac950f9b4ba571606"}, {file = "typed_ast-1.4.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:c1c876fd795b36126f773db9cbb393f19808edd2637e00fd6caba0e25f2c7b64"}, {file = "typed_ast-1.4.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:5dcfc2e264bd8a1db8b11a892bd1647154ce03eeba94b461effe68790d8b8e07"}, {file = "typed_ast-1.4.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:8db0e856712f79c45956da0c9a40ca4246abc3485ae0d7ecc86a20f5e4c09abc"}, {file = "typed_ast-1.4.2-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:d003156bb6a59cda9050e983441b7fa2487f7800d76bdc065566b7d728b4581a"}, {file = "typed_ast-1.4.2-cp36-cp36m-win32.whl", hash = "sha256:4c790331247081ea7c632a76d5b2a265e6d325ecd3179d06e9cf8d46d90dd151"}, {file = "typed_ast-1.4.2-cp36-cp36m-win_amd64.whl", hash = "sha256:d175297e9533d8d37437abc14e8a83cbc68af93cc9c1c59c2c292ec59a0697a3"}, {file = "typed_ast-1.4.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:cf54cfa843f297991b7388c281cb3855d911137223c6b6d2dd82a47ae5125a41"}, {file = "typed_ast-1.4.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:b4fcdcfa302538f70929eb7b392f536a237cbe2ed9cba88e3bf5027b39f5f77f"}, {file = "typed_ast-1.4.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:987f15737aba2ab5f3928c617ccf1ce412e2e321c77ab16ca5a293e7bbffd581"}, {file = "typed_ast-1.4.2-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:37f48d46d733d57cc70fd5f30572d11ab8ed92da6e6b28e024e4a3edfb456e37"}, {file = "typed_ast-1.4.2-cp37-cp37m-win32.whl", hash = "sha256:36d829b31ab67d6fcb30e185ec996e1f72b892255a745d3a82138c97d21ed1cd"}, {file = "typed_ast-1.4.2-cp37-cp37m-win_amd64.whl", hash = "sha256:8368f83e93c7156ccd40e49a783a6a6850ca25b556c0fa0240ed0f659d2fe496"}, {file = "typed_ast-1.4.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:963c80b583b0661918718b095e02303d8078950b26cc00b5e5ea9ababe0de1fc"}, {file = "typed_ast-1.4.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:e683e409e5c45d5c9082dc1daf13f6374300806240719f95dc783d1fc942af10"}, {file = "typed_ast-1.4.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:84aa6223d71012c68d577c83f4e7db50d11d6b1399a9c779046d75e24bed74ea"}, {file = "typed_ast-1.4.2-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:a38878a223bdd37c9709d07cd357bb79f4c760b29210e14ad0fb395294583787"}, {file = "typed_ast-1.4.2-cp38-cp38-win32.whl", hash = "sha256:a2c927c49f2029291fbabd673d51a2180038f8cd5a5b2f290f78c4516be48be2"}, {file = "typed_ast-1.4.2-cp38-cp38-win_amd64.whl", hash = "sha256:c0c74e5579af4b977c8b932f40a5464764b2f86681327410aa028a22d2f54937"}, {file = "typed_ast-1.4.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:07d49388d5bf7e863f7fa2f124b1b1d89d8aa0e2f7812faff0a5658c01c59aa1"}, {file = "typed_ast-1.4.2-cp39-cp39-manylinux1_i686.whl", hash = "sha256:240296b27397e4e37874abb1df2a608a92df85cf3e2a04d0d4d61055c8305ba6"}, {file = "typed_ast-1.4.2-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:d746a437cdbca200622385305aedd9aef68e8a645e385cc483bdc5e488f07166"}, {file = "typed_ast-1.4.2-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:14bf1522cdee369e8f5581238edac09150c765ec1cb33615855889cf33dcb92d"}, {file = "typed_ast-1.4.2-cp39-cp39-win32.whl", hash = "sha256:cc7b98bf58167b7f2db91a4327da24fb93368838eb84a44c472283778fc2446b"}, {file = "typed_ast-1.4.2-cp39-cp39-win_amd64.whl", hash = "sha256:7147e2a76c75f0f64c4319886e7639e490fee87c9d25cb1d4faef1d8cf83a440"}, {file = "typed_ast-1.4.2.tar.gz", hash = "sha256:9fc0b3cb5d1720e7141d103cf4819aea239f7d136acf9ee4a69b047b7986175a"}, ] typing-extensions = [ {file = "typing_extensions-3.7.4.3-py2-none-any.whl", hash = "sha256:dafc7639cde7f1b6e1acc0f457842a83e722ccca8eef5270af2d74792619a89f"}, {file = "typing_extensions-3.7.4.3-py3-none-any.whl", hash = "sha256:7cb407020f00f7bfc3cb3e7881628838e69d8f3fcab2f64742a5e76b2f841918"}, {file = "typing_extensions-3.7.4.3.tar.gz", hash = "sha256:99d4073b617d30288f569d3f13d2bd7548c3a7e4c8de87db09a9d29bb3a4a60c"}, ] urllib3 = [ {file = "urllib3-1.26.3-py2.py3-none-any.whl", hash = "sha256:1b465e494e3e0d8939b50680403e3aedaa2bc434b7d5af64dfd3c958d7f5ae80"}, {file = "urllib3-1.26.3.tar.gz", hash = "sha256:de3eedaad74a2683334e282005cd8d7f22f4d55fa690a2a1020a416cb0a47e73"}, ] xmltodict = [ {file = "xmltodict-0.12.0-py2.py3-none-any.whl", hash = "sha256:8bbcb45cc982f48b2ca8fe7e7827c5d792f217ecf1792626f808bf41c3b86051"}, {file = "xmltodict-0.12.0.tar.gz", hash = "sha256:50d8c638ed7ecb88d90561beedbf720c9b4e851a9fa6c47ebd64e99d166d8a21"}, ] xvfbwrapper = [ {file = "xvfbwrapper-0.2.9.tar.gz", hash = "sha256:bcf4ae571941b40254faf7a73432dfc119ad21ce688f1fdec533067037ecfc24"}, ] zipp = [ {file = "zipp-3.4.0-py3-none-any.whl", hash = "sha256:102c24ef8f171fd729d46599845e95c7ab894a4cf45f5de11a44cc7444fb1108"}, {file = "zipp-3.4.0.tar.gz", hash = "sha256:ed5eee1974372595f9e416cc7bbeeb12335201d8081ca8a0743c954d4446e5cb"}, ] ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9791858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/pyproject.toml����������������������������������������������������������������������0000644�0001750�0001750�00000002642�00000000000�015416� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������[tool.poetry] name = "quodlibet" version = "4.4.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.dependencies] python = "^3.7" mutagen = "^1.44" feedparser = "^5.2 || ^6.0" pycairo = "^1.19" pygobject = "^3.34.0" # Optional (mainly plugins) musicbrainzngs = { version = "0.*", optional = true } pyinotify = { version = "*", optional = true } dbus-python = { version = "*", optional = true } soco = { version = "^0.21.1", optional = true } [tool.poetry.extras] # Use with poetry install -E plugins plugins = ["musicbrainzngs", "pyinotify", "dbus-python", "paho-mqtt", "soco"] [tool.poetry.dev-dependencies] pytest = '^6.0' polib = '^1.1.0' sphinx = '^3.2.0' sphinx_rtd_theme = '*' xvfbwrapper = { version = "^0.2", platform = "linux" } flake8 = "^3.7.9" coverage = { extras = ["toml"], version = "^5.0.3" } mypy = "^0.790" [tool.coverage.run] omit = ["quodlibet/packages/*"] include = ["quodlibet/*", "tests/*"] [build-system] requires = ["setuptools", "wheel"] ����������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614542835.1254697 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/��������������������������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�014466� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9791858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/__init__.py���������������������������������������������������������������0000644�0001750�0001750�00000002554�00000000000�016605� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9791858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/_import.py����������������������������������������������������������������0000644�0001750�0001750�00000003334�00000000000�016514� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9791858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/_init.py������������������������������������������������������������������0000644�0001750�0001750�00000030661�00000000000�016150� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 environ, argv, 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 = 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)" % 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 environ: environ["PANGOCAIRO_BACKEND"] = "fontconfig" # disable for consistency and trigger events seem a bit flaky here if config.getboolean("settings", "scrollbar_always_visible"): 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', '2.4') 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 ourself initialized, argv[:] = Gtk.init_check(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") 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) 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, argv[:] = Gst.init_check(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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9791858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/_main.py������������������������������������������������������������������0000644�0001750�0001750�00000027620�00000000000�016132� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 environ, 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 sub-modules. 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 environ: USERDIR = 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 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 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=1614542835.1254697 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/browsers/�����������������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�016334� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9791858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/browsers/__init__.py������������������������������������������������������0000644�0001750�0001750�00000005357�00000000000�020457� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2005 Joe Wreschnig, Michael Urman, Iñigo Serna # 2012 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 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9791858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/browsers/_base.py���������������������������������������������������������0000644�0001750�0001750�00000032720�00000000000�017763� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2005 Joe Wreschnig, Michael Urman, Iñigo Serna # 2012 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 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): """Do filtering base 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): """Do filtering 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 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, time=None): tmpl = numeric_phrase("%d song", "%d songs", count) return tmpl + " (%s)" % time replaygain_profiles: Optional[List[str]] = None """Replay Gain profiles for this browser.""" 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: cls.__pattern_text = f.read().rstrip() except EnvironmentError as e: print_d("Couldn't load pattern for %s (%s), using default." % (cls.__name__, e)) cls.__pattern_text = cls._DEFAULT_PATTERN_TEXT cls.__refresh_pattern() @classmethod def update_pattern(cls, pattern_text): """Saves `pattern_text` to disk (and caches)""" if pattern_text == cls.__pattern_text: return cls.__pattern_text = pattern_text cls.__refresh_pattern() cls.refresh_all() print_d("Saving pattern for %s to %s" % (cls.__name__, cls._PATTERN_FN)) with open(cls._PATTERN_FN, "w", encoding="utf-8") as f: f.write(pattern_text + "\n") @classmethod def __refresh_pattern(cls): cls.__pattern = XMLFromMarkupPattern(cls.__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 @classmethod def refresh_all(cls): """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=1614542835.1254697 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/browsers/albums/����������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�017617� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9791858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/browsers/albums/__init__.py�����������������������������������������������0000644�0001750�0001750�00000000641�00000000000�021731� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9791858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/browsers/albums/main.py���������������������������������������������������0000644�0001750�0001750�00000071016�00000000000�021122� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2007 Joe Wreschnig, Michael Urman, Iñigo Serna # 2009-2010 Steven Robertson # 2012-2020 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 gi.repository import Gtk, Pango, Gdk, GLib, Gio from quodlibet.util.i18n import numeric_phrase from .prefs import Preferences, DEFAULT_PATTERN_TEXT from .models import AlbumModel, AlbumFilterModel, AlbumSortModel, AlbumItem 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.query import Query from quodlibet.browsers._base import DisplayPatternMixin from quodlibet.qltk.completion import EntryWordCompletion from quodlibet.qltk.information import Information from quodlibet.qltk.properties import SongProperties from quodlibet.qltk.songsmenu import SongsMenu from quodlibet.qltk.views import AllTreeView 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 copool, connect_destroy, cmp from quodlibet.util.library import background_filter from quodlibet.util import connect_obj, DeferredSignal from quodlibet.qltk.cover import get_no_cover_pixbuf from quodlibet.qltk.image import add_border_widget, get_surface_for_pixbuf 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_artist(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), (_("_Artist"), self.__compare_artist), (_("_Date"), self.__compare_date), (_("_Date Added"), self.__compare_date_added), (_("_Original Date"), self.__compare_original_date), (_("_Genre"), self.__compare_genre), (_("_Rating"), self.__compare_rating), (_("_Playcount"), 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) 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_artist(self, model, i1, i2, data): a1, a2 = model.get_value(i1), model.get_value(i2) return compare_artist(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() @classmethod def refresh_all(cls): cls.__model.refresh_all() @classmethod def _init_model(klass, library): klass.__model = AlbumModel(library) klass.__library = library @util.cached_property def _no_cover(self): """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) 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) # 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 = "<b>%s</b>\n" % _("All Albums") 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) self.pack_start(Align(search, left=6, top=6), 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9791858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/browsers/albums/models.py�������������������������������������������������0000644�0001750�0001750�00000010060�00000000000�021451� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9791858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/browsers/albums/prefs.py��������������������������������������������������0000644�0001750�0001750�00000006605�00000000000�021317� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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=1614540385.9831858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/browsers/audiofeeds.py����������������������������������������������������0000644�0001750�0001750�00000037466�00000000000�021036� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2005 Joe Wreschnig # 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 sys import threading import time 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.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.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: 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): try: doc = feedparser.parse(self.uri) except Exception as e: print_w("Couldn't parse feed: %s (%s)" % (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 location of an audio feed:"), button_label=_("_Add"), button_icon=Icons.LIST_ADD) def run(self, text='', test=False): uri = super().run(text=text, test=test) if uri: if not isinstance(uri, str): uri = uri.decode('utf-8') return Feed(uri) return None 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 AudioFeeds(Browser): __feeds = Gtk.ListStore(object) # unread headers = ("title artist performer ~people album date website language " "copyright organization license contact").split() name = _("Audio Feeds") accelerated_name = _("_Audio Feeds") keys = ["AudioFeeds"] 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 = "<b>%s</b>" % util.escape(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] AudioFeeds.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=()) thread.setDaemon(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, AudioFeeds.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(_("_New"), 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 __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]) AudioFeeds.write() else: self.feed_error(feed).run() def __popup_menu(self, view): model, paths = view.get_selection().get_selected_rows() menu = Gtk.Menu() refresh = MenuItem(_("_Refresh"), Icons.VIEW_REFRESH) delete = MenuItem(_("_Delete"), Icons.EDIT_DELETE) connect_obj(refresh, 'activate', self.__refresh, [model[p][0] for p in paths]) connect_obj(delete, 'activate', self.__remove_paths, model, paths) menu.append(refresh) menu.append(delete) menu.show_all() menu.connect('selection-done', lambda m: m.destroy()) # XXX: keep the menu around self.__menu = menu return view.popup_menu(menu, 0, Gtk.get_current_event_time()) def __save(self, view): AudioFeeds.write() def __refresh(self, feeds): changed = list(filter(Feed.parse, feeds)) AudioFeeds.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]) AudioFeeds.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 an audio feed.") % util.bold(util.escape(feed.uri))) def restore(self): try: names = config.get("browsers", "audiofeeds").split("\t") except: 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 = [AudioFeeds] else: print_w(_("The current audio backend does not support URLs, " "Audio Feeds browser disabled.")) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614542835.1254697 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/browsers/collection/������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�020467� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9831858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/browsers/collection/__init__.py�������������������������������������������0000644�0001750�0001750�00000000555�00000000000�022605� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9831858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/browsers/collection/main.py�����������������������������������������������0000644�0001750�0001750�00000034036�00000000000�021773� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2010, 2012-2014 Christoph Reiter # 2017 Uriel Zajaczkovski # 2017-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 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=6), 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9831858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/browsers/collection/models.py���������������������������������������������0000644�0001750�0001750�00000020554�00000000000�022332� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2010, 2012-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. 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 = "<b><i>%s</i></b>" % _("Unknown %s") MULTI_PATTERN = "<b><i>%s</i></b>" % _("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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9831858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/browsers/collection/prefs.py����������������������������������������������0000644�0001750�0001750�00000015326�00000000000�022167� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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=1614542835.1254697 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/browsers/covergrid/�������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�020320� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9831858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/browsers/covergrid/__init__.py��������������������������������������������0000644�0001750�0001750�00000000641�00000000000�022432� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 CoverGrid, AlbumTagCompletion AlbumTagCompletion browsers = [CoverGrid] �����������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9831858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/browsers/covergrid/main.py������������������������������������������������0000644�0001750�0001750�00000057115�00000000000�021627� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2007 Joe Wreschnig, Michael Urman, Iñigo Serna # 2009-2010 Steven Robertson # 2012-2018 Nick Boultbee # 2009-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 os from gi.repository import Gtk, Pango, Gdk, Gio from .prefs import Preferences, DEFAULT_PATTERN_TEXT from quodlibet.browsers.albums.models import (AlbumModel, AlbumFilterModel, AlbumSortModel) from quodlibet.browsers.albums.main import (get_cover_size, AlbumTagCompletion, PreferencesButton as AlbumPreferencesButton, VisibleUpdate) 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._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.library import background_filter from quodlibet.util import connect_obj from quodlibet.qltk.cover import get_no_cover_pixbuf from quodlibet.qltk.image import add_border_widget, get_surface_for_pixbuf 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), (_("_Artist"), self.__compare_artist), (_("_Date"), self.__compare_date), (_("_Genre"), self.__compare_genre), (_("_Rating"), self.__compare_rating), ] 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 IconView(Gtk.IconView): # XXX: disable height for width etc. Speeds things up and doesn't seem # to break anyhting in a scrolled window def do_get_preferred_width_for_height(self, height): return (1, 1) def do_get_preferred_width(self): return (1, 1) def do_get_preferred_height(self): return (1, 1) def do_get_preferred_height_for_width(self, width): return (1, 1) class CoverGrid(Browser, util.InstanceTracker, VisibleUpdate, DisplayPatternMixin): __gsignals__ = Browser.__gsignals__ __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 STAR = ["~people", "album"] 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() def finalize(self, restored): if not restored: # Select the "All Albums" album, which is None self.select_by_func(lambda r: r[0].album is None, one=True) @classmethod def _destroy_model(klass): klass.__model.destroy() klass.__model = None @classmethod def toggle_text(klass): on = config.getboolean("browsers", "album_text", True) for covergrid in klass.instances(): covergrid.__text_cells.set_visible(on) covergrid.view.queue_resize() @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): mag = config.getfloat("browsers", "covergrid_magnification", 3.) for covergrid in klass.instances(): covergrid.__cover.set_property('width', get_cover_size() * mag + 8) covergrid.__cover.set_property('height', get_cover_size() * mag + 8) covergrid.view.set_item_width(get_cover_size() * mag + 8) covergrid.view.queue_resize() covergrid.redraw() def redraw(self): model = self.__model for iter_, item in model.iterrows(): album = item.album if album is not None: item.scanned = False model.row_changed(model.get_path(iter_), iter_) @classmethod def _init_model(klass, library): klass.__model = AlbumModel(library) klass.__library = library @classmethod def _refresh_albums(klass, albums): """We signal all other open album views that we changed something (Only needed for the cover atm) so they redraw as well.""" if klass.__library: klass.__library.albums.refresh(albums) @util.cached_property def _no_cover(self): """Returns a cairo surface representing a missing cover""" mag = config.getfloat("browsers", "covergrid_magnification", 3.) cover_size = get_cover_size() scale_factor = self.get_scale_factor() * mag pb = get_no_cover_pixbuf(cover_size, cover_size, scale_factor) return get_surface_for_pixbuf(self, pb) def __init__(self, library): Browser.__init__(self, spacing=6) self.set_orientation(Gtk.Orientation.VERTICAL) 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() if self.__model is None: self._init_model(library) self._cover_cancel = Gio.Cancellable() self.scrollwin = sw = ScrolledWindow() sw.set_shadow_type(Gtk.ShadowType.IN) model_sort = AlbumSortModel(model=self.__model) model_filter = AlbumFilterModel(child_model=model_sort) self.view = view = IconView(model_filter) #view.set_item_width(get_cover_size() + 12) self.view.set_row_spacing(config.getint("browsers", "row_spacing", 6)) self.view.set_column_spacing(config.getint("browsers", "column_spacing", 6)) self.view.set_item_padding(config.getint("browsers", "item_padding", 6)) self.view.set_has_tooltip(True) self.view.connect("query-tooltip", self._show_tooltip) self.__bg_filter = background_filter() self.__filter = None model_filter.set_visible_func(self.__parse_query) mag = config.getfloat("browsers", "covergrid_magnification", 3.) self.view.set_item_width(get_cover_size() * mag + 8) self.__cover = render = Gtk.CellRendererPixbuf() render.set_property('width', get_cover_size() * mag + 8) render.set_property('height', get_cover_size() * mag + 8) view.pack_start(render, False) def cell_data_pb(view, 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) # 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) view.set_cell_data_func(render, cell_data_pb, self._no_cover) self.__text_cells = render = Gtk.CellRendererText() render.set_visible(config.getboolean("browsers", "album_text", True)) render.set_property('alignment', Pango.Alignment.CENTER) render.set_property('xalign', 0.5) render.set_property('ellipsize', Pango.EllipsizeMode.END) view.pack_start(render, False) def cell_data(view, cell, model, iter_, data): album = model.get_album(iter_) if album is None: text = "<b>%s</b>" % _("All Albums") text += "\n" + ngettext("%d album", "%d albums", len(model) - 1) % (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) view.set_cell_data_func(render, cell_data, None) view.set_selection_mode(Gtk.SelectionMode.MULTIPLE) sw.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) sw.add(view) view.connect('item-activated', self.__play_selection, None) self.__sig = connect_destroy( view, 'selection-changed', util.DeferredSignal(self.__update_songs, 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) # NOT WORKING connect_obj(view, 'button-press-event', self.__rightclick, view, library) 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) self.pack_start(Align(search, left=6, top=6), False, True, 0) self.pack_start(sw, True, True, 0) self.connect("destroy", self.__destroy) self.enable_row_update(view, sw, self.view) self.__update_filter() 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_)) mag = config.getfloat("browsers", "covergrid_magnification", 3.) def callback(): path = tref.get_path() if path is not None: model.row_changed(path, model.get_iter(path)) # XXX: icon view seems to ignore row_changed signals for pixbufs.. self.queue_draw() item = model.get_value(iter_) scale_factor = self.get_scale_factor() * mag 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=None, text=None, scroll_up=True, restore=False): model = self.view.get_model() self.__filter = None query = self.__search.get_query(self.STAR) if not query.matches_all: self.__filter = query.search self.__bg_filter = background_filter() self.__inhibit() # If we're hiding "All Albums", then there will always # be something to filter ­— probably there's a better # way to implement this if (not restore or self.__filter or self.__bg_filter) or (not config.getboolean("browsers", "covergrid_all", True)): model.refilter() self.__uninhibit() def __parse_query(self, model, iter_, data): f, b = self.__filter, self.__bg_filter album = model.get_album(iter_) if f is None and b is None and album is not None: return True else: if album is None: return config.getboolean("browsers", "covergrid_all", 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 config.getboolean("browsers", "covergrid_all", 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 __rightclick(self, view, event, library): x = int(event.x) y = int(event.y) current_path = view.get_path_at_pos(x, y) if event.button == Gdk.BUTTON_SECONDARY and current_path: if not view.path_is_selected(current_path): view.unselect_all() view.select_path(current_path) self.__popup(view, library) def __popup(self, view, library): albums = self.__get_selected_albums() songs = self.__get_songs_from_albums(albums) items = [] 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() popup_menu_at_widget(menu, view, Gdk.BUTTON_SECONDARY, Gtk.get_current_event_time()) def _show_tooltip(self, widget, x, y, keyboard_tip, tooltip): w = self.scrollwin.get_hadjustment().get_value() z = self.scrollwin.get_vadjustment().get_value() path = widget.get_path_at_pos(int(x + w), int(y + z)) if path is None: return False model = widget.get_model() iter = model.get_iter(path) album = model.get_album(iter) if album is None: text = "<b>%s</b>" % _("All Albums") text += "\n" + ngettext("%d album", "%d albums", len(model) - 1) % (len(model) - 1) markup = text else: markup = self.display_pattern % album tooltip.set_markup(markup) return True 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): model = self.view.get_model() paths = self.view.get_selected_items() return model.get_items(paths) def __get_selected_albums(self): model = self.view.get_model() paths = self.view.get_selected_items() 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,), None, False) # 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 select_by_func(self, func, scroll=True, one=False): model = self.view.get_model() if not model: return False selection = self.view.get_selected_items() first = True for row in model: if func(row): if not first: selection.select_path(row.path) continue self.view.unselect_all() self.view.select_path(row.path) self.view.set_cursor(row.path, None, False) if scroll: self.view.scroll_to_path(row.path, True, 0.5, 0.5) first = False if one: break return not first def filter_albums(self, values): self.__inhibit() changed = self.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("") def activate(self): self.view.emit('selection-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", "covergrid", "").split("\n") self.__inhibit() if keys != [""]: def select_fun(row): album = row[0].album if not album: # all return False return album.str_key in keys self.select_by_func(select_fun) else: self.select_by_func(lambda r: r[0].album is None) 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.select_by_func(select, one=True) def __get_config_string(self): model = self.view.get_model() paths = self.view.get_selected_items() # 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", "covergrid", conf) text = self.__search.get_text() config.settext("browsers", "query_text", text) def __update_songs(self, selection): songs = self.__get_selected_songs(sort=False) self.songs_selected(songs) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9831858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/browsers/covergrid/prefs.py�����������������������������������������������0000644�0001750�0001750�00000012574�00000000000�022022� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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")) 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)) def refilter(s): mod = browser.view.get_model() if mod: mod.refilter() cb2.connect('toggled', refilter) 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) # Redraws the covers only when the user releases the slider def mag_button_press(*_): self.mag_lock = True def mag_button_release(mag, _): self.mag_lock = False mag_changed(mag) def mag_changed(mag): if self.mag_lock: return 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), 0., 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('button-press-event', mag_button_press) mag_scale.connect('button-release-event', mag_button_release) 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9831858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/browsers/filesystem.py����������������������������������������������������0000644�0001750�0001750�00000021731�00000000000�021076� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2005 Joe Wreschnig, Michael Urman, Iñigo Serna # 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. # 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 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 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 = list(filter(klass.__library.__contains__, songs)) klass.__library.remove(songs) 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 = list(filter(lambda s: not s.can_add, songs)) 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 = list(filter(self.__library.__contains__, 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 = list(filter(self.__library.__contains__, songs)) self.__library.librarian.move(songs, self.__library, self.__glibrary) def __remove_songs(self, songs): songs = list(filter(self.__glibrary.__contains__, songs)) 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 list(filter(formats.filter, sorted(os.listdir(dir)))): 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9831858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/browsers/iradio.py��������������������������������������������������������0000644�0001750�0001750�00000077107�00000000000�020171� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2011 Joe Wreschnig, Christoph Reiter # 2013-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 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 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 from quodlibet.qltk.x import SymbolicIconImage from quodlibet.qltk.menubutton import MenuButton 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) 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(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(STATION_LIST_URL) except (EnvironmentError, HTTPException) as e: print_e("Failed fetching from %s" % STATION_LIST_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): 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) 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) menu = Gtk.Menu() new_item = MenuItem(_(u"_New Station…"), Icons.LIST_ADD) new_item.connect('activate', self.__add) menu.append(new_item) update_item = MenuItem(_("_Update Stations"), Icons.VIEW_REFRESH) update_item.connect('activate', self.__update) menu.append(update_item) menu.show_all() button = MenuButton( SymbolicIconImage(Icons.EMBLEM_SYSTEM, Gtk.IconSize.MENU), arrow=True) button.set_menu(menu) 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) box.pack_start(button, False, True, 0) self._searchbox = Align(box, left=0, right=6, top=6) 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 self._is_library_empty(): self.qbar.show() pane = qltk.ConfigRHPaned("browsers", "internetradio_pos", 0.4) pane.show() pane.pack1(scrolled_window, resize=False, shrink=False) songbox = Gtk.VBox(spacing=6) songbox.pack_start(self._searchbox, False, True, 0) self._songpane_container = Gtk.VBox() self._songpane_container.show() songbox.pack_start(self._songpane_container, True, True, 0) songbox.pack_start(self.qbar, False, True, 0) songbox.show() pane.pack2(songbox, resize=True, shrink=False) self.pack_start(pane, True, True, 0) self.show() def _is_library_empty(self): return not len(self.__stations) and not len(self.__fav_stations) 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.__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 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, time=None): 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=1614542835.1254697 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/browsers/paned/�����������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�017423� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9831858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/browsers/paned/__init__.py������������������������������������������������0000644�0001750�0001750�00000000530�00000000000�021532� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9831858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/browsers/paned/main.py����������������������������������������������������0000644�0001750�0001750�00000025012�00000000000�020721� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2008 Joe Wreschnig, Michael Urman, Iñigo Serna # 2009,2010 Steven Robertson # 2009-2013 Christoph Reiter # 2011-2018 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=6) 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() app.window.playlist.enqueue(songs) 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9831858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/browsers/paned/models.py��������������������������������������������������0000644�0001750�0001750�00000026211�00000000000�021262� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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. 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, "<b>%s</b>" % _("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, "<b>%s</b>" % _("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] = list(filter( lambda v: v[0], self.config.format(song))) 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9831858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/browsers/paned/pane.py����������������������������������������������������0000644�0001750�0001750�00000023605�00000000000�020726� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9831858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/browsers/paned/prefs.py���������������������������������������������������0000644�0001750�0001750�00000021725�00000000000�021123� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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, escape 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<tt>%s</tt>" % escape(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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9831858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/browsers/paned/util.py����������������������������������������������������0000644�0001750�0001750�00000007052�00000000000�020756� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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. 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](<~#tracks>)[/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=1614542835.1254697 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/browsers/playlists/�������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�020360� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9831858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/browsers/playlists/__init__.py��������������������������������������������0000644�0001750�0001750�00000000534�00000000000�022473� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9831858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/browsers/playlists/main.py������������������������������������������������0000644�0001750�0001750�00000063206�00000000000�021665� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2005 Joe Wreschnig # 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. import os 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 from quodlibet.browsers.playlists.prefs import Preferences, \ DEFAULT_PATTERN_TEXT from quodlibet.formats import AudioFile from quodlibet.plugins.playlist import PLAYLIST_HANDLER from quodlibet.qltk.completion import LibraryTagCompletion from quodlibet.qltk.menubutton import MenuButton from quodlibet.qltk.models import ObjectStore, ObjectModelSort from quodlibet.qltk.msg import ConfirmationPrompt 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.qltk import Icons from quodlibet.qltk.chooser import choose_files, create_chooser_filter from quodlibet.qltk.information import Information from quodlibet.qltk.properties import SongProperties from quodlibet.util import connect_obj from quodlibet.util.dprint import print_d, print_w from quodlibet.util.collection import XSPFBackedPlaylist, FileBackedPlaylist from quodlibet.util.urllib import urlopen from .util import parse_m3u, parse_pls, PLAYLISTS,\ confirm_remove_playlist_dialog_invoke, _name_for 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 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=6) 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.library = library model = klass.__lists.get_model() for playlist in os.listdir(PLAYLISTS): if os.path.isdir(os.path.join(PLAYLISTS, playlist)): continue try: playlist = XSPFBackedPlaylist(PLAYLISTS, playlist, library) model.append(row=[playlist]) except TypeError: legacy = FileBackedPlaylist(PLAYLISTS, playlist, library) print_w("Converting \"%s\" to XSPF format" % playlist) playlist = XSPFBackedPlaylist.from_playlist(legacy, library) model.append(row=[playlist]) except EnvironmentError: print_w("Invalid Playlist '%s'" % playlist) klass._ids = [ library.connect('removed', klass.__removed), library.connect('added', klass.__added), library.connect('changed', klass.__changed), ] klass.load_pattern() @classmethod def deinit(cls, library): model = cls.__lists.get_model() model.clear() for id_ in cls._ids: library.disconnect(id_) del cls._ids @classmethod def playlists(klass): return [row[0] for row in klass.__lists] @classmethod def changed(klass, playlist, refresh=True): model = klass.__lists for row in model: if row[0] is playlist: if refresh: print_d("Refreshing playlist %s..." % row[0]) klass.__lists.row_changed(row.path, row.iter) playlist.write() break else: model.get_model().append(row=[playlist]) playlist.write() @classmethod def __removed(klass, library, songs): print_d(f"Removing {len(songs)} song(s) " f"across {len(klass.playlists())} playlist(s)") for playlist in klass.playlists(): if playlist.remove_songs(songs): klass.changed(playlist) @classmethod def __added(klass, library, songs): filenames = {song("~filename") for song in songs} for playlist in klass.playlists(): if playlist.add_songs(filenames, library): klass.changed(playlist) @classmethod def __changed(klass, library, songs): for playlist in klass.playlists(): for song in songs: if song in playlist.songs: print_d(f"Playlist song {song.key!r} changed, so updating") klass.changed(playlist) break 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, 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 __lists = ObjectModelSort(model=ObjectStore()) __lists.set_default_sort_func(ObjectStore._sort_on_value) def __init__(self, library, Confirmer=ConfirmationPrompt): self.library = library # 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 super().__init__(spacing=6) 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(library) self.__configure_dnd(view, library) self.__connect_signals(view, library) self._sb_box = self.__create_searchbar(library) self._main_box = self.__create_box() self.show_all() for child in self.get_children(): child.show_all() @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(None, Icons.DOCUMENT_NEW, Gtk.IconSize.MENU) new_pl.set_tooltip_text(_("New")) new_pl.connect('clicked', self.__new_playlist, library) import_pl = qltk.Button(None, Icons.LIST_ADD, Gtk.IconSize.MENU) import_pl.set_tooltip_text(_("Import")) 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) # 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, 0) hb.pack_start(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, library): 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.drag_source_set(Gdk.ModifierType.BUTTON1_MASK, targets[:2], Gdk.DragAction.COPY) view.connect('drag-data-received', self.__drag_data_received, library) 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, library): view.connect('row-activated', lambda *x: self.songs_activated()) view.connect('popup-menu', self.__popup_menu, library) 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(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] response = confirm_remove_playlist_dialog_invoke( self, playlist, self.Confirmer) if response: playlist.delete() model.get_model().remove( model.convert_iter_to_child_iter(iter)) 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.library.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.library.librarian, songs, self) window.show() return True return False 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(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] # 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.library.emit('changed', removals.values()) else: playlist.remove_songs(removals.values(), True) remove_from_model(iters, smodel) print_d("Removed %d song(s) from %s" % (len(removals), playlist)) self.changed(playlist) self.activate() def __rebuild_playlist_from_songs_model(self, playlist, smodel): playlist.inhibit = True playlist.clear() playlist.extend([row[0] for row in smodel]) playlist.inhibit = False def __get_name_of_current_selected_playlist(self): model, iter = self.__selected_playlists() if not iter: return None path = model.get_path(iter) playlist = model[path][0] return playlist def __drag_data_received(self, view, ctx, x, y, sel, tid, etime, library): # 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, [library.get(f) for f in filenames])) if not songs: Gtk.drag_finish(ctx, False, False, etime) return try: path, pos = view.get_dest_row_at_pos(x, y) except TypeError: playlist = XSPFBackedPlaylist.from_songs(PLAYLISTS, songs, library) GLib.idle_add(self._select_playlist, playlist) else: playlist = model[path][0] playlist.extend(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.__get_name_of_current_selected_playlist(): 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) if uri.lower().endswith('.pls'): playlist = parse_pls(sock, name, library=library) elif (uri.lower().endswith('.m3u') or uri.lower().endswith('.m3u8')): playlist = parse_m3u(sock, name, library=library) else: raise IOError library.add(playlist.songs) 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() model.get_model().remove( model.convert_iter_to_child_iter(itr)) 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) @classmethod def refresh_all(cls): model = cls.__lists.get_model() for iter_, value in model.iterrows(): 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 = XSPFBackedPlaylist.new(PLAYLISTS, library=library) self.model.append(row=[playlist]) 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, newname): playlist = self.__lists[path][0] try: playlist.rename(newname) except ValueError as s: qltk.ErrorMessage( None, _("Unable to rename playlist"), s).run() 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) 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, library) def _import_playlists(self, fns, library): added = 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, library=library) elif filename.endswith(".pls"): playlist = parse_pls(f, name, library=library) else: print_w("Unsupported playlist type for '%s'" % filename) continue self.changed(playlist) library.add(playlist) added += 1 return added 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 = XSPFBackedPlaylist.from_songs(PLAYLISTS, songs, self.library) 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9831858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/browsers/playlists/menu.py������������������������������������������������0000644�0001750�0001750�00000007223�00000000000�021702� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 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 Gtk, Pango, GObject from quodlibet import app from quodlibet import ngettext, _ from quodlibet import qltk from quodlibet.browsers.playlists.util import GetPlaylistName, PLAYLISTS from quodlibet.qltk import SeparatorMenuItem, get_menu_item_top_parent, Icons from quodlibet.util.collection import Playlist, FileBackedPlaylist class PlaylistMenu(Gtk.Menu): __gsignals__ = { 'new': (GObject.SignalFlags.RUN_LAST, None, (object,)), } def __init__(self, songs, playlists): super().__init__() 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 playlists: 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): 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 playlist = FileBackedPlaylist.new(PLAYLISTS, title, library=app.library) playlist.extend(songs) self._emit_new(playlist) 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 _emit_new(self, playlist): # TODO: signals directly from a new playlist library (#518) self.emit('new', playlist) 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9831858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/browsers/playlists/prefs.py�����������������������������������������������0000644�0001750�0001750�00000004656�00000000000�022064� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9831858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/browsers/playlists/util.py������������������������������������������������0000644�0001750�0001750�00000011001�00000000000�021700� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 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 os from senf import uri2fsn, fsnative, fsn2text, path2fsn, bytes2fsn, text2fsn import quodlibet from quodlibet import _, print_d from quodlibet import formats from quodlibet.qltk import Icons from quodlibet.qltk.msg import ConfirmationPrompt from quodlibet.qltk.getstring import GetStringDialog from quodlibet.qltk.wlw import WaitLoadWindow from quodlibet.util import escape from quodlibet.util.collection import FileBackedPlaylist from quodlibet.util.path import mkdir, uri_is_valid # Directory for playlist files PLAYLISTS = os.path.join(quodlibet.get_user_dir(), "playlists") assert isinstance(PLAYLISTS, fsnative) if not os.path.isdir(PLAYLISTS): mkdir(PLAYLISTS) 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 class GetPlaylistName(GetStringDialog): def __init__(self, parent): super().__init__( parent, _("New Playlist"), _("Enter a name for the new playlist:"), button_label=_("_Add"), button_icon=Icons.LIST_ADD) def parse_m3u(filelike, pl_name, library=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, library) def parse_pls(filelike, pl_name, library=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, library) def __attempt_add(filename, filenames): try: filenames.append(bytes2fsn(filename, 'utf-8')) except ValueError: return def __create_playlist(name, source_dir, files, library): playlist = FileBackedPlaylist.new(PLAYLISTS, name, library=library) print_d("Created playlist %s" % playlist) songs = [] win = WaitLoadWindow( None, len(files), _("Importing playlist.\n\n%(current)d/%(total)d songs added.")) win.show() for i, filename in enumerate(files): if not uri_is_valid(filename): # Plain filename. songs.append(_af_for(filename, library, source_dir)) else: try: filename = uri2fsn(filename) except ValueError: # Who knows! Hand it off to GStreamer. songs.append(formats.remote.RemoteFile(filename)) else: # URI-encoded local filename. songs.append(_af_for(filename, library, source_dir)) if win.step(): break win.destroy() playlist.extend(list(filter(None, songs))) return playlist 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: return os.path.dirname(path2fsn(filelike.name)) except AttributeError: # Probably a URL return text2fsn(u'') �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614542835.1294696 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/browsers/soundcloud/������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�020513� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9831858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/browsers/soundcloud/__init__.py�������������������������������������������0000644�0001750�0001750�00000000722�00000000000�022625� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9831858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/browsers/soundcloud/api.py������������������������������������������������0000644�0001750�0001750�00000025034�00000000000�021642� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 datetime import datetime from urllib.parse import urlencode from gi.repository import GObject, Gio, Soup from quodlibet import util, config from quodlibet.util import website from quodlibet.util.dprint import print_w, print_d from quodlibet.util.http import download_json, download 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): super().__init__() self._cancellable = Gio.Cancellable.new() self.root = root def _default_params(self): return {} def _get(self, path, callback, **kwargs): args = self._default_params() args.update(kwargs) msg = Soup.Message.new('GET', self._url(path, args)) download_json(msg, self._cancellable, callback, None) def _post(self, path, callback, **kwargs): args = self._default_params() args.update(kwargs) msg = 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('application/x-www-form-urlencoded', Soup.MemoryUse.COPY, post_body) download_json(msg, self._cancellable, callback, None) def _put(self, path, callback, **kwargs): args = self._default_params() args.update(kwargs) msg = Soup.Message.new('PUT', self._url(path)) body = urlencode(args) if not isinstance(body, bytes): body = body.encode("ascii") msg.set_request('application/x-www-form-urlencoded', Soup.MemoryUse.COPY, body) download_json(msg, self._cancellable, callback, None) 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 = Soup.Message.new('DELETE', self._url(path)) msg.set_request('application/x-www-form-urlencoded', Soup.MemoryUse.COPY, 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 = 150 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,)), '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.access_token = config.get("browsers", "soundcloud_token", None) self.online = bool(self.access_token) self.user_id = config.get("browsers", "soundcloud_user_id", None) if not self.user_id: self._get_me() self.username = None def _default_params(self): params = {'client_id': self.__CLIENT_ID} if self.access_token: params["oauth_token"] = self.access_token return params 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.save_auth() self.online = False def get_token(self, code): print_d("Getting access token...") options = { 'grant_type': 'authorization_code', 'redirect_uri': self.REDIRECT_URI, 'client_id': self.__CLIENT_ID, 'client_secret': self.__CLIENT_SECRET, 'code': code, } self._post('/oauth2/token', self._receive_token, **options) @json_callback def _receive_token(self, json): self.access_token = json['access_token'] print_d("Got an access token: %s" % self.access_token) self.save_auth() self.online = True self._get_me() def _get_me(self): self._get('/me', self._receive_me) @json_callback def _receive_me(self, json): 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, } 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) @json_callback def _on_track_data(self, json): songs = list(filter(None, [self._audiofile_for(r) for r in json])) self.emit('songs-received', songs) def get_favorites(self): self._get('/me/favorites', 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('/tracks/%s/comments' % track_id, self._receive_comments, limit=200) @json_callback def _receive_comments(self, json): print_d("Got comments: %s" % json) 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_user_id", self.user_id or "") def put_favorite(self, track_id): print_d("Saving track %s as favorite" % track_id) url = '/me/favorites/%s' % track_id self._put(url, self._on_favorited) def remove_favorite(self, track_id): print_d("Deleting favorite for %s" % track_id) url = '/me/favorites/%s' % track_id self._delete(url, self._on_favorited) @json_callback def _on_favorited(self, json): print_d("Successfully updated favorite: %s" % json) def _audiofile_for(self, response): r = Wrapper(response) d = r.data dl = d.get("downloadable", False) and d.get("download_url", None) try: url = dl or r.stream_url except AttributeError as e: print_w("Unusable result (%s) from SC: %s" % (e, d)) return None uri = SoundcloudApiClient._add_secret(url) song = SoundcloudFile(uri=uri, track_id=r.id, favorite=d.get("user_favorite", False), client=self) 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: pass try: song.update(title=r.title, artist=r.user["username"], soundcloud_user_id=str(r.user_id), website=r.permalink_url, genre=u"\n".join(r.genre and r.genre.split(",") or [])) if dl: song.update(format=r.original_format) song["~#bitrate"] = r.original_content_size * 8 / r.duration else: 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 # print_d("Got song: %s" % song) except Exception as e: print_w("Couldn't parse a song from %s (%r). " "Had these tags:\n %s" % (r, e, song.keys())) return song @classmethod def _add_secret(cls, stream_url): return "%s?client_id=%s" % (stream_url, cls.__CLIENT_ID) @util.cached_property def _authorize_url(self): url = '%s/connect' % (self.API_ROOT,) options = { 'scope': 'non-expiring', 'client_id': self.__CLIENT_ID, 'response_type': 'code', 'redirect_uri': self.REDIRECT_URI } return '%s?%s' % (url, urlencode(options)) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9831858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/browsers/soundcloud/library.py��������������������������������������������0000644�0001750�0001750�00000011204�00000000000�022527� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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.util.dprint import print_d, print_w from quodlibet.browsers.soundcloud.query import SoundcloudQuery from quodlibet import config from quodlibet.formats.remote import RemoteFile from quodlibet.library.libraries import SongLibrary from quodlibet.util import cached_property, print_exc class SoundcloudLibrary(SongLibrary): STAR = ["artist", "title", "genre", "tags"] def __init__(self, client, player=None): super().__init__("Soundcloud") self.client = client self.client.connect('songs-received', self._on_songs_received) self.client.connect('comments-received', self._on_comments_received) if player: player.connect('song-started', self.__song_started) 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, text, sort=None, star=STAR): """Queries Soundcloud for some (more) relevant results, then filters""" current = self._contents.values() query = SoundcloudQuery(text, star=star) 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 _on_songs_received(self, client, songs): new = len(self.add(songs)) print_d("Got %d songs (%d new)." % (len(songs), new)) self.emit('changed', songs) 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] 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, track_id, favorite=False, client=None): super().__init__(uri) self.client = client self["soundcloud_track_id"] = track_id self.favorite = favorite if self.favorite: self['~#rating'] = 1.0 if not self.client: raise EnvironmentError("Must have a Soundcloud client") 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 "rating" in k 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.put_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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9831858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/browsers/soundcloud/main.py�����������������������������������������������0000644�0001750�0001750�00000041201�00000000000�022007� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 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.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): self.api_client.disconnect(self.__auth_sig) if not self.instances(): self._destroy() def __init__(self, library): print_d("Creating Soundcloud Browser") 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) self.__auth_sig = self.api_client.connect('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_footer(), False, False, 6) vbox.pack_start(self._create_category_widget(), True, True, 0) vbox.pack_start(self.create_login_button(), False, False, 6) 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() @property def online(self): return self.api_client.online def _create_footer(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=6) 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_token(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("Updating view") self.activate() def __query_changed(self, bar, text, restore=False): try: self.__filter = SoundcloudQuery(text, self.STAR) self.library.query_with_refresh(text) 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 == "soundcloud_user_id=%s" % 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_token(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._refresh_online_filters() msg = Message(Gtk.MessageType.INFO, app.window, _("Connected"), _("Quod Libet is now connected, <b>%s</b>!") % 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9831858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/browsers/soundcloud/query.py����������������������������������������������0000644�0001750�0001750�00000012310�00000000000�022227� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 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. 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') # Convert QL to Soundcloud tags with optional value mapper _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) } 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) or isinstance(node, 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9831858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/browsers/soundcloud/util.py�����������������������������������������������0000644�0001750�0001750�00000005473�00000000000�022053� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 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 datetime import datetime 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): self.data = data 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('Invalid JSON ({message.status_code}): ' '{message.response_body.data} (request: {data})' .format(**locals())) 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) 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9831858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/browsers/tracks.py��������������������������������������������������������0000644�0001750�0001750�00000011161�00000000000�020175� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2020 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 config from quodlibet import qltk from quodlibet import _ from quodlibet.browsers import Browser 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 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__(margin=6, 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) self._sb_box = sbb prefs = PreferencesButton(sbb) sbb.pack_start(prefs, False, True, 0) self.pack_start(sbb, 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 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9831858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/build.py������������������������������������������������������������������0000644�0001750�0001750�00000001143�00000000000�016136� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9831858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/cli.py��������������������������������������������������������������������0000644�0001750�0001750�00000024125�00000000000�015613� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 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")), ]: 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") elif command == "print-queue": queue("dump-queue") 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(util.path.expanduser(arg)) queue("play-file", filename) elif command == 'add-location': try: path = uri2fsn(arg) except ValueError: path = arg path = os.path.abspath(util.path.expanduser(arg)) queue("add-location", path) elif command == "print-playing": try: queue("print-playing", args[0]) except IndexError: queue("print-playing") elif command == "print-query": queue(command, arg) 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9831858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/commands.py���������������������������������������������������������������0000644�0001750�0001750�00000034335�00000000000�016651� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 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.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) 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") def _dump_playlist(app): window = app.window uris = [] for song in window.playlist.pl.get(): uris.append(song("~uri")) return text2fsn(u"\n".join(uris) + u"\n") @registry.register("dump-queue") def _dump_queue(app): window = app.window uris = [] for song in window.playlist.q.get(): uris.append(song("~uri")) return text2fsn(u"\n".join(uris) + u"\n") @registry.register("refresh") def _refresh(app): scan_library(app.library, False) @registry.register("print-query", args=1) def _print_query(app, query): """Queries library, dumping filenames of matches to stdout See Issue 716 """ query = arg2text(query) songs = app.library.query(query) return "\n".join([song("~filename") 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 from quodlibet.pattern import Pattern if fstring is None: fstring = u"<artist~album~tracknumber~title>" else: fstring = arg2text(fstring) 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(fstring).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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9831858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/config.py�����������������������������������������������������������������0000644�0001750�0001750�00000031615�00000000000�016313� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2008 Joe Wreschnig # 2009-2020 Nick Boultbee # 2011-2014 Christoph Reiter # 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 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", }, "library": { "exclude": "", "refresh_on_start": "true", }, # 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", }, "browsers": { # search bar text "query_text": "", # 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", }, # 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" }, "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", # 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614542653.2604055 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/const.py������������������������������������������������������������������0000644�0001750�0001750�00000014270�00000000000�016172� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the 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 "" raise ImportError("%s %s required. %s found.%s" % ( self.name, self, Version("", *version_tuple), message)) class MinVersions: """Dependency requirements for Quod Libet / Ex Falso""" PYTHON3 = Version("Python3", 3, 7) MUTAGEN = Version("Mutagen", 1, 34, 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, 4, 0) VERSION = str(VERSION_TUPLE) # 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 = u"Copyright 2004-2019" AUTHORS = sorted(u"""\ 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(u""" Å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(u"""\ 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=1614542835.1294696 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/errorreport/��������������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�017053� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9831858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/errorreport/__init__.py���������������������������������������������������0000644�0001750�0001750�00000000551�00000000000�021165� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9831858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/errorreport/faulthandling.py����������������������������������������������0000644�0001750�0001750�00000006665�00000000000�022262� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9831858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/errorreport/logdump.py����������������������������������������������������0000644�0001750�0001750�00000004025�00000000000�021075� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9831858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/errorreport/main.py�������������������������������������������������������0000644�0001750�0001750�00000013300�00000000000�020346� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9831858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/errorreport/sentrywrapper.py����������������������������������������������0000644�0001750�0001750�00000020575�00000000000�022363� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9831858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/errorreport/ui.py���������������������������������������������������������0000644�0001750�0001750�00000007634�00000000000�020054� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9831858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/exfalso.py����������������������������������������������������������������0000644�0001750�0001750�00000004153�00000000000�016504� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 from senf import fsnative, argv as sys_argv 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=1614542835.1294696 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/����������������������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�015266� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9831858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/__init__.py�����������������������������������������������������������0000644�0001750�0001750�00000000727�00000000000�017405� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the 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=1614542835.1294696 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/_shared/��������������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�016673� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9831858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/_shared/__init__.py���������������������������������������������������0000644�0001750�0001750�00000000615�00000000000�021006� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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=1614542835.1294696 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/_shared/squeezebox/���������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�021065� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9831858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/_shared/squeezebox/__init__.py����������������������������������������0000644�0001750�0001750�00000000431�00000000000�023174� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9831858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/_shared/squeezebox/base.py��������������������������������������������0000644�0001750�0001750�00000015160�00000000000�022354� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/_shared/squeezebox/server.py������������������������������������������0000644�0001750�0001750�00000020041�00000000000�022742� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/_shared/squeezebox/util.py��������������������������������������������0000644�0001750�0001750�00000003237�00000000000�022421� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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=1614542835.1294696 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/covers/���������������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�016567� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/covers/__init__.py����������������������������������������������������0000644�0001750�0001750�00000000370�00000000000�020700� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/covers/artwork_url.py�������������������������������������������������0000644�0001750�0001750�00000002477�00000000000�021526� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 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 = _("Downloads covers linked to by the artwork_url tag. " "This works with the Soundcloud browser.") @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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/covers/discogs.py�����������������������������������������������������0000644�0001750�0001750�00000010110�00000000000�020565� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/covers/lastfm.py������������������������������������������������������0000644�0001750�0001750�00000006456�00000000000�020442� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/covers/musicbrainz.py�������������������������������������������������0000644�0001750�0001750�00000004405�00000000000�021472� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2013 Simonas Kazlauskas # 2018-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 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 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 = Soup.URI.encode(self.mbid, None) 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=1614542835.1294696 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/editing/��������������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�016711� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/editing/__init__.py���������������������������������������������������0000644�0001750�0001750�00000000370�00000000000�021022� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/editing/iconv.py������������������������������������������������������0000644�0001750�0001750�00000004407�00000000000�020406� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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: return [(tag, value)] ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/editing/kakasi.py�����������������������������������������������������0000644�0001750�0001750�00000004073�00000000000�020532� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/editing/resub.py������������������������������������������������������0000644�0001750�0001750�00000003112�00000000000�020400� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the 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 = _("Allows arbitrary regex substitutions (s///) 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/editing/titlecase.py��������������������������������������������������0000644�0001750�0001750�00000004475�00000000000�021252� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614542835.1334698 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/���������������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�016572� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/__init__.py����������������������������������������������������0000644�0001750�0001750�00000000370�00000000000�020703� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/advanced_preferences.py����������������������������������������0000644�0001750�0001750�00000017404�00000000000�023300� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2015 Christoph Reiter # 2016-20 Nick Boultbee # 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 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) 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", "Search tags:", ("Tags which get searched in addition to " "the ones present in the song list. Separate with \",\"")), 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", "DateColumn timestamp format", "A timestamp format, e.g. %Y%m%d %X "), text_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") ] 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614542835.1334698 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/animosd/�������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�020224� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/animosd/__init__.py��������������������������������������������0000644�0001750�0001750�00000001011�00000000000�022326� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/animosd/config.py����������������������������������������������0000644�0001750�0001750�00000003433�00000000000�022046� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/animosd/main.py������������������������������������������������0000644�0001750�0001750�00000005760�00000000000�021532� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/animosd/osdwindow.py�������������������������������������������0000644�0001750�0001750�00000025470�00000000000�022623� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/animosd/prefs.py�����������������������������������������������0000644�0001750�0001750�00000025626�00000000000�021730� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/appinfo.py�����������������������������������������������������0000644�0001750�0001750�00000007666�00000000000�020617� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/auto_library_update.py�����������������������������������������0000644�0001750�0001750�00000015574�00000000000�023216� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Automatic library update plugin # # (c) 2009 Joe Higton # 2011 - 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 operator import os import sys from functools import reduce from typing import Set from quodlibet.qltk import Icons if os.name == "nt" or sys.platform == "darwin": from quodlibet.plugins import PluginNotSupportedError raise PluginNotSupportedError try: from pyinotify import WatchManager, EventsCodes, ProcessEvent from pyinotify import Notifier, ThreadedNotifier except ImportError: from quodlibet import plugins raise plugins.MissingModulePluginException("pyinotify") from quodlibet import _ from quodlibet.util.dprint import print_d, print_w from quodlibet.plugins.events import EventPlugin from quodlibet.util.library import get_scan_dirs from quodlibet import app from gi.repository import GLib class LibraryEvent(ProcessEvent): """pynotify event handler for library changes""" # Slightly dodgy state mechanism for updates _being_created: Set[str] = set() def my_init(self, library=None): self._library = library def process_default(self, event): print_d('Uncaught event for %s' % (event.maskname if event else "??")) def process_IN_CLOSE_WRITE(self, event): path = os.path.join(event.path, event.name) # No need to add files for modifications only if path in self._being_created: GLib.idle_add(self.add, event) self._being_created.remove(path) elif event.path in self._being_created: # The first file per new-directory gets missed for me (bug?) # TODO: so work out how/when to remove parent path properly GLib.idle_add(self.add, event) self._being_created.remove(event.path) else: # Refresh library on modification self._log(event) GLib.idle_add(self.update, event) def process_IN_MOVED_TO(self, event): self._log(event) GLib.idle_add(self.add, event) def process_IN_CREATE(self, event): if not event.dir: self._log(event) # Just remember that they've been created, will process later path = os.path.join(event.path, event.name) if os.path.exists(path): self._being_created.add(path) else: print_w("Couldn't find %s" % path) def process_IN_DELETE(self, event): self._log(event) if event.dir: try: del self._moved[event.pathname] except KeyError: pass GLib.idle_add(self.update, event) def process_IN_MOVED_FROM(self, event): self._log(event) GLib.idle_add(self.update, event) def _log(self, event): print_d('%s for "%s" on %s' % (event.maskname, event.name, event.path)) def add(self, event): """Add a library file / folder based on an incoming event""" lib = self._library path = os.path.join(event.path, event.name) if event.dir: print_d('Scanning directories...') songs = [] for path, dnames, fnames in os.walk(path): print_d('Found %d file(s) in "%s"' % (len(fnames), path)) for filename in (os.path.join(path, fn) for fn in fnames): song = lib.add_filename(filename, add=False) if song: songs.append(song) lib.add(songs) else: lib.add_filename(path) return False def update(self, event): """Update a library / file. Typically this means deleting it""" lib = self._library path = os.path.join(event.path, event.name) if event.dir: print_d('Checking directory %s...' % path) to_reload = [] for filename in lib._contents: if filename.startswith(path): item = lib.get(filename, None) if item: # Don't modify whilst iterating... to_reload.append(item) print_d('Reloading %d matching songs(s)' % len(to_reload)) for item in to_reload: lib.reload(item) else: item = lib.get(path, None) if item: lib.reload(item) return False class AutoLibraryUpdate(EventPlugin): PLUGIN_ID = "Automatic library update" PLUGIN_NAME = _("Automatic Library Update") PLUGIN_DESC = _("Keeps your library up to date with inotify. " "Requires %s.") % "pyinotify" PLUGIN_ICON = Icons.VIEW_REFRESH # TODO: make a config option USE_THREADS = True event_handler = None running = False def enabled(self): if not self.running: wm = WatchManager() self.event_handler = LibraryEvent(library=app.library) FLAGS = ['IN_DELETE', 'IN_CLOSE_WRITE', # 'IN_MODIFY', 'IN_MOVED_FROM', 'IN_MOVED_TO', 'IN_CREATE'] masks = [EventsCodes.FLAG_COLLECTIONS['OP_FLAGS'][s] for s in FLAGS] mask = reduce(operator.or_, masks, 0) if self.USE_THREADS: print_d("Using threaded notifier") self.notifier = ThreadedNotifier(wm, self.event_handler) # Daemonize to ensure thread dies on exit self.notifier.daemon = True self.notifier.start() else: self.notifier = Notifier(wm, self.event_handler, timeout=100) GLib.timeout_add(1000, self.unthreaded_callback) for path in get_scan_dirs(): real_path = os.path.realpath(path) print_d('Watching directory %s for %s (mask: %x)' % (real_path, FLAGS, mask)) # See https://github.com/seb-m/pyinotify/wiki/ # Frequently-Asked-Questions wm.add_watch(real_path, mask, rec=True, auto_add=True) self.running = True def unthreaded_callback(self): """Processes as much of the inotify events as allowed""" assert self.notifier._timeout is not None, \ 'Notifier must be constructed with a [short] timeout' self.notifier.process_events() # loop in case more events appear while we are processing while self.notifier.check_events(): self.notifier.read_events() self.notifier.process_events() return True # disable hook, stop the notifier: def disabled(self): if self.running: self.running = False if self.notifier: print_d("Stopping inotify watch...") self.notifier.stop() ������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/auto_update_tags_in_files.py�����������������������������������0000644�0001750�0001750�00000022233�00000000000�024346� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2019-2020 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 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, \ background_check_wrapper_changed 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 self._write_tags_to_files([song_wrapper]) 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) self._write_tags_to_files(song_wrappers) def _write_tags_to_files(self, song_wrappers): background_check_wrapper_changed(app.library, song_wrappers) 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/automask.py����������������������������������������������������0000644�0001750�0001750�00000003277�00000000000�021001� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/autorating.py��������������������������������������������������0000644�0001750�0001750�00000002064�00000000000�021323� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/bansheeimport.py�����������������������������������������������0000644�0001750�0001750�00000013435�00000000000�022012� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 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 expanduser, 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 = 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/clock.py�������������������������������������������������������0000644�0001750�0001750�00000010056�00000000000�020241� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/equalizer.py���������������������������������������������������0000644�0001750�0001750�00000032613�00000000000�021152� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/gajim_status.py������������������������������������������������0000644�0001750�0001750�00000015533�00000000000�021645� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/headphonemon.py������������������������������������������������0000644�0001750�0001750�00000013033�00000000000�021611� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/inhibit.py�����������������������������������������������������0000644�0001750�0001750�00000010172�00000000000�020573� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/iradiolog.py���������������������������������������������������0000644�0001750�0001750�00000002345�00000000000�021121� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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. 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.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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/jep118.py������������������������������������������������������0000644�0001750�0001750�00000003125�00000000000�020155� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 = _("Outputs a Jabber User Tunes file to ~/.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 ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.987186 quodlibet-4.4.0/quodlibet/ext/events/language.py0000644000175000017500000000512300000000000020730 0ustar00lazkalazka# 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=1614540385.987186 quodlibet-4.4.0/quodlibet/ext/events/mediaserver.py0000644000175000017500000005645000000000000021464 0ustar00lazkalazka# 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 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("{}".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 = """ """ ISPEC = """ """ 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 = """ """ 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 = """ """ 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//SongID This lets us reconstruct the original parent path: /org/gnome/UPnP/MediaServer2/ atm. a prefix can look like "Albums/123456" """ SUPPORTS_MULTIPLE_OBJECT_PATHS = False __pattern = Pattern( ".>. ") 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614542835.1334698 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/mpdserver/�����������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�020601� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/mpdserver/__init__.py������������������������������������������0000644�0001750�0001750�00000014150�00000000000�022713� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/mpdserver/avahi.py���������������������������������������������0000644�0001750�0001750�00000017027�00000000000�022252� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/mpdserver/main.py����������������������������������������������0000644�0001750�0001750�00000055632�00000000000�022112� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/mpdserver/tcpserver.py�����������������������������������������0000644�0001750�0001750�00000017116�00000000000�023176� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614542835.1334698 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/mpris/���������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�017724� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/mpris/__init__.py����������������������������������������������0000644�0001750�0001750�00000005707�00000000000�022046� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 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 = _("Allows control of Quod Libet using the " "MPRIS 2 D-Bus Interface Specification.") 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/mpris/mpris2.py������������������������������������������������0000644�0001750�0001750�00000033052�00000000000�021515� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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.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 player_options.single = False elif value == "Track": player_options.repeat = True player_options.single = True elif value == "None": player_options.repeat = False player_options.single = False 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/mpris/util.py��������������������������������������������������0000644�0001750�0001750�00000001046�00000000000�021254� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/mqtt.py��������������������������������������������������������0000644�0001750�0001750�00000021146�00000000000�020135� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 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 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, escape 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(escape('<~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"), Config.HOST, _("broker hostname / IP (defaults to localhost)")), (_("Broker port"), Config.PORT, _("broker port (defaults to 1883)")), (_("Broker username"), Config.USERNAME, _("broker username")), (_("Broker password"), Config.PASSWORD, _("broker password")), (_("Topic"), Config.TOPIC, _("Topic")), (_("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) 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/musicbrainzsync.py���������������������������������������������0000644�0001750�0001750�00000007173�00000000000�022377� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 music brainz.") 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/notify.py������������������������������������������������������0000644�0001750�0001750�00000040721�00000000000�020460� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/qlscrobbler.py�������������������������������������������������0000644�0001750�0001750�00000051454�00000000000�021467� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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> # Nick Boultbee <nick.boultbee@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 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 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" DUMP = 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.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()) 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 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() if not self.broken and not self.offline and (self.queue or (self.nowplaying_song and not self.nowplaying_sent)): 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() url = "%s/?hs=true&p=%s&c=%s&v=%s&u=%s&a=%s&t=%d" % ( self.base_url, self.PROTOCOL_VERSION, self.CLIENT, self.CLIENT_VERSION, self.username, auth, stamp) print_d("Sending handshake to service.") 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) print_d("Handshake status: %s" % status) 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 elif 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] = '' print_d('Submitting song(s): %s' % ('\n\t'.join(['%s - %s' % (s['a'], s['t']) for s in to_submit]))) 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 def __init__(self): self.__enabled = False self.queue = QLSubmitQueue() def queue_run(): try: self.queue.run() except Exception: errorhook() queue_thread = threading.Thread(None, 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 # 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.") def disabled(self): self.__enabled = False print_d("Plugin disabled - not accepting any new songs.") 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/radioadmute.py�������������������������������������������������0000644�0001750�0001750�00000004220�00000000000�021440� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/randomalbum.py�������������������������������������������������0000644�0001750�0001750�00000023654�00000000000�021457� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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("<i>%s</i>" % util.escape(_("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("<i>%s</i>" % util.escape(_("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(util.escape(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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/rbimport.py����������������������������������������������������0000644�0001750�0001750�00000010272�00000000000�021004� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 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 expanduser, 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 = 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/screensaver.py�������������������������������������������������0000644�0001750�0001750�00000006135�00000000000�021471� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.987186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/searchprovider.py����������������������������������������������0000644�0001750�0001750�00000020355�00000000000�022171� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 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. """ For this plugin to work GNOME Shell needs this file: /usr/share/gnome-shell/search-providers/io.github.quodlibet.QuodLibet-search-provider.ini with the following content: [Shell Search Provider] DesktopId=quodlibet.desktop BusName=io.github.quodlibet.QuodLibet.SearchProvider ObjectPath=/io/github/quodlibet/QuodLibet/SearchProvider Version=2 """ 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 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""" quodlibet_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: quodlibet_installed = True break except EnvironmentError: pass if not quodlibet_installed: raise PluginImportException( _("No GNOME Shell search provider for " "Quod Libet installed.")) 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" /> </method> <method name="GetSubsearchResultSet"> <arg direction="in" type="as" name="previous_results" /> <arg direction="in" type="as" name="terms" /> <arg direction="out" type="as" /> </method> <method name="GetResultMetas"> <arg direction="in" type="as" name="identifiers" /> <arg direction="out" type="aa{sv}" /> </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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/seekbar.py�����������������������������������������������������0000644�0001750�0001750�00000010445�00000000000�020564� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/seekpoints.py��������������������������������������������������0000644�0001750�0001750�00000012157�00000000000�021336� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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" "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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/squeezebox_sync.py���������������������������������������������0000644�0001750�0001750�00000006035�00000000000�022376� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2011-2014 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 = _("Makes Logitech Squeezebox mirror Quod Libet output, " "provided both read from an identical library.") 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/synchronize_to_device.py���������������������������������������0000755�0001750�0001750�00000133355�00000000000�023555� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# -*- coding: utf-8 -*- # 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 as ngt 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 from quodlibet.util.string.titlecase import human_title 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 = human_title(PLUGIN_CONFIG_SECTION.replace('_', ' ')) 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!'), 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: 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( _('attempt to write {count} {file_str}') .format(count=counter, file_str=ngt('file', 'files', counter))) if self.c_song_dupes > 0: counter = self.c_song_dupes preview_progress.append( _('skip {count} duplicate {file_str}') .format(count=counter, file_str=ngt('file', 'files', 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( _('delete {count} {file_str}') .format(count=counter, file_str=ngt('file', 'files', 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<b>{}</b>\n\ncontains "/" but does not start ' 'from root. Please provide an absolute destination path by ' 'making sure it starts with / or ~/.') .format(util.escape(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, __ in os.walk(self.expanded_destination, topdown=False): for dirname in dirs: dir_path = os.path.realpath(os.path.join(root, dirname)) if not os.listdir(dir_path): 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: 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( _('written {count}/{total} {file_str}') .format(count=counter, total=self.c_songs_copy, file_str=ngt('file', 'files', counter))) if self.c_files_skip > 0: counter = self.c_files_skip text.append( _('(skipped {count} existing {file_str})').format( count=counter, file_str=ngt('file', 'files', counter))) sync_summary.append(self.summary_sep.join(text)) if self.c_files_dupes > 0: counter = self.c_files_dupes sync_summary.append( _('skipped {count}/{total} duplicate {file_str}') .format(count=counter, total=self.c_song_dupes, file_str=ngt('file', 'files', counter))) if self.c_files_delete > 0: counter = self.c_files_delete sync_summary.append( _('deleted {count}/{total} {file_str}') .format(count=counter, total=self.c_songs_delete, file_str=ngt('file', 'files', counter))) if self.c_files_failed > 0: counter = self.c_files_failed sync_summary.append( _('failed to sync {count} {file_str}') .format(count=counter, file_str=ngt('file', 'files', counter))) if self.c_files_skip_previous > 0: counter = self.c_files_skip_previous sync_summary.append( _('skipped {count} {file_str} synchronized previously') .format(count=counter, file_str=ngt('file', 'files', 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/synchronizedlyrics.py������������������������������������������0000644�0001750�0001750�00000025127�00000000000�023120� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Synchronized Lyrics: a Quod Libet plugin for showing synchronized lyrics. # Copyright (C) 2015 elfalem # 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. 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 _ 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 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("<b>" + _("Colors") + "</b>") 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("<b>" + _("Font") + "</b>") 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 def _get_text_color(self): v = self.config_get(self.CFG_TXTCOLOR_KEY, self.DEFAULT_TXTCOLOR) return v[:3] + v[5:7] + v[9:11] def _get_background_color(self): v = self.config_get(self.CFG_BGCOLOR_KEY, self.DEFAULT_BGCOLOR) return v[:3] + v[5:7] + v[9:11] def _get_font_size(self): return int(self.config_get(self.CFG_FONTSIZE_KEY, self.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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/telepathy_status.py��������������������������������������������0000644�0001750�0001750�00000014437�00000000000�022557� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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( util.escape("<~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( util.escape("<~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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/themeswitcher.py�����������������������������������������������0000644�0001750�0001750�00000012174�00000000000�022024� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/thumbrating.py�������������������������������������������������0000644�0001750�0001750�00000013204�00000000000�021470� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 _ 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("<b>" + str(int(score)) + "</b>") 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 = _('Adds a thumb-up/thumb-down scoring system ' 'which is converted to a rating value. Useful ' 'for keeping running vote totals and sorting by ' '\'~#score\'.') 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/toggle_menu.py�������������������������������������������������0000644�0001750�0001750�00000003610�00000000000�021451� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614542835.1334698 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/trayicon/������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�020422� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/trayicon/__init__.py�������������������������������������������0000644�0001750�0001750�00000004577�00000000000�022550� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 _ from quodlibet import app from quodlibet.plugins.events import EventPlugin from quodlibet.qltk import Icons from quodlibet.util import (is_linux, is_osx, print_exc, 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: print_w("importing app indicator failed") print_exc() # 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/trayicon/appindicator.py���������������������������������������0000644�0001750�0001750�00000007777�00000000000�023473� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 gi try: gi.require_version("AppIndicator3", "0.1") except ValueError as e: raise ImportError(e) 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/trayicon/base.py�����������������������������������������������0000644�0001750�0001750�00000002106�00000000000�021705� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/trayicon/menu.py�����������������������������������������������0000644�0001750�0001750�00000016566�00000000000�021756� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 import PlaylistsBrowser 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() if submenu: submenu.destroy() playlist_menu = PlaylistMenu([song], PlaylistsBrowser.playlists()) def on_new(widget, playlist): PlaylistsBrowser.changed(playlist) playlist_menu.connect('new', on_new) 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/trayicon/prefs.py����������������������������������������������0000644�0001750�0001750�00000007265�00000000000�022125� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/trayicon/systemtray.py�����������������������������������������0000644�0001750�0001750�00000025145�00000000000�023227� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/trayicon/util.py�����������������������������������������������0000644�0001750�0001750�00000002135�00000000000�021752� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/viewlyrics.py��������������������������������������������������0000644�0001750�0001750�00000012702�00000000000�021346� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# # 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/visualisations.py����������������������������������������������0000644�0001750�0001750�00000006351�00000000000�022226� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/waveformseekbar.py���������������������������������������������0000644�0001750�0001750�00000064740�00000000000�022342� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2016 0x1777 # 2016-17 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._waveform_scale.set_placeholder(False) 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._waveform_scale.set_placeholder(True) 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._waveform_scale.set_placeholder(True) 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 _placeholder = True 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 set_placeholder(self, placeholder): self._placeholder = placeholder 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("Length is zero for %s, using redraw interval of 1000 ms" % self._player.info) 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 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(*list(color)) cr.move_to(hw, half_height) cr.line_to(width - hw, 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()) context.restore() elapsed_color = get_fg_highlight_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): elapsed_color = Gdk.RGBA() elapsed_color.parse(elapsed_color_config) # 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 not self._placeholder and 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) 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/weblyrics.py���������������������������������������������������0000644�0001750�0001750�00000026216�00000000000�021156� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2014 Christoph Reiter # 2015 Joschua Gandert # 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 threading from xml.dom import minidom from urllib.parse import quote import queue from quodlibet import _, print_d from quodlibet.plugins.gui import UserInterfacePlugin from quodlibet.util import gi_require_versions, is_windows, is_osx from quodlibet.plugins.events import EventPlugin from quodlibet.plugins import (PluginImportException, PluginConfig, ConfProp, BoolConfProp, FloatConfProp, PluginNotSupportedError) try: gi_require_versions("WebKit2", ["4.0", "3.0"]) except ValueError as e: if is_windows() or is_osx(): raise PluginNotSupportedError raise PluginImportException("GObject Introspection: " + str(e)) from gi.repository import WebKit2, Gtk, GLib from quodlibet import qltk from quodlibet.util import escape, cached_property, connect_obj from quodlibet.qltk import Icons, Align from quodlibet.qltk.entry import UndoEntry from quodlibet.pattern import URLFromPattern from quodlibet.util.urllib import urlopen # for the mobile version USER_AGENT = ("Mozilla/5.0 (Linux; Android 5.1.1; Nexus 5 Build/LMY48B; wv) " "AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0" "Chrome/43.0.2357.65 Mobile Safari/537.36") LYRICS_WIKIA_URL = ("https://lyrics.wikia.com/api.php?client=QuodLibet" "&action=lyrics&func=getSong&artist=%s&song=%s&fmt=xml") DEFAULT_ALTERNATE_SEARCH_URL = ("https://duckduckgo.com/" "?q=lyrics+<artist|<artist>+-+><title>") def create_api_search_url(song): artist, title = song("artist"), song("title") artist = quote(artist.encode('utf-8')) title = quote(title.encode('utf-8')) return LYRICS_WIKIA_URL % (artist, title) class LyricsWikiaSearchThread(threading.Thread): TIMEOUT = 4.0 def __init__(self): super().__init__() self.daemon = True self._queue = queue.Queue() self._stopped = False self._current = None def search_song(self, song, done_cb): """Trigger a new search, old ones will be canceled""" assert song assert done_cb if not self.is_alive(): self.start() self._current = song while not self._queue.empty(): self._queue.get_nowait() self._queue.put((song, done_cb)) def stop(self): """Stop all active searches, no callback will be called after this returns. """ self._stopped = True self._queue.put((None, None)) def __idle(self, song, func, *args, **kwargs): def delayed(): if self._stopped or song is not self._current: return func(song, *args, **kwargs) GLib.idle_add(delayed) def _do_search(self, song): """Returns a URL or None""" fetch_url = create_api_search_url(song) try: response = urlopen(fetch_url, timeout=self.TIMEOUT) except EnvironmentError: return try: xml = response.read() except IOError: return try: dom = minidom.parseString(xml) except Exception: # who knows... return page_id_nodes = dom.getElementsByTagName("page_id") if not page_id_nodes or not page_id_nodes[0].hasChildNodes(): return url_nodes = dom.getElementsByTagName("url") try: page = url_nodes[0].firstChild.data except (IndexError, AttributeError): return else: return page def run(self): while not self._stopped: song, cb = self._queue.get() if self._stopped: break result = self._do_search(song) self.__idle(song, cb, result) class LyricsWebView(Gtk.ScrolledWindow): def __init__(self, conf): print_d("Creating Lyrics web view") super().__init__() self.conf = conf self._thread = LyricsWikiaSearchThread() self.connect("destroy", lambda *x: self._thread.stop()) self.current_song = None self._reload_web_view() def _reload_web_view(self, web_view=None): if web_view is not None: self.remove(web_view) self._view = view = WebKit2.WebView() self.set_zoom_level(self.conf.zoom_level) # stop alert windows view.connect('script-dialog', lambda *args: True) view.connect('web-process-crashed', self._reload_web_view) settings = view.get_settings() settings.set_property("user-agent", USER_AGENT) settings.set_media_playback_requires_user_gesture(True) def scroll_to_lyrics(view, load_event): if load_event != WebKit2.LoadEvent.COMMITTED: return view.run_javascript(""" document.addEventListener('DOMContentLoaded', function() { var box = document.getElementsByClassName('lyricbox')[0]; box.scrollIntoView(true); }, false); """, None, None, None) view.connect('load-changed', scroll_to_lyrics) self.add(view) self.show_all() if self.current_song is not None: self.set_song(self.current_song) def set_zoom_level(self, zoom_level): self._view.set_zoom_level(zoom_level) def set_song(self, song): """Display lyrics for the given song""" self.current_song = song if song is None: message = _("No active song") self._set_html(message) return self._thread.search_song(song, self._callback) def _set_html(self, message, details=None): html = "<center><h2>%s</h2></center>" % escape(message) if details: html += "<center><p>%s</p><center>" % escape(details) self._view.load_html(html, "http://foo.bar") def _callback(self, song, page): if page is None: message = _("No lyrics found") if self.conf.alternate_search_enabled: url = URLFromPattern(self.conf.alternate_search_url) % song self._view.load_uri(url) else: self._set_html(message, song("~artist~title")) else: self._view.load_uri(page) def get_config(prefix): class LyricsWindowConfig: plugin_conf = PluginConfig(prefix) alternate_search_url = ConfProp(plugin_conf, "alternate_search_url", DEFAULT_ALTERNATE_SEARCH_URL) alternate_search_enabled = BoolConfProp(plugin_conf, "alternate_search_enabled", True) zoom_level = FloatConfProp(plugin_conf, "zoom_level", 1.4) return LyricsWindowConfig() 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 LyricsWindowPrefs(Gtk.VBox): def __init__(self, plugin): super().__init__(spacing=6) self.Conf = plugin.Conf self.plugin = plugin def build_display_widget(): vb2 = Gtk.VBox(spacing=3) hb = Gtk.HBox(spacing=6) zoom_level = Gtk.SpinButton( adjustment=Gtk.Adjustment.new( self.Conf.zoom_level, -10, 10, 0.1, 1, 0), climb_rate=0.1, digits=2) zoom_level.set_numeric(True) def change_zoom_level(button): value = float(button.get_value()) self.Conf.zoom_level = value pane = self.plugin._pane if pane is not None: pane.set_zoom_level(value) zoom_level.connect('value-changed', change_zoom_level) l1 = ConfigLabel(_("_Zoom level:"), zoom_level) hb.pack_start(l1, False, True, 0) hb.pack_start(zoom_level, False, True, 0) vb2.pack_start(hb, False, True, 0) return vb2 def build_alternate_search_widget(): vb2 = Gtk.VBox(spacing=3) hb = Gtk.HBox(spacing=6) def on_entry_changed(entry, *args): self.Conf.alternate_search_url = entry.get_text() URL_entry = UndoEntry() URL_entry.set_text(self.Conf.alternate_search_url) URL_entry.connect("changed", on_entry_changed) l1 = ConfigLabel(_("URL:"), URL_entry) URL_revert = Gtk.Button() URL_revert.add(Gtk.Image.new_from_icon_name( Icons.DOCUMENT_REVERT, Gtk.IconSize.MENU)) URL_revert.set_tooltip_text(_("Revert to default")) connect_obj(URL_revert, "clicked", URL_entry.set_text, DEFAULT_ALTERNATE_SEARCH_URL) hb.pack_start(l1, False, True, 0) hb.pack_start(URL_entry, True, True, 0) hb.pack_start(URL_revert, False, True, 0) vb2.pack_start(hb, False, True, 0) def on_alternate_search_toggled(button, *args): self.Conf.alternate_search_enabled = button.get_active() alternate_search_enabled = Gtk.CheckButton( label=_("Search via above URL if the lyrics " "couldn't be found in LyricsWikia."), use_underline=True) alternate_search_enabled.set_active( self.Conf.alternate_search_enabled) alternate_search_enabled.connect("toggled", on_alternate_search_toggled) vb2.pack_start(alternate_search_enabled, 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) frame = qltk.Frame(label=_("Alternate search"), child=build_alternate_search_widget()) frame.set_border_width(6) self.pack_start(frame, False, True, 0) class WebLyrics(EventPlugin, UserInterfacePlugin): PLUGIN_ID = 'WebLyrics' CONFIG_SECTION = "lyricswindow" PLUGIN_NAME = _('Web Lyrics') PLUGIN_DESC = _("Shows a sidebar containing online lyrics " "of the playing song.") PLUGIN_ICON = Icons.APPLICATION_INTERNET _pane = None def _destroy(self, *args): self._pane = None def enabled(self): if self._pane is None: self._pane = self._create_sw() @cached_property def Conf(self): return get_config(self.CONFIG_SECTION) def PluginPreferences(self, parent): return LyricsWindowPrefs(self) def _create_sw(self): sw = LyricsWebView(self.Conf) sw.show() sw.connect("destroy", self._destroy) return sw def create_sidebar(self): return Align(self._pane) def plugin_on_song_started(self, song): pane = self._pane if pane is not None: pane.set_song(song) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/events/write_cover.py�������������������������������������������������0000644�0001750�0001750�00000004061�00000000000�021475� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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=1614542835.1374698 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/gstreamer/������������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�017257� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/gstreamer/__init__.py�������������������������������������������������0000644�0001750�0001750�00000000370�00000000000�021370� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/gstreamer/compressor.py�����������������������������������������������0000644�0001750�0001750�00000010472�00000000000�022031� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/gstreamer/crossfeed.py������������������������������������������������0000644�0001750�0001750�00000013631�00000000000�021612� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/gstreamer/karaoke.py��������������������������������������������������0000644�0001750�0001750�00000010342�00000000000�021246� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/gstreamer/mono.py�����������������������������������������������������0000644�0001750�0001750�00000001534�00000000000�020604� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/gstreamer/pitch.py����������������������������������������������������0000644�0001750�0001750�00000007322�00000000000�020744� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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=1614542835.1374698 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/playlist/�������������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�017127� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/playlist/__init__.py��������������������������������������������������0000644�0001750�0001750�00000000370�00000000000�021240� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/playlist/export_to_folder.py������������������������������������������0000644�0001750�0001750�00000014240�00000000000�023060� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 = _(u"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(self, 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/playlist/export_to_sonos.py�������������������������������������������0000644�0001750�0001750�00000021443�00000000000�022751� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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. import quodlibet 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 from quodlibet.qltk.notif import Task from quodlibet.util import copool 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 = _(u"Export to Sonos Playlist") PLUGIN_DESC = _("Exports a playlist to Sonos playlist, " "provided both share a directory structure.") 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.device: Optional[SoCo] = None 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) 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) track = None if track: try: self.device.add_item_to_sonos_playlist(track, spl) except SoCoException as e: 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() print_d(f"Finished export to {spl.title!r}") @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): # TODO - only get coordinator nodes, somehow self.device: SoCo = soco.discovery.any_soco() 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!r}") device.remove_sonos_playlist(spl) print_d(f"Creating new playlist {name!r}") spl = device.create_sonos_playlist(name) task = Task("Sonos", _("Export to Sonos playlist"), stop=self.__cancel_add) copool.add(self.__add_songs, task, playlist.songs, spl, funcid="sonos-playlist-save") �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/playlist/export_to_squeezebox.py��������������������������������������0000644�0001750�0001750�00000007676�00000000000�024016� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 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 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 = \ _("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>.") 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/playlist/remove_duplicates.py�����������������������������������������0000644�0001750�0001750�00000004235�00000000000�023217� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/playlist/shuffle.py���������������������������������������������������0000644�0001750�0001750�00000001444�00000000000�021140� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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=1614542835.1374698 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/playorder/������������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�017267� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/playorder/__init__.py�������������������������������������������������0000644�0001750�0001750�00000000370�00000000000�021400� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/playorder/follow.py���������������������������������������������������0000644�0001750�0001750�00000003400�00000000000�021140� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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.") __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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/playorder/playcounteq.py����������������������������������������������0000644�0001750�0001750�00000003504�00000000000�022207� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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") 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/playorder/queue.py����������������������������������������������������0000644�0001750�0001750�00000002216�00000000000�020766� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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.plugins.playorder import ShufflePlugin from quodlibet.qltk import Icons from quodlibet.qltk.playorder import OrderInOrder 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.") 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 app.window.playlist.enqueue([playlist[iter][0]]) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/playorder/reverse.py��������������������������������������������������0000644�0001750�0001750�00000001505�00000000000�021315� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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.") def previous(self, playlist, iter): return super().next(playlist, iter) def next(self, playlist, iter): return super().previous(playlist, iter) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/playorder/shufflebygrouping.py����������������������������������������0000644�0001750�0001750�00000016237�00000000000�023414� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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") 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/playorder/skip_disliked.py��������������������������������������������0000644�0001750�0001750�00000004762�00000000000�022470� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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.") @classmethod def PluginPreferences(self, 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/playorder/track_repeat.py���������������������������������������������0000644�0001750�0001750�00000005515�00000000000�022313� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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.") 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=1614542835.1374698 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/query/����������������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�016433� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/query/__init__.py�����������������������������������������������������0000644�0001750�0001750�00000000370�00000000000�020544� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/query/conditional.py��������������������������������������������������0000644�0001750�0001750�00000002216�00000000000�021311� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 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' usage = "<b><tt>@(if: condition-query, then-query, else-query)</tt></b>" 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/query/missing.py������������������������������������������������������0000644�0001750�0001750�00000002656�00000000000�020467� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 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' usage = "<b><tt>@(missing: artist)</tt></b>" 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/query/pythonexpression.py���������������������������������������������0000644�0001750�0001750�00000004335�00000000000�022453� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 class PythonQuery(QueryPlugin): PLUGIN_ID = "python_query" PLUGIN_NAME = _("Python Query") PLUGIN_DESC = _("🐍Use Python expressions in queries.") key = 'python' usage = """ <b><tt>@(python: expression)</tt></b> The variable <tt>s</tt> (or <tt>a</tt>) is the song / album being matched. <tt>_ts</tt> is a (real number) timestamp at start of query. Modules <tt>time</tt> and <tt>random</tt> are also available, and the class <tt>Random</tt> (==<tt>random.Random</tt>) too. """.strip() 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/query/savedsearch.py��������������������������������������������������0000644�0001750�0001750�00000004057�00000000000�021303� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 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" usage = "<b><tt>@(saved: search-name)</tt></b>" 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614542835.1414697 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/songsmenu/������������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�017304� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/songsmenu/__init__.py�������������������������������������������������0000644�0001750�0001750�00000000370�00000000000�021415� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/songsmenu/albumart.py�������������������������������������������������0000644�0001750�0001750�00000105247�00000000000�021476� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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-2017 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 json import os import re import time import threading import gzip from io import BytesIO from urllib.parse import urlencode from xml.dom import minidom from gi.repository import Gtk, Pango, GLib, Gdk, GdkPixbuf 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.util import format_size, print_exc from quodlibet.util.dprint import print_d, print_w from quodlibet import _ from quodlibet import util, qltk, app from quodlibet.qltk.msg import ConfirmFileReplace from quodlibet.qltk.x import Paned, Align, Button from quodlibet.qltk.views import AllTreeView from quodlibet.qltk import Icons from quodlibet.qltk.image import scale, add_border_widget, \ get_surface_for_pixbuf from quodlibet.plugins.songsmenu import SongsMenuPlugin 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 AmazonParser: """A class for searching covers from Amazon""" def __init__(self): self.page_count = 1 self.covers = [] self.limit = 0 def __parse_page(self, page, query): """Gets all item tags and calls the item parsing function for each""" # Amazon now requires that all requests be signed. # I have built a webapp on AppEngine for this purpose. -- wm_eddie # url = 'https://webservices.amazon.com/onca/xml' url = 'https://qlwebservices.appspot.com/onca/xml' parameters = { 'Service': 'AWSECommerceService', 'AWSAccessKeyId': '0RKH4ZH1JCFZHMND91G2', # Now Ignored. 'Operation': 'ItemSearch', 'ResponseGroup': 'Images,Small', 'SearchIndex': 'Music', 'Keywords': query, 'ItemPage': page, # This specifies where the money goes and needed since 1.11.2011 # (What a good reason to break API..) # ...so use the eff.org one: https://www.eff.org/helpout 'AssociateTag': 'electronicfro-20', } data = get_url(url, get=parameters) dom = minidom.parseString(data) pages = dom.getElementsByTagName('TotalPages') if pages: self.page_count = int(pages[0].firstChild.data) items = dom.getElementsByTagName('Item') print_d("Amazon: 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.""" large = item.getElementsByTagName('LargeImage') small = item.getElementsByTagName('SmallImage') title = item.getElementsByTagName('Title') if large and small and title: cover = {} artist = item.getElementsByTagName('Artist') creator = item.getElementsByTagName('Creator') text = '' if artist: text = artist[0].firstChild.data elif creator: if len(creator) > 1: text = ', '.join([i.firstChild.data for i in creator]) else: text = creator[0].firstChild.data title_text = title[0].firstChild.data if len(text) and len(title_text): text += ' - ' cover['name'] = text + title_text url_tag = small[0].getElementsByTagName('URL')[0] cover['thumbnail'] = url_tag.firstChild.data url_tag = large[0].getElementsByTagName('URL')[0] cover['cover'] = url_tag.firstChild.data #Since we don't know the size, use the one from the HTML header. cover['size'] = get_size_of_url(cover['cover']) h_tag = large[0].getElementsByTagName('Height')[0] height = h_tag.firstChild.data w_tag = large[0].getElementsByTagName('Width')[0] width = w_tag.firstChild.data cover['resolution'] = '%s x %s px' % (width, height) cover['source'] = 'https://www.amazon.com' self.covers.append(cover) def start(self, query, limit=5): """Start the search and returns the covers""" 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 DiscogsParser: """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): """Start the search and returns the covers""" 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 = qltk.entry.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) 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.setDaemon(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, PluginConfigMixin): """The main window including the search list""" CONFIG_SECTION = PLUGIN_CONFIG_SECTION THUMB_SIZE = 50 def __init__(self, songs): super().__init__() 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 + 4 + border_width) rend_pix.set_property('height', self.THUMB_SIZE + 4 + 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 = '<b><i>%s</i></b>' % esc(cover['name']) txt += "\n<small>%s</small>" % ( _('from %(source)s') % { "source": util.italic(esc(cover['source']))}) if 'resolution' in cover: txt += "\n" + _('Resolution: %s') % util.italic( esc(cover['resolution'])) if 'size' in cover: txt += "\n" + _('Size: %s') % util.italic(esc(cover['size'])) 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.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 = Paned() hpaned.set_border_width(widget_space) hpaned.pack1(left_vbox, shrink=False) hpaned.pack2(image, shrink=False) hpaned.set_position(275) 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('<b>' + clean + '</b>') 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) 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.setDaemon(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': AmazonParser, 'url': 'https://www.amazon.com/', 'replace': ' ', 'config_id': 'amazon', }, { 'class': DiscogsParser, '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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/songsmenu/ape2id3.py��������������������������������������������������0000644�0001750�0001750�00000002606�00000000000�021111� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/songsmenu/bookmarks.py������������������������������������������������0000644�0001750�0001750�00000005373�00000000000�021656� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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=1614542835.1414697 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/songsmenu/brainz/�����������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�020571� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/songsmenu/brainz/__init__.py������������������������������������������0000644�0001750�0001750�00000004103�00000000000�022700� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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(self, 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/songsmenu/brainz/mb.py������������������������������������������������0000644�0001750�0001750�00000012343�00000000000�021544� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/songsmenu/brainz/query.py���������������������������������������������0000644�0001750�0001750�00000003402�00000000000�022307� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540385.991186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/songsmenu/brainz/util.py����������������������������������������������0000644�0001750�0001750�00000001417�00000000000�022123� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9951859 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/songsmenu/brainz/widgets.py�������������������������������������������0000644�0001750�0001750�00000040440�00000000000�022613� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 = "<b>%s</b>\n%s - %s, %s (%s)" % ( util.escape(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( "<b>%s</b>" % _("Please enter a query.")) self.search_button.set_sensitive(True) return self.result_label.set_markup("<i>%s</i>" % _(u"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("<i>%s</i>" % _(u"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("<i>%s</i>" % _(u"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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9951859 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/songsmenu/console.py��������������������������������������������������0000644�0001750�0001750�00000034223�00000000000�021324� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright (C) 2006 - Steve Frécinaux # 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. # 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 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, "* { background-color: white; padding: 6px; } ") 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: # 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()]) 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" self.history_add(line) # 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:] != "\n\n" and self.block_command)): # Unfinished block command self.block_command = True com_mark = "... " elif cur_strip.endswith("\\"): com_mark = "... " else: # Eval the command 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) 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 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) or isinstance(command, 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 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 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9951859 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/songsmenu/cover_download.py�������������������������������������������0000644�0001750�0001750�00000036627�00000000000�022701� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2018-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 operator import os import shutil from functools import reduce from typing import Iterable from gi.repository import GObject, Gtk, Gdk, Gio, GLib, Soup, GdkPixbuf from quodlibet import _, app, print_d, print_w from quodlibet import qltk from quodlibet.formats import AudioFile from quodlibet.packages.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 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_property('response-headers') self.size = int(headers.get('content-length')) self._content_type = headers.get('content-type') print_d("Loading %d KB (of %s)" % (len(result) / 1024, self._content_type)) 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) # Only supported on GTK >= 3.18 (not Ubuntu 16.04) # Re-enable some day perhaps... # box.bind_model(self.model, self.create_widget, None) 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 _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"<b>{format_size(size)}</b>") 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): 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): self.__cancellable.cancel() 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': escape(albums), 'providers': escape(providers)} text = _("Nothing found for albums:\n<i>%(albums)s</i>.\n\n" "Providers used:\n<tt>%(providers)s</tt>") % data dialog = qltk.Message(Gtk.MessageType.INFO, parent=self, title=_("No covers found"), description=text) 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", f"<tt>{escape(text)}</tt>") 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) first_path = paths.pop() print_d(f"Saving {data} to {first_path}") img.save_image(first_path) # Copying faster than potentially resizing for path in paths: shutil.copy(first_path, path) ���������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9951859 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/songsmenu/custom_commands.py������������������������������������������0000644�0001750�0001750�00000025256�00000000000�023063� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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)")), } def __init__(self, name=None, command=None, pattern="<~filename>", unique=False, parameter=None, max_args=10000, 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.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(" ") 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("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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9951859 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/songsmenu/duplicates.py�����������������������������������������������0000644�0001750�0001750�00000040252�00000000000�022016� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# # 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9951859 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/songsmenu/editplaycount.py��������������������������������������������0000644�0001750�0001750�00000011302�00000000000�022537� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2012-2015 Ryan "ZDBioHazard" Turner <zdbiohazard2@gmail.com> # 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.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 = _("Edit a song's ~#playcount and ~#skipcount." "\n\n" "When multiple songs are selected, counts will be " "incremented, rather than set." "\n\n" "When setting a song's ~#playcount to 0, the " "~#lastplayed and ~#laststarted 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("<b>Multiple files selected.</b>\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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9951859 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/songsmenu/embedded.py�������������������������������������������������0000644�0001750�0001750�00000006101�00000000000�021405� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2013 Christoph Reiter # 2013,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 util from quodlibet.plugins.songshelpers import any_song, has_writable_image 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 from quodlibet.plugins.songsmenu import SongsMenuPlugin class EditEmbedded(SongsMenuPlugin): PLUGIN_ID = "embedded_edit" PLUGIN_NAME = _("Edit Embedded Images") PLUGIN_DESC = _("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: try: song.set_image(image) except AudioFileError: util.print_exc() WriteFailedError(win, song).run() if win.step(): break win.destroy() self.plugin_finish() def _init_submenu_items(self, menu, songs): remove_item = MenuItem(_("_Remove all Images"), "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"), "edit-paste") set_item.connect('activate', self.__set_image, songs) menu.append(set_item) menu.show_all() return menu def plugin_songs(self, songs): return True ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9951859 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/songsmenu/exact_rating.py���������������������������������������������0000644�0001750�0001750�00000003721�00000000000�022331� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9951859 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/songsmenu/filterall.py������������������������������������������������0000644�0001750�0001750�00000006321�00000000000�021636� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9951859 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/songsmenu/filterbrowser.py��������������������������������������������0000644�0001750�0001750�00000002162�00000000000�022550� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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=1614542835.1414697 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/songsmenu/fingerprint/������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�021633� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9951859 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/songsmenu/fingerprint/__init__.py�������������������������������������0000644�0001750�0001750�00000006274�00000000000�023755� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9951859 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/songsmenu/fingerprint/acoustid.py�������������������������������������0000644�0001750�0001750�00000026013�00000000000�024022� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9951859 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/songsmenu/fingerprint/analyze.py��������������������������������������0000644�0001750�0001750�00000014663�00000000000�023662� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 any more. """ 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9951859 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/songsmenu/fingerprint/search.py���������������������������������������0000644�0001750�0001750�00000034721�00000000000�023461� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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"]: 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9951859 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/songsmenu/fingerprint/submit.py���������������������������������������0000644�0001750�0001750�00000015053�00000000000�023514� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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, Pango, GLib from quodlibet import _ 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("<b>%s</b>" % _("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" + "<i>%s</i>" % _("Fingerprints:") text += " %d/%d" % (valid_fp, all_) text += "\n" + "<i>%s</i>" % _("Songs with MBIDs:") text += " %d/%d" % (got_mbid, all_) text += "\n" + "<i>%s</i>" % _("Songs with sufficient tags:") text += " %d/%d" % (got_meta, all_) text += "\n" + "<i>%s</i>" % _("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("<b>%s</b>" % _("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(_(u"Submitting…")) def __acoustid_done(self): self.__acoustid_thread.join() self.__set_fraction(1.0) GLib.timeout_add(500, self.destroy) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9951859 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/songsmenu/fingerprint/util.py�����������������������������������������0000644�0001750�0001750�00000002260�00000000000�023162� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9951859 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/songsmenu/forcewrite.py�����������������������������������������������0000644�0001750�0001750�00000001565�00000000000�022036� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540385.9951859 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/ext/songsmenu/html.py�����������������������������������������������������0000644�0001750�0001750�00000004233�00000000000�020624� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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")) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540385.9951859 quodlibet-4.4.0/quodlibet/ext/songsmenu/ifp.py0000644000175000017500000000454200000000000020441 0ustar00lazkalazka# 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)): qltk.ErrorMessage( None, _("Error uploading"), _("Unable to upload %s. The device may be " "out of space, or turned off.") % ( util.escape(filename))).run() return True ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540385.9951859 quodlibet-4.4.0/quodlibet/ext/songsmenu/importexport.py0000644000175000017500000001472500000000000022443 0ustar00lazkalazka# Copyright 2005 Michael Urman # 2016-18 Nick Boultbee # 2018 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 from gi.repository import Gtk from os.path import splitext, dirname from senf import fsn2bytes, extsep from quodlibet import _ from quodlibet import app, print_e from quodlibet.plugins.songshelpers import each_song, is_writable, is_a_file, \ is_finite from quodlibet.qltk import ErrorMessage, Icons from quodlibet.util.path import get_home_dir from quodlibet.plugins.songsmenu import SongsMenuPlugin __all__ = ['Export', 'Import'] lastfolder = get_home_dir() def filechooser(save, title): chooser = Gtk.FileChooserDialog( title=(save and "Export %s Metadata to ..." or "Import %s Metadata from ...") % title, action=(save and Gtk.FileChooserAction.SAVE or Gtk.FileChooserAction.OPEN)) chooser.add_button(_("_OK"), Gtk.ResponseType.ACCEPT) chooser.add_button(_("_Cancel"), Gtk.ResponseType.REJECT) for name, pattern in [('Tag files (*.tags)', '*.tags'), ('All Files', '*')]: filter = Gtk.FileFilter() filter.set_name(name) filter.add_pattern(pattern) chooser.add_filter(filter) chooser.set_current_folder(lastfolder) chooser.set_default_response(Gtk.ResponseType.ACCEPT) return chooser def sort_key_for(s): return s('~#track', 1), s('~basename'), s class Export(SongsMenuPlugin): PLUGIN_ID = "ExportMeta" PLUGIN_NAME = _("Export Metadata") PLUGIN_DESC = _("Exports metadata of selected songs as a .tags file.") PLUGIN_ICON = Icons.DOCUMENT_SAVE_AS REQUIRES_ACTION = True plugin_handles = each_song(is_finite) def plugin_album(self, songs): songs.sort(key=sort_key_for) chooser = filechooser(save=True, title=songs[0]('album')) resp = chooser.run() fn = chooser.get_filename() chooser.destroy() if resp != Gtk.ResponseType.ACCEPT: return base, ext = splitext(fn) if not ext: fn = extsep.join([fn, 'tags']) global lastfolder lastfolder = dirname(fn) export_metadata(songs, fn) def export_metadata(songs, target_path): """Raises OSError/IOError""" with open(target_path, 'wb') as out: for song in songs: out.write(fsn2bytes(song('~basename'), "utf-8")) out.write(os.linesep.encode("utf-8")) for key in sorted(song.keys()): if key.startswith('~'): continue for val in song.list(key): line = '%s=%s' % (key, val) out.write(line.encode("utf-8")) out.write(os.linesep.encode("utf-8")) out.write(os.linesep.encode("utf-8")) class Import(SongsMenuPlugin): PLUGIN_ID = "ImportMeta" PLUGIN_NAME = _("Import Metadata") PLUGIN_DESC = _("Imports metadata for selected songs from a .tags file.") PLUGIN_ICON = Icons.DOCUMENT_OPEN REQUIRES_ACTION = True plugin_handles = each_song(is_writable, is_a_file) # Note: the usage of plugin_album here is sometimes NOT what you want. It # supports fixing up tags on several already-known albums just by walking # them via the plugin system and just selecting a new .tags; this mimics # export of several albums. # # However if one of the songs in your album is different from the rest # (e.g. # one isn't tagged, or only one is) it will be passed in as two different # invocations, neither of which has the right size. If you find yourself in # that scenario a lot more than the previous one, change this to # def plugin_songs(self, songs): # and comment out the songs.sort line for safety. def plugin_album(self, songs): songs.sort(key=sort_key_for) chooser = filechooser(save=False, title=songs[0]('album')) box = Gtk.HBox() rename = Gtk.CheckButton("Rename Files") rename.set_active(False) box.pack_start(rename, True, True, 0) append = Gtk.CheckButton("Append Metadata") append.set_active(True) box.pack_start(append, True, True, 0) box.show_all() chooser.set_extra_widget(box) resp = chooser.run() append = append.get_active() rename = rename.get_active() fn = chooser.get_filename() chooser.destroy() if resp != Gtk.ResponseType.ACCEPT: return global lastfolder lastfolder = dirname(fn) metadata = [] names = [] index = 0 for line in open(fn, 'r', encoding="utf-8"): if index == len(metadata): names.append(line[:line.rfind('.')]) metadata.append({}) elif line == '\n': index = len(metadata) else: key, value = line[:-1].split('=', 1) try: metadata[index][key].append(value) except KeyError: metadata[index][key] = [value] if not (len(songs) == len(metadata) == len(names)): ErrorMessage(None, "Songs mismatch", "There are %(select)d songs selected, but %(meta)d " "songs in the file. Aborting." % dict(select=len(songs), meta=len(metadata))).run() return self.update_files(songs, metadata, names, append=append, rename=rename) def update_files(self, songs, metadata, names, append=True, rename=False): for song, meta, name in zip(songs, metadata, names): for key, values in meta.items(): if append and key in song: values = song.list(key) + values song[key] = '\n'.join(values) if rename: path = song('~dirname') base = os.path.basename(name) newname = os.path.join(path, base) try: app.library.rename(song._song, newname) except ValueError: print_e("File {} already exists. Ignoring file " "rename.".format(newname)) app.library.changed(songs) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540385.9951859 quodlibet-4.4.0/quodlibet/ext/songsmenu/k3b.py0000644000175000017500000000402600000000000020337 0ustar00lazkalazka# Copyright 2005 Joe Wreschnig, # 2009,2012 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 util from quodlibet.plugins.songsmenu import SongsMenuPlugin from quodlibet.plugins.songshelpers import is_a_file, each_song from quodlibet.util.path import iscommand from quodlibet.qltk import Icons from quodlibet.util import connect_obj class BurnCD(SongsMenuPlugin): PLUGIN_ID = 'Burn CD' PLUGIN_NAME = _('Burn CD') PLUGIN_DESC = _('Burns CDs with K3b, Brasero or xfburn.') PLUGIN_ICON = Icons.MEDIA_OPTICAL plugin_handles = each_song(is_a_file) burn_programs = { # args, reverse order 'K3b': (['k3b', '--audiocd'], False), 'Brasero': (['brasero', '--audio'], False), 'Xfburn': (['xfburn', '--audio-composition'], True), } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.prog_name = None items = self.burn_programs.items() progs = [(iscommand(x[1][0][0]), x) for x in items] progs.sort(reverse=True) submenu = Gtk.Menu() for (is_cmd, (name, (args, reverse))) in progs: item = Gtk.MenuItem(label=name) if not is_cmd: item.set_sensitive(False) else: connect_obj(item, 'activate', self.__set, name) submenu.append(item) self.set_submenu(submenu) def __set(self, name): self.prog_name = name def plugin_songs(self, songs): if self.prog_name is None: return args, reverse = self.burn_programs[self.prog_name] songs = sorted(songs, key=lambda s: s.sort_key, reverse=reverse) util.spawn(args + [song['~filename'] for song in songs]) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540385.9951859 quodlibet-4.4.0/quodlibet/ext/songsmenu/lastfmsync.py0000644000175000017500000002631700000000000022052 0ustar00lazkalazka# Copyright 2010 Steven Robertson # 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 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 _ 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 API_KEY = "f536cdadb4c2aec75ae15e2b719cb3a1" def log(msg): util.print_d('[lastfmsync] %s' % msg) 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)]) log(url) uobj = urlopen(url) json_text = uobj.read().decode("utf-8") resp = json.loads(json_text) if 'error' in resp: errmsg = 'Last.fm API error: %s' % resp.get('message', '') log(errmsg) raise EnvironmentError(resp['error'], errmsg) return resp def config_get(key, default=None): return config.get('plugins', 'lastfmsync_%s' % 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 = list( map(lambda s: int(chart[s]), ('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 list(filter(None, self.charts.values())): # No charts to fetch, no update scheduled. prog(_("Already up-to-date."), 1.) return False new_charts = list( filter(lambda k: self.charts[k], self.charts.keys())) 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." log(msg % (err.code, 15)) for i in range(15, 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: util.print_exc() prog(_("Error during sync"), 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: pass 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) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540385.9951859 quodlibet-4.4.0/quodlibet/ext/songsmenu/makesorttags.py0000644000175000017500000000315500000000000022366 0ustar00lazkalazka# 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) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540385.9951859 quodlibet-4.4.0/quodlibet/ext/songsmenu/migratemetadata.py0000644000175000017500000001343500000000000023015 0ustar00lazkalazka# Copyright 2013-2015 Ryan "ZDBioHazard" Turner # 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 math from typing import Dict from gi.repository import Gtk from quodlibet import _, ngettext from quodlibet.plugins.songsmenu import SongsMenuPlugin from quodlibet.formats._audio import MIGRATE from quodlibet.util.tags import readable from quodlibet.qltk import Icons from quodlibet.qltk.window import Dialog # This global info variable is where the song metadata # is stored so we can use it between plugin activations. # I know it's kinda ugly, but it's a lot more convenient # for the user than writing and parsing temporary files. songinfo: Dict[str, str] = {} def get_number(song, tag): """Gets a discnumber-like tag that may be '2' of '1/2'""" value = song.get(tag, '0').split('/')[0] return int(value) class MetadataCopier(SongsMenuPlugin): PLUGIN_ID = "Migrate Metadata" PLUGIN_NAME = _("Migrate Metadata") PLUGIN_VERSION = "1.0" PLUGIN_ICON = Icons.EDIT_COPY PLUGIN_DESC = _("Copies the quodlibet-specific metadata between songs.") def plugin_songs(self, songs): global songinfo # Create a dialog. dlg = Dialog(title=_("Migrate Metadata"), transient_for=self.plugin_window, flags=(Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT)) dlg.set_border_width(4) dlg.vbox.set_spacing(4) dlg.add_icon_button(_("_Copy"), Icons.EDIT_COPY, Gtk.ResponseType.OK) dlg.add_icon_button( _("_Paste"), Icons.EDIT_PASTE, Gtk.ResponseType.APPLY) # Default to the "Copy" button when the songsinfo # list is empty, default to "Paste" button otherwise. if len(songinfo) == 0: dlg.set_default_response(Gtk.ResponseType.OK) else: dlg.set_default_response(Gtk.ResponseType.APPLY) # Create the tag table. frame = Gtk.Frame(label=_("Information to copy/paste")) # Try to make a nice even square-ish table. bias = 3 # Columns count for 3 rows, due to label text using space. columns = int(max(1, math.ceil(math.sqrt(len(MIGRATE) / bias)))) rows = int(max(1, math.ceil(len(MIGRATE) / columns))) table = Gtk.Table(rows=rows, columns=columns, homogeneous=True) table.set_border_width(4) table.set_row_spacings(4) table.set_col_spacings(4) # Create check boxes. tags = {} for ctr, tag in enumerate(sorted(MIGRATE)): tags[tag] = Gtk.CheckButton(label=readable(tag).capitalize()) tags[tag].set_active(True) # These floors and casts make sure we don't get floats. col = int(math.floor(ctr % columns)) row = int(math.floor(ctr / columns)) table.attach(tags[tag], col, col + 1, row, row + 1) # Create the indexing box. index = Gtk.CheckButton(label=_("Map tracks by disc and track number")) index.set_tooltip_markup(_("Enable this when you want to migrate " "metadata from one album to another while " "matching the disc and track numbers." "\n\n" "Note: this must be enabled when " "metadata is copied for track information " "to be stored.")) # Automatically check when there is more # than one song in the songs or songinfo lists. if len(songs) > 1 or len(songinfo) > 1: index.set_active(True) # Assemble the window. frame.add(table) dlg.vbox.add(frame) dlg.vbox.add(index) dlg.vbox.add(Gtk.Label(ngettext("There is %d stored track.", "There are %d stored tracks.", len(songinfo)) % len(songinfo))) dlg.show_all() response = dlg.run() # Only accept expected responses. if response not in [Gtk.ResponseType.OK, Gtk.ResponseType.APPLY]: dlg.destroy() return # If copying, erase the currently stored metadata. if response == Gtk.ResponseType.OK: songinfo = {} # Go through the songs list and process it. for tid, song in enumerate(songs): # This tid will be what we index all of our tracks by, # so they will be easier to find when pasting metadata. if index.get_active() is True: tid = "%d-%d" % (get_number(song, 'discnumber'), get_number(song, 'tracknumber')) # Erase track info if copying. if response == Gtk.ResponseType.OK: songinfo[tid] = {} for tag in tags.keys(): if tags[tag].get_active() is False: continue # Skip unchecked tags. try: if response == Gtk.ResponseType.OK: # Copy information. songinfo[tid][tag] = song[tag] elif response == Gtk.ResponseType.APPLY: # Paste information. song[tag] = songinfo[tid][tag] except KeyError: continue # Just leave out tags that aren't present. # Erase songinfo after pasting. if response == Gtk.ResponseType.APPLY: songinfo = {} # Aaaaaand we're done. dlg.destroy() return ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540385.9951859 quodlibet-4.4.0/quodlibet/ext/songsmenu/playlist.py0000644000175000017500000001267000000000000021525 0ustar00lazkalazka# Copyright 2009 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. # 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 glib2fsn, get_home_dir from quodlibet.qltk.msg import ConfirmFileReplace from quodlibet.qltk import Icons from quodlibet.plugins.songsmenu import SongsMenuPlugin 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(playlist.songs, playlist.name) def plugin_songs(self, songs): self.__save_playlist(songs) def __save_playlist(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("m3u") ffilter.add_mime_type("audio/x-mpegurl") ffilter.add_pattern("*.m3u") dialog.add_filter(ffilter) ffilter = Gtk.FileFilter() ffilter.set_name("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 = glib2fsn(dialog.get_filename()) dir_path = os.path.dirname(file_path) 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 files = self.__get_files(songs, dir_path, relative) if file_format == "m3u": self.__m3u_export(file_path, files) elif file_format == "pls": self.__pls_export(file_path, files) self.lastfolder = dir_path dialog.destroy() 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) 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): qltk.ErrorMessage( None, _("Unable to export playlist"), _("Writing to %s failed.") % util.escape(file_path)).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() ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540385.9951859 quodlibet-4.4.0/quodlibet/ext/songsmenu/refresh.py0000644000175000017500000000256100000000000021320 0ustar00lazkalazka# 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) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540385.9951859 quodlibet-4.4.0/quodlibet/ext/songsmenu/replaygain.py0000644000175000017500000005304700000000000022022 0ustar00lazkalazka# ReplayGain Album Analysis using gstreamer rganalysis element # Copyright (C) 2005,2007,2009 Michael Urman # 2012,2014,2016 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, _ 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]) column = Gtk.TreeViewColumn(_("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": format_int_locale(num_to_process), "all": 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 = _('Analyzes and updates ReplayGain information, ' 'using GStreamer. Results are grouped by album.') 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(["%s" % _("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") ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540385.9951859 quodlibet-4.4.0/quodlibet/ext/songsmenu/splitting.py0000644000175000017500000000421500000000000021675 0ustar00lazkalazka# 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 ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540385.9951859 quodlibet-4.4.0/quodlibet/ext/songsmenu/tapbpm.py0000644000175000017500000001466400000000000021154 0ustar00lazkalazka# 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() ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540385.9951859 quodlibet-4.4.0/quodlibet/ext/songsmenu/website_search.py0000644000175000017500000001403600000000000022651 0ustar00lazkalazka# 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 _ 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 = _("Searches your choice of website using any song tags.\n" "Supports patterns e.g. %(pattern-example)s.") % { "pattern-example": "https://google.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 ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540385.9951859 quodlibet-4.4.0/quodlibet/ext/songsmenu/wikipedia.py0000644000175000017500000000757600000000000021643 0ustar00lazkalazka# Copyright 2005 Inigo Serna # 2018 Phoenix Dailey, 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 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): tags = widget.get_strings() config.setlist("plugins", "wiki_tags", 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=1614542835.1414697 quodlibet-4.4.0/quodlibet/formats/0000755000175000017500000000000000000000000016141 5ustar00lazkalazka././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540385.9951859 quodlibet-4.4.0/quodlibet/formats/__init__.py0000644000175000017500000000153700000000000020260 0ustar00lazkalazka# 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 ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540385.9951859 quodlibet-4.4.0/quodlibet/formats/_apev2.py0000644000175000017500000001447600000000000017703 0ustar00lazkalazka# 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 ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540385.9951859 quodlibet-4.4.0/quodlibet/formats/_audio.py0000644000175000017500000011725000000000000017761 0ustar00lazkalazka# Copyright 2004-2005 Joe Wreschnig, Michael Urman # 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. # 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 os import re import shutil import time from typing import List from collections import OrderedDict from itertools import zip_longest from senf import fsn2uri, fsnative, fsn2text, devnull, bytes2fsn, path2fsn from quodlibet import _, print_d from quodlibet import util from quodlibet import config from quodlibet.util.path import mkdir, mtime, expanduser, 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 from quodlibet.util import human_sort_key as human, capitalize from quodlibet.util.tags import TAG_ROLES, TAG_TO_SORT from ._image import ImageContainer from ._misc import AudioFileError, translate_errors translate_errors 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""" 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) class AudioFile(dict, ImageContainer): """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""" 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): return (human(self("albumsort", "")), human(self("albumartistsort", "")), self.get("album_grouping_key") or self.get("labelid") or self.get("musicbrainz_albumid") or "") @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): 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 = {} for key in self: if key in MIGRATE: 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 list(filter(lambda s: s[:1] != "~", self.keys())) 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=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`. """ if key[:1] == "~": key = key[1:] if "~" in key: real_key = "~" + 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, "~" + 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("~" + 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("~" + 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": parts = filter(None, [self.get("~encoding"), self.get("encodedby")]) encoding = u"\n".join(parts) 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. try: with open(self.lyric_filename, "rb") as fileobj: print_d("Reading lyrics from %s" % self.lyric_filename) text = fileobj.read().decode("utf-8", "replace") # try to skip binary files if "\0" in text: return default return text except EnvironmentError: return default elif key == "filesize": return util.format_size(self("~#filesize", 0)) elif key == "playlists": # See Issue 876 # Avoid circular references from formats/__init__.py from quodlibet.util.collection import Playlist playlists = Playlist.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 key[:1] == "#": key = "~" + key if key in self: return self[key] elif key in NUMERIC_ZERO_DEFAULT: return 0 else: try: val = self[key[2:]] except KeyError: return default try: return int(val) except ValueError: try: return float(val) except ValueError: return default else: return dict.get(self, "~" + key, default) elif key == "title": title = dict.get(self, "title") if title is None: basename = self("~basename") return "%s [%s]" % ( decode_value("~basename", basename), _("Unknown")) else: 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): """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 = expanduser(rpf.root) pathfile = 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 santisied 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_ = "" 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. """ 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 v.replace("\n", ", ") 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 synthetic tag cannot be distinguished from a non-existent synthetic tag; both result in []. """ if "~" in key or key == "title": v = self(key) if v == "": return [] else: return v.split("\n") if isinstance(v, str) else [v] else: v = self.get(key) return [] if v is None else v.split("\n") 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. The sort value is only an empty string if the display one is empty as well. """ 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 is not None: 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: if scale > 1: scale = 1.0 # don't clip 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': devnull, 'artist': 'The Artist', 'album': 'An Example Album', 'title': 'First Track', 'tracknumber': 1, 'date': '2010-12-31', }) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540385.9951859 quodlibet-4.4.0/quodlibet/formats/_id3.py0000644000175000017500000004366200000000000017344 0ustar00lazkalazka# Copyright 2004-2020 Joe Wreschnig, Michael Urman, Niklas Janlert, # 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. 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 = 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 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 a 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"]) # lyrics are single string, not array tag.add(mutagen.id3.USLT(encoding=enc, text=self["lyrics"], desc=u"", lang="\x00\x00\x00")) # 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 ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540385.9951859 quodlibet-4.4.0/quodlibet/formats/_image.py0000644000175000017500000001474200000000000017744 0ustar00lazkalazka# 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 ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540385.9951859 quodlibet-4.4.0/quodlibet/formats/_misc.py0000644000175000017500000000634500000000000017615 0ustar00lazkalazka# 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 ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540385.9951859 quodlibet-4.4.0/quodlibet/formats/_serialize.py0000644000175000017500000001103300000000000020637 0ustar00lazkalazka# 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) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540385.9951859 quodlibet-4.4.0/quodlibet/formats/aac.py0000644000175000017500000000237500000000000017246 0ustar00lazkalazka# 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] ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540385.9951859 quodlibet-4.4.0/quodlibet/formats/aiff.py0000644000175000017500000000135200000000000017421 0ustar00lazkalazka# 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] ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540385.9951859 quodlibet-4.4.0/quodlibet/formats/dsf.py0000644000175000017500000000150300000000000017266 0ustar00lazkalazka# 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. try: from mutagen.dsf import DSF except ImportError: DSF = None 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] if DSF: extensions = [".dsf"] else: extensions = [] ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540385.9951859 quodlibet-4.4.0/quodlibet/formats/midi.py0000644000175000017500000000205300000000000017435 0ustar00lazkalazka# 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"] ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540385.9951859 quodlibet-4.4.0/quodlibet/formats/mod.py0000644000175000017500000000430000000000000017267 0ustar00lazkalazka# 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] ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540385.9951859 quodlibet-4.4.0/quodlibet/formats/monkeysaudio.py0000644000175000017500000000173700000000000021232 0ustar00lazkalazka# 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"] ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540385.9951859 quodlibet-4.4.0/quodlibet/formats/mp3.py0000644000175000017500000000233100000000000017211 0ustar00lazkalazka# 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] ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540385.9951859 quodlibet-4.4.0/quodlibet/formats/mp4.py0000644000175000017500000001765700000000000017233 0ustar00lazkalazka# 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', '.m4v', '.3gp', '.3g2', '.3gp2'] ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540385.9951859 quodlibet-4.4.0/quodlibet/formats/mpc.py0000644000175000017500000000336500000000000017301 0ustar00lazkalazka# 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+"] ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540385.9951859 quodlibet-4.4.0/quodlibet/formats/remote.py0000644000175000017500000000262500000000000020013 0ustar00lazkalazka# 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] ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540385.9951859 quodlibet-4.4.0/quodlibet/formats/spc.py0000644000175000017500000000435500000000000017307 0ustar00lazkalazka# 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] ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/formats/trueaudio.py0000644000175000017500000000125300000000000020515 0ustar00lazkalazka# 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"] ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/formats/vgm.py0000644000175000017500000001130000000000000017277 0ustar00lazkalazka# 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"] ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/formats/wav.py0000644000175000017500000000250200000000000017307 0ustar00lazkalazka# 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] ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/formats/wavpack.py0000644000175000017500000000156600000000000020157 0ustar00lazkalazka# 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"] ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/formats/wma.py0000644000175000017500000002072200000000000017302 0ustar00lazkalazka# 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: if final is None: final = "/" + total else: final += "/" + 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 ["", ":" + const.EMAIL, ":" + email]] for subkey in emails: key = keyed_key + subkey if key in self: try: self["~#" + 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["rating:" + email] = str(self("~#rating")) playcount = self.get("~#playcount", 0) if playcount != 0: comments["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 'rating:' + email in tags and '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 = [] 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") ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614542835.1414697 quodlibet-4.4.0/quodlibet/images/0000755000175000017500000000000000000000000015733 5ustar00lazkalazka././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/images/Makefile0000644000175000017500000000330500000000000017374 0ustar00lazkalazkaTHEME=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-png $@ -w $(shell echo $* | cut -dx -f1) -h $(shell echo $* | cut -dx -f2) ; $(THEME)/%/apps/$(EF_DEST): $(EF_SOURCE) mkdir -p $(dir $@) inkscape $< --export-png $@ -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-png $@ -w $(shell echo $* | cut -dx -f1) -h $(shell echo $* | cut -dx -f2) ; $(SYMBOLIC_TARGET): $(SYMBOLIC_SRC) cp $(@:.svg=.svg.in) "_temp.svg" inkscape -f "_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-% ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614542835.1054695 quodlibet-4.4.0/quodlibet/images/hicolor/0000755000175000017500000000000000000000000017372 5ustar00lazkalazka././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614542835.1014695 quodlibet-4.4.0/quodlibet/images/hicolor/128x128/0000755000175000017500000000000000000000000020327 5ustar00lazkalazka././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614542835.1414697 quodlibet-4.4.0/quodlibet/images/hicolor/128x128/apps/0000755000175000017500000000000000000000000021272 5ustar00lazkalazka././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/images/hicolor/128x128/apps/io.github.quodlibet.ExFalso.png0000644000175000017500000002241500000000000027223 0ustar00lazkalazkaPNG  IHDR>asBIT|d pHYsetEXtSoftwarewww.inkscape.org< IDATxyUOUw'Ig;{: ّd%YbD!EpGq@D Kb a@XMIc ԭ{k[N`~>{Oݳp+M7/r%*-uٮWgE?Ɣ/@;r*K?|P)o͇֑r]Y =~ZW,ʥ=fๅJDN#w+NU_6T{ݲw ;FK#rݦ,-tx :~yEQ6's$nO{i+D /,-T;N:5S7+\7ڪz;pɻ0n5U7Z҉BRϚbLU5 U;֬˧]?wv!g_4 HOU#( T-U}FUnvC-C楚V ο rQqc~vTtS_1bO3oC@/Q\q |څS% LTqZDhSU &n  8u}fEE;йWEauj9u;@+"uYg|8^p.C"̙3^׎*F=$ 3k [a(Q]}gRLPӫ `DՎ Š>[GϗWB)//FEEEՓDde.y˖-kDY j`ϊDP{ ABE~SOD2墾'̸i*|TbC}jb|ͨ8oд[brԋ"_8t“6>^^jt'ڠr_)75I͙c=ZZicnuٝ>#VɃe'n +Zd!> A_Ǥ>S~kSdS;nUA-rF}(gqY Ǐ [҉LO>x3g xΊ_d1mE`+_`ݲ2}|C~1@` u葛nlgaݨm"C~LϲhWmؓS(KPUHF!Gs'Yu^S`*Dz rX:$̲,/D&;QjARuȐh;U1gV(uUj!r7}(gfsh۾)u41aؐAa+Y > CB~È>nVռ*2OLxuH:KB?8 \fx9_ ºt9wPc FaߞwU햗`j>*cXiv@ԧyãQD Zt߮EDC9yޯPo|7Ö;غc'@k Ma >N,4P-LMv7-;kS@3^}YmY*?ݳT4zρυw+G&s@qT2Kym tfkPo36@ /zM ~Mr6\1TPtjj,JRyiZ>]$m۶ټeK9DЁ&mp1/uGϕ)^?ySϢ(jEP?Sث=RvKD/"S0'j+tW0HsWI~B m64voJM'QG/1h4]{Fʀ1hjc6'd4ka7f[D%q7V?eeaU8g(J7r\tG/wgW V_m>$0pB{d]}S>/0(YU~n)u?bPXgG}|jf}fc x,V<ƪ%oϩS8S~a<'`M(v35`;-xζ>ݳ'O,'dɇJcA}:{çf?UU}dSHQ>s_WD$po+J* P}ыoDBmc{ӏ`~ihzǍ@[bPf[\2'7|*lY=01kbQ_+[ G";r+Ot߰y h縶K7?꽴e | w"DeBrn҉/AG/"mK#ޏX0^AûlNi[_ի$Dx^D6(6vA~~gH2ш>˅<ql}FL rdVkx /d^AK9?O fq9rfU٫M#|z"&><v;#^F\*9.XnՊr51.pP9k\Q# X(3U{ߕ襪cz8UTҜ <{ӛ?J[_|IU۠d0CW{ꨣY˖;6 {ZZ^|;z鶔/gC Xܚ!Ly 0"ȋhS`B}i߮ҼR|l %:CB:Mԕy߿XV "r}b蘝2C}z˨]t.ԓl1:Imk;bp7z[mae|_}r}P)fH/xx^y/Kݣ+I4+Pp{ ac'΃/XLJgL?nA~2Ly:)CtROn߹?,\,K-n#&uϳ1o,FLD\!_Tmw/F㤳 Yʧ^Dd!&"?͖P:.B%oȚulz-6{wvǁ9;s]Oi ߎ|D}0/QE, T]G]QQFء#]t[UWwb` ĘQ#fbU\#"?'s!tNSӁUdvLclNM*Oz!S"urX8ơMN25|}{O^t܉V"Ϛ 0p< ]2+cGXW}`!Gj.d /Xbq޹lj'RQ !}p7Mio*nq!λw8xhBƷ, ^0_E^kJ$E!GB"h/O;tg wW<q.b PZۼ[3s|ͣg6U:qˏ"7*}8;  ښwPBTot#'r"o,?AضE}N:j?~""W>(zM因UEEܷT<>x1,1~}lHQo_sn5>d|u>RAčbP2~̼Ve74с6nxL;nT4YOq*J'0% :sFy|b.yEq 7ig۶bx?qwޣ'CdQ TV!R]: )iy tn3?9HAbtCjŽ[^ݚ;i=ez7~ Ŕy|4[ԪQ,Y,x7p,:@1apn4H91/ <)XjҞYv,^~SE 2(.K.XORȷ-Q?bQCW:H ;t9zg80gݫ/R~eMF^e3_ˮ={|Bh;h|Q']lAhݾs#oX췀cުpU 6WlG϶-:wfɃQ٦5g]I|k c2ݔ1WEuUpS.V,ה1Otԉ_2ųyNr|r*Ɲ8-JP)ߨMlҮ~Bq-?;To¸1\KC콪m;Z.ؐ9x.Yv#K}3lȍ`Z#q4PKx=e ο*/̫//M[:^L/W&sk4ˢ-w/5;ie\Q&tY:[%|ܳ6v鵲ņ|pqԮp~-xSYzP *' Q~6%t{؞{x'Hvu_#U$@1TQ@aLwuQ--l?ѦukADF:pnxv!ԓg ꪬfg=J@%B>l\!?/^Z0uS6?' x'?&ReDϴa!TLZ!?Qԧ2$8LA/^2v0mj+(:|3)(%{PrUͺ>-_*=ePw&>ʳ(w_|f2F9s2",Q2c,ɧC7{-JA퀂LJPy:FV`[" z"z¨.m[Y>jpj,94@q"6yFޝ(LeG}OP ǰnm% qPoMM9>3ʏ*rQ~I2z/iK92K9ɒ5][=s$ɓGMQ:ԻB>};wj]HUtGr~7 -֯_]l}/5Pg*çɨ*?z8H'6/fqG/@1N(XD·jF:޲>)䧾g57emU1\zqI<`߉-3mD}3U֗nÆ601 ^SP[_^ Cj c@bOw(+, nq\ "9w,*^Bۙ+Q.'n(7wwI{*7c0 ap Cwh˖𭜷2mGQKPTe߾ڝ 0ɇiTsg2'#/verDZ-EnOTo?ȳ>`\;yիR @dc.j-ibX,C+>w?8qw,;ޚr7 9ߐ;^?9Z(mY}ֻRވ,jcfd3bˁ2rŠ^Dhݺ5Nw K&s`[W86mZ%%A}*}RibJ 8P~1dȐ!HCAxLfeLrTD3;z̝õ_z w[&Or-fSsΡD}+}3I\__U\~a0DF}Ta|S.['oொ/,uhΝswl۾ Kw/ 1SLV-KTSSQutIC}h%B-gNkG`wٌG BY+s1zQ?Xp]̃ oヒ ?`D(6d3Tܽ?gƘt=zP3j#fpƏCr^=qG6)~,qذ_xu7P[[˚ukٿ@Z?mc%c˶2qc~IDATy2=Ļ4RDs`2zOw*Xn5|(# eؐjʈaCо}l;5%nZ)\ܗ6&⾁{{XW[˫ c]z)d?KI'T|OD;@ULB^,ЪUƍɓ2&4PUVHI6cqVrtwWrճ\^zz,KR?pɶ-&O-Xt2j*GP/ݪr9gѳdʤ Mچ'ǁ'?hlT`q"QYGeU,\.d޽XqȐ#wYE$fy;@'t*T#v+}vFwpmxXsQ!.{P\g0aY ,^~}X۲Dlݺҋ/6oAd W u{UHSU=JV4VUԪ_|:5j}{ޥ_WsUȕjP UUtvԯgyFO; mۮQ۶mڵk*_c{uͅUGQZU=T jPUJUizBHUUuO{_^Xkvm[mۮ.ZQUkr y9SqjBHbTUOz_R}}Tc͖֔6 ߩj%Z@EUM7VrcZBTV_loB 97^k&q+Uu08B-B  @IIENDB`././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/images/hicolor/128x128/apps/io.github.quodlibet.QuodLibet.png0000644000175000017500000001042000000000000027543 0ustar00lazkalazkaPNG  IHDR>asBIT|d pHYsetEXtSoftwarewww.inkscape.org<IDATxytU?n 1 < ( GQ;>3u7AFatFゾ"78(*р*,]G;t%Iҩ}[w[ M4iҤI&M4iҤI&+d?g4C |osz}H9TNvW2 # }QgEt]@Ÿ\ d! S#K׮w®IJ`Y6yׂP~aZI=hwP9?֪pu+w&ﮇ7v环_F=ÃG z=~Ǭ?PYC$+c4 <_V}KJ=twm`n!<ĝ|utf&qwxڝ4 &O. {KoS_f箯5UZ /z}.K4  O۝둟0lPE*o<Ύca|k͆Y޵HZg尛sYW0p@D2*e36mيaT֦!K%G\MMDIZɪ#PUTQϤq}pPxDPDJ|8`FfFƺ/X94G5>3|Ib@\QG"ZcEd"E*yTDcFp;oٛ/0:H#s;S$,w&MMM)"}YHq?yf~  7CxG4d6ͩ {g#os3g;T`gF:I@ڵ8PK7 ;ۃu9Q$YUwBW^lcoF띹g~.-|ݡU57Ѳ j鱲PU]32Hu1_z Lg!$sޖ&*HDR "{ssW>K>aWW4Mƃ~STuLBIHv 0؁Gpnڅ;;{cκbܸdGMxf@$Ҟ&%= 0탪O[P]xЁO_ln?C4zNRz!PaeΊGLJ("&U fW̜=wnZ?|VvNqy*7ÛrxDtKݪx8gc8gcz'^y׽I͗Mjn>x𑾽K2^}cC;="@;Tu080}yokdgm-?HVV&yT(gHe}= xU̾/CrL+:)Wmzp)p3Pa>ߧ)g;?5&\HJi^e e4@#""򄈌7_0/|t`\K6OO Ŀ" (M{~pAB+N'3"lkIz?v}wҩj,w~I`jYDQ:'}Gg2p9d+=sv$~lb 1ܔ̿~ۿ@UmCةk`v$5ˡܾ2UkN7P]olx XJY#1uQI̥~= R0[|s}5_IU'9RH;^აGzOG r@ :<|yC>s xTXY-dG@= S2T;n|K˱50|F0U@UU.La ط?թk^^9F#PVqۚ@Cy~F}c^n}splӢP]\zfjv>ҜRU= o9řpDcǛ̗v>yJ#oB4J Qm4/C[I{3 ~\#B:ɦM0en$<5ܞ5h[CD곛yR5+ÛbtZx)PGW}ďkܙN_o0qFk3h@%` Z"@z&5 [ h%˻f+MU/x^ƞbmsV@e5ʝ*hU|a*cFbާN\#@aiQ:2s&G]1CZ` "1 JQK#τyyyL=+zB$\j>0%c."XgR\\d?E Li40GM ނzphqQg}mS!{}M?nAٳϏ݊[ X[oAq5MX VSҋ3Z~^Z"x(un7H˙hr1{bл= l? ?|oZ={6wpO!D;ܔ+%%,b.k58z x7y饃<޽dps_VbMW0)[%68}idgٳg/u)kV3|ذX("v%,"O#"ͪ1lX'so5MHwC ag9L* 1l P6ʨQXl)EE>3=q=x>2^a%v/"5m5pM@7 xWl?>jH`c9Lii)?|<FDV'ng #l^zc=_.= lݺucɒ% =\ L}͛7ccG/ex"ϔ)Sꪫb%ypgnIq*++k؞u_FpO N,XkG].X1SF;}&"uZd$5kVviŝի'NvkaI1;hMJ>n@LN?h 4CqD$j z9S~F5ŠA(((vz}GѤIQv$7 j-UΛ:IQʊ:?dW -{uÿn@& 333کcJ&D,ک?ޤ|ˋ6YDgGDß9s&߶Qi:̜srr4''GKKK[oզ& CU=#v!$@=z̟?I&5g;D:I&M4iҤI&M4iҤI>?0}GIENDB`././@PaxHeader0000000000000000000000000000003200000000000010210 xustar0026 mtime=1614542835.14547 quodlibet-4.4.0/quodlibet/images/hicolor/128x128/status/0000755000175000017500000000000000000000000021652 5ustar00lazkalazka././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/images/hicolor/128x128/status/quodlibet-missing-cover.png0000644000175000017500000003740400000000000027143 0ustar00lazkalazkaPNG  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`././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614542835.1014695 quodlibet-4.4.0/quodlibet/images/hicolor/16x16/0000755000175000017500000000000000000000000020157 5ustar00lazkalazka././@PaxHeader0000000000000000000000000000003200000000000010210 xustar0026 mtime=1614542835.14547 quodlibet-4.4.0/quodlibet/images/hicolor/16x16/apps/0000755000175000017500000000000000000000000021122 5ustar00lazkalazka././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/images/hicolor/16x16/apps/io.github.quodlibet.ExFalso.png0000644000175000017500000000154000000000000027047 0ustar00lazkalazkaPNG  IHDRasBIT|d pHYsItEXtSoftwarewww.inkscape.org<IDAT8[HqƟossߦmt-͂Y:ZR*tQTU7]uȢ "D-L)ee9`n~;|.ryx[VI4?tjk3VIʂu0|>מ\7`8;|xn3iV xkcOGnUL5;E)r捫>hQ`(^uھcĺ8KElwnAR@GGGb c @<9)?5y)hѨCQ TjUgC(tg sʲ5_)us14OM' %5| Bjۻ꼁+筆ʍH)knsmn^7c+?Ro8 :mCXo$^W[1Otm ށjK{E-9++޷?N1'Nln> 8F,MԮwGffn(}^%;&D$O&A?Z'(xIɖMgG3-XU7|7944h 3Sں@ tj=)"*#Q,--55 U\l ""/c>3LIENDB`././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/images/hicolor/16x16/apps/io.github.quodlibet.QuodLibet.png0000644000175000017500000000076200000000000027403 0ustar00lazkalazkaPNG  IHDRasBIT|d pHYsItEXtSoftwarewww.inkscape.org<oIDAT8M(qǿ).IKPGZ99\\rrsvgMZcVy_'BIۻi%n#) <[ G6wH~bVo3t;4 v*u95,M`aR lwg c:g}uή;8308&eTr`0DrdANUU@ @k$'FoHczBtݭ6șaDFIENDB`././@PaxHeader0000000000000000000000000000003200000000000010210 xustar0026 mtime=1614542835.14547 quodlibet-4.4.0/quodlibet/images/hicolor/16x16/status/0000755000175000017500000000000000000000000021502 5ustar00lazkalazka././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/images/hicolor/16x16/status/quodlibet-missing-cover.png0000644000175000017500000000163600000000000026771 0ustar00lazkalazkaPNG  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`././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614542835.1014695 quodlibet-4.4.0/quodlibet/images/hicolor/24x24/0000755000175000017500000000000000000000000020155 5ustar00lazkalazka././@PaxHeader0000000000000000000000000000003200000000000010210 xustar0026 mtime=1614542835.14547 quodlibet-4.4.0/quodlibet/images/hicolor/24x24/apps/0000755000175000017500000000000000000000000021120 5ustar00lazkalazka././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/images/hicolor/24x24/apps/io.github.quodlibet.ExFalso.png0000644000175000017500000000243700000000000027053 0ustar00lazkalazkaPNG  IHDRw=sBIT|d pHYsmhtEXtSoftwarewww.inkscape.org<IDATH[legvfJ[ln˭r)0"B"5|'1 ECCK,n-E""ҽJ(~aw>x'dw9a7~w+u̬YiG/q_'5+3 :Rظkm{|"9|BO*Ag]j,kp "*_5{G:tm[:#, Rd=EڽɖE0Bx#KB2% UE*"RL٫V.K wxYzs`B1?󿒢"TW() 7;&.`8 du,,cef^DTr5X,EH-)u'%qFU\"255oR#NYJH B$\J >{AG]qiBc4D5DIa,^tq7d x,[z8tk232J-a /3g8:TJu],8ߕDvf&܎϶]Eܜ1c:dӊ+3,r"x)ȴeb w xtGg_&ҘXDT5tplm6BLL96˴u6xkCC#zL+ѓ,yD-%܎6&n8M?.oi9 Vm&3xJ bƎ-hXvruoۿ DtB=4%S5U q"Fk9?%%?scl,˽;MZU˔9!{KЖtNs]e%X&9a?TK2*w 5Eyl_1K^ݽu?"gfjtp876kW8AD@hۿ|7 i~~zXGwww3kDd`[R_q}{ V,p4"?6+] k׮ $ {?a沙bǘYEI!ElSZKWV6E`0BLEXBDsC:e3޹ޯMe<suF$,ohI(-g? Z[-Y/X$࣫ ֖4"_H>yjY;چR75%!A!đ5{*J=\ӁLrS39[sx1;=:/ *! &H6aB!ĉ쬬JCjQ˙gI&H^Rs+eF^C/\q$C$foߌeb_'i3=%VP&T95=@Z?%\uR `r^QQP];2^ twIلQu߂?H9x?s̵;uvu&"Ylb$QI,H8xÿ{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 ;Ӌ=Q1 *"*JG.4i~s_r{Ͻ9w;wf>|Ç>|Ç>|Ç>|Ç>|Ç>|4M3Rm>̜UV6-/Aiu b;K7Y:l<}8,x_fy'_cGU@ٴiy \jqGÇQR>7*w[m֭#DQ t:Z@<zU,sҏ>CA#{(9Q$foڲI?qdzxUR/Z?>|8Cqň#` ,oŊ3Nr+qG Om̚O>|F灣3Y <~+@i5U n E|a5gɄP3Gv`՟۸M<UZi:e|ؐ\s߇@cJAeG (/_oߎ&غ .gY U&ϜH>|4ut0 aʦ?# /~;}1\`in&4 AU@=ʦ̨tC+F;Jǂ~j33 S.^ƕtzeJh'P1^->|4Rp. A ̹p"zJ-Z^\9xs{@cAĿcnO .a~0m̚.>RN5Q |X>(q7|< GZ脬cO`Ɠ lYw`')P%{eBفo]֬0O_q5w/uUGD{l,TTly6 յz_k췫fV>FʂZePxO] j6}|XSwU) [YkTo |x-5_!w-#qtzlp+wM(6L{=g KlRQ%Q w/@j}JLllP)=ѡenVH0 C}7 I_))H8On~OILiY_ c~q8 `p> dhGwp]*ƴ&x,?&^"CH%ʲD4ݮI`.-6krf L&ٙ}D;Ѥ#2(0" ɨ2]Y?ύW_$k|Ϯ0xOPڢb'@s>E>,PV6-Lc&_ V+9v b傹h׶D^]vEHjWRmN|5;L֛-***rO䴟_ t +2 %Nߞxܤ$IOfCa}D22Y6fN mG2QdqP倬@Lj '~ Ld`PZys> DT7 O;?.3ذ頬lZ^m3 BӐ?gyy9^Zhn>cq;fHz_(4 +ӚUŖf߷ƀn#Tt¸@a4q/Y?&g7&5x+lW  z-4?#zƭ.FM.aL_4?KCuE1vrw# W /h¸@α,u^7 mٮR2;VtsnӎM x.`Dz*ӷf: =d *PaMջ(*lxf$(=1DO)Ruis͓ՙA.c4Cm@3 C@Mm Y?zդ/ &Q]a+'0ZR,χ򆱪g_}ز.c t:tpZ)12γ4GG0P 4gI"U-VoqY:Fz ZP @c7N#chm[Ӊu'NCN$8 |ADX-_}iG.R6:o90k`}sNK:ս_8ngS¾ZO4Md}itYn]: n?Z_ȆD2H#KSjuł_ضS oMȯϟ_6jZk:E^[ ,I.$%IgT\ߤ ^+)MJ8 \ַ/hKHjLmaÆHI>*+a|V 6ZlrJ%Y2/0v @Q*Sʃ_i$F ÙSjl4\c}.Q&r";T+Y Q!ɘAS+)PjY_Z(FȓSvu,! g\C~Z]2Wr ̈́ۻqIC 33JΠ v!2a^E>:# R¯hm\aˬ~mO8eܿx׽<  # K)6%ShCv^J~ ۷#Mi}h+]&lW;>̝lmm)X̣eR^"+WmLև ;3 D :Eް~}&}A[buf\ѧ->_v13$i :8~$F8eݟۈhxzyKh9c}igгe}4rJc39eG$ G@9" GτK}ޱ2,#/RZS ȔJɹN͂_%jl,tU]\57}lxyؘr1a?3h]$ 2T2kjsиy`UrsNSc}c3NWވl̮,B %_`썮lG<|7g__o{#vEf >lOh,79o9<Ϙٵg6lX!;$>_wM5ogN_>VѱCXo+AW+T'Nu֗) ~.gNiCN9|)&Jč} '#ijYbE7f~y66~,O-{̐ Xo,߉"/sXOxsʏ>ӌx]}3r5R]L4uF]&s~o#"( a}N묏RWC;Xo8 M:ŠY_%47K̳dMX_K:~ ]E  FbP|=L.CEXߙSBӍ)wه= /~ Aa0p&)k ; Wh K116CM+֗e~5McYY'.N~mOL`MCtτM_l,3"!Z,X_lؔNIBO:~YzOT -7GIbj4@K$t}H9͜;H4Nmphe؅# )b}2<%4ahJ2;›{m|{脕PH@D J.MK:c3 ֗Sn۹G;@gПHh7Is((Lk K2,hJ>KY9ke 8pN)KbMpo &?ʊ2(d|!1N V rԲJۙ3sJE b2Ci#MXmMao(_SG#^ҴF;fے'>2hX_#ᚣ2I&M0:~i!,K_}D;Q:XlIa@yԡ!/zFe{G\N);XC]z G>% `,LIX_gXװ!TH f#}Uo-e뛱̐8Y_ɓ&K sz9':ѧo`dggcb{ŽHR& u"Yg4F!w is:~q2];h,_[v@&ĤΚ!o)T}zB'2M*e #DSh6 EGd$?)Re,u6Rf6$cڹS:a}打_I`feR=R : z׎=BlۈK{>{ gY LZf.As뒲aq|um$=Cɒ9 . ~YH@VVFۨZkv  kOi"ϒfVN)`YN#vN: EQLGYĤg/-/˂_ҧ#6x x^%2(_o3}f( N># @b>kַNzˉ>3*ǏڣHМ2PNk3֗9OX_hM`>j5JK+ OF 뼺gI@2;n!-< M&F@U$OX_C֗'c'L5ԣ͹2^H\yl/iA6m0uɜ41?ukX/>e}Q6,3wj}f7OVC~56elZR@:',if]Btʨˬng Xh#/w!OSn!m;RnOIY߰khu7gCF<%TLPЦƏ%S*n!m@6a}gNv Maqxk堀/0$XI/VLbh.f{]A7 `g 2 :S b}3B8-_"(_ lE{s*ް*%r]ϐ__N~!\tGƸq:U7:mqY-UZl!Q*hW65w2maל.d߿f^~)dj`$$ @nW8uVtSuUe}M)7m؇6l3`D^e#7\S ַ ~#KHa}pUyM `y@$YF0a2* 72t3ar_l$32 oS)Js`@/-a}yթMY_K@9vpm ]A _ F_[l6jg2jV5ua[@׍^-S `/X_(t\/ ~p b>GB*c4d۬/K=3 mN *"2g%2")6Kx9a}%ե dp2b]9}X_է@W$\?JUk1 4uB8|2_"g]ݿ/~[PQaNJ"#Da~5F6OP=# VKe#yv{RxމI NxMk?q{AM47<3S)Gp῾}\QF^!YV$pQ~G'cq8X^ŋ |gchBq%=]X)֌9CRg'תsigR`ꔚ`~ӽMm U}+#q#_PWW+ uŷW/z?n.G 3ԷQkPɰ|G`k㦤QbUH\ǝ-[Б>]`.L IDATToq&3- 2:Ci4@'xM L K񳾾y0g}gSַs%z x׏"ٌץ˭?5 C+m'T+3la72kKePM2a?K&Z7e d 'Eؽjy=o1ﴰ[7u"@ o\1KI$#^Q"`\^(zwqNa鎮8b]WsD);*LtYID4NDN#T=¬]UNu*gh+sX?_o,xڶŕ_\p =FG^'` VWoOe|ͺC2v8wru3:@ ?f7Ǝ/;xp3$07p+X5ض3was(*m/3I߬Y>J{WR,~3b8jNOm4<$Jlm-:pq9cp⫓8qd߯NWpZFX?\fжMiimڠm6ء ۷CQBu(DqQbJD\X9:Ko S& C(@C0-^|KH 9URߺ\{h< I":jcAO_u!\Elt*ߎȔ<|7~͚9~t6T~+ %@_gH૓'qŜylQ7ftGW,+<={e C66XID{RiX2': . +hٿ^?z1)wM{rsU]p1տ0C:?U +3kqGr/;+y5N1[%/7F Q pBoՋ[ܱ 3nB:M?m{0a4edlc<(37^ ,6{q҇ 6^[s&">? wXf틧Ϝ.}[7\+ 7?HC~!?1BOnIt2]%q#77hKIeeey' S;'6:۴i͛unYm&O)DAZ!w /0@g V{l[.Yo>.c 01 S2KoWsĴIY]mVn ~pm X!J Q\@ ӅaD+lO"̜UewW%t" A:P- n P 8 !MZW'~{Ͼ.Ioh81b>ʄc%1&a%?CJ{~^ |P18@Ya#?RwY?TQ}Yîyf(&ukxӏ]4y𘡊|Bմw~¬/1| Wlk˒}(8r a`r(E< ~uOȞퟛh 1%AEyUgڱ.ڧ`j҃U}::vk]fgZfrF: }=a}X:Md}>#wtq%ar:z3ZhX_1>/~P Vyh4 Vy s1)RK D_~^ZjCs &e}i݂@m552 Rm(;UNn$ QGa}P~IS.wt'l<'1gо][mc.qϳ$3TP޺ ¾Fd2>Mm XkuL>!ST'{c҄q(Qgrss4bFK扅U2Y|jf;sLγ{6n1y52 y]? +]ŭKm$v lpҹ:u?"d}] ɁMt;Dړ3szdt(0;vs~\YQW}^Ayشh䱾ֱ[~L?fm ~uc鏌2`Ԡ ^OK4NVaᛳ:~+Lv9ҽA0J퐊d599clۼL1seeB/Mɺ1 doU7~Mk<$Yg)2oϨK~E*.*p͚5$BiLg`PrY_P)c*&]:wj.q{o`eIOc LM8p]͝Jf!oȸСbDBtYVd}@9X[2YuD~|J|j.踟_s*3/$q `hn*%r]d}y]θ%F=  ,!E1c};$z={?cafBF%!KQX:R)e/kI]lG<ٺE+#%f+Yw6XJP'6!iƜyV4H+dT@rG3vd`};Ni'`H9v9ixm':M,mPO H@؃d'>M}y\A1 ¯n-jI2b1cX?\j3iwe} R0 /E rmdJ{u~N)L i#ldrv!]\`}gIOs{Wp.SrEF$#P^h71krJYnOKIgyZwǎ荵}{%uY?V`4ח9roϝ./tRdD' ]O'l1t/gK#E|q2CETRO/=ς -3``\S כ_ ݊I>t0+iZK & OI8R4x@i:ADkEY^eIs'GˬsGO%=Ög/@.2]Z; {?V{(pd!-ĭX0 ɴͭRֽ9ΞS9뫝~#L@@ؚ 6/A*R[DDZ&&Lm͜Re.++ -[ˆ`$ j.XEbeA%|Oq;2֬AV-X^ڭV:gZGtn丗\cǏ+i4;5@s ~:142Vu҈֭[K`cxYVL"Ѩ?XBW{KP`X?S;uJ= Zpn;B*KόUSmJ;j'ַJ4>CbZ'"-36K`k~Q֗XR+щ>ml@Qř"DX?ܧ/6L%c6vϗ 譭n",0Fa}U 7I4o`H̰Z A`UP;9o=7")HСb@[^3֏)MX'"sб>Չc0KD; XzRlH(cjU%"]x{OOtj:oo``:~-q^eE(i24u1}{~ϛA]c}^PץlַJ4K+0ltE /6/&UI/3S0ˁoKէSv(,4i PpH!>4K0?=_k_ȬIIH@YYYKL%}9FX+ҧLܻ"!.6l}2]Z; {ѕ|#%+߻w=*3zHp:9 U&YY-}ΣE,9@L q ƛ`}.Ud}qgŶd^!mDX<'}r9]Rڳ(vl `&sUO>=" ٬Ni:X_X7BҿVքDX?ܧ͒KM7J4 ~UQ̙3سgѲ / @ 4L,gHJKub[dƌ4"ȪY!oOw,̿dՌ[Ha E*L!13sJѽ;td;Bzl:D#`'Xgorun֏;n7m5bұHL,/KX? ƏA2I .% ~x<%ioM/Q̶vi-b}:~ ivʉR {)γ!KX*$y|kܸYHX_*!HC~Y?R׼EsL`DRϳ/$]=$ }ZLWHOlV&R@IoVN)S&tyf&H(U `l1ԻV98b}'NA\aMWHy~Ǟ3so)>N} q!o@ @IMz&=X_YLUb,3U'E ~[1DN])qGb@ۤas`fٷ}Hyy{/\ GGuY5U F ual(dn# @l']-XL] Wl֗$=ݐ?"}w%ÀC66sO薳i>Y]LN8pc5׵3a}̦@!3cH}`%EsY tZ/jW㲋ba&hp|5~>Ve}B\dbC~X__f6I%]yH*d}.ghۦ ~L1`a+)X?\e͆MIp%IoV )M j[|GIu&r֏8c=⎶?->+ll=0ndo$H>Tq 9rD \`F'钳~۾u qe&v߿ f<-3e:~Y:CXu$64An(dw]}[>0^p.C[y34Q17OF܇V~ A4% ~N)Cr'N9j0<#;;>xR*~QÕ Z)u8uRY_:V&kjiAj'C#([ duHw*dɐ_FĬA˖-䶋D}ɩ?{0Iv^alh=kKc}q$ HY((RFosևf/5]=Zh.O~Q<8|-.' VBt't':3_޹kjjjd-oV&Ȥu΂"ј)1(CDK@֭s#tLuV6KU+ 0>d)K ).C2auU?*cٸ햛$Yb)mNݺv }7mnX_%&e}.gD/xG`kI')녾{O틾{!?dYBr&=6&̽ ~]63c=ؼe36l܄͛`MظiNqfO(-е0j(uj"rII*JfH9[]eۻ }{B^hiox-0s`ׇgƍyflذ1$!&ǼsŽh!8 lE<_[geeg) ` Wn;yx\":b{2 g\jA2PѣX ^+WªksΈ5:;R?_ߜ='ORWKD9^'Ы3w%@b˜ј0v4F-"+U8`7  W Cp|'pb,^7nJ5>l-Z^K7)[8T(Ob…,ZTZmIǗ^|ӧOW]@D ݱж6T[𧿝~~>vA%.6S*Gfi3IgS> BoJIM 1" o^~< hC K555xv[d2(Uvmo~)lí;D$^/1a>˾=wR91 mP`#B6:"ڑJ|fn`B`BY_E -(!"_PQ[T˫̤O]w ?| OhW6Q} "4T 4@D|2<èk.yyyp@O7zh߫aG_ |b,U|Y ^m&fT#𛉨.I6`SXr[ 1h"w@eevC L? n=cçf!Nd#|,nlO/><3Ch & }6 #0a~mdgg('ne+՟ {FE {?aÄߴbw8~a滘{ׇ7ecf^wsÏ<­Z[Gx)=² {Wtυ=+,+cf~0sJ^iÇ`a<3שKKK5߼ysnѢϝ;7"]ث|Xa'_Ciշܞ:#3f>2\3ш۷NjHEEErJf.v޷GaulߣðXj SfW}h2`V#f>\__<h)УG޾};3ߓf\=+6D^Ye拘Y[-ɂ fef~wHGQo]tiVسG_X<)<\1ÛuÇ0;3_pYY& L8O:uCjeݻw˂ xѺzJ?̀:R[3^f왱>|4b0ӧOky|H\r>.n聙1s ?`"ό pҘ=p߇fbGzAJc:2)1ȇFfZX̹6:CV3sIR ᣉ!{.\:3`Aʆ">|410sKf~W'K:/$}G32X#R)|,C>|D)+U< y$=ϕpL&I>|Ç>|Ç6/KIENDB`././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/images/hicolor/256x256/apps/io.github.quodlibet.QuodLibet.png0000644000175000017500000002205700000000000027560 0ustar00lazkalazkaPNG  IHDR\rfsBIT|d pHYs;;̶tEXtSoftwarewww.inkscape.org< IDATxw|Ɵw7@%RD`A@Qܫ 슗v`XPx"VDH3@("ґ@y&ݝݙٝmg/sμy9s                   wI 8R;\.`nC \8?#pa;k`<=bV6n2At.&Uț ࢯ]|aGbЦY2vͣxr?{%BAN?$hk31euuC1"P8`X+0< ޱAO5j!GӆCD3;?4Ulx#CӋK9 ?{km1/'& p͇ OD x]>y ;ēۍ\Ms*r]]'"NV3e 6hٵt#Rm8Hʹ3NqlGtP >؁K?KWFeeUm&{ם +JN+E#e O#p)5ÆS8x ,/,ZÇ2A_.3IIh7\Ua [6C\:;Ceo0坹Xa'ц="~N2N/r!%>N_ѯ 1a,4ox\ҡÇi?v2 )@hT9(U;7Ț4]!<'շW7̈ $D-кY,_Sʼ >Ϗ=0I+%B )жcū ^OApp=?oF|<qpJǃko"\x]38F%}=~9== ];W?e庎Ђþ{7(eH@=Ē9Nf KKVDth[tgh?i6\{õ+ /3- AYl{ ` .0t&j"DDhu(m&Wh<j<Yet};O2kuB_HP41|ucVVk@]OD" h!]vdQnN6Уk'Kfbذ{|I9`t3&n]+U?` ODfzbcSڊk~[o-X! \ oV&*N@Dܺ٭ή=оYbo ; U'"Sv|75i`%Cg +P"4l0/57e"\fNzO|S <좫&& Gf3.`5ΊNHp૏>Ӻw;vz3 n9~Qe~NXGk17@ϫٰe̜rBR3\AfY(^":hQVY~/[>tfNI9Xp ( <+xO[XQP~+fl5䝻o3sFBLBǐ9fPXQQ^{ǿ̜`|jEM"s̩R4D0 7- >#.-_|5QE"% `ݢ7dՙi&x+*+qi>̛ q?p=3P % 5P, 7^t*<7-}U&b;@C`波,|sZ阑ﳶ}/_V}TfnC;#ъCZ Lfn`W ʁdyK>V<7D=XhrjEJ0k40K$ M >D{W=x.j,pWoBnq8P!Hu~\L7ina?_~$Ƣb\qP `!];k/=8X^w=&N| i~,>c ' `ÜlTHROo/Ad*x6M0t w;TSp D,$)m^&;ELĵqmwA_<1h;-8RG 3#/?z:+$G O!͵U3_js`h_}@^9 ܱ`f>ޱ/ ĕ7/+ܺ985, X=.MKCISZ4A}YiXBb_ձۆyB" 0s1O507 }ā+Zqo;tѪ Z_#0w\6 IlBj.+?Qw?~$T~d ?hknkKZʶؔqȝ\jQU'}\@_r^]~qÕ-L$f先63XOTˏc/o]2.ȍ8DN0#됧1@U o5ѵL5(xA|OHsq]I߃:r<}K5 uy/b:Hp]~;NF_&>XYE " P{j^~wߵt\w" "xO} He EF@n {yb!JH9@DS vMfxcxѹ}If}k@hL?>> OV_H+ 0yqu>C8G|xTCX^`Lw.a)1X]oϛ?>j-$j^nÕUY0wKH "Dbkؾ-y} ~i\yhתeTY8ωwa's2[6o! h3A70Fг+zul߹ [֖dfCaku~'qH[WƇH? p+3 `*v7o!OÐդ'm܄`8p<P'+YȫGvm਼=[x@"&D r­~^=8Xbm[<*Dth `qɋ_A@7!%p"AD³0F`W)v" @SWX8Hh&x $D"ODQ_<L/O] #D @4Z׬ki22 Ch;7>. %v LJ#3Duef5PT1@u@!=0s]x @*KM izIZ,^!UH` ^QHR+HED/XC @EPJ#,&7#bJ!FSM;ukܚ{5?XsA1+8Nj߾}4ePE :aEe%KAf*cZXf2-w f̦# $ (qڒ#o9;1 b*6!6W{b8p`/0FGUuO5@L9 m۾㟝/)|'nN^w˯Uk{x2b*bWqll_r߯5+UU}>`V=T>5azR|Kaw92ib ԆON;J~Z &=ػO1RQTĮqd~w4VgW'RP @\RfmAqA1%&x#HqkUUGidxM^$B @E k 2;p0|'2xm a!$ }-KT>?]T<ͱO5]V8}/_D&{{O2N0A @AC]J9]|!ڤF @En5 ~h}%y˫S[xSC @Eo.H7٧&L}&c}FL]0-'s*^k7S/Ibb"xFM`7񤴴'uÄ{PYUU}`&37QI@*kB&:.Nl+Vٗ1 5iPH%Vaؾa`|d|jÜykK3G܈(H4 1.`4O ÇqwWOf 3-'bʓ\gWyf~%?.ûg SMM6D x0aҥcS Oȑ#x[61F @EH~O)WM&xaBƦ-akoWd?(`SP X -av&?yD4LFԄo_C'Adflݶ _`T )&bjO:X_OFmfUSyӐ14|rU0W"=>|Oc<h1U#$h--b(}?`Սd泣jR!$fGȩ J<5܏Ԡ%f@11LMA`eXj o( V]sD#dB @Ul!zjmC)}[&T#(f"xAdk]kG><4Tϭ1}dx,زeK<;O̪=D+DG @A ^I~%xJ7m={ۢs"#"fON*?C ޠ6n4@~g}i:\ґ(0Vo7!pȅoݻv[:%gJ @I$3s4ɀqT_Tݘ[:l *\6@DaO!E.pԡMFz^dɋhoh0sdfdXDʽ]X @E^ '0? ݘP }kFo  5jCN`4t`b>yfV/r{!?$%hLնfB ?yV/s@C&M1k.-Om -P xF1!+}?Di8昣^J @H~ؤW/ 'sjԩ#2-g3G %"t2vF9Bqw˙nbJL&ySz[6@hT+sj9%,$ *\U 8Bz\n7kbJϏ!{ aKXo'Gn_(;]k' ( 1ZY@_r5 ~6Ś|Yv.B!"b g{V%1n\8._^;T@ @Id!ר`<{sZhRb p^O^~k|3!x.~e }%;\^4_$Ovv UF U0Y@O;/`:wYnUg%) bjb}܆M.'d>qؘؼE \8|a|d*WvVŃMngpZ ݃ [U3nUP,ڴhQ^ّI 2KBmiһwhJ|g*(9t!y"+XÈ=?@0=dOkr\Õ E}]_ïᖛn@Qvcb@Z9HBhРAJ%V;6gd.,OQ1SPTjѾ}fޞ}VwACNl$[CSR 1e oC4{Kc3 0<DGwNkJ(f; ۰=̧m{U^~j'|=?\}ՕxuT';#DE&m;Q"=w߅1^ >#hS$ᙧe&ӉhS$k2#';: <3d~pS_ דwfݻ,krQʽbbs]m6xolk.h0~tBP- <oM` MrBUa@1nD0,lv4C )9̛;i`p}& ?a^?7`ԨcήgJUFTJs= ٤YoI_'HVۍ?#GZ)P ywH9996m4B?mvbP')h(^OA̞.?flpmrT@ @E40Lua64ӶIxжm[ ׳/p2X ѓХK{hڴkb3d(x彽lOЯ Go>#SOgO46"P&6|=, o67 @睇Ann#K\LD8UGaf" D|РW1H^u] &r %DJSi(mቀƁn O>@f*ݬ7|M~_;p;MJDNV,xGe Soڤ9me?{Zhr׏.PLH!2zh<΄a6DGZ*RwƍFD/9U1%aA@gСxꩧkz*̑G Io޽{cpݑVU ^}EGZbioxj oFM@XBH @Mub֬YhܸqUP$/bj58q"=H`xe!O j>\pA$U08z2IDAT!bjx Odffo߾KDG.b y/@xN:5! пpp(B P[ ":5! Ԑ=zS=cbPCQQQX  мyp y')bjV@^^^8G2 1zSlqC @Mº#gggSlE8@ @!̵CbB a.tBPhε@ @!}nF @!''nh!10 h!150\GH$,hԨk|uA @e˖v/'=ъE bu֨["F+!vGݻ-2n!sN$B,>N*ZC @Ml=~vi;"!!P-V3믷DTVTB! < >|}| +np?AHtgggGnxƌ|Nf~%Bⓟ~A޽[uԩk׮nw. F,?AAAAAAAAAAAAAAAAAAAhryIENDB`././@PaxHeader0000000000000000000000000000003200000000000010210 xustar0026 mtime=1614542835.14547 quodlibet-4.4.0/quodlibet/images/hicolor/256x256/status/0000755000175000017500000000000000000000000021656 5ustar00lazkalazka././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/images/hicolor/256x256/status/quodlibet-missing-cover.png0000644000175000017500000011717400000000000027152 0ustar00lazkalazkaPNG  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(@`3 DTN&흃ZSɿ<ԡ=P]CG-IEVVMu\<UPHt>yQ':Ƀ$F1fZ$d3_<Dܷd],.YNVdg,-)z Gɭ$qE$8QSS38S\VHV~RӧOdaŧH,/H,KXIENDB`././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/images/hicolor/32x32/apps/io.github.quodlibet.QuodLibet.png0000644000175000017500000000177400000000000027403 0ustar00lazkalazkaPNG  IHDR szzsBIT|d pHYsbb8ztEXtSoftwarewww.inkscape.org<yIDATX_L[U?rAf0ΨѠf%σRc2‹ò`|e/bKӘ(:861ʬW |}0RfA'GVp-q`!nO9lP`WvyБRBsT'hW綋ߎ ɩڟ^{q+Dy >&"n6=QˬqM`kmBWӳϛO<9ٰ(P=@R^z3sI3И>ov*I\=iM?r"P15u"$y}#HTZ)*`qd] 'W^VƟ&'.u\pɫ7mz*KM(؄+@7DdOP9 n$I Ykc)^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`././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614542835.1014695 quodlibet-4.4.0/quodlibet/images/hicolor/48x48/0000755000175000017500000000000000000000000020171 5ustar00lazkalazka././@PaxHeader0000000000000000000000000000003200000000000010210 xustar0026 mtime=1614542835.14547 quodlibet-4.4.0/quodlibet/images/hicolor/48x48/apps/0000755000175000017500000000000000000000000021134 5ustar00lazkalazka././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/images/hicolor/48x48/apps/io.github.quodlibet.ExFalso.png0000644000175000017500000000533100000000000027063 0ustar00lazkalazkaPNG  IHDR00WsBIT|d pHYs  tEXtSoftwarewww.inkscape.org< VIDAThyl\wf,,^xcYdk!P hE؊!em! "TҊR5-Adl, @H(Il'b{x<3o #Yޝsw}MlʙVH6aܚ%Ǟ?qe|[\q_ t =Ʒc/H J KᲶlm _ղC_t+_X/ >~xXn|]=Kƍ9ceִe;%3U{|: Tʐ^l;[%Ƙ}P#!j)Ck]Ӵe[H%5cEȆ@%0~MϯW>:ncJ,UK/y]vOAb,lb0OozbS^,ѭNhV Xy\ۀEܼ*v)8% h Yݠ{Zq8'=?nUl>@R6@ x* ҺPⱵF:p`X$Cvv1}Υ+_zi' Ir^DQ(E Ϥt%5VӝKBr,{dAw<_8}N:y,݄lQIvT4cF$lKœpwݦote;o\waU(At"Y :aM{ݹ㦖1mdgmJ_-& ˶zùSۃjI0guRM}}YֆK-Jt#GgWW8 pv{ K+فk|9c)@;RBo1Ύ#+h?n:>S-Ll 9scLCs P]jU]]= X.64qyث(} ?M0&[nYLe%/o]=LMNI-T >i]ͩRN[8`7 7Hڙ}M-lfW]hdjvIY CAx<Ƙ+\n@k{؛X#-(/UVno(L ܟT\?>x->`1qX;_ٴ}[vG^~y4& `srr䐛ϧ[iSkZc~;QH`ҥ@MOn~{u`oS30YJE Hey9˖,b)'S^:P`T'1UE TD,~swʒh8 =p}j$|#HܟK 9N)h>x,և4c 7~Fsss (}213rzX(fUgWdR0x7l|E O>ƗcSFM"tr==<̟J_;E5#8D?-Ƙp :sdaOc#Xl$1ko&eGfDɭr90 +N4keuwVvDc"`H=~v"7KA(޳Kh\.gHwW׭.s9d47Yvd TGa$6mp/ÈXp]ejZ omk(qᄚNSژX\-? t=zےo.҅/ա:a"`ʨLUe ܣxzT ᚫ^7agvFSQ~D"455X] X[ Q: 7Yˊ+/ʺRpmϩqkk7u3W\3sAg&B Q]Uɍ 'xoh4zk7.ٳֶ6"RZ"%Kkc@Qm}ƷI 1@OQ(DaA98eLZ|k%WH6Ib vUp6"]]n_iiֽl{MRqt}cዯqճj>pPk͒twCH%m[RxzwO .Tm4jr+!MRjzWq<>Vo$}WR>͍P$=!i]ssse ^׵'̬.vhBմ $.Wے4v&iV^Ieeݸqc/@OmREmY%ߊ$φ V<製fMJ"iWo&iΠ//4pIENDB`././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/images/hicolor/48x48/apps/io.github.quodlibet.QuodLibet.png0000644000175000017500000000304100000000000027406 0ustar00lazkalazkaPNG  IHDR00WsBIT|d pHYs  tEXtSoftwarewww.inkscape.org<IDAThilTUδ3 E-ZSl#RW0\bAA1jE  [.*k q[QH+m%B[:^ CFw:j“d2{spSŠ+o2-a7<|$ M]RN#pIbܐF{!.z=bP<+ ]OL G0WzPFX|mCwκ,?c뺏YJWV~~-9R1u^e}@e3Ztߜ%i.9: [\H@ "ID"櫯TY>-bpڒ^zIltnAw}*J"EH^`+:z" <9y" $5֓ =4w#3J"}Cϼړ Lr.˒E)cԋ\DZs}g^TήD; G` fҔA5Ϙ^!\ "]E. ٵW!(UU@HaQ'ՀF!m~KI4@G'c4ci%,>!˜B%.+0@с65YCNu"a6^7/!YH}z<I5ɾ%,o'?-TP &;}kos{VDǹJ Q>|$oVƑ{^&f|mmƖDm߹ 7m}de6ZΕ&KHf?i󇆆6q&@0f`~ 0v nvv&g![Kbp78'8CߴH9Z% TD<.<&QJ `ƅ cK/6F ɳRb˓c@oچ\ j"< `XBPdLmYr%r?#/D"z$̣" v 4Op $OX7EɬߍlPDI`R GH 7ܠkV p"'[H8`Q0 %P! Ü_WeɆ $p TH0D0@0ĆaH֏ῐ2ԔnܐO>[ZZRc$HNm|L`+VHЩ7u9#e> qԩTԝ_KGvޝh~|>qQVWWCD \xpDz|BoD$ `Y, 3f̈PsCmmmMsswm?8E~ -S|IENDB`././@PaxHeader0000000000000000000000000000003200000000000010210 xustar0026 mtime=1614542835.14547 quodlibet-4.4.0/quodlibet/images/hicolor/48x48/status/0000755000175000017500000000000000000000000021514 5ustar00lazkalazka././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/images/hicolor/48x48/status/quodlibet-missing-cover.png0000644000175000017500000000770300000000000027004 0ustar00lazkalazkaPNG  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`././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614542835.1054695 quodlibet-4.4.0/quodlibet/images/hicolor/64x64/0000755000175000017500000000000000000000000020165 5ustar00lazkalazka././@PaxHeader0000000000000000000000000000003200000000000010210 xustar0026 mtime=1614542835.14547 quodlibet-4.4.0/quodlibet/images/hicolor/64x64/apps/0000755000175000017500000000000000000000000021130 5ustar00lazkalazka././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/images/hicolor/64x64/apps/io.github.quodlibet.ExFalso.png0000644000175000017500000000770200000000000027063 0ustar00lazkalazkaPNG  IHDR@@iqsBIT|d pHYs+tEXtSoftwarewww.inkscape.org<?IDATxyp\ՕnfeK`dYޅ70`LL<II"PL U3CX&El0^ ƞSƖ-ɲEn[[}G~Sۖ*nYw}=WUK4Ӵ5Wp L\\3u}˜MzE7PI&:<\]YZ^~z ꑌsIdig ^-YtHp8}$Z'iUG*n_ ;y֎8:O֓}vɧeS"+ޔ2M[a$+K*1Q`M"Uad=9.~({~*f/F&7]YwV˗M)SlacFEYG0ʺeD'j+t\KO.y9!Ο16wKm_H:OlJ+D}%m7 +Mj2pSXfQ[{,tnv^ս `Ɋi($[a.K[ܸ48kӉ @x!"`|G V08ܺaܦ$-D<(^xAGW@hH ƏFҪKac{r"t,5:}m&E+t>-}+S+.M.'EV #'t~[a1,hLx0`JuOkES~yy?]|4R=b'[T?K# gjjE{6nB@w yO4H+YgJX *jE孰x4-9-Zgxru,*Jd+ `ӷ/w5U};wk佾+N?i})TA~~ijG}@2ڶ 5[{ ڰ |yY p=&}>֗ QUUɲ瞥ix xx4+W,٫oW?0Ht8J@?C <3&}CvVc  põp׭kC19#$Vomݹ7{? ;㎝ qu>xYq EE;qꨪqu4o|lP"c:N$Qnnʀ\;d*s{|u{V<﹛0fDQ0@|1fDc8%MRmPi7_]s+9pQ>v,?\sNx$~vcwCѓhƘOZ[[ =f:d{Ƙ 0_zlYR`&X ]z%0nh=| g6^1&j0Ȫ4H:s.F#a,Ch'ٝ%Ł=w QP֖oE# 9B˛hdgEdR^t`iWWW'vIL{ys=b}c0'}_޹Hwm dub\ukgƻ?o;{)s҄T6Dǃ/-'>Biq#);pkY! c -\xi! mZMHc*O=f_}W|Z'z#J"w8Xqif!M!qd]q,b.t>7q #U!1eE7^Ri%9p |n(D[zݷϣ{~;T_8x OO&,\s`zʧ+*coo{ R%EjloͦBPauF*: ɳCƘmsVsWX; Tp8̫ x qPBɺW+}XjYwLeW{y -t~GbdȺDUem$\${+۷o"zҌ B2t:JdeeQSUFeщ oSk(aW{{S"2Y3qy0Yx0]5%@e=`0RA|V@8ӭ2rBt߬;5dB8f$Om;$sD9vp` >(N^ M/Ñ?_sCASٵ[xHI;&M ~Rt4F4V&a:P0k\c$~e^UX" }hk JV^F˘uVTWWqϝcNwON߬]zIaJLh4 0wTT &/> ٟ:::I[MnClaO ].΢3LB+++hG ?G;;׏i5}z_YYi* sKÇYf5ą#HyS>b{`%6QXXȜY}mLk4"cLg&ߒ׮_O?S-h}>ۋun%Ƙ il?T:peˣ P0ĤյׯPir/wun $ ]ת^^ ۷o'>f``<+D7*++X Pq 6@",rshi1)[MjG}D!bCbV޾O~F6mDGgD"E%+ֿcLCP4P-6u5Ձ%q5]0ɓ}| %1&6}&&GQlaŊKOOV̢^/*ϙn97r1[L>I;$mkIH4I.HڜӺt njX~|\Lkl7}AK-i$5ؗ$I-[zꩧI*⊦M-w$d%H/mJg}`ii/_zeMEy%.YW_ڟITbŊU-3"#i;KZt]"9&iYuV["}8$E_2IENDB`././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/images/hicolor/64x64/apps/io.github.quodlibet.QuodLibet.png0000644000175000017500000000413600000000000027410 0ustar00lazkalazkaPNG  IHDR@@iqsBIT|d pHYs+tEXtSoftwarewww.inkscape.org<IDATxZ}pg~~ܒ IK‡Nc#"%300PHC:*iGF$VtPp@i)RB#$*dWmPZH) .>%\d晻}v~dwŸ0kEu9# b&vJp= NIh 0rbEl00šQ@=.9t6\OLL{m4兦Ƭ֖L :'ܻuug% 3 QhS>7q{gasM-6T`{,& EoѣM~(V$,\{)0r惒-]>Ze #wO.<:K* #O"RDf^d7 2%; h AP9mo^$"]Q7=af@) Y3MzY.ÌO敝xD<] g@}HP $KHTXVAa&,\JKS #y*XB^. --.}D_/yyv1/Qfв0a0Is= _ZpeŲ_!7=94|]/Fc*oL^g{e6ti0+(+6i隠%@OpyCnx?!YR^@kY PHTF Hw5A@D-ϠbNf`<;$<,I*Zd ',"@` ۊ=X[Ou  VTVo.@D Ĵ4i>mf@`ߡWAegl.H0@!a\<yVP }A;^2iH2-)߼VoqqEѿjѷozͣ{+&/ZZv3I8 PHb@?O;Q%#XEYÍ@p=g?57l%v5*RAh:qxi<<w2Z r,LKM*|'NE$Yw,LZ hiny$b(CK arG(%V*juC[{`3nZ?:TDz0Zia&`*0*YiQ#ۻɠ<øsKGwWP*)" *nN ~\ .n`}u2}&vCl*zÊwҠU [)HFfַT*?!RRPXZ.+ox22gj/J_\R},"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`././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614542835.1054695 quodlibet-4.4.0/quodlibet/images/hicolor/scalable/0000755000175000017500000000000000000000000021140 5ustar00lazkalazka././@PaxHeader0000000000000000000000000000003200000000000010210 xustar0026 mtime=1614542835.14547 quodlibet-4.4.0/quodlibet/images/hicolor/scalable/apps/0000755000175000017500000000000000000000000022103 5ustar00lazkalazka././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/images/hicolor/scalable/apps/io.github.quodlibet.ExFalso-symbolic.svg0000644000175000017500000002033200000000000031662 0ustar00lazkalazka image/svg+xml ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/images/hicolor/scalable/apps/io.github.quodlibet.ExFalso-symbolic.svg.in0000644000175000017500000000605300000000000032273 0ustar00lazkalazka image/svg+xml ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/images/hicolor/scalable/apps/io.github.quodlibet.ExFalso.svg0000644000175000017500000001432500000000000030050 0ustar00lazkalazka image/svg+xml ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/images/hicolor/scalable/apps/io.github.quodlibet.QuodLibet-symbolic.svg0000644000175000017500000001452400000000000032217 0ustar00lazkalazka image/svg+xml ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/images/hicolor/scalable/apps/io.github.quodlibet.QuodLibet-symbolic.svg.in0000644000175000017500000001157000000000000032622 0ustar00lazkalazka image/svg+xml ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/images/hicolor/scalable/apps/io.github.quodlibet.QuodLibet.svg0000644000175000017500000002203700000000000030376 0ustar00lazkalazka image/svg+xml ././@PaxHeader0000000000000000000000000000003200000000000010210 xustar0026 mtime=1614542835.14547 quodlibet-4.4.0/quodlibet/images/hicolor/scalable/status/0000755000175000017500000000000000000000000022463 5ustar00lazkalazka././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/images/hicolor/scalable/status/quodlibet-missing-cover.svg0000644000175000017500000010427200000000000027765 0ustar00lazkalazka image/svg+xml Missing Album Cover Art cdrom missing artwork inlay Jakub Steiner ././@PaxHeader0000000000000000000000000000003200000000000010210 xustar0026 mtime=1614542835.14547 quodlibet-4.4.0/quodlibet/library/0000755000175000017500000000000000000000000016132 5ustar00lazkalazka././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/library/__init__.py0000644000175000017500000000322700000000000020247 0ustar00lazkalazka# 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 from quodlibet.library.libraries import SongFileLibrary, SongLibrary from quodlibet.library.librarians import SongLibrarian 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() library = SongFileLibrary("main") 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() ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/library/librarians.py0000644000175000017500000001714500000000000020642 0ustar00lazkalazka# Copyright 2006 Joe Wreschnig # 2012-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. """ Librarians for libraries. """ import itertools from typing import Generator from gi.repository import GObject from quodlibet.util.dprint import print_d 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 = {} self.__signals = {} def destroy(self): pass def register(self, library, name): """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, name): # 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, items): self.emit('changed', items) def __added(self, library, items): self.emit('added', items) def __removed(self, library, items): self.emit('removed', items) def changed(self, items): """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): """Remove items from all libraries.""" for library in self.libraries.values(): library.remove(items) def __contains__(self, item): """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): """Iterate over all items in all libraries.""" return itertools.chain(*self.libraries.values()) def move(self, items, from_, to): """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) -> Generator: if old_root == new_root: print_d("Not moving to same root") for library in self.libraries.values(): if hasattr(library, "move_root"): yield from library.move_root(old_root, new_root) 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) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/library/libraries.py0000644000175000017500000007462300000000000020474 0ustar00lazkalazka# Copyright 2006 Joe Wreschnig # 2011-2021 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. """Base library classes. These classes are the most basic library classes. As such they are the least useful but most content-agnostic. """ import os import shutil import time from pathlib import Path from typing import Set, Optional, Generator from gi.repository import GObject from quodlibet import _ from quodlibet import formats from quodlibet import util from quodlibet.formats import (MusicFile, AudioFileError, load_audio_files, dump_audio_files, SerializationError, AudioFile) from quodlibet.qltk.notif import Task from quodlibet.query import Query from quodlibet.util.atomic import atomic_save from quodlibet.util.collection import Album from quodlibet.util.collections import DictMixin from quodlibet.util.dprint import print_d, print_w from quodlibet.util.path import unexpand, mkdir, normalize_path, ishidden, ismount from senf import fsn2text, fsnative class Library(GObject.GObject, DictMixin): """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 = None dirty = False def __init__(self, name=None): super().__init__() self._contents = {} self._name = name if self.librarian is not None and name is not None: self.librarian.register(self, name) 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): """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): assert isinstance(items, set) # Called by the changed method and Librarians. if not items: return print_d(f"Changing {len(items)} items.", self._name) self.dirty = True self.emit('changed', items) def __iter__(self): """Iterate over the items in the library.""" return iter(self._contents.values()) def iteritems(self): return iter(self._contents.items()) def iterkeys(self): return iter(self._contents.keys()) def itervalues(self): return iter(self._contents.values()) def __len__(self): """The number of items in the library.""" return len(self._contents) def __getitem__(self, key): """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): """All items including hidden ones for saving the library (see FileLibrary with masked items) """ return list(self.values()) def keys(self): return self._contents.keys() def values(self): return self._contents.values() def _load_item(self, item): """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): """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): """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 not in self} if not items: return items 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): """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)} items.", self._name) for item in items: del self._contents[item.key] self.dirty = True self.emit('removed', items) return items def _load_items(filename): """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 class PicklingLibrary(Library, PicklingMixin): """A library that pickles its contents to disk""" def __init__(self, name=None): print_d("Using pickling persistence for library \"%s\"" % name) PicklingMixin.__init__(self) Library.__init__(self, name) class AlbumLibrary(Library): """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) class SongLibrary(PicklingLibrary): """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) def destroy(self): super().destroy() if "albums" in self.__dict__: self.albums.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 != "": songs = list(filter(Query(text, star).search, songs)) return songs def iter_paths(root, exclude=[], skip_hidden=True): """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 (fsnative) exclude (List[fsnative]) skip_hidden (bool): Ignore files which are hidden or where any of the parent directories are hidden. Yields: fsnative: absolute dereferenced paths """ assert isinstance(root, fsnative) assert all((isinstance(p, fsnative) for p in exclude)) assert os.path.abspath(root) def skip(path): if skip_hidden and ishidden(path): return True # FIXME: normalize paths.. return any((path.startswith(p) for p in exclude)) if skip_hidden and ishidden(root): return for path, dnames, fnames in os.walk(root): if skip_hidden: dnames[:] = list(filter( lambda d: not ishidden(os.path.join(path, d)), dnames)) for filename in fnames: fullfilename = os.path.join(path, filename) if skip(fullfilename): continue fullfilename = os.path.realpath(fullfilename) if skip(fullfilename): continue yield fullfilename class FileLibrary(PicklingLibrary): """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=[], 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, add=True): """Add a file based on its filename. Subclasses must override this to open the file correctly. """ raise NotImplementedError def contains_filename(self, filename): """Returns if a song for the passed filename is in the library. Returns: bool """ raise NotImplementedError def scan(self, paths, exclude=[], 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) \ -> 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 """ old_path = Path(normalize_path(old_root, canonicalise=True)).expanduser() new_path = Path(normalize_path(new_root)).expanduser() if not old_path.is_dir(): raise ValueError(f"Source {old_path!r} is not a directory") if not new_path.is_dir(): raise ValueError(f"Destination {new_path!r} is not a directory") print_d(f"{self._name}: checking {len(self.values())} item(s) for {old_path!r}") 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}") # We need to update ~filename and ~mountpoint song.sanitize() 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}") if not i % 100: yield self.changed(changed) if missing: print_w(f"Couldn't find {len(list(missing))} files: {missing}") yield self.save() print_d(f"Done moving to {new_path!r}.") 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}") try: del self._contents[key] except KeyError: existed = False # Continue - maybe it's already moved song.sanitize(new_path) self._contents[new_path] = song return existed class SongFileLibrary(SongLibrary, FileLibrary): """A library containing song files. Pickles contents to disk as `FileLibrary`""" def __init__(self, name=None): print_d(f"Initializing {type(self)}: {name!r}") super().__init__(name) def contains_filename(self, filename): key = normalize_path(filename, True) return key in self._contents def get_filename(self, filename): key = normalize_path(filename, True) return self._contents.get(key) def add_filename(self, filename, add=True): """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 ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/main.py0000644000175000017500000001531200000000000015766 0ustar00lazkalazka# Copyright 2004-2005 Joe Wreschnig, Michael Urman, Iñigo Serna # 2012,2013 Christoph Reiter # 2010-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 senf import environ, argv as sys_argv 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 = 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 environ["PULSE_PROP_media.role"] = "music" 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) 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() config.save() session_client.close() print_d("Finished shutdown.") if app.is_restarting: os.execv(sys.executable, [sys.executable] + sys.argv) ././@PaxHeader0000000000000000000000000000003200000000000010210 xustar0026 mtime=1614542835.14547 quodlibet-4.4.0/quodlibet/mmkeys/0000755000175000017500000000000000000000000015773 5ustar00lazkalazka././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/mmkeys/__init__.py0000644000175000017500000000725000000000000020110 0ustar00lazkalazka# 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" ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/mmkeys/_base.py0000644000175000017500000000242200000000000017416 0ustar00lazkalazka# 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 ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/mmkeys/gnome.py0000644000175000017500000001327500000000000017462 0ustar00lazkalazka# 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" ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/mmkeys/keybinder.py0000644000175000017500000000311700000000000020323 0ustar00lazkalazka# 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 ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/mmkeys/osx.py0000644000175000017500000001267600000000000017172 0ustar00lazkalazka# 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 ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/mmkeys/winhook.py0000644000175000017500000000503500000000000020026 0ustar00lazkalazka# 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 ././@PaxHeader0000000000000000000000000000003200000000000010210 xustar0026 mtime=1614542835.14547 quodlibet-4.4.0/quodlibet/operon/0000755000175000017500000000000000000000000015770 5ustar00lazkalazka././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/operon/__init__.py0000644000175000017500000000047700000000000020111 0ustar00lazkalazka# 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 ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/operon/base.py0000644000175000017500000000517500000000000017264 0ustar00lazkalazka# 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) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/operon/commands.py0000644000175000017500000006025000000000000020146 0ustar00lazkalazka# 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") # 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) try: try: os.write(fd, dump) finally: os.close(fd) # 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): raise CommandError(_("Can not set %r") % tag) 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") ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/operon/main.py0000644000175000017500000000630700000000000017274 0ustar00lazkalazka# 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 from senf import argv as sys_argv 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 ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/operon/util.py0000644000175000017500000000766200000000000017332 0ustar00lazkalazka# 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 senf import environ 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 environ: editor = environ["VISUAL"] elif "EDITOR" in environ: editor = 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=1614542835.1494699 quodlibet-4.4.0/quodlibet/order/0000755000175000017500000000000000000000000015601 5ustar00lazkalazka././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/order/__init__.py0000644000175000017500000001274600000000000017724 0ustar00lazkalazka# 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 Optional 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.""" def __init__(self): super().__init__() self._played = [] def next(self, playlist, iter): if iter is not None: self._played.append(playlist.get_path(iter).get_indices()[0]) def previous(self, playlist, iter): try: path = self._played.pop() except IndexError: return None else: return playlist.get_iter(path) def set(self, playlist, iter): if iter is not None: self._played.append(playlist.get_path(iter).get_indices()[0]) return iter def reset(self, playlist): del(self._played[:]) def remaining(self, playlist): """Gets a map of all song indices to their song from the `playlist` that haven't yet been played""" all_indices = set(range(len(playlist))) played = set(self._played) print_d("Played %d of %d song(s)" % (len(self._played), len(playlist))) remaining = list(all_indices.difference(played)) all_songs = playlist.get() return {i: all_songs[i] for i in remaining} 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 ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/order/reorder.py0000644000175000017500000000366100000000000017623 0ustar00lazkalazka# 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) played = set(self._played) songs = set(range(len(playlist))) remaining = songs.difference(played) if remaining: return playlist.get_iter((random.choice(list(remaining)),)) self.reset(playlist) return None 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 len(remaining) <= 0: 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 ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540385.999186 quodlibet-4.4.0/quodlibet/order/repeat.py0000644000175000017500000000420600000000000017435 0ustar00lazkalazka# 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=1614542835.1494699 quodlibet-4.4.0/quodlibet/packages/0000755000175000017500000000000000000000000016244 5ustar00lazkalazka././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/README.rst0000644000175000017500000000036100000000000017733 0ustar00lazkalazkaDon'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" ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/__init__.py0000644000175000017500000000046400000000000020361 0ustar00lazkalazka# -*- 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=1614542835.1494699 quodlibet-4.4.0/quodlibet/packages/raven/0000755000175000017500000000000000000000000017357 5ustar00lazkalazka././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/raven/__init__.py0000644000175000017500000000232500000000000021472 0ustar00lazkalazka""" 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 ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/raven/base.py0000644000175000017500000007211300000000000020647 0ustar00lazkalazka""" 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 ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/raven/breadcrumbs.py0000644000175000017500000002656600000000000022241 0ustar00lazkalazkafrom __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=1614542835.1494699 quodlibet-4.4.0/quodlibet/packages/raven/conf/0000755000175000017500000000000000000000000020304 5ustar00lazkalazka././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/raven/conf/__init__.py0000644000175000017500000000242600000000000022421 0ustar00lazkalazka""" 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 ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/raven/conf/defaults.py0000644000175000017500000000262400000000000022471 0ustar00lazkalazka""" 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') ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/raven/conf/remote.py0000644000175000017500000001001200000000000022143 0ustar00lazkalazkafrom __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, ) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/raven/context.py0000644000175000017500000000727100000000000021424 0ustar00lazkalazka""" 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 from collections import Mapping, Iterable 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, Mapping, 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 ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/raven/events.py0000644000175000017500000001107100000000000021235 0ustar00lazkalazka""" 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), } } ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/raven/exceptions.py0000644000175000017500000000113300000000000022110 0ustar00lazkalazkafrom __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=1614542835.1494699 quodlibet-4.4.0/quodlibet/packages/raven/handlers/0000755000175000017500000000000000000000000021157 5ustar00lazkalazka././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/raven/handlers/__init__.py0000644000175000017500000000030700000000000023270 0ustar00lazkalazka""" 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 ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/raven/handlers/logbook.py0000644000175000017500000000635200000000000023173 0ustar00lazkalazka""" 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 ) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/raven/handlers/logging.py0000644000175000017500000001367200000000000023170 0ustar00lazkalazka""" 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, object): 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) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/raven/middleware.py0000644000175000017500000000700200000000000022045 0ustar00lazkalazka""" 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() ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/raven/processors.py0000644000175000017500000001234400000000000022137 0ustar00lazkalazka""" 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=1614542835.1494699 quodlibet-4.4.0/quodlibet/packages/raven/scripts/0000755000175000017500000000000000000000000021046 5ustar00lazkalazka././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/raven/scripts/__init__.py0000644000175000017500000000030000000000000023150 0ustar00lazkalazka""" 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 ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/raven/scripts/runner.py0000644000175000017500000000623400000000000022736 0ustar00lazkalazka""" 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=1614542835.1494699 quodlibet-4.4.0/quodlibet/packages/raven/transport/0000755000175000017500000000000000000000000021413 5ustar00lazkalazka././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/raven/transport/__init__.py0000644000175000017500000000142000000000000023521 0ustar00lazkalazka""" 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 ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/raven/transport/base.py0000644000175000017500000000227300000000000022703 0ustar00lazkalazka""" 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 ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/raven/transport/eventlet.py0000644000175000017500000000274400000000000023622 0ustar00lazkalazka""" 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)) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/raven/transport/exceptions.py0000644000175000017500000000100500000000000024142 0ustar00lazkalazka""" 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 """ ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/raven/transport/gevent.py0000644000175000017500000000310400000000000023253 0ustar00lazkalazka""" 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) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/raven/transport/http.py0000644000175000017500000000343300000000000022747 0ustar00lazkalazka""" 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 ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/raven/transport/registry.py0000644000175000017500000000504600000000000023642 0ustar00lazkalazka""" 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, ] ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/raven/transport/requests.py0000644000175000017500000000174500000000000023647 0ustar00lazkalazka""" 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) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/raven/transport/threaded.py0000644000175000017500000001171300000000000023550 0ustar00lazkalazka""" 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) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/raven/transport/threaded_requests.py0000644000175000017500000000204300000000000025477 0ustar00lazkalazka""" 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) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/raven/transport/tornado.py0000644000175000017500000000341700000000000023440 0ustar00lazkalazka""" 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) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/raven/transport/twisted.py0000644000175000017500000000437000000000000023454 0ustar00lazkalazka""" 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=1614542835.1534698 quodlibet-4.4.0/quodlibet/packages/raven/utils/0000755000175000017500000000000000000000000020517 5ustar00lazkalazka././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/raven/utils/__init__.py0000644000175000017500000001127100000000000022632 0ustar00lazkalazka""" 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 ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/raven/utils/compat.py0000644000175000017500000001304400000000000022356 0ustar00lazkalazka""" 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).')) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/raven/utils/conf.py0000644000175000017500000000444700000000000022027 0ustar00lazkalazkafrom __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 ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/raven/utils/encoding.py0000644000175000017500000000634700000000000022671 0ustar00lazkalazka""" 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') ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/raven/utils/http.py0000644000175000017500000000372000000000000022052 0ustar00lazkalazka""" 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) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/raven/utils/imports.py0000644000175000017500000000062400000000000022570 0ustar00lazkalazkafrom __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) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/raven/utils/json.py0000644000175000017500000000503600000000000022046 0ustar00lazkalazka""" 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=1614542835.1534698 quodlibet-4.4.0/quodlibet/packages/raven/utils/serializer/0000755000175000017500000000000000000000000022670 5ustar00lazkalazka././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/raven/utils/serializer/__init__.py0000644000175000017500000000047700000000000025011 0ustar00lazkalazka""" 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 ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/raven/utils/serializer/base.py0000644000175000017500000001255700000000000024166 0ustar00lazkalazka# -*- 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) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/raven/utils/serializer/manager.py0000644000175000017500000000513700000000000024662 0ustar00lazkalazka""" 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) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/raven/utils/ssl_match_hostname.py0000644000175000017500000000701600000000000024750 0ustar00lazkalazka"""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" ) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/raven/utils/stacks.py0000644000175000017500000002345200000000000022367 0ustar00lazkalazka""" 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 ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/raven/utils/testutils.py0000644000175000017500000000124500000000000023133 0ustar00lazkalazka""" 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) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/raven/utils/transaction.py0000644000175000017500000000207000000000000023415 0ustar00lazkalazkafrom __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 ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/raven/utils/urlparse.py0000644000175000017500000000073400000000000022732 0ustar00lazkalazkafrom __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 ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/raven/utils/wsgi.py0000644000175000017500000000722300000000000022046 0ustar00lazkalazka""" 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') ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/raven/versioning.py0000644000175000017500000000467600000000000022131 0ustar00lazkalazkafrom __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=1614542835.1534698 quodlibet-4.4.0/quodlibet/packages/senf/0000755000175000017500000000000000000000000017177 5ustar00lazkalazka././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/senf/__init__.py0000644000175000017500000000521000000000000021306 0ustar00lazkalazka# -*- 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__ = [] ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/senf/__init__.pyi0000644000175000017500000000417400000000000021467 0ustar00lazkalazkaimport 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: ... ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/senf/_argv.py0000644000175000017500000000653100000000000020654 0ustar00lazkalazka# -*- 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() ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/senf/_compat.py0000644000175000017500000000347400000000000021203 0ustar00lazkalazka# -*- 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()) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/senf/_environ.py0000644000175000017500000001530700000000000021376 0ustar00lazkalazka# -*- 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 ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/senf/_fsnative.py0000644000175000017500000004461600000000000021542 0ustar00lazkalazka# -*- 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) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/senf/_print.py0000644000175000017500000003011600000000000021045 0ustar00lazkalazka# -*- 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 ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/senf/_stdlib.py0000644000175000017500000001052600000000000021175 0ustar00lazkalazka# -*- 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) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/senf/_temp.py0000644000175000017500000000632200000000000020660 0ustar00lazkalazka# -*- 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) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/senf/_winansi.py0000644000175000017500000002451700000000000021371 0ustar00lazkalazka# -*- 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)) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/senf/_winapi.py0000644000175000017500000001605000000000000021201 0ustar00lazkalazka# -*- 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 ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/packages/update.sh0000755000175000017500000000064200000000000020067 0ustar00lazkalazka#!/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=1614542835.1534698 quodlibet-4.4.0/quodlibet/pattern/0000755000175000017500000000000000000000000016143 5ustar00lazkalazka././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/pattern/__init__.py0000644000175000017500000000100700000000000020252 0ustar00lazkalazka# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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 ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/pattern/_pattern.py0000644000175000017500000003656100000000000020344 0ustar00lazkalazka# 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 re import Scanner # type: ignore from urllib.parse import quote_plus from senf import sep, fsnative, expanduser 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={}): if (Kind, string) not in cache: if len(cache) > MAX_CACHE_SIZE: cache.clear() 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) 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(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 = expanduser(value) value = limit_path(value) if 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): super_object = super(_ArbitraryExtensionFileFromPattern, self) return super_object._post(value, song, False) 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=1614542835.1534698 quodlibet-4.4.0/quodlibet/player/0000755000175000017500000000000000000000000015762 5ustar00lazkalazka././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/player/__init__.py0000644000175000017500000000341000000000000020071 0ustar00lazkalazka# 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 ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/player/_base.py0000644000175000017500000002241600000000000017412 0ustar00lazkalazka# 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 of 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): """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=True) 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=1614542835.1534698 quodlibet-4.4.0/quodlibet/player/gstbe/0000755000175000017500000000000000000000000017066 5ustar00lazkalazka././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/player/gstbe/__init__.py0000644000175000017500000000061600000000000021202 0ustar00lazkalazka# 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 ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/player/gstbe/player.py0000644000175000017500000010756500000000000020752 0ustar00lazkalazka# Copyright 2004-2011 Joe Wreschnig, Michael Urman, Steven Robertson, # 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. 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.multisong: print_d("multisong: ignore about to finish") 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 = self._source.current if next_song is None else next_song # 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 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 changed, 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 loose 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) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/player/gstbe/plugins.py0000644000175000017500000000516200000000000021125 0ustar00lazkalazka# 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]) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.003186 quodlibet-4.4.0/quodlibet/player/gstbe/prefs.py0000644000175000017500000001071000000000000020556 0ustar00lazkalazka# Copyright 2004-2011 Joe Wreschnig, Michael Urman, Steven Robertson, # 2011-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. from gi.repository import Gtk from quodlibet import config from quodlibet import _ from quodlibet.qltk.ccb import ConfigCheckButton 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=6) e = UndoEntry() e.set_tooltip_text(_("The GStreamer output pipeline used for " "playback. Leave blank for the default pipeline. " "In case 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")) def format_buffer(scale, value): return _("%.1f seconds") % 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.RIGHT) 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 = ConfigCheckButton( _('Disable _gapless playback'), "player", "gst_disable_gapless", populate=True, tooltip=_("Disabling gapless playback can avoid track changing problems " "with some GStreamer versions")) jack_button = ConfigCheckButton( _('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 = ConfigCheckButton( _('Auto-connect to JACK output devices'), "player", "gst_jack_auto_connect", populate=True, tooltip="Tells `jackaudiosink` to auto-connect") def _jack_toggled(widget: ConfigCheckButton) -> None: jack_connect.set_sensitive(widget.get_active()) jack_button.connect("clicked", _jack_toggled) _jack_toggled(jack_button) widgets = [(pipe_label, e, apply_button), (buffer_label, scale, None)] table = Gtk.Table(n_rows=len(widgets) + 3, n_columns=3) table.set_col_spacings(6) table.set_row_spacings(6) for i, (left, middle, right) in enumerate(widgets): left.set_alignment(0.0, 0.5) table.attach(left, 0, 1, i, i + 1, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK) if right: table.attach(middle, 1, 2, i, i + 1) table.attach(right, 2, 3, i, i + 1, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK) else: table.attach(middle, 1, 3, i, i + 1) table.attach(gapless_button, 0, 3, 2, 3) table.attach(jack_button, 0, 3, 3, 4) table.attach(jack_connect, 0, 3, 4, 5) self.pack_start(table, True, True, 0) if debug: def print_bin(player): player._print_pipeline() b = Button("Print Pipeline", Icons.DIALOG_INFORMATION) connect_obj(b, 'clicked', print_bin, player) self.pack_start(b, True, True, 0) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.007186 quodlibet-4.4.0/quodlibet/player/gstbe/util.py0000644000175000017500000002135000000000000020416 0ustar00lazkalazka# 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. import collections 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(collections.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 ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.007186 quodlibet-4.4.0/quodlibet/player/nullbe.py0000644000175000017500000000565200000000000017625 0ustar00lazkalazka# Copyright 2004 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 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 = self._source.current if next_song is None else next_song # 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) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614542835.1534698 quodlibet-4.4.0/quodlibet/player/xinebe/0000755000175000017500000000000000000000000017234 5ustar00lazkalazka././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.007186 quodlibet-4.4.0/quodlibet/player/xinebe/__init__.py0000644000175000017500000000050300000000000021343 0ustar00lazkalazka# 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 ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.007186 quodlibet-4.4.0/quodlibet/player/xinebe/cdefs.py0000644000175000017500000002315000000000000020673 0ustar00lazkalazka# 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 ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.007186 quodlibet-4.4.0/quodlibet/player/xinebe/player.py0000644000175000017500000002751300000000000021112 0ustar00lazkalazka# Copyright 2006-2007 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. 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 = self._source.current if next_song is None else next_song # 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): super().setup(playlist, song, seek_pos) # 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) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614542835.1534698 quodlibet-4.4.0/quodlibet/plugins/0000755000175000017500000000000000000000000016147 5ustar00lazkalazka././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.007186 quodlibet-4.4.0/quodlibet/plugins/__init__.py0000644000175000017500000004145600000000000020272 0ustar00lazkalazka# 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.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 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 an 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)) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.007186 quodlibet-4.4.0/quodlibet/plugins/cover.py0000644000175000017500000001407000000000000017641 0ustar00lazkalazka# Copyright 2013 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, 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 "%s for %s" % (self.name, self.group_by(self.song)) 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 ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.007186 quodlibet-4.4.0/quodlibet/plugins/editing.py0000644000175000017500000001311100000000000020141 0ustar00lazkalazka# 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) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.007186 quodlibet-4.4.0/quodlibet/plugins/events.py0000644000175000017500000001172300000000000020031 0ustar00lazkalazka# 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: from quodlibet import app songs = args[0] if not isinstance(songs, (set, list)): songs = [songs] songs = filter(None, songs) check_wrapper_changed(librarian, app.window, 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) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.007186 quodlibet-4.4.0/quodlibet/plugins/gstelement.py0000644000175000017500000000252500000000000020674 0ustar00lazkalazka# 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) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.007186 quodlibet-4.4.0/quodlibet/plugins/gui.py0000644000175000017500000000666700000000000017324 0ustar00lazkalazka# 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 ././@PaxHeader0000000000000000000000000000003200000000000010210 xustar0026 mtime=1614542835.15747 quodlibet-4.4.0/quodlibet/plugins/listenbrainz/0000755000175000017500000000000000000000000020653 5ustar00lazkalazka././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1614540386.007186 quodlibet-4.4.0/quodlibet/plugins/listenbrainz/__init__.py0000644000175000017500000005121600000000000022771 0ustar00lazkalazka# -*- 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(object): """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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.007186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/plugins/listenbrainz/listenbrainz.py��������������������������������������0000644�0001750�0001750�00000014453�00000000000�023740� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.007186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/plugins/playlist.py�������������������������������������������������������0000644�0001750�0001750�00000016741�00000000000�020373� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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() �������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.007186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/plugins/playorder.py������������������������������������������������������0000644�0001750�0001750�00000004230�00000000000�020521� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.007186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/plugins/query.py����������������������������������������������������������0000644�0001750�0001750�00000005510�00000000000�017667� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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.formats import AudioFile from quodlibet.plugins import PluginHandler, PluginManager from quodlibet.qltk import Icons, Align, Frame 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) return Frame(_("Usage"), child=Align(label, border=9, halign=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() ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.007186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/plugins/songshelpers.py���������������������������������������������������0000644�0001750�0001750�00000002023�00000000000�021232� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.007186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/plugins/songsmenu.py������������������������������������������������������0000644�0001750�0001750�00000005354�00000000000�020546� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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.plugin_window, self.__songs) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000032�00000000000�010210� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������26 mtime=1614542835.16147 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/���������������������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�015441� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.007186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/__init__.py����������������������������������������������������������0000644�0001750�0001750�00000042225�00000000000�017557� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2005 Joe Wreschnig, Michael Urman # 2012 Christoph Reiter # 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. import os import signal import socket 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/<plugin id> 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("<Primary>")[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, "<shift><ctrl>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 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, css): """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 ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.007186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/_editutils.py��������������������������������������������������������0000644�0001750�0001750�00000014376�00000000000�020173� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 = "<b>%s</b>" % util.escape(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 = "<b>%s</b>" % util.escape(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) 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 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.007186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/about.py�������������������������������������������������������������0000644�0001750�0001750�00000002056�00000000000�017130� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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(const.COPYRIGHT + "\n" + "<%s>" % const.SUPPORT_EMAIL) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.007186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/appwindow.py���������������������������������������������������������0000644�0001750�0001750�00000002001�00000000000�020014� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.007186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/bookmarks.py���������������������������������������������������������0000644�0001750�0001750�00000020231�00000000000�020001� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.007186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/browser.py�����������������������������������������������������������0000644�0001750�0001750�00000030175�00000000000�017504� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2005 Joe Wreschnig, Michael Urman # 2016 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 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 = """ <menu action='Filters'> <menuitem action='FilterGenre' always-show-image='true'/> <menuitem action='FilterArtist' always-show-image='true'/> <menuitem action='FilterAlbum' always-show-image='true'/> <separator/> <menuitem action='RandomGenre' always-show-image='true'/> <menuitem action='RandomArtist' always-show-image='true'/> <menuitem action='RandomAlbum' always-show-image='true'/> <separator/> <menuitem action='All' always-show-image='true'/> <menuitem action='PlayedRecently' always-show-image='true'/> <menuitem action='AddedRecently' always-show-image='true'/> <menuitem action='TopRated' always-show-image='true'/> </menu>""" __OUTER_MENU = """ <ui> <menubar name='Menu'> %s </menubar> </ui>""" % 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, "<Primary>" + 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 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)) 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) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.007186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/cbes.py��������������������������������������������������������������0000644�0001750�0001750�00000035734�00000000000�016743� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 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", f"<b>{escape(name)}</b>\n" f"<tt>{escape(content)}</tt>") 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() ������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.007186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/ccb.py���������������������������������������������������������������0000644�0001750�0001750�00000003654�00000000000�016552� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2005 Joe Wreschnig, Michael Urman # 2012 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 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()) ������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.007186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/chooser.py�����������������������������������������������������������0000644�0001750�0001750�00000015361�00000000000�017463� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 fsn2glib, glib2fsn, 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(fsn2glib(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 = [glib2fsn(fn) for fn in chooser.get_filenames()] current_dir = chooser.get_current_folder() if current_dir: set_current_dir(glib2fsn(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(fsn2glib(path2fsn(pattern))) return filter_ def choose_folders(parent, title, action_title): """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(True) 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 saving a file. 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] �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.007186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/color.py�������������������������������������������������������������0000644�0001750�0001750�00000001310�00000000000�017124� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.007186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/completion.py��������������������������������������������������������0000644�0001750�0001750�00000013624�00000000000�020172� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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): print_d("Updating tag model for %d songs" % len(songs)) 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("Done updating 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 ������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.007186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/controls.py����������������������������������������������������������0000644�0001750�0001750�00000024635�00000000000�017670� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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() ���������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.007186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/cover.py�������������������������������������������������������������0000644�0001750�0001750�00000023765�00000000000�017146� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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() 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 �����������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.007186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/data_editors.py������������������������������������������������������0000644�0001750�0001750�00000032504�00000000000�020461� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 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. 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) or isinstance(val, 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 = '<b>%s</b>\n%s' % (obj_name, 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.data = values or [] 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() # Main view view = self.view = HintedTreeView(model=self.model) view.set_fixed_height_mode(True) view.set_headers_visible(False) 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) 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 __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('text', util.tag(row[0])) render = Gtk.CellRendererText() column = Gtk.TreeViewColumn(_("Tag expression"), render) column.set_cell_data_func(render, tag_cdf) column.set_sizing(Gtk.TreeViewColumnSizing.FIXED) column.set_expand(True) view.append_column(column) render = Gtk.CellRendererText() render.set_property('ellipsize', Pango.EllipsizeMode.END) column = Gtk.TreeViewColumn(_("Description"), render) column.set_cell_data_func(render, 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): for s in self.data: self.model.append(row=[s]) def get_strings(self): strings = [row[0] for row in self.model if row] return strings 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 __popup(self, view, menu): return view.popup_menu(menu, 0, Gtk.get_current_event_time()).show() ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.007186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/dbus_.py�������������������������������������������������������������0000644�0001750�0001750�00000015255�00000000000�017117� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2006 Federico Pelloni <federico.pelloni@gmail.com> # 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: """ <!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> <node name="/net/sacredchao/QuodLibet"> <interface name="org.freedesktop.DBus.Introspectable"> <method name="Introspect"> <arg direction="out" type="s" /> </method> </interface> <interface name="net.sacredchao.QuodLibet"> <signal name="SongStarted"> <arg type="v" name="song" /> </signal> <signal name="SongEnded"> <arg type="v" name="song" /> <arg type="v" name="skipped" /> </signal> <signal name="Paused"></signal> <signal name="Unpaused"></signal> <method name="GetPosition"> <arg direction="out" type="u" /> </method> <method name="IsPlaying"> <arg direction="out" type="b" /> </method> <method name="CurrentSong"> <arg direction="out" type="a{ss}" /> </method> <method name="Rate"> <arg direction="in" type="s" name="rating" /> </method> <method name="Next"></method> <method name="Previous"></method> <method name="Pause"></method> <method name="Play"></method> <method name="PlayPause"> <arg direction="out" type="b" /> </method> <method name="Query"> <arg direction="in" type="s" name="text" /> <arg direction="out" type="aa{ss}" /> </method> </interface> </node> """ 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 ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.007186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/delete.py������������������������������������������������������������0000644�0001750�0001750�00000021073�00000000000�017260� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.007186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/edittags.py����������������������������������������������������������0000644�0001750�0001750�00000117767�00000000000�017642� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2012 Joe Wreschnig, Michael Urman, Iñigo Serna # 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. import sys from typing import Optional, Type, Sequence from gi.repository import Gtk, Pango, Gdk from quodlibet import C_, _, 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( ['%s<i> (%s)</i>' % (util.escape(s), util.escape(self._paren())) for s in self.text.split("\n")]) else: return '<i>(%s)</i>' % util.escape(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.__all_tags_toggled) self.pack_start(cb, 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 __all_tags_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, "<Primary>s"): # Issue 697: allow Ctrl-s to save. self._save.emit('clicked') return Gdk.EVENT_STOP elif qltk.is_accel(event, "<Primary>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, "<Primary>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 <b>%s</b>") % util.escape(tag) msg += "\n\n" msg += _("The files currently" " selected do not support multiple values for <b>%s</b>." ) % util.escape(tag) qltk.ErrorMessage(self, title, msg).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 = _("Invalid tag") msg = _("Invalid tag <b>%s</b>\n\nThe files currently" " selected do not support editing this tag." ) % util.escape(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: <b>%(value)s</b>\n\n%(error)s") % { "value": 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 = _("Invalid tag") msg = _("Invalid tag <b>%s</b>\n\nThe files currently" " selected do not support editing this tag." ) % util.escape(new_tag) qltk.ErrorMessage(self, title, msg).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: <b>%(value)s</b>\n\n%(error)s") % { "value": 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 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) ���������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.007186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/entry.py�������������������������������������������������������������0000644�0001750�0001750�00000021245�00000000000�017160� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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, "<Primary>z"): self.undo() return True elif is_accel(event, "<Primary><shift>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, "<Primary>z") redo = MenuItem(_("_Redo"), Icons.EDIT_REDO) add_fake_accel(redo, "<Primary><shift>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) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.007186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/exfalsowindow.py�����������������������������������������������������0000644�0001750�0001750�00000023654�00000000000�020716� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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, \ Button, 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("<Primary>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__() self.set_title(_("Ex Falso Preferences")) self.set_border_width(12) self.set_resizable(False) self.set_transient_for(qltk.get_top_parent(parent)) tagging = self.Tagging() f = qltk.Frame(_("Tag Editing"), child=(tagging.tag_editing_vbox())) 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) main_vbox = Gtk.VBox(spacing=12) main_vbox.pack_start(f, True, True, 0) self.use_header_bar() if not self.has_close_button(): main_vbox.pack_start(button_box, False, True, 0) self.add(main_vbox) connect_obj(self, 'destroy', PreferencesWindow.__destroy, self) self.get_child().show_all() def __destroy(self): config.save() ������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.007186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/filesel.py�����������������������������������������������������������0000644�0001750�0001750�00000053544�00000000000�017451� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 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, \ glib2fsn, 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(glib2fsn(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 dir_ = glib2fsn(dir_) fullpath = os.path.realpath(os.path.join(directory, dir_)) try: os.makedirs(fullpath) except EnvironmentError as err: error = "<b>%s</b>: %s" % (err.filename, err.strerror) qltk.ErrorMessage( None, _("Unable to create folder"), error).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 = "<b>%s</b>: %s" % (err.filename, err.strerror) qltk.ErrorMessage( None, _("Unable to delete folder"), error).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) ������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.007186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/getstring.py���������������������������������������������������������0000644�0001750�0001750�00000005320�00000000000�020021� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0111861 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/icons.py�������������������������������������������������������������0000644�0001750�0001750�00000011076�00000000000�017133� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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_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" ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0111861 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/image.py�������������������������������������������������������������0000644�0001750�0001750�00000012221�00000000000�017073� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 gi.repository import GdkPixbuf, Gtk, Gdk, GLib import cairo def get_surface_for_pixbuf(widget, pixbuf): """Returns a cairo surface""" 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. """ w, h = pixbuf.get_width(), pixbuf.get_height() w += width * 2 h += width * 2 surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h) ctx = cairo.Context(surface) pi = math.pi r = min(radius, min(w, h) / 2) ctx.new_path() ctx.arc(w - r, r, r, -pi / 2, 0) ctx.arc(w - r, h - r, r, 0, pi / 2) ctx.arc(r, h - r, r, pi / 2, pi) ctx.arc(r, r, r, pi, pi * 3 / 2) ctx.close_path() Gdk.cairo_set_source_pixbuf(ctx, pixbuf, width, width) ctx.clip_preserve() ctx.paint() ctx.set_source_rgba(color.red, color.green, color.blue, color.alpha) ctx.set_line_width(width * 2) ctx.stroke() 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()) 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) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0111861 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/info.py��������������������������������������������������������������0000644�0001750�0001750�00000013626�00000000000�016756� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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']<title>[/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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0111861 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/information.py�������������������������������������������������������0000644�0001750�0001750�00000055753�00000000000�020357� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2005 Joe Wreschnig, Michael Urman, Iñigo Serna # 2016-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 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 ("<i>%s</i>" % util.escape(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 = ["<span size='x-large'><i>%s</i></span>" % util.escape(song.comma("album"))] secondary = [] if "discnumber" in song: secondary.append(_("Disc %s") % song["discnumber"]) if "discsubtitle" in song: secondary.append("<i>%s</i>" % util.escape(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 = ["<i>%s</i>" % util.escape(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 = "<i>%s</i>" % util.escape(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 markup = util.escape(song.comma("~title~version")) text.append("{ts}{cur: >2}. <i>{text}</i>".format( ts=ts, cur=track, text=markup)) 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 = "<big><i>%s</i></big>" % util.escape(album) 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("<i>%s</i>" % util.escape(a) for a in albums) if none: text = ngettext("%d song with no album", "%d songs with no album", none) % none markup += "\n%s" % util.escape(text) label = Label() label.set_markup(markup) box.pack_start(Frame( "%s (%d)" % (util.capitalize(_("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 = list(filter(lambda s: s not in gone, self.__songs)) 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", u""), s.get("album", u"")) 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0111861 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/lyrics.py������������������������������������������������������������0000644�0001750�0001750�00000011230�00000000000�017315� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2005 Eduardo Gonzalez, Joe Wreschnig # 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. # FIXME: # - Too many buttons -- saving should be automatic? import os import threading 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): artist = song.comma('artist').encode('utf-8') title = song.comma('title').encode('utf-8') util.website("http://lyrics.wikia.com/%s:%s" % (quote(artist), quote(title))) def __refresh(self, refresh, add, buffer, song): buffer.set_text(_(u"Searching for lyrics…")) refresh.set_sensitive(False) thread = threading.Thread( target=self.__search, args=(song, buffer, refresh, add)) thread.setDaemon(True) thread.start() 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("Couldn't write embedded lyrics (%s)" % e) self._save_to_file(song, text) else: print_d("Wrote embedded lyrics into %s" % song("~filename")) app.librarian.emit('changed', [song]) self._delete_file(song.lyric_filename) def _save_to_file(self, song, text): lyricname = song.lyric_filename try: os.makedirs(os.path.dirname(lyricname), exist_ok=True) except EnvironmentError: errorhook() try: with open(lyricname, "wb") as f: f.write(text.encode("utf-8")) print_d("Saved lyrics to file (%s)" % lyricname) 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): try: os.unlink(filename) print_d("Removed lyrics file '%s'" % filename) except EnvironmentError: pass lyric_dir = os.path.dirname(filename) try: os.rmdir(lyric_dir) print_d("Removed lyrics directory '%s'" % lyric_dir) except EnvironmentError: pass ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0111861 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/maskedbox.py���������������������������������������������������������0000644�0001750�0001750�00000011264�00000000000�017774� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0111861 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/menubutton.py��������������������������������������������������������0000644�0001750�0001750�00000002554�00000000000�020221� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0111861 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/models.py������������������������������������������������������������0000644�0001750�0001750�00000020225�00000000000�017277� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0111861 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/msg.py���������������������������������������������������������������0000644�0001750�0001750�00000007546�00000000000�016615� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 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 gi.repository import Gtk from senf import fsn2text, path2fsn from quodlibet import _ from quodlibet import util from quodlibet.qltk.icons import Icons from quodlibet.qltk import get_top_parent from quodlibet.qltk.window import Dialog 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, parent, title, description, buttons=Gtk.ButtonsType.OK): parent = get_top_parent(parent) text = ("<span weight='bold' size='larger'>%s</span>\n\n%s" % (title, description)) super().__init__( transient_for=parent, modal=True, destroy_with_parent=True, message_type=kind, buttons=buttons) self.set_markup(text) 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 an 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 = "<b>%s</b>" % util.escape(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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0111861 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/notif.py�������������������������������������������������������������0000644�0001750�0001750�00000024721�00000000000�017140� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2010 Steven Robertson # # This program is free software; you can redistribute it and/or modify # it under the terms of the 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 _ from quodlibet.util import copool from quodlibet.qltk.x import SmallImageToggleButton, SmallImageButton, Align from quodlibet.qltk import Icons 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 = list(filter(lambda t: t is not finished_task, self.active_tasks)) self.update() # Oh so deliciously hacky. TaskController.default_instance = TaskController() class TaskWidget(Gtk.HBox): """ Displays a task. """ def __init__(self, task): super().__init__(spacing=2) 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, True, 12) self.progress = Gtk.ProgressBar() self.progress.set_size_request(100, -1) self.pack_start(self.progress, True, True, 0) 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, 0) 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 = "<small><b>%s</b>\n%s</small>" % (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, True, True, 0) # The history button will eventually hold the full list of running # tasks, as well as the list of previous notifications. #self.history_btn = Gtk.Button() #self.pack_start(self.history_btn, False, True, 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0111861 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/paned.py�������������������������������������������������������������0000644�0001750�0001750�00000021775�00000000000�017116� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0111861 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/playorder.py���������������������������������������������������������0000644�0001750�0001750�00000027252�00000000000�020024� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0111861 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/pluginwin.py���������������������������������������������������������0000644�0001750�0001750�00000046302�00000000000�020034� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2005 Joe Wreschnig, Michael Urman, Iñigo Serna # 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, 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 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="<b>%s</b>" % util.escape(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([_("All"), 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([_("All"), 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) 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>") if plugin.description: text += "<span font='4'>\n\n</span>" text += util.escape(plugin.description) 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 text.lower() for p in filter_.lower().split()) filter_ = entry.get_text() return (matches(plugin.name, 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0111861 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/prefs.py�������������������������������������������������������������0000644�0001750�0001750�00000101206�00000000000�017132� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2009 Joe Wreschnig, Michael Urman, Iñigo Serna, # Steven Robertson # 2011-2017 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 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 ConfigCheckButton as CCB from quodlibet.qltk.data_editors import TagListEditor from quodlibet.qltk.entry import ValidatingEntry, UndoEntry 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 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 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_behaviour_frame(): vbox = Gtk.VBox(spacing=6) jump_button = CCB(_("_Jump to playing song automatically"), 'settings', 'jump', populate=True, tooltip=_("When the playing song changes, " "scroll to it in the song list")) autosort_button = CCB(_("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")) vbox.pack_start(jump_button, False, True, 0) vbox.pack_start(autosort_button, False, True, 0) return qltk.Frame(_("Behavior"), child=vbox) def create_visible_columns_frame(): buttons = {} vbox = Gtk.VBox(spacing=12) table = Gtk.Table.new(3, 3, True) for i, (k, t) in enumerate(self.PREDEFINED_TAGS): x, y = i % 3, i / 3 buttons[k] = Gtk.CheckButton(label=t, use_underline=True) table.attach(buttons[k], x, x + 1, y, y + 1) vbox.pack_start(table, False, True, 0) # Other columns hbox = Gtk.HBox(spacing=6) 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 = Gtk.Button( label=_(u"_Edit…"), use_underline=True) 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.CheckButton(label=_("Title includes _version"), use_underline=True) aio = Gtk.CheckButton(label=_("Artist includes all _people"), use_underline=True) aip = Gtk.CheckButton(label=_("Album includes _disc subtitle"), use_underline=True) fip = Gtk.CheckButton(label=_("Filename includes _folder"), use_underline=True) self._toggle_data = [ (tiv, "title", "~title~version"), (aip, "album", "~album~discsubtitle"), (fip, "~basename", "~filename"), (aio, "artist", "~people") ] t = Gtk.Table.new(2, 2, True) t.attach(tiv, 0, 1, 0, 1) t.attach(aip, 0, 1, 1, 2) t.attach(aio, 1, 2, 0, 1) t.attach(fip, 1, 2, 1, 2) return qltk.Frame(_("Column Preferences"), child=t) def create_apply_button(): vbox = Gtk.VBox(spacing=12) apply = Button(_("_Apply")) 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) vbox.pack_start(b, True, True, 0) return vbox super().__init__(spacing=12) self.set_border_width(12) self.title = _("Song List") self.pack_start(create_behaviour_frame(), False, True, 0) columns_frame, buttons = create_visible_columns_frame() self.pack_start(columns_frame, False, True, 0) self.pack_start(create_columns_prefs_frame(), False, True, 0) self.pack_start(create_apply_button(), True, True, 0) 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""" 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 on the end result.extend(new_headers - set(result)) # 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): cols = widget.get_strings() self.__update(buttons, self._toggle_data, cols) 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=6) 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=6) 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=6) hb = Gtk.HBox(spacing=6) 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) hb.pack_start(l, False, True, 0) hb.pack_start(e, True, True, 0) vb.pack_start(hb, False, True, 0) # Translators: The heading of the preference group, no action return qltk.Frame(C_("heading", "Search"), child=vb) super().__init__(spacing=12) self.set_border_width(12) self.title = _("Browsers") self.pack_start(create_search_frame(), False, True, 0) self.pack_start(create_display_frame(), False, True, 0) # Ratings vb = Gtk.VBox(spacing=6) c1 = CCB(_("Confirm _multiple ratings"), 'browsers', 'rating_confirm_multiple', populate=True, tooltip=_("Ask for confirmation before changing the " "rating of multiple songs at once")) c2 = CCB(_("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=6) 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, 0) vb = Gtk.VBox(spacing=6) # Filename choice algorithm config cb = CCB(_("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(cb, False, True, 0) hb = Gtk.HBox(spacing=3) 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.") cb = CCB(_("_Preferred image filename(s):"), 'albumart', 'force_filename', populate=True, tooltip=preferred_image_filename_tooltip) hb.pack_start(cb, 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(cb.get_active()) cb.connect('toggled', self.__toggled_force_filename, entry) hb.pack_start(entry, True, True, 0) vb.pack_start(hb, False, True, 0) f = qltk.Frame(_("Album Art"), child=vb) self.pack_start(f, False, True, 0) for child in self.get_children(): child.show_all() def __changed_text(self, entry, name): config.set('albumart', name, entry.get_text()) def __toggled_force_filename(self, cb, fn_entry): fn_entry.set_sensitive(cb.get_active()) def _entry(self, entry, name, section="settings"): config.set(section, name, entry.get_text()) class Player(Gtk.VBox): name = "playback" def __init__(self): super().__init__(spacing=12) self.set_border_width(12) self.title = _("Playback") # 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, 0) # replaygain fallback_gain = config.getfloat("player", "fallback_gain", 0.0) adj = Gtk.Adjustment.new(fallback_gain, -12.0, 12.0, 0.5, 0.5, 0.0) fb_spin = Gtk.SpinButton(adjustment=adj) fb_spin.set_digits(1) fb_spin.connect('changed', self.__changed, 'player', 'fallback_gain') fb_spin.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 (dB):")) fb_label.set_use_underline(True) fb_label.set_mnemonic_widget(fb_spin) pre_amp_gain = config.getfloat("player", "pre_amp_gain", 0.0) adj = Gtk.Adjustment.new(pre_amp_gain, -12, 12, 0.5, 0.5, 0.0) adj.connect('value-changed', self.__changed, 'player', 'pre_amp_gain') pre_spin = Gtk.SpinButton(adjustment=adj) pre_spin.set_digits(1) pre_spin.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 (dB):")) pre_label.set_use_underline(True) pre_label.set_mnemonic_widget(pre_spin) widgets = [pre_label, pre_spin, fb_label, fb_spin] c = CCB(_("_Enable Replay Gain volume adjustment"), "player", "replaygain", populate=True) c.connect('toggled', self.__toggled_gain, widgets) # packing table = Gtk.Table.new(3, 2, False) table.set_col_spacings(6) table.set_row_spacings(6) table.attach(c, 0, 2, 0, 1) fb_label.set_alignment(0, 0.5) table.attach(fb_label, 0, 1, 1, 2, xoptions=Gtk.AttachOptions.FILL) pre_label.set_alignment(0, 0.5) table.attach(pre_label, 0, 1, 2, 3, xoptions=Gtk.AttachOptions.FILL) fb_align = Align(halign=Gtk.Align.START) fb_align.add(fb_spin) table.attach(fb_align, 1, 2, 1, 2) pre_align = Align(halign=Gtk.Align.START) pre_align.add(pre_spin) table.attach(pre_align, 1, 2, 2, 3) f = qltk.Frame(_("Replay Gain Volume Adjustment"), child=table) c.emit('toggled') self.pack_start(f, False, True, 0) vbox = Gtk.VBox() c = CCB(_("_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(c, False, False, 0) f = qltk.Frame(_("Startup"), child=vbox) self.pack_start(f, False, True, 0) for child in self.get_children(): child.show_all() def __toggled_gain(self, activator, 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=6) # 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 = Gtk.Grid(column_spacing=6, row_spacing=6) 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, 6) # 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 hb = Gtk.HBox(spacing=6) hb.pack_start(bayes_label, False, True, 0) hb.pack_start(bayes_spin, False, True, 0) vb.pack_start(hb, True, True, 0) cb = CCB(_("Save ratings and play _counts in tags"), "editing", "save_to_songs", populate=True) def update_entry(widget, email_entry): email_entry.set_sensitive(widget.get_active()) vb.pack_start(cb, True, True, 0) hb = Gtk.HBox(spacing=6) 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 cb.connect('clicked', update_entry, entry) update_entry(cb, entry) hb.pack_start(lab, False, True, 0) hb.pack_start(entry, True, True, 0) lab.set_mnemonic_widget(entry) lab.set_use_underline(True) vb.pack_start(hb, True, True, 0) return vb def tag_editing_vbox(self): """Returns a new VBox containing all tag editing widgets""" vbox = Gtk.VBox(spacing=6) cb = CCB(_("Auto-save tag changes"), 'editing', 'auto_save_changes', populate=True, tooltip=_("Save changes to tags without confirmation " "when editing multiple files")) vbox.pack_start(cb, False, True, 0) split_entry = UndoEntry() 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_entry.props.expand = True sub_entry = UndoEntry() sub_entry.set_text(config.get("editing", "sub_split_on")) sub_entry.connect('changed', self.__changed, '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_entry.props.expand = True def do_revert_split(button, entry, section, option): config.reset(section, option) entry.set_text(config.get(section, option)) split_revert = Button(_("_Revert"), Icons.DOCUMENT_REVERT) split_revert.connect("clicked", do_revert_split, split_entry, "editing", "split_on") split_label = Gtk.Label(label=_("Split _tag on:")) split_label.set_use_underline(True) split_label.set_mnemonic_widget(split_entry) sub_revert = Button(_("_Revert"), Icons.DOCUMENT_REVERT) sub_revert.connect("clicked", do_revert_split, sub_entry, "editing", "sub_split_on") sub_label = Gtk.Label(label=_("Split _subtag on:")) sub_label.set_use_underline(True) sub_label.set_mnemonic_widget(split_entry) split_align = Align(halign=Gtk.Align.START) split_align.add(split_label) sub_align = Align(halign=Gtk.Align.START) sub_align.add(sub_label) grid = Gtk.Grid(column_spacing=6, row_spacing=6) grid.add(split_align) grid.add(split_entry) grid.add(split_revert) grid.attach(sub_align, 0, 1, 1, 1) grid.attach(sub_entry, 1, 1, 1, 1) grid.attach(sub_revert, 2, 1, 1, 1) grid.props.expand = False vbox.pack_start(grid, False, False, 6) return vbox def __init__(self): super().__init__(spacing=12) 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, 0) f = qltk.Frame(_("Ratings"), child=self.ratings_vbox()) self.pack_start(f, False, True, 0) 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=12) self.set_border_width(12) self.title = _("Library") cb = CCB(_("Scan library _on start"), "library", "refresh_on_start", populate=True) scan_dirs = ScanBox() vb3 = Gtk.VBox(spacing=6) vb3.pack_start(scan_dirs, True, True, 0) 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.VIEW_REFRESH) reload_.connect("clicked", reload_cb) reload_.set_tooltip_text( _("Reload all songs in your library. " "This can take a long time.")) grid = Gtk.Grid(column_spacing=6, row_spacing=6) cb.props.hexpand = True grid.attach(cb, 0, 0, 1, 1) grid.attach(refresh, 1, 0, 1, 1) grid.attach(reload_, 1, 1, 1, 1) vb3.pack_start(grid, False, True, 0) f = qltk.Frame(_("Scan Directories"), child=vb3) self.pack_start(f, False, True, 0) # 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, 0) for child in self.get_children(): child.show_all() def __init__(self, parent, open_page=None): if self.is_not_unique(): return super().__init__() self.current_scan_dirs = get_scan_dirs() self.set_title(_("Preferences")) self.set_resizable(False) self.set_transient_for(qltk.get_top_parent(parent)) self.__notebook = notebook = qltk.Notebook() pages = [self.SongList, self.Browsers, self.Player, self.Library, self.Tagging] 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() if self.current_scan_dirs != get_scan_dirs(): print_d("Library paths have changed, re-scanning...") scan_library(app.library, force=False) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0111861 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/properties.py��������������������������������������������������������0000644�0001750�0001750�00000015423�00000000000�020214� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0111861 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/queue.py�������������������������������������������������������������0000644�0001750�0001750�00000035070�00000000000�017144� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2005 Joe Wreschnig, Michael Urman, Iñigo Serna # 2016-2017 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 from gi.repository import Gtk, Gdk, Pango from senf import bytes2fsn, fsn2bytes import quodlibet from quodlibet import ngettext, _ from quodlibet import config from quodlibet import util from quodlibet import qltk from quodlibet import app from quodlibet.util import connect_destroy, connect_after_destroy, \ format_time_preferred, print_exc 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) self.queue = PlayQueue(library, player) 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) 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 b: 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) clear_item = MenuItem(_("_Clear Queue"), Icons.EDIT_CLEAR) menu.append(clear_item) clear_item.connect("activate", self.__clear_queue) button = SmallMenuButton( SymbolicIconImage(Icons.EMBLEM_SYSTEM, Gtk.IconSize.MENU), arrow=True) button.set_relief(Gtk.ReliefStyle.NONE) button.show_all() button.hide() button.set_no_show_all(True) menu.show_all() button.set_menu(menu) outer.pack_start(button, False, False, 0) 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, 6) 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', util.DeferredSignal(self.__check_expand), count_label) self.queue.model.connect_after('row-deleted', util.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): """Own class for debugging""" class PlayQueue(SongList): sortable = False _activated = False def __init__(self, library, player): super().__init__(library, player, model_cls=QueueModel) 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() self.connect('destroy', self.__write, self.model) self.__fill(library) self.connect('key-press-event', self.__delete_key_pressed) 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, model): 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: print_exc() continue f.write(line + b"\n") except EnvironmentError: print_exc() 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0111861 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/quodlibetwindow.py���������������������������������������������������0000644�0001750�0001750�00000141121�00000000000�021233� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2005 Joe Wreschnig, Michael Urman, Iñigo Serna # 2012 Christoph Reiter # 2012-2017 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 _ 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() # 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(Align(text, border=3), 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, border=2), 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='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(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 main_box.pack_start( Align(statusbox, border=3, top=-3), 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 __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)).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 = 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(act) 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) 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 __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 __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(util.escape(name)))).run() elif not app.player.can_play_uri(name): ErrorMessage( self, _("Unable to add location"), _("%s uses an unsupported protocol.") % ( util.bold(util.escape(name)))).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) 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) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0111861 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/ratingsmenu.py�������������������������������������������������������0000644�0001750�0001750�00000010670�00000000000�020353� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0111861 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/renamefiles.py�������������������������������������������������������0000644�0001750�0001750�00000044155�00000000000�020316� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 <b>%(old-name)s</b> to <b>%(new-name)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.") % { "old-name": util.escape(old_name), "new-name": util.escape(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<b>%s</b>\ncontains / but " "does not start from root. To avoid misnamed " "folders, root your pattern by starting " "it with / or ~/.") % ( util.escape(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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0111861 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/scanbox.py�����������������������������������������������������������0000644�0001750�0001750�00000013346�00000000000�017457� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 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.connect("clicked", self.__add) remove = Button(_("_Remove"), Icons.LIST_REMOVE) 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): 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 Quodlibet '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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0111861 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/searchbar.py���������������������������������������������������������0000644�0001750�0001750�00000032015�00000000000�017746� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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") combo = ComboBoxEntrySave(filename, count=8, 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0111861 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/seekbutton.py��������������������������������������������������������0000644�0001750�0001750�00000030632�00000000000�020202� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0111861 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/shortcuts.py���������������������������������������������������������0000755�0001750�0001750�00000006417�00000000000�020064� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0111861 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/showfiles.py���������������������������������������������������������0000644�0001750�0001750�00000012721�00000000000�020021� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0111861 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/songlist.py����������������������������������������������������������0000644�0001750�0001750�00000124763�00000000000�017672� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2005 Joe Wreschnig # 2012 Christoph Reiter # 2014 Jan Path # 2011-2020 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, Tuple from gi.repository import Gtk, GLib, Gdk, GObject from senf import uri2fsn from quodlibet import app 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_cb) 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 __selection_changed_cb(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": "", "~length": "~#length" } if tag == "~title~version": tag = "title" elif tag == "~album~discsubtitle": tag = "album" if "<" in tag: for key, value in replace_order.items(): tag = tag.replace("<%s>" % key, "<%s>" % 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: """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 to_add = [] for filename in filenames: if filename not in library.librarian: library.add_filename(filename) elif filename not in library: to_add.append(library.librarian[filename]) library.add(to_add) songs = 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 = { # changed(songs:list) 'orders-changed': (GObject.SignalFlags.RUN_LAST, None, []) } headers: List[str] = [] # The list of current headers. star = list(Query.STAR) sortable = True 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): super().__init__() 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 = [] 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, librarian) self.connect('key-press-event', self.__key_press, librarian, player) self.setup_drop(library) self.disable_drop() self.set_search_equal_func(self.__search_func, None) self.connect('destroy', self.__destroy) @property def model(self): 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 reversed_ = False 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() reversed_ = True 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() if reversed_: # python sort is faster if presorted songs.reverse() self.set_songs(songs, scroll_select=True) 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 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 _sort_songs(self, songs): """Sort passed songs in place based on the column sort orders""" order = self.get_sort_orders() if not order: return for key, reverse in self.__get_song_sort_key_func(order): songs.sort(key=key, reverse=reverse) 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, sorted=False, scroll=True, scroll_select=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 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) self._sort_songs(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) # 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): model, rows = self.get_selection().get_selected_rows() rows = rows or [] iters = [model[r].iter for r in rows if model[r][0] in songs] complete = len(iters) == len(songs) return (iters, 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): # 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, complete = self.__find_iters_in_selection(songs) # if not all songs were in the selection, search the whole view if not complete: iters = model.find_all(songs) self.remove_iters(iters) def __song_properties(self, librarian): model, rows = self.get_selection().get_selected_rows() if rows: songs = [model[row][0] for row in rows] else: from quodlibet import app if app.player.song: songs = [app.player.song] else: return window = SongProperties(librarian, songs, parent=self) window.show() def __information(self, librarian): model, rows = self.get_selection().get_selected_rows() if rows: songs = [model[row][0] for row in rows] else: from quodlibet import app if app.player.song: songs = [app.player.song] else: return window = Information(librarian, songs, self) window.show() 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(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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0111861 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/songlistcolumns.py���������������������������������������������������0000644�0001750�0001750�00000037474�00000000000�021275� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2005 Joe Wreschnig # 2012 Christoph Reiter # 2011-2020 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 _ 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(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(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): 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'. """ 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0111861 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/songmodel.py���������������������������������������������������������0000644�0001750�0001750�00000023652�00000000000�020012� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 gi.repository import Gtk 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 other.go_to(None) res = main.go_to(song, explicit) 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 = None """The last valid current song""" def set(self, songs): """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): """A list of all contained songs""" return list(self.itervalues()) @property def current(self): """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): """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): """Returns a list of iters for all occurrences of all songs. (since a song can be in the model multiple times) """ songs = set(songs) found = [] append = found.append for iter_, value in self.iterrows(): if value in songs: append(iter_) return found 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 = None """The active `PlayOrder`""" sourced = False """True in case this model is the source of the currently playing song""" def __init__(self, order_cls=OrderInOrder): super().__init__(object) self.order = order_cls() # The playorder plugins use paths atm to remember songs so # we need to reset them if the paths change somehow. self.__sigs = [] for sig in ['row-deleted', 'row-inserted', 'rows-reordered']: s = self.connect(sig, lambda pl, *x: self.order.reset(pl)) self.__sigs.append(s) 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): """Clear the model and add the passed songs""" self.order.reset(self) for signal_id in self.__sigs: self.handler_block(signal_id) super().set(songs) for signal_id in self.__sigs: self.handler_unblock(signal_id) 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0111861 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/songsmenu.py���������������������������������������������������������0000644�0001750�0001750�00000040043�00000000000�020032� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2006 Joe Wreschnig # 2013-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 gi.repository import Gtk from quodlibet.plugins.gui import MenuItemPlugin from quodlibet.plugins.songshelpers import is_a_file from quodlibet.qltk.pluginwin import PluginWindow from quodlibet import ngettext, _, print_d from quodlibet import qltk from quodlibet.errorreport import errorhook from quodlibet.qltk.showfiles import show_songs from quodlibet.util import print_e, print_w from quodlibet.qltk.msg import ConfirmationPrompt, ErrorMessage 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)) title = (ngettext("Remove track: \"%%(title)s\" from library?", "Remove %(count)d tracks from library?", count) % {'count': count}) % { 'title': song('title') or song('~basename')} return ConfirmationPrompt.RESPONSE_INVOKE == ConfirmationPrompt( parent, title, "", _("Remove from Library")).run() 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, parent, 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, ratings=True, show_files=True, items=None, accels=True, removal_confirmer=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: # Needed here to avoid a circular import; most browsers use # a SongsMenu, but SongsMenu needs access to the playlist # browser for this item. # FIXME: Two things are now importing browsers, so we need # some kind of inversion of control here. from quodlibet.browsers.playlists.menu import PlaylistMenu from quodlibet.browsers.playlists import PlaylistsBrowser try: submenu = PlaylistMenu(songs, PlaylistsBrowser.playlists()) def on_new(widget, playlist): PlaylistsBrowser.changed(playlist) submenu.connect('new', on_new) 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) 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) 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0111861 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/tagscombobox.py������������������������������������������������������0000644�0001750�0001750�00000004725�00000000000�020512� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0111861 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/tagsfrompath.py������������������������������������������������������0000644�0001750�0001750�00000026122�00000000000�020515� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 _ 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<b>%s</b>\nis invalid. " "Possibly it contains the same tag twice or " "it has unbalanced brackets (< / >).") % ( util.escape(pattern_text))).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) if len(invalid) and songs: if len(invalid) == 1: title = _("Invalid tag") msg = _("Invalid tag <b>%s</b>\n\nThe files currently" " selected do not support editing this tag.") else: title = _("Invalid tags") msg = _("Invalid tags <b>%s</b>\n\nThe files currently" " selected do not support editing these tags.") qltk.ErrorMessage( self, title, msg % ", ".join(invalid)).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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0111861 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/textedit.py����������������������������������������������������������0000644�0001750�0001750�00000014074�00000000000�017653� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.015186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/tracker.py�����������������������������������������������������������0000644�0001750�0001750�00000014223�00000000000�017450� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2005 Joe Wreschnig, Michael Urman, Iñigo Serna # 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. import os import time from gi.repository import GObject, GLib from quodlibet import config 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) if self.elapsed > 0.5 * song.get("~#length", 1): 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): self.path = path self._player = player self._ids = [ player.connect('song-started', self.__started), player.connect('song-ended', self.__ended), ] def destroy(self): for id_ in self._ids: self._player.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 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.015186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/tracknumbers.py������������������������������������������������������0000644�0001750�0001750�00000017305�00000000000�020521� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.015186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/unity.py�������������������������������������������������������������0000644�0001750�0001750�00000004271�00000000000�017167� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.015186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/util.py��������������������������������������������������������������0000644�0001750�0001750�00000006441�00000000000�016775� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.015186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/views.py�������������������������������������������������������������0000644�0001750�0001750�00000133605�00000000000�017160� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2005 Joe Wreschnig, Michael Urman # 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 contextlib from gi.repository import Gtk, Gdk, GObject, Pango, GLib import cairo from senf import environ from quodlibet import _, print_e 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') 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 = list(filter(lambda p: p[0][0] < cellx, pos)) 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) 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): """Conext 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 = "<i>%s</i>" % 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 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 parents 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.015186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/window.py������������������������������������������������������������0000644�0001750�0001750�00000035171�00000000000�017331� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.015186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/wlw.py���������������������������������������������������������������0000644�0001750�0001750�00000020520�00000000000�016623� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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)) self.set_modal(True) 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.015186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/qltk/x.py�����������������������������������������������������������������0000644�0001750�0001750�00000042451�00000000000�016270� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2005 Joe Wreschnig, Michael Urman # 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. """ Things that are more or less direct wrappers around GTK widgets to ease constructors. """ 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("<b>%s</b>" % util.escape(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=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) 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=2) 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�00000000032�00000000000�010210� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������26 mtime=1614542835.16147 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/query/��������������������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�015633� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.015186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/query/__init__.py���������������������������������������������������������0000644�0001750�0001750�00000000461�00000000000�017745� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.015186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/query/_match.py�����������������������������������������������������������0000644�0001750�0001750�00000040103�00000000000�017436� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2005 Joe Wreschnig, Michael Urman # 2011 Christoph Reiter # 2016 Ryan Dellenbaugh # 2016-20 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 numbers import Real from typing import TypeVar, List, Iterable from quodlibet.formats import FILESYSTEM_TAGS, TIME_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 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 class NumexprTag(Numexpr): """Numeric tag""" def __init__(self, tag: str): self._tag = tag self._ftag = "~#" + self._tag 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: # Strip aggregate function from tag func_start = self._ftag.find(":") tag = self._ftag[:func_start] if func_start >= 0 else self._ftag if tag 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): self._value = float(value) def evaluate(self, data, time, use_date): return self._value 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)) def numexprUnit(value, unit): """Process numeric units and return NumexprNumber""" unit = unit.lower().strip() # 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 elif unit.startswith("m"): value *= 1024 ** 2 elif unit.startswith("k"): value *= 1024 elif unit.startswith("b"): pass elif unit: raise ParseError("No such unit: %r" % unit) return NumexprNumber(value) 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.015186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/query/_parser.py����������������������������������������������������������0000644�0001750�0001750�00000024742�00000000000�017651� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2005 Joe Wreschnig, Michael Urman # 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 codecs import re from . import _match as match from ._match import ParseError 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{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) 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.015186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/query/_query.py�����������������������������������������������������������0000644�0001750�0001750�00000012443�00000000000�017515� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.015186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/remote.py�����������������������������������������������������������������0000644�0001750�0001750�00000010311�00000000000�016327� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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(self): """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 EnvironmentError 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�00000000032�00000000000�010210� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������26 mtime=1614542835.16147 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/session/������������������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�016151� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.015186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/session/__init__.py�������������������������������������������������������0000644�0001750�0001750�00000002051�00000000000�020260� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.015186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/session/_base.py����������������������������������������������������������0000644�0001750�0001750�00000001005�00000000000�017570� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.015186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/session/_xsmp.py����������������������������������������������������������0000644�0001750�0001750�00000021645�00000000000�017661� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.015186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/session/gnome.py����������������������������������������������������������0000644�0001750�0001750�00000006416�00000000000�017637� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.015186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/session/xfce.py�����������������������������������������������������������0000644�0001750�0001750�00000001072�00000000000�017450� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.015186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/session/xsmp.py�����������������������������������������������������������0000644�0001750�0001750�00000003522�00000000000�017514� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000032�00000000000�010210� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������26 mtime=1614542835.16147 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/unisearch/����������������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�016447� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.015186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/unisearch/__init__.py�����������������������������������������������������0000644�0001750�0001750�00000001417�00000000000�020563� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 a english keyboard without any knowledge of other languages. """ from .parser import compile compile �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.015186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/unisearch/db.py�����������������������������������������������������������0000644�0001750�0001750�00000033722�00000000000�017415� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.015186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/unisearch/parser.py�������������������������������������������������������0000644�0001750�0001750�00000022672�00000000000�020326� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.015186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/update.py�����������������������������������������������������������������0000644�0001750�0001750�00000011534�00000000000�016326� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 _ 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 "<b>%s</b>" % escape(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�00000000032�00000000000�010210� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������26 mtime=1614542835.16547 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/util/���������������������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�015443� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.015186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/util/__init__.py����������������������������������������������������������0000644�0001750�0001750�00000102665�00000000000�017566� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2009 Joe Wreschnig, Michael Urman, Steven Robertson # 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. import os import random import re import ctypes import ctypes.util import sys import unicodedata import threading import locale from typing import Dict, List 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, argv 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 _, 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": 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 = 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.") % 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(str): """Escape a string in a manner suitable for XML/Pango.""" return str.replace("&", "&").replace("<", "<").replace(">", ">") def unescape(str): """Unescape a string in a manner suitable for XML/Pango.""" return str.replace("<", "<").replace(">", ">").replace("&", "&") def bold(string): return "<b>%s</b>" % string def monospace(string): return "<tt>%s</tt>" % string def italic(string): return "<i>%s</i>" % 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 _("Invalid tag") 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.015186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/util/atomic.py������������������������������������������������������������0000644�0001750�0001750�00000005343�00000000000�017276� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.015186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/util/collection.py��������������������������������������������������������0000644�0001750�0001750�00000063545�00000000000�020165� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2013 Joe Wreschnig, Michael Urman, Iñigo Serna, # Christoph Reiter, Steven Robertson # 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 __future__ import absolute_import from __future__ import annotations import os import random from typing import Any, Set, Union, MutableSequence from urllib.parse import quote from senf import fsnative, fsn2bytes, bytes2fsn, path2fsn from quodlibet import ngettext, _ from quodlibet import util from quodlibet import config from quodlibet.formats._audio import (TAG_TO_SORT, NUMERIC_ZERO_DEFAULT, AudioFile) from quodlibet.formats._audio import PEOPLE as _PEOPLE from quodlibet.pattern import Pattern from collections import Iterable 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): """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, Iterable): """A Playlist is a `Collection` that has list-like features Songs can appear more than once. """ __instances: Set["Playlist"] = set() @classmethod def playlists_featuring(cls, song: AudioFile) -> Iterable[Playlist]: """Returns a generator yielding playlists in which this song appears""" return (pl for pl in cls.__instances if song in pl._list) 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): 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 self.finalize() @property def songs(self): return [s for s in self._list if not isinstance(s, str)] def __init__(self, name, library=None): super().__init__() self.__inhibit_library_signals = False self.__instances.add(self) name = str(name) if not name: raise ValueError("Playlists must have a name") # we require a file library here with masking assert library is None or hasattr(library, "masked") self.name = name self.library = library self._list: MutableSequence[Union[str, AudioFile]] = HashedList() @classmethod def suggested_name_for(cls, 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}) return title 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): 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, leave_dupes=False): """Removes `songs` from this playlist if they are there, removing only the first reference if `leave_dupes` is True """ changed = False for song in songs: # TODO: document the "library.masked" business if self.library is not None and self.library.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.library and not self.inhibit and songs: self.library.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): try: self.__instances.remove(self) except KeyError: print_w(f"Can't delete {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) 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_, filename, library=None, validate=False): assert isinstance(dir_, fsnative) name = self.name_for(filename) super().__init__(name, library) self.dir = dir_ 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.library 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"), library=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, library, 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, library=None): assert isinstance(dir_, fsnative) title = cls.suggested_name_for(songs) playlist = cls.new(dir_, title, library) playlist.extend(songs) return playlist @property def path(self): return os.path.join(self.dir, self.filename_for(self.name)) def _validated_name(self, new_name): 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 class XSPFBackedPlaylist(FileBackedPlaylist): 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, library): """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, library) new.extend(old_pl) new.write() os.rename(old_pl.path, backup_for(old_pl.path)) return new def _populate_from_file(self): library = self.library try: tree = ET.parse(self.path) # TODO: validate some top-level tag data node = tree.find("title") if self.name != node.text: print_w("Playlist was named %r in XML instead of %r at %r" % (node.text, self.name, self.path)) for node in tree.iterfind('.//track'): location = node.findtext('location').strip() path = location.replace('\n', '').replace('\r', '') 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 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() != (".%s" % cls.EXT): raise TypeError("XSPFs should end in '.%s', not '%s'" % (cls.EXT, ext)) return filename def write(self): track_list = Element("trackList") for song in self._list: if isinstance(song, str): track = {"location": song} else: creator = self.CREATOR_PATTERN.format(song) track = { "location": song("~filename"), "title": song("title"), "creator": creator, "album": song("album"), "trackNum": song("~#track"), "duration": int(song("~#length") * 1000.) } track_list.append(self._element_from("track", track)) playlist = Element("playlist", attrib={"version": "1"}) 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 _text_element(cls, name: str, value: Any) -> Element: el = Element("%s" % name) el.text = str(value) return el @classmethod def _element_from(cls, name: str, d: dict) -> 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) return out �����������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.015186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/util/collections.py�������������������������������������������������������0000644�0001750�0001750�00000012242�00000000000�020334� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2006 Joe Wreschnig # 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 __future__ import absolute_import from collections import MutableSequence, defaultdict 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 __iter__(self): return iter(self.keys()) def has_key(self, key): 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(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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.015186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/util/config.py������������������������������������������������������������0000644�0001750�0001750�00000035117�00000000000�017271� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.015186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/util/copool.py������������������������������������������������������������0000644�0001750�0001750�00000010234�00000000000�017310� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000032�00000000000�010210� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������26 mtime=1614542835.16547 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/util/cover/���������������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�016561� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.015186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/util/cover/__init__.py����������������������������������������������������0000644�0001750�0001750�00000000451�00000000000�020672� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.015186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/util/cover/built_in.py����������������������������������������������������0000644�0001750�0001750�00000016147�00000000000�020751� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 = [] 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) try: for path in glob.glob(escaped_path): images.append((score, path)) except sre_constants.error: # Use literal filename if globbing causes errors path = os.path.join(base, filename) # We check this here, so we can search for alternative # files in case no preferred file was found. if os.path.isfile(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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.015186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/util/cover/http.py��������������������������������������������������������0000644�0001750�0001750�00000007671�00000000000�020125� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2013 Simonas Kazlauskas # 2016-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 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): ostream.close(None) 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') ostream = request.ostream ostream.close(None) 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('Not enough data to get cover from %s' % 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 Soup.URI.encode(s, '&') �����������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.015186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/util/cover/manager.py�����������������������������������������������������0000644�0001750�0001750�00000026224�00000000000�020553� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2013 Simonas Kazlauskas # 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 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("Registered {0} cover source".format(plugin.cls.__name__)) def plugin_disable(self, plugin): self.providers.remove(plugin) print_d("Unregistered {0} cover source".format(plugin.cls.__name__)) @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('Successfully got cover from {0}'.format(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("Didn't get cover from {0}: {1}".format(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('Found local cover from {0}: {1}'.format(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})") 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('No covers from {0}'.format(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('Failed to get cover from {name} ({msg})'.format( name=name, msg=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("Got %d plugin groupings" % self._total_groupings(all_groups)) 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("%d artist groups in %s - probably a compilation. " "Using provider to search for compilation" % (len(artists), key)) 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 "CoverData<url=%s @ %s>" % (self.url, self.dimensions) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.015186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/util/dbusutils.py���������������������������������������������������������0000644�0001750�0001750�00000025371�00000000000�020043� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.015186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/util/dprint.py������������������������������������������������������������0000644�0001750�0001750�00000020022�00000000000�017311� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 = ("%2.3f" % (time.time() - start_time))[-6:] 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.015186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/util/enum.py��������������������������������������������������������������0000644�0001750�0001750�00000003010�00000000000�016753� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.015186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/util/environment.py�������������������������������������������������������0000644�0001750�0001750�00000005151�00000000000�020363� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.015186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/util/fifo.py��������������������������������������������������������������0000644�0001750�0001750�00000016745�00000000000�016755� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 errno import signal import stat from quodlibet import print_e try: import fcntl fcntl except ImportError: fcntl = None # type: ignore from gi.repository import GLib from senf import mkstemp, fsn2bytes from quodlibet.util.path import mkdir from quodlibet.util import print_d FIFO_TIMEOUT = 10 """time in seconds until we give up writing/reading""" def _write_fifo(fifo_path, data): """Writes the data to the FIFO or raises `EnvironmentError`""" 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: # This is a total abuse of Python! Hooray! signal.signal(signal.SIGALRM, lambda: "" + 2) signal.alarm(FIFO_TIMEOUT) with open(fifo_path, "wb") as f: signal.signal(signal.SIGALRM, signal.SIG_IGN) f.write(data) except (OSError, IOError, TypeError): # Unable to write to the fifo. Removing it. try: os.unlink(fifo_path) except OSError: pass raise EnvironmentError("Couldn't write to fifo %r" % fifo_path) 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) arg = 0 args = [] while data: if arg == 0: index = data.find(b"\x00") if index == 0: arg = 1 data = data[1:] continue if index == -1: elm = data data = b"" else: elm, data = data[:index], data[index:] for l in elm.splitlines(): yield (l, None) elif arg == 1: elm, data = data.split(b"\x00", 1) args.append(elm) arg = 2 elif arg == 2: elm, data = data.split(b"\x00", 1) args.append(elm) yield tuple(args) del args[:] arg = 0 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: EnvironmentError: In case of timeout and other errors """ 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" + data + b"\x00" + fsn2bytes(filename, None) + b"\x00") try: signal.signal(signal.SIGALRM, lambda: "" + 2) signal.alarm(FIFO_TIMEOUT) with open(filename, "rb") as h: signal.signal(signal.SIGALRM, signal.SIG_IGN) return h.read() except TypeError: # 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 EnvironmentError("timeout") finally: try: os.unlink(filename) except EnvironmentError: 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 FIFOError(Exception): pass class FIFO: """Creates and reads from a FIFO""" def __init__(self, path, callback): """ Args: path (pathlike) callback (Callable[[bytes], None]) """ self._callback = callback self._path = path def open(self): """Create the FIFO and listen to it. Raises: FIFOError in case another process is already using it. """ self._open(False, None) 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._id is not None: GLib.source_remove(self._id) self._id = None try: os.unlink(self._path) except EnvironmentError: pass def _open(self, ignore_lock, *args): from quodlibet import qltk self._id = None 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 IOError as e: # EINTR on linux if e.errno == errno.EINTR: continue if ignore_lock: break # OSX doesn't support FIFO locking, so check errno if e.errno == errno.EWOULDBLOCK: raise FIFOError("fifo already locked") else: print_d("fifo locking failed: %r" % e) break try: f = os.fdopen(fifo, "rb", 4096) except OSError as e: print_e("Couldn't open FIFO (%s)" % e) else: self._id = qltk.io_add_watch( f, GLib.PRIORITY_DEFAULT, GLib.IO_IN | GLib.IO_ERR | GLib.IO_HUP, self._process, *args) def _process(self, source, condition, *args): if condition in (GLib.IO_ERR, GLib.IO_HUP): self._open(True, *args) return False while True: try: data = source.read() except (IOError, OSError) as e: if e.errno in (errno.EWOULDBLOCK, errno.EAGAIN): return True elif e.errno == errno.EINTR: continue else: self.__open(*args) return False break if not data: self._open(*args) return False self._callback(data) return True ���������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.015186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/util/http.py��������������������������������������������������������������0000644�0001750�0001750�00000017242�00000000000�017002� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2013 Simonas Kazlauskas # 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. import json from collections import Callable from typing import Optional, Any 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(False) def send(self): """ Send the request and receive HTTP headers. Some of the body might get downloaded too. """ session.send_async(self.message, 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.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.method)) self.emit('sent', self.message) except GLib.GError as e: print_w('Failed sending {method} request to {uri} ({err})'.format( method=self.message.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) else: session.cancel_message(self.message, Soup.Status.CANCELLED) 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) def download(message: Any, cancellable: Gio.Cancellable, callback: Callable, data, try_decode: bool = False, failure_callback: Optional[Callable] = 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) request.send() def download_json(message, cancellable, callback, data): def cb(message, result, d): try: callback(message, json.loads(result), data) except ValueError: callback(message, None, data) download(message, cancellable, cb, None, True) session = Soup.Session() ua_string = "Quodlibet/{0} (+{1})".format(VERSION, WEBSITE) session.set_properties(user_agent=ua_string, timeout=15) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.015186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/util/i18n.py��������������������������������������������������������������0000644�0001750�0001750�00000026266�00000000000�016610� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 environ, 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: environ.setdefault('LANG', langs[0]) 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) environ.setdefault('LANG', lang) preferred_langs = NSLocale.preferredLanguages() if preferred_langs: languages = map(bcp47_to_language, preferred_langs) 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 = 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") 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" % environ.get("LANGUAGE")) print_d("LANG: %r" % 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: environ["LANGUAGE"] = text2fsn(language) print_d("LANGUAGE: %r" % 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 = set(["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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.015186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/util/importhelper.py������������������������������������������������������0000644�0001750�0001750�00000005745�00000000000�020542� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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, list(filter(is_ok, [join(root, name) for name in names]))) 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/util/iso639.py������������������������������������������������������������0000644�0001750�0001750�00000051465�00000000000�017064� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/util/json_data.py���������������������������������������������������������0000644�0001750�0001750�00000011415�00000000000�017761� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/util/library.py�����������������������������������������������������������0000644�0001750�0001750�00000007107�00000000000�017466� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2017 Joe Wreschnig, Michael Urman, Iñigo Serna, # 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 re from senf import fsn2bytes, bytes2fsn, fsnative, expanduser 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 [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(): """Returns a list of paths which should be ignored during scanning Returns: list """ paths = split_scan_dirs( bytes2fsn(config.getbytes("library", "exclude"), "utf-8")) return [expanduser(p) for p in paths] def scan_library(library, force): """Start the global library re-scan Args: library (Library) force (bool): if True, reload all existing valid items """ 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/util/logging.py�����������������������������������������������������������0000644�0001750�0001750�00000004060�00000000000�017443� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/util/massagers.py���������������������������������������������������������0000644�0001750�0001750�00000013720�00000000000�020005� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/util/misc.py��������������������������������������������������������������0000644�0001750�0001750�00000004640�00000000000�016754� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 environ, argv, path2fsn from .environment import is_linux environ, argv 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/util/modulescanner.py�����������������������������������������������������0000644�0001750�0001750�00000011130�00000000000�020650� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/util/path.py��������������������������������������������������������������0000644�0001750�0001750�00000032156�00000000000�016760� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2004-2009 Joe Wreschnig, Michael Urman, Steven Robertson # 2011-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 os import io import re 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, expanduser, sep, expandvars, fsn2text, path2fsn, uri2fsn) from . import windows from .environment import is_windows from .misc import environ, 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 glib2fsn(path): """Takes a glib filename and returns a fsnative path""" return path def fsn2glib(path): """Takes a fsnative path and returns a glib filename""" return path 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 = 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 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(glib2fsn(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 glib2fsn(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 glib2fsn(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 glib2fsn(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(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(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 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 expanduser("~") def ishidden(path): """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. In case the file/dir does not exist the result is implementation defined. Args: path (fsnative) Returns: bool """ # TODO: win/osx return os.path.basename(path).startswith(".") 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/util/picklehelper.py������������������������������������������������������0000644�0001750�0001750�00000005611�00000000000�020467� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/util/songwrapper.py�������������������������������������������������������0000644�0001750�0001750�00000010632�00000000000�020366� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2005 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. from quodlibet import _ from quodlibet.util.dprint import print_w from quodlibet.formats import AudioFileError from quodlibet import util from quodlibet import qltk from quodlibet.qltk.wlw import WritingWindow 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, parent, songs): need_write = [s for s in songs if s._needs_write] if need_write: win = WritingWindow(parent, len(need_write)) win.show() for song in need_write: try: song._song.write() except AudioFileError as e: qltk.ErrorMessage( None, _("Unable to edit song"), _("Saving <b>%s</b> failed. The file " "may be read-only, corrupted, or you " "do not have permission to edit it.") % util.escape(song('~basename'))).run() print_w("Couldn't save song %s (%s)" % (song("~filename"), e)) if win.step(): break win.destroy() _inform_library_of_changed(library, songs) def background_check_wrapper_changed(library, songs): need_write = [s for s in songs if s._needs_write] for song in need_write: 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�00000000032�00000000000�010210� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������26 mtime=1614542835.16547 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/util/string/��������������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�016751� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/util/string/__init__.py���������������������������������������������������0000644�0001750�0001750�00000006325�00000000000�021070� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/util/string/date.py�������������������������������������������������������0000644�0001750�0001750�00000002161�00000000000�020240� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/util/string/filter.py�����������������������������������������������������0000644�0001750�0001750�00000001540�00000000000�020610� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# -*- 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/util/string/splitters.py��������������������������������������������������0000644�0001750�0001750�00000007557�00000000000�021372� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/util/string/titlecase.py��������������������������������������������������0000644�0001750�0001750�00000006670�00000000000�021311� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/util/tags.py��������������������������������������������������������������0000644�0001750�0001750�00000023644�00000000000�016764� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 _ """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 _("Invalid tag") 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/util/tagsfrompath.py������������������������������������������������������0000644�0001750�0001750�00000005421�00000000000�020516� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/util/thread.py������������������������������������������������������������0000644�0001750�0001750�00000007740�00000000000�017274� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/util/thumbnails.py��������������������������������������������������������0000644�0001750�0001750�00000012307�00000000000�020166� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2009-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 hashlib from gi.repository import GdkPixbuf, GLib from senf import fsn2uri, fsnative, gettempdir 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): """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): pass 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: return new_from_file_at_size(path, width, height) try: pb = new_from_file_at_size(thumb_path, width, height) except GLib.GError: # in case it fails to load, we recreate it pass 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/util/trash.py�������������������������������������������������������������0000644�0001750�0001750�00000011636�00000000000�017145� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/util/urllib.py������������������������������������������������������������0000644�0001750�0001750�00000002542�00000000000�017311� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/util/winapi.py������������������������������������������������������������0000644�0001750�0001750�00000036632�00000000000�017316� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/util/windows.py�����������������������������������������������������������0000644�0001750�0001750�00000012432�00000000000�017511� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet/util/winpipe.py�����������������������������������������������������������0000644�0001750�0001750�00000011562�00000000000�017475� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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=1614540385.9791858 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/quodlibet.py������������������������������������������������������������������������0000755�0001750�0001750�00000000621�00000000000�015042� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/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=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/setup.cfg���������������������������������������������������������������������������0000644�0001750�0001750�00000001213�00000000000�014314� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������[flake8] ignore=E12,E261,E265,E713,W602,E402,E731,W503,W504,E741,E305,W601,E722 builtins= exclude=build,dist,quodlibet/packages,dev-utils max-line-length=88 [mypy] python_version = 3.7 ignore_missing_imports = True mypy_path=quodlibet/packages follow_imports=silent [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 filterwarnings = ignore::DeprecationWarning markers = quality: Code quality tests (e.g. PEP-8 compliance) network: Tests that need working internet connectivity �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/setup.py����������������������������������������������������������������������������0000755�0001750�0001750�00000010711�00000000000�014213� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/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�00000000032�00000000000�010210� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������26 mtime=1614542835.18147 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/������������������������������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�013640� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/__init__.py�������������������������������������������������������������������0000644�0001750�0001750�00000021014�00000000000�015747� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the 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 xvfbwrapper except ImportError: xvfbwrapper = None import quodlibet from quodlibet.util.path import xdg_get_cache_home from quodlibet import util from senf import fsnative, path2fsn, environ 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.libraries 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-")) # needed for dbus/dconf runtime_dir = tempfile.mkdtemp(prefix=fsnative(u"RUNTIME-"), dir=_TEMP_DIR) os.chmod(runtime_dir, 0o700) environ["XDG_RUNTIME_DIR"] = runtime_dir # force the old cache dir so that GStreamer can re-use the GstRegistry # cache file 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. environ["GST_REGISTRY_UPDATE"] = fsnative(u"no") # 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) environ["HOME"] = home_dir # set to new default environ.pop("XDG_DATA_HOME", None) environ.pop("XDG_CONFIG_HOME", None) # don't use dconf environ["GSETTINGS_BACKEND"] = "memory" # don't use dconf environ["GSETTINGS_BACKEND"] = "memory" # Force the default theme so broken themes don't affect the tests environ["GTK_THEME"] = "Adwaita" if xvfbwrapper is not None: _VDISPLAY = xvfbwrapper.Xvfb() _VDISPLAY.start() _BUS_INFO = None if os.name != "nt" and sys.platform != "darwin": _BUS_INFO = dbus_launch_user() 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": environ["LANG"] = locale.setlocale(locale.LC_ALL, "en_US.UTF-8") else: 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) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/conftest.py�������������������������������������������������������������������0000644�0001750�0001750�00000001700�00000000000�016035� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 sys import pytest @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 happesn 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) ����������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000032�00000000000�010210� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������26 mtime=1614542835.18147 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/data/�������������������������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�014551� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/data/2822400-1ch-0s-silence.dsf�����������������������������������������������0000644�0001750�0001750�00000010134�00000000000�020500� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������DSD �������\��������������fmt 4���������������������+�������������������data ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/data/5644800-2ch-s01-silence.dsf����������������������������������������������0000644�0001750�0001750�00000334534�00000000000�020610� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������DSD �������\�������������fmt 4���������������������"V�����������������data �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/data/adif.aac�����������������������������������������������������������������0000644�0001750�0001750�00000010000�00000000000�016111� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/data/coverart.wv��������������������������������������������������������������0000644�0001750�0001750�00000110071�00000000000�016754� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/data/empty.aac����������������������������������������������������������������0000644�0001750�0001750�00000005021�00000000000�016353� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/data/empty.flac���������������������������������������������������������������0000644�0001750�0001750�00000143330�00000000000�016542� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/data/empty.ogg����������������������������������������������������������������0000644�0001750�0001750�00000016660�00000000000�016416� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/data/empty.opus���������������������������������������������������������������0000644�0001750�0001750�00000050511�00000000000�016621� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/data/empty.xm�����������������������������������������������������������������0000644�0001750�0001750�00000030544�00000000000�016263� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/data/h264_aac.mp4�������������������������������������������������������������0000644�0001750�0001750�00000010703�00000000000�016463� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/data/h265_aac.mp4�������������������������������������������������������������0000644�0001750�0001750�00000012732�00000000000�016470� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/data/image.bmp����������������������������������������������������������������0000644�0001750�0001750�00000002212�00000000000�016330� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/data/image.gif����������������������������������������������������������������0000644�0001750�0001750�00000000225�00000000000�016321� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������GIF89a����sssrssrstt������������������!�� �,�������BPIBXا7JU%+^Hd㳾NV2r @]`]A(اI-AmC"�;���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/data/image.jpg����������������������������������������������������������������0000644�0001750�0001750�00000001267�00000000000�016343� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/data/image.png����������������������������������������������������������������0000644�0001750�0001750�00000001055�00000000000�016342� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/data/image.svg����������������������������������������������������������������0000644�0001750�0001750�00000007226�00000000000�016363� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/data/lame.mp3�����������������������������������������������������������������0000644�0001750�0001750�00000004046�00000000000�016114� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/data/mac-396.ape��������������������������������������������������������������0000644�0001750�0001750�00000000150�00000000000�016313� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������MAC x��D��,����������z��������RIFF$ �WAVEfmt �����D�����data� �X�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.019186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/data/mutagen-bug.mp3����������������������������������������������������������0000644�0001750�0001750�00000003720�00000000000�017407� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0231862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/data/silence-44-s.ape���������������������������������������������������������0000644�0001750�0001750�00000224141�00000000000�017353� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������MAC ��4���������,���'���������I C(|'|<�����z������D��|���RIFF$ �WAVEfmt �����D�����data� �YE����������������?��ڪJN9T�`T������nhO( �����Z�OC)3 ���������������������������������������������������jU 9D� y����������#< ZJ&�������������������������� �k , ng} vibMQK���������������������������N��k[+`娺 ���.6.������������������������O�nfB�8keFq5N^  &iޖu 𜮓; C��^�����������"|[I'E&A���X.混[ܼ�eV*8���I����0���6 }q֕"b!V���&�6"Nl�+JF#Fl--6FھQnhlCnR�8!tj Rs Z@Ќgjϑ#+ғ3~ Y� S#dZQ4/.�~}�����7{�Gw�������wmDLUZ귀M.u5*G�xBHn[.�m@�q$��^n$HudZ/z~`]<h`���9�����������J`�?%M]~q*ku T(>oއ`lF!ung mX^? ّ=|} ͖����.�BY� ����%j�5mh���ډ2��E5��ÎT"0QجpĻt�=}+! MJl�RP�^-7(P]έQRzvG\pQ��=U=h^$I^Yp���p}�2K]MkC~.d;*F�uT�Eۿ FvQ.z,z/9 2{M3nJ0gfhJ0"Ck)aN]L ϙ!u��]��;Q=LJw݉brH]%熼;pZ͂&Q?-$ŚlŚ(f%7,YcE0Cי1xMJ`E` T{����N��4>w.P�g����0�]|zYmmKXvck�~s(xnX3��فobƅɼx t�G^\'6B{gGcC LUxb@pXV^uNQETqQx`G$S7�ǙWspQ3"maؐҢ}}� ZFڷ;Ffؒ{f!Z> V#1mƺ"}����.C;0��������\� ,BF 8l��XOiw�7м2mB��Du $z�T<enI7T|2 DfN[B ۵{-wy+qDכd,&[ 4CK]bmgA RO��Z�� "H G�]r7BqMw#ovgW,iܮ|$GRWs} 619n<[K촾V_9VvNJΙ3DP]u?5 űv徥3@zqI&"~7yړ~,K:=& #.ӚrZ!6X2>\Zv¦ܷ|>j[ogĔ^˭u>~甴<]VE *6ESmLD5^,ulf̻ �m}Nek} ]Ի:KT O`0�ykeFxkAJX4Ϋ刯E0XЖʦ!̘J ��߂c�>jǶ*k&zK"LI-Af Pn2 \���k{-o PxVaWN8 A$j���hXʷs|7Mr<FwTE})[ǾsX5X;UjZ~O ?jajI �1LqAm+? Cu���5rxSI[~ ;:2TٷDƿРyl7Vh"Fp�8w)⦖Q}AF k9\Zw?DŽO%bwç k /۠>^IVu@hX o`cq6_ E񧇟c1dž���E\6��/zL5@"c\yޔS310P%{MbRu?>LHtj5l �A԰|egpkٛ(&zH $πw���q_PV4ołK҃ENJ".?R��wͻkX)�Dhy8d yq "4ҪL`F2z wGL0^aKM$>t3 XOh_{>0lCj3bV_<K/Nkm6G';'%73r��moѻݏDNDI(j$vWV=J h~ꦬdJ�m�I����`�v|ӭOdk9&zf]ٛ3%VD{a/We _2ia8OsRpD۾GLĠzgcN/x|~wB *=PLLk.*\zxCQ՜���� ����.6�LH/(1~k ��2#˿ >&cT\1/u!q1'\=َt\UDlW֮鷞Jh�p����� 7$�) �, f<rﱀ%��"�x�k X2E.r\(KJѣ+C7˅u�x"F��ݹs\b ]$�pXa���gn#zN ֮̀����0VxʶddeXC!Ak8~+WOSn_ސ< b4)VJbl0>t|&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��~yYNTSIE�xo?7;I�p͙\ ;2+>ZV^ׯ,ow?NKդsa1׻ٿ>A"M0Y4gFyV� x ��{�j6-mz@ 1?ᄀs@5Ddh?%P���ir�������� Ymp^�B_gLz2V˘&C"# v^ԥ�ym5Fxlq {89�@Jr@R=4&c\k Tϧ'z'|.mR��D؝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ٴ%GElO<IJCE�s���lƤzR$<>22 >.Uߍ$j4?&ݮ&�ȊeLlGWE)Gh$U6t &F#mcmb,�</<]r/Ξ/5펐:5&uENg|]pfJ˾=4?a<:!lMT@/Ɇ'9U+tK:*Úv9wIluWAeّe<U2>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"A�RHIp/"I��ʗVKty[ԒN@sz-JVf�I N|lCALEILqqG=~ ` Y qo֢8gj?$/G,Ώ_ (�/O�xVf[V~��$t�������~<W>%y�Xn(1=>mϗgbe{);k׮pq6ˉ3dMWR<w Հ<75Ŕ  . m*Oמ=G)�P'xyQX+M sHܞU8!(bdyJ*szU%�箈sY8aV| {Cޡ31P 1t]QHpy"sNzsjC,6UPJV0n ո��(}�d jd�@L��H7S3CxBmX5=w~H�<a��B��ROe�8 n u'% xv# 0RE[Bou<Տ*�wn*/j|x4jѲϓ�J3_Fᖁ}( #_Ծi��w^pUvE{F&���ufɭYA(3 Nm)Vsm k禝s+Ƞ/WCa@3It 7pI[Ee|[|!��@CUn&%(*_d3,Lֿ7��# `=p1IV $*0xK8o�D$ ^\$SBٮG߄<pfT4]vrl9G}�eɃOF�/n�gظΙ�y,PyL\[ߪ &# B(ϕ!L^JP;=\7>w#y@D�# -=kGD71�8 f]�@waWYP`cX Xͩ}uULP)sɟKvEz \0c#]2'mWZx7H{x,:6yg҄<B{V.v< ;;v{柭n ,W5`qB�f-3.GF A 4T%n50T>)#m�cjLgS1^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/3U�WJj]H+؈ �('.�p!Q8��Pvd<>e2NUͯ)A�XM?LTj rr<Ầaǡ<cDl"B3,lMw̜ "õn[�(PXdKy-u*Gdn9%^Em" g6'fnɚa ڸR$@9�Tꕫ+/��1���<xu„R��r  �ǐL�f <�eID7`��LSܑ���gȄ Q1g<(8~!dhL O~xf/Z&2�aB%*+jKQ4u-H/͵\[s,Hf�Ig DIHuARD��|� Á�. Y a|d wWGVH%cLH�1"���0(9G��[<<Di2�.T[_)BҤ]/4d3P%���&2���4,#o&\.5T&]ƀ)@Q��w/Hf?B~Ù@4��h* YI���p�1g|2lDy�� ����tCJ��<G7GredTBb�q���7R充fɭ\s+uG&שi:Co܂_$!=0p ԏOWY`0:SIÂpo :!Zd^3 /WvA`i`Q/0{͘QXFQRj%M7'�ا!HF@X@'&>]C^9ݕ �& ;ŨbĽ3C!il;�؎[8g[`i F`߿Svgo ~Iwԏu k:}@ WD Y]8pgkcډLVҋy$c �&4lc$?gb@-Em�b3v#�[6Gjمe,YZC�`"xo8џ޾ 4<w(7Z:dUG3DXd vlҚ&�tWH=^Esxw]Ga4$D"g�0.?-<d,[gފ0pO0}&)��1_da��r̟2F�~\ڪ@) ��--UEt 35J]ҝ*27uثUEa\m5H!)u޽)Am\\�h_VĔޭ2~v7NqRl7Z>.y;ML1(yc<HK{k=B"ZpOWFnkWGt1<I�_:WS$B`FwrvE91/�ݦ-^hb׹P[S sKxlXW~LT]-(;(jnBrK;!СbO5n<d-'ͼEs% Jʻ[OGG�qN�+cRj Avu1۴PH˪ 3_ ~��tHIQ!>^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.<sMbK Z3Jav /E:H~d}ds͠7(bguYtkQV� �洲7h!Aij/+ ~I+qzR2���N�8}xbx���9K`_N{L1Q���ti�'َW Tt״Xls //s% !=ҳn@Sۯ!("L!Zxj)s'� _`Nnm!(suh4Uf%B+s[Bo0(*!;/%>Wy#$yǾD6F'z&qסn?dOՑq?;cO-p R:6ٰ"k^tvF+(\Y'xwƀ&Vj@:MY-݈V(ᗜlT6|ZkNVxL�D*ÔECv&oQYC L�[h;g��J4 o���9bSpDE1,'8���p���c/0<tBh̀Ux[5yjŠ��T(}wZ]>~K}eb,NFFRg6i7 XљJGUG=l}�u<5־vC.}g�c(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=�vh5P�vף6ڗڕh_k�tw0tIotr|S����+,z8 �=�c��9��|U�;���?Ѻxja$P%T/���̢��VsU:F\mKR΁oϾWM?}0FzR^ 8Y/*SX*goCIA4bM2=XjN$�vѹYېN*!V\楇hB:Xt{jD]h?���>kݹU��6.*8' !4ӣ1~21G?Ioxm$"�\Tdܧ:1 �=!A9X3wD3pVJ7"ôӿS7C�#_[,)h@YGh\<PAڵ vBR%l Z>ze** 7�I �� ��������C�h7Y#Y��}5RlYK|�Sl�s��U��������6ST(H��� ����,j +XV1��qi"��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"Y�L^bvLw!"�3#ZT :" a3h6�' x�xLj^AdO ,nui&@Mݾr/MUx" =NkRLj 8_9>6]aïzDŽa:}Wt.V'uZ}6e NKInZ!N{vdٝ\e��u)j4#(��hh'�$`KbNCy�lLkѶ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_śͮ̋ (r1�YǖqZkrLoַ,D#a J=b�)GzOjӖ"Uc$⼭Z;,lVZŰVD�Y'rR90w4!F_hoƭkN�\BQ1KTI Őt Hox;V?HݽlW+K:EFS|UwW@Fġ�冑���+-V$=ljf5{]/ ܣG�<eAW �4/ !Q^>fێ*S3/u^7߬ƙp߱M>\yC [$,9P MOmv캀';Ķ}N��R򊧑 k%TΔ@Y&-6;*W)Lecar.m9ӱ3 |}׮�^x�~*(/K!DQ,l: !0La  Gi9(=dc5Ȓ:bxTǺ6M}<Di,.Z<C[#i;53t"y XPu\gNE$�0��CZ M7y���MvW 7#ys,V֥uӯ&KbtfgJkdjf3qjMə~0" vr�V>!͖A R{ƀ 1Rt7-cYz.ᡁ0,A2pߣr /h+XҾ�V��Bfy�/4z5vR��|�_Y\Ez0 Y%;�V`�1i2pFK/y:q*)kk/9kSRF#^ �D3\tj��"T=�p1*�¾\:�͑s ���D �; H���nDD l[fhmbF��#eKXGr" aD����[J]>"Q��$= �L\!]dmPəQ���h!!8x3 aءG@ܻP` �$9Pe_]+Rzqe_XO`g[Q5@)铇gmQXuncBEcXO.9J�DgKz*` X QN!"K~+c87>?!wOS8>Lvf+5WD\("תP|syIz lp��j Ʃ%F](0V_W�6̥l=�skj` |ڔ,rC#h߼DQZ��[QA�rh8�Rsq�$z'7ȡlT<WbєAM0_|P.���w%K6͹n 9�< S%Z3# Mv,"o[y0RKf%B hpĊy[7K‡U25_g L^ YYPq?FǺlcVW6qxpP .�) CXaUd ,J^ ZT{-eKYəp]Km}\3w �%g_R� M\?T#]8]Ĩ(%[5h!*pDq+W(ĩrl�=&r2DV0%< |گ%ڃM!k݀."����a%��2t4�_b6bYP5ߨB4˴$[L��dac��f%֍wu'z?Kjs MDG\eרA5 CK-ɧ-ħ_a*> "~zڎƖ�fnKA=%II Zm VUtUPa-˨ Yڞ. wڎ-%.Rr26BR2FUO9;z9=CeFH!s7`Y�Z[`fg)+c/p넲wg-@m}%P嫘o֝GcblU^ (^?`źj;7.R IS^.dcȁ[yW`�#^-ե /AfB~}hHI$Mq [s?/m[%fQ'QqS#cǀ2ڕgr7J�JAP5o[Nq;a4^bpƯfRU1z s=/ǓD.Ƭ�o,!nRR,_j[4 x@m)H@mI em7GR=8d&?JSnO(><o_!t5 K # \�� ?}q:Cf �E4:&"ԙn tr&_i:- {' /1`^[5jv}$SϏp%ʀF^4D-`s h@2NƗ�5! w�&LuA|AL#v*xx^iWXF[(8#ڈ컉2p.$;'�Ye}.�Gtj?bfk@4N+s�%M���� yRnfX0NlX��6mK)6QyHJ;}H8uw f 4m�w=<̺J;<j}Rw!Tl. Cc^ԍ$b@ $#;+Ѝ$jFÕ @ߑ~��D$��̻㴫jsZ6pH4 NuU_9T^�oT>әƅ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+8�K�a]_|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<oGD4^IM Ң[ƥ+b|yC]lY-q(9Z]ՑƁl¼EPT?C<܉b^³_ƩWO$l�6523&Du{75GYFmnmTZcPc(往P/fVA|0Q(3~uy /Q\t8=Q(P)~�z��ʳ&zE49-�xW��������?+�� 6fSbJ=^D@Vm=r`5[�Հ`������@�^P3"L^1s��6 �衻g5cQsaV0,buLg� D���Kʄcn���AX Nh0xU04�.�� UUdLvrW PVEU3zaƌ(2q:O<P'[)L)Jn@=nZҎ/<8<��w(<@!xC]nd1)4�� t`j//ڢǎaMOՒ( @bgz8>^ThRR ��D^,X�3G<EO.<6 ߀UQjFƈNLRZ[SOܝ#x1qZYsGb`^ja�hq#UDx1C�oЦje5o�T;lAPf^=kgy.#d��<���=Q\UV)L7?9 L ޲dSVؗXj= qr )k{b5z8VR? @.uݫ-ϊ:l?(cFK|Uth|{WIA�9]32 M%\P[Hx]+K df q<9)u<c3%O�q/M-<suNml#VAtUK쏀rH@��JGAmך%|jQ+�A #j0Urvti 66b�]��Ղ~�lț ���bp P(h9ؾi߶EAK 7J؛EμX!4(ˆrC/ec84J z+�CyH^l9Y� oeM)(!Z\Q{}%Dc =y尘Sꊝj<̬`_4􏇞lG(M[Zp�k�Ǫl/e'%;_nR㔷 =|O���miC�%&0jA/j_{ *~rFe iۅ縣:D&m#]>W҉#;wR&4lj4v<B'BY1e|om8��Pn"y�0OBee^\ά=$Do従HEhdf⤭5ٳcgtؕ&萴<0o1/)W}7vjMħ{s\ b? vg ,F  rI/ĄD3sE?.F@Q2,s|*jυ (@} 0{I/IS2&AAW]_Do.=GP0[ 2o%Pޮ١}-RsV=PV\O +yp(j|68L5!|FU᧶RP pQ@s$1~70lxgo-UCZ 5]ثYU#F \ta9Dl,nA5z*%ۍ�`d\[.}kP[Y bmCWP/&tؑ@TS|d!B+N=?]T\Ө b %�Lこ+܉]6k^mSuiX!|ޯ]s*+ri�L-]:PrnȄ᧤!ftbs;r@7BhOкWi(E$f|t +\_�RgGxLPL-; NjzQ'.�}!| isdJδBZ.Y}N9#I^XĶl0/w$8d{<5έhVk%�xaɡTt�]ʪ'q!>v 4Z>3WXa{G �d ��<_\Cm}5+# 4l (hRu eDGD?1��6nxe 4vdʊ㓌s޸nҭ<T,{= ���"2; |sfs/<eȮꮧdZK;6~=WP�(vܓ��� �ovbtSI(bCnx%#MKnH䬫HY ԥ6oOl.9xf_iJ{X"=\+�r>h%wM:hTjTkʩR%w 0d'�]Yrb'_ڊG&KamNNfƦ ̄n4\|$$�Y= e{ V H5N$kN J_W~ #ž%?@([%F~"H^�ѹTX�4J��5�$5 B,Ž4WcE79BC]?#&bC_D׫BdJ]�WL0xK+dVW!� )�������DzMƍ �Mjs�p=iĤDYv"컖g'��� [ ����̞����������,=h`كM�ؔ�`E����'���mPצ]#p/7X?C�ux40=~AML��<{Pt+hj�hyŏ�ݼ˱ |��lo�I [d 8 @�= skpGx6coy<)܁h",ТV4.B< ��`��_ �`xŵaW@iJQ|�=W@xB$7B�,|UkC lT��< H8z8}�['"Z(s迕: . 7hX4<N1 �[Q,~V|'d6YQ!�-s˒WuS]Ձ)xGMNۑ&,=2܌H�]X]rC`r P"C^A(LV8>'TZv}=ѯ@JfE&.̈j\G�f3F`,iuּ��\?$�MU?i#5M3yK:;AU\JV>u͑7&bH%Qp$}߿@L19$EH e6ӌf뮎73>8=,1ڽ'6CzyK=Ӭk2 zTZzU@8v| B�O��QbX} ���菙�,>/��Z�HѤwMEi�?+ZC\ftjԞH# e4+g]INP2B�9BւvOgm�skzL6w$wq۴O'$4ݖ:\ Mab ;pC{OԒjΉ!tN  6ξ���(RwwbJ�cV�$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,/s������oP.Txa9~%x*/VL> 5'uwW-K6)X|!-aE�#bNlVwl"LI`e2bGyf8G��X���0GwdAFƊhv?f,UsH<e@.'4Un85Md9Oe`m,jh3�J@Mt<*7t(Y~���e=b�&smR��8]����en;sAcRd4!Vi}uA!}2x:uG6o_1׶?,�'(dt2|xgiz8hW 5U;��Ҍ>Vv1Th �X$q1Ū Y>* c2gÍΏB%yҐ2sڪK$��`)Gh-oPAPV^(kt!^W%qUտL�#֢}<<�^}9<ݠR|-sk C+�;8M��=?#y$ c 2/zSq7 J�VH'Vׁ eQOul6ym@:LͿ6h8Fpi2v+<nJ-2K]dY<'!K `�t^'RCRpiOlKe��:v0 HDS]�^m  =ǒܐh QD�ɿ�Xp$)XMwr �L/ط-p���'�uB+�N]wfLv6}4`r;N!�N/p Q))7x|1N Z9QoE9; �S坩 o3NtP Q&-ظ3mXa_ll4ZQtU -cp%�\~�%:3U; $ 4z:�=^BB�@Y#M0k�԰z_ 4 & :'8��`v{kN�d�T6y1Hf�>f:2su �xo[xjb~J-��;Z�;3Hbo��8#H@pI;%y=\�=M"��71oz�+hr ܸMbch_��B1��-d��������2w�BŠՓoɢG ;���4:)'JU��t+v�b>|�����y0`h.dI6ۺZ�����������ك�ͅPT!��c�"E,H0B#/·�h����F��i�u_HrFQ~^l$����"�{c ��#!%��35y�x{(M�<��i? ��%z"��6=d��Q �@fBEO(<`/4mqw`wO$�wF�X<���`z_-F%~�?U1��2_|��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<_d<OZ%Q+Q�R�e�䇜yx<t,0"(%]d'PbpG؀��I))K4Aycs/7p5��>p�8*|*kb1nϳM^/*3MT V/RxUY*0<i�-&J�[@A՝g�䰒TeA*�=Rh$t7����~)㷄 "4����B\tF �0fC����YӲ�r�PĈ=���xr1�Em 9H0ϢiJqGbj_(d�BR^z"��QBFر~^n]-�LA.4FH0�����pTO!R.[I[ẃF 8s B("eX:VFn,:BB�< T8&XH�>D @ r`̇E�H4A/{KYk)<��pq ��.ʓ� dטFU8��H%�Wm�0����(<��������PC��w8Uh����ରq�$#tI����xu����rF�>��Q,LBfW��`,4]# c7xg^l xMP^>^ҿCGto����vV ����Pn�DGVѨl\q ꉑU1FIEolq7O7n}"LHø.pP+ ���x��������&j ̍3"2ך leRdDkG+z@p;v7� TGZ��������uB8\<�rKJB3D�4 ���FΚ"T4[k C z0 �)FPB5&"8 % aMckt[j?Ӊ Ұ@3/���T��������h��0;7,�D6z2}  �/�m18k��l&����1wZѭ.�D ygϖ^�OfX �n����^Ydn�RľTdu]z\���KI'�v1rqY� jpN���c����pi?7ɪ)�Z{.����5C��e !T>H{H  rU�� 8��pqF-�%kbฬ�� ��������%'���������Rm���P�\ d�E�%:._{-p!8 b?~>C ���`j��Nra�|@N$g([h y5 Ce0KNsZ/o�}^ uS:0¹:{q{\j�ee*4~ )�jh5#'k@n_5h]7#[k�TVDk=( G<�(q(|G@�o2D3̾BaUĆ;ugsweKC5:q3k11{Izx[^|AT)/ |gWL@p6|%]KH9eQ.yf4�d�-wM�G�A' ��7.q'@Fȭ0]99a+i]H�e+8k*S�!Z%5`{#Kh~<oe �HY����y):<]nqc۱R9Q'|<;>By)hOsAŸݲ4wȧ>9��n��I�����+K6PC8 u^ gըUjtl.psútU 1:Sf)bD`C&dVkB ;[ّi� k Eap_{H+x CP5',TL,ш�diF�N)������\]$  Va!#8��-�r1:L ���tP#��#m��TΰZƩat\n.�5���5]Ʋ�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@1Ov��U6NOUkۯ�^,K��vW&!7Tn3:�h/JI6_7]k&�NlW]<[ J6훰-Xz}c1*)9giuH-�%h?-Cva8FqK?�~|鯄~�<FҨ/t|ʋ��rY%��^2N�^c{s���!���l*W)a<ߑfJsH�7O4 ��85����z�Z@�*Gbƛ,W~aMN|\A�br8k/p^M�;�`�I@|SAwX���bev˔-Q/-N?EU0WҚV�PYИ0�V!S cr�wz����nAuqQ3H:d>"/%͋aXgJ"+ ~Y1X׀p% FA/MG7F(Jſf��B��)sTLUD8X2"bv1>L �ːk�KA~} ?b_0PM�e*����v :bUPTrY &Mx~rFX R &ն| 4�4~��OJ|��-m@�m9C2��A;>wv-,��a r�ra [f\|Joa3 UZ~#XE A{!I XVs;qFzUR/.OR7B�$` ƶo�48Tu,Q`*4*z2)$��2n qD,rUK՗3�&?nJIgXPG4NUm@ifHH,Y .eչ :�ʹ0(4T)TZH�|꨺�wL M��l۝5R[B2SgXr`C#z���!*6o��2i3m2"-= ��CjgKڮYY^p��`qs�ҫR�txnR>SePIuAߴg-:OQֿ!y� t��0Y0w&k2#|5�D聒a">l?=h�1M,��sٶy,+hGhd*76'wPM)2!R&QqnV<{\q<|���(j;�"H9)1Du�I��zIP�v7��������t {—>��tţ������p59ר]ȗ(�T>iF5=^���J�-]=c~ Mjh���\%�q~YyhWl8 p�>UcXfZw[NR���H�e5*�eM=-1��f����h&PCY۝�@`AD~3@5?NGz&ՄIfYWTjQ)<!ab?I��K,#P�O6-k sP'bZ݈��5~�[j-�6H������t6L6����GA�ZňEu���=Ak�lS�d�I����rF����Q��1������������C{��q;p&gO&^� }v����&:I���8u���� ��������$�ЏSa��$����g��9YBI��*�PY:��xGZ^%]Sv*o"��������4)��������<U\q oJǽSIͦY8&oKuH/^�a6^��!(0ӿi�T݁x庑�ZsӡbtϚ9ǵnLnylyf��9H����aN,Ns%9ZF-�RTƣ�"h2i 7\IqM(K߅tQh1.d34Z*A1sԛ7 $6t/)�㳣l1hz|4 p`N�e=�t?lm%"�M�NyF\�$d"b:H7mhJH#%Ζ!9tDl6v3+_`ecw- |f~z[C}+!cP.cf�5mrYKjM#H^hFUYN K2 />-chٺ7z)=b;^|1Ƒ�![`D'Lӂou5ݏ���,����3��H!�=1،%/Wc$^BX�X~kQ�2mrŠwy`'Y\΀"M`"<MO|�gֻ)c : ׆U/��P����+��'1,RSˇq�d$7퟇U1� �[CH&\Fi띖IYmzW e^)xηpS&5] .*�3(k/X8P�EG��Pn.��djtA+KtLxWO�F-��\|C\�����?cr5DG<x�eŠ99It�K9n���pC*�xTWm�q-L}p%fpF��ԩx1$` Gho��� ���B�"8_ LVv*L~c}C��43�;6Ne|��8]4cl9\rK]5dx~)[}|qp(�,:3#JUqZ�(Cr�+�R4\)r������byQ r���k7+&��c�N�H!�h���d hHh_KL/��LvpB"扞*$h&d �uO�}O����vHVU /9#H}fbni�fl���D,bmEo]H;%Ӯ2JdXV/' P)��w#u {:`zM-JP.Ci,C##�F^Y P2I����K/7]QǎLi6X*��Fn``c`_§z3��8elWU��jJ$l0 %% ���N4 Ŷ,ԡ"9\T��L_~2�E֞ÀDq�c��U=i ԡL)���p�����rG;<-0e4/j8t=l��~9uq歹oZb0/| t(Kw5 d|~ɞpSP��\taOdQٯJb����$%$Li��,( |ٺf40iX]Yȝ* \QEI�\K`w65܀�P99D۾F2 -%T2[ v+Ik9{ Y8|d6|4̴? ����pP-5 $0ޕRXg40[9y/Ve����zN�I% vxZO€bS�������M���ӝc%HSnXT;~��3ݦLXIC=����L]'0��4�"TSaMDwJBd��������PU#�Zp����������Č%~��G( ~X-ј0+0f{IG5~d+-^N OZ �z l�� ^9D=c�@BX޿ Tp%����������)>BS~@?dV>>iO9 ,U4Gx�:���VLHyވf/߃^<x.Pn4��!%����ɠK��;\5�\:]K@�|x ��+_�75{d�����������s$\jKIM<k�J=q.L:�NGwq*H=!`rp58酸I��)EmG"r�fLVXI�%3Y !ːsCd,J;O/<.׏]1Su<)tmBo�KJoo4W\1дo�e G(% TB9=bfMdGxr`H5!HAW�YII4 v*PVM-şbe�h`לS ɰfq:3y����z4 �������%����l��������������>5TlѐrNL�P���ۨAƸ���m%WoeRRyF$@՜r>>2S5jS�� �Zd*`"�x{fS.EV+ I4Y1fu ɭ� Q渽R�yz,kA d%)t@=l cgױEOj= 8'.ዟ޲(iR�0!B�)ݒ?Ԕ�86)<Y3�-Ks�Յ< $i_P.NX\@ޗ>Ow[QI`Ɍ' ÛJ;%I����qe[ E $/_J _\O7>$x_ߋ xC#UJ# 7ѰR73Fd�9i�eX5IZ6a*JۤzXK~$x%DVֹXjmzpjS l�I _mbg"h�W����-�9JK24~Ï)fNL A{*`̤ DrcO!BT�n*,5)2a VJYT 8����bB�d[.wIl_�=bMJfX) ~��&[8�M;U2b4�4$B"<5O���f9i0vu%e!���DZʧ8 Ԏ@��M/p7D ���q_�9EgNt/�Xž;!io!hQe<vCзS { �e(<9@sd*E� K]_1rI }%T��Ɍc����-w/Ow\�E ��_�- [ӣJ('r 8Xm+C=�p���l=�P.b<��Ӕ߂s.,WS fa@o��� 7OG -;@ ȀxD�,PQ���E·Ogۀ�㵈c>4p\ ch4 ��>!GJMgE !P\O`* e)}'! x:N勹<J̱+<^zJ `ny��Dl �/Z VagL)Gt mrAq+�cv�aM|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[I��2O?~&)Ǯ���4 &95��� W��kԸ׀i[bw&Q {3WL߮bw$zm<VdcfK,Җg< �`%Khx5l+C9Kp[/n�k=.=Ϲ_�M$&D[T�����$��\�Y%&~ GkL&e/%|c$l.�tռ RWp�.kCՉ3���0Z-hUp4|?�� ٩Uq=~�lĥ v� ���1'���,ޗ6>1T%P[ AU[I0|� ��d�̞[����tN�s\K�` U],�wZzzӭ:~g��#_)?,M�YSQ6 \ 83*BƤļ#����\Rf�ѼMNCz�������,�����������FJ^ n�n����p'����s'����������j ��Bd�O6�����* ����hn�e/��Pam-"KְIX[OD/�^-���P"Iv����H9o,)dD|u���8���`JtEV�j��(��rs���� ��dd�L���������2R_\ǻack_P|f.5( �G�_ٞկ?)��`_)��8i�x{ ��gqۏ0pjF�TB<�P���� ����D�����$���LY,L5�YkpAv׾IH>YAx6]�,\�2?G���פ�$E����'k 'dt1*K02B,vl'5QȲahJiPkhO0 03|}4~?zn*%�.5XqaKg�#2V] ��đ Kamp ң}ʀ�J0���) �Cb66��LH9ec�y ���m\\%!Ra$j{IY)C{*&j�"#Ur*BO 5)bxY<` Z+x(lqҡ��~8�2kR>n`Ŀ݆`v'%ĢZ]" {F��p)IΏl3H]%���hϝjn"E<V"g`2>A^<@|C8wpxաns2sQDP;>T\23@fR M"O-����?3=*G ��� �{42ťU\5;G"ɼ4G%JU@6'ݎ+&4@u�W�@����L�[wdחp ;�ϻdߥ2[Lu; ̈́FLq(�{āL fYQ6o^3f(,�Dky&(�DvpKp�����������ϲg%u8n��d%|܅ ��M1��������i�-m��ƴMևd x{3nUeӖͫx h:2?_ď"h�u>{~ ������/���d ����4��QW7cB@bH@VfȠ[ՁmcEY$7dh&R}ڤr*hKgg-'$d1���qDD pC-�=L=#/IўgJ:&507eb@.S 3k Yf��4P=];ȽP("XFoJ'ӤcçIM,x5Co�vuu+AkA]ЕXM$kp;`NgUw��'QInS u:_ヮn'[<BIʍVV1s\Y- &p TSs%Wfz w?=5-sg3宲=Oʘ5捝I v3kȖxT,FlKA>u6ĹEP��Z3I>C(p3UC+P/(}mGd+�5éd/EvV([EN.$bHDshDsSpj0Z 뵛)H6v8 8ީ]"aPHG= cW q9�$Fb(Ƽrh? O�w6o%6m��Z'j Cw>=���-qu:1m +� ۛ\�Re�Lm p+ND?"3r/dI6$ԩ}^qHp/D�plN!0u�Փ��{ �Z>t/3<: 3̔g*#hS- VD$dfw�6@V�`�I1AT&F�A+�0{yWO+*:'{|������}KCs<)pօIȖ=h0^Db�3�����J{)�)|{k0y-~^^qͪ|||n3kEtr4*g2B��Scķ+'ڡ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`2Kn�qEbR[��ʂDkMVǭ(M2 �:g�6U#��r!�Ԋ޻zw+児�lx1��U m-`",�D!?3y�4, ౹kF`kuvd��T������������͝���x�t�Uyڹ�2�0�@S����4*%v2������(�����������+?�h?QGak�';�S�������? �>opЄ$TޡNa��� ����HxD,SBE.P<��h"0 3�Ro���X;���`��~얢|zrٿ ���{ ������������:��31# }`1.D?$ RYW{c �X[R[..~��� 1���������������� pzg5���L8#Sv ت]��pO{ �'5R 3=\*�O6 �wluǾi_| 71jNbTD%��<m pB8h>A�A �m\+ 8& RfL:R)6K?eUI]hP2"nc֤~A-8/mZR��uR�\, &4`yT]d_?Uf&�@Ӆ'�#SH{ I6*{gKƴ-uJ |��_�{TX룞m1*S}�=Py`H M[;ks vJ)F@?ý,zҥXL`XNԖik4?>�k�bD6U��7a놔 JE=,ᴟPMAY"1%¾-_C4ԏW��Dӆ!(XV8 -b������/GR�Ț\쌿@<K; \=8& ~B.����LT^�xU}UD+CQ$:Syb~`8#VQyHӜXy� [3��] .��na[nNa #"2[ϿPcaK=\<xE}^^o 8ɜë*LβQjЎ՜%ڞ) �:@"~dޛ8 |sҏ��,'A1P H)E4?#3/ Ԯ|(R=@&f#<Hq�/�.ݝ}[田 K�H= ɪkF2x}M#D4齳di�s4VZт�qc7nn?.=�d��{2���ͶB'Pܿ�6٤ nJ#:n/0@C |��P����.��EsP���8 ̻6"I(xwq-~$_�P``rC$&!<N}'&L�%#>w &a!GȲMâ�tu݁H���u|9Ѐ^։>#"+-[lu�"kc?�(b]Fh f;S۳�W5D�t��p8¯v#|!���\ނY9L�ṯ"�h.{�+OR ������� 8��������Q� n9ޚX+TN[�iT_n��V(*0sW����������SGl�*P0aq<������R7d�{Wկ (²� fV7ǁC5G\Ù;LE8 Mtp"H#bܓZݸ%> -hpwz� z�746���{yj/,/Ml���p���vK|^[Ӱ9!�O^BR·(�⪯E(4X N;gYե({w h81EZn!ԯF\] �Qk9 PQs\+}(Vm{\H^\O1rrI`�ǮD&/?sI݂�ba  vy�xnk._!r�j- ���|K�l-oE-ؤc ��r<2'}pE_hh����y���K&ҕamX���(L�Wۙ3r ݦwc~�۪le\3f6]zX9"Hm�䯏!C2'7W7rBU,JI"֫ʦC%ԉ�g`ԲD}0� >�d�ܗ"~u,��~1O�R5ɗ�蜀͝�Z��6cX {��0‚6[-1�$BBD^j�"X'O,�Vm��r #Z� �w,^؄{�0DXF��,Ns@;���������:n ��HyDӿ!È\xiL,3y[�@ Э�$@Alr ��ҏ@ oc֦B47{�������=S4Kx/iogbdt u��bϷ|= ����$�ĉ:O`�����hgH+?6?��xB��������@`���<d����h���|3,̮6AjɔA�p����*�`c����;iFy+V�%P������D �wm@HV���Xu�(*A2|)az�Nˇc����$���?^1����E:2Y�Lqˎ|SQ`ACOG`h( (օmS�|�4�hzq���4eۜ8;#2d�6H��P=��' ɫcH�,rR<.>U#X 'V6` -cqPS�@n`� _* 9br68��yiw#�ʗKӱ: LqQ(mD`b-KDYŀZ_=��Gs�^Ԟ�+#xq�`Yrl%/oDe})'XdWcF (ExX l�|7y2Jnrc}0!$��%ۨe�0KE0|rlc^ ڸb6L3e\0�բ=<LG :M(fSr4dx@?K|!/ѳSVE^<0H}C\'L"Zo*L�:/B�\rY#zr.4e So\�`!Ȱ4y Tcc r:]�XdIwPaS7/SB;p;JCym0>q쇢�*]*ʽD�LIY %��PT?4ݞ_b?p)VїH lzw1���P%h��cO0ʪvl\1��-����|W���x.�V&a�59S:ZAANn"-=i+;'E,U*�)4؀mI|i*B炑�I[-@ � :ā%�rp ����<;`ɏ hۏJXT4/w_��0C �UE�������_ Rf����d����Y ��Rˌq]��q(�8ݨTY6_+&�)�� ��#,>�gQ� a#�hFt�|yV�DpI"α|a#!AYu[ Y*ӕ����� ak��T.@��C}~2hXbrrA#3Oy? ���d7bYc*Mr{;Rie`��8Ue|���&(a���������2%%ZH*�Z+?='h=<�� -ip.�� m%\�����yphX D��p 74f�s:+Fd>���By՚$1[&k>$q' $C(zMNj8?ރ[L6�$Ԣ������������cNd��tU/�Unb'�|@D���0= t�tN8�����()qcQg8�-.;� zؒq[���n Q[�N+ @k9r x:V,g׊,(cS�v&x���;�H�hMJoB�xT>��"r`nosL_g{ h"I(LI`�mRH��� ?tT|!J��TP��������0����8 ����T���P~(� �Ȇ�A٧%* YZ/+zD6py6t7 Hboe51���v����8=/6`����-�~΍�d; /�ޥ��fY<~yf*��5iʠOªrO2 ]GrT���i%KB,H|l f8�i90ixpa7f����DlY sɷ? ."g@n)/v{BUM a"wQ�9 ̠$==@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�!^_QNT7tRd�1x����X�(z�ƮPDc.L`pjx;8uk`<u\ʼnVpV秣W 3";mu6�UAt&n]NlQϰr ;fZ,*��\T�DWZ���,P'qt��Ƅz߅).���`���Ɗ�"KB]*O#B*���Pt!!</ `�Fy� ����$ QtfڅRWœA�Iqq��EΕ8��� O}8.g,i6g \s5 Nͤ*OBq1onPDۮh;2#9 ;*8\:NK桐�;AҀ@IC_:X\fx VN4pA$@=Jh�ƍ����.{�sv u`ۅ>kV D]oҀ1eJ�` m_qфsx]~4#7E � 8�o )Y@L`)wvPLu;JؠZϿ�|el7%'08Eg]Ij/̗30&j��H �� IS<^&v%M!ҥ"0+q��NF �h��/K�.7��,S$i &c Msku5�<`@\b1�r;DmO���hL��tg)d&cldE��jDiҌH16Ӥ8e߹_LS `����+3Ƭݠ!=:���.IQ V;^An&l}~EO<)kD=1mc`.% $?RђS^13Yӣ~Q'U���Z ��Dو:�l ;fE4ar!1xJ=H�� V97�K`�/rgbxL_N燀2]t/�CxGkk/^eJE΅lT[3!wc�o�_0܀@lQ"mQ;U�3,M[㡉-G٫ތPlyx�#���MJ!aݜH 䕰7#`"g/^P5%�,E倄flԐyrrFc+d1l],x<xQ�h2i%ϛCK̠T`K`H|ܽ(���xs}~w�.@ؚFQV�c�o�<����H~Z1�U�8e;ΡKVFPx1 zG+}.-Qۀ&N#X$���x:w�d}67+ .pC0\U٭Q"@gE������Ǣډ[l7�-�>���R92T{EPHt��cF>��:`U ����] B+Z9 D4Զ }/{Ȧ2:H8:iџP"h�W.k]xӦIbY$XX ?xR<l:DV����u��'*(4{NFz$z3[t{(kuׯًwE͵<UvGF)UbtG�RM7?ǎQ �`kQ(rMx :P{~U@闲�Tf����̞�b~8oiF%�\[Nz����/ ��b;J45�D�1�M+ ���ùT) yt �F/IhT5O׶wʔZ��ޚU$ji]O? ���Yq%�2ar /<t �������� ���Gt Ы9zx^�0|W ��)8��4��[vNP���"����c�DT�O\�iV�`}i ,�BPA}z�&|����p ��0>�ɹ!gn'WV�lJ�<���� �9�� \]�p������������Y:�� *Cñ��d�pqb���$�!K�#I����p��������c��D'3��$�������Lx� ��(d:S����� s�}7[2J��������C��������9 kɴSͭ2ȋq̗2�N6 hLn=� �������Y88eIF �N_gL1�Ptuiv g^Z��"ăf �xp����_��!><՟dxU����� GK���\��+6V"匥<o!rm %yhȕo@e;m\\yѸ)ޚTU�e&ģ tt1GKhBxSd#v\.ߟseuH!2@s%iLMYyC4/5eрK 9M;㠡:�uň G>+VUa7V#t4\~wwpzLeE8 M E#1ƅ(^@nh)Tԧ�)Jօ6!o~f���0v8i{ iO <Ja+`R+:eRnܾ\^ m,E)W �%_X+djXbs:H�HR���2'0p^سT/ ~9zeoPf>RQ*,Jbb0�P/bp$^D���r w'CsFHz} }�o.pCP%l������D!gB �� (��`^Nrz3TLh��H����8 �} l>&&$6ޢ< �QN}uPD '� 6\>'JXA ~(vU+WYmQj؆)Wz}j�R�a���$�qEMw8�:Fڅ;� W���E8Cd9#ǃK��K(y��<$��@xLmP�Z }mLTc^���� �^z),/��s���: Mt��� ��hπjM�� x73R3�u��������HԬUj�pS.vSeVt����kzBe7co�C;�eߐ�k8$�LR@Y`N�P0y 5}PA�n�Cx?P��KfXōWY`h{汀h���x0Ϣ���7*�n��E��\�,U/*���:5{/~Q,x? �<XB���-r@UpDl������n~hྌ 5O4�ZIYR#uv"�Kd s<fxik2N) ĘVz��PW̎�"%=���iCC)K�wH6z>��@kR��G| #h ww8CnE/:Q"4$8�. |oQ⫙(3<A*=AMwDpފd�_Lh| @���wqav8���Pr$&S/e�Omp]ۙ?"t#,l�o=2鞴/ݸ?_NJ;6~۝h�?x ��lc:NT ���:-,��< A` ���;��05 G͞��Y@9���bVeV�R4y`�,Wb7k5P8ݎi§JWc.Vh":JN �Y�қ��C`�� N;Ҩ|U w~drd6fO����NBC�j]%D;'? ����P#�������wggM�|"sNO (B0* Hg+\Ŝ<�Ϸv=B �30.ATӕ�' ����h�9*J�{{��_�������/85&wQի!Nl"f".dPA;y5>-zUVViIdEvb ��<���� �,Aq1Ud m-�������.�����ν�$&�b �im���8|ǭD<T����� �c\٘\?X���{)x �L!*����>߯+��:X�KP�PE;nkPn��)dkp g]�B3��&ZE)E'E��e$s�d봇VIo�B/���xy<.,MUs�pڎ�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/��Tr����S����\����C ���))��.]@^ �< ��&(oi ���}Nҫ itnW~(G4OƠF=Q"+E��� `�w,\|Th��%S�y�X$Wk^5u%b=�xqb*�!^s$+r�@^, ބP.E?/-}wS\YGدGW&u<<��LRm*.��^*oB��1IXJl@ �@8UX3u&'mPd{Drkر2>1<yne+C`ף�C}V} bo'=x!�� s��>agc�HHL��>NBdd`@ջZ0y؂qi< tx#.`+}ˉ4\:4ec�#iT<W@"A9^uw�di.�-km/S $*RMx�����]xt.�NmFgʽlܚ B1uުO]B񖟮�& ޣUtӝPb`ދcH^t\�)B���@��ZYB�4h ��[ AE�(sYBT;p�ԝE��W1ٷpe6@{?�VVZ[đ�Ň*��O_VNW��,&!L"%S���5m����0����"3� ��.'K�>fe]ԙB73q =^�5n��rSd8-NJ ~4LN����@b�T$��h7�c)w;g%Fz7v{)[p,p���9O��pW}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*-���<����S�Sf#��(Mn ov?o.,֘m&DӇ1 cr ps5=478,[X]5q152s3؍5-o�D& Mr��x�� lϞ>So0 oZM <�i.}N1n� 0����* |iB>�ַՍV%s$Ut!�)vے'Ȃ>ָ&�Z|՗6.mg}¬{k���<[4X@ =<[[btZIb��%l.����6��0\'{@����?/Dy5K •��;W�{ .n`|WJ#[ )SI h_HJzRK��ѦLmja|m���ܰ���������������EF O�x,a���F'�tYNS���|4"+C�����������ԚޚO��f { ����Y<T?lֳXq# R�k0pM>*>@� ��H��'�pj�#3��gF*3/$(" ������q��N31�9]���8p���������G[}����������3-6_rΌ~E0#} 耟x�v$ ����˴���\�BS3l@2K�ߵV�����������������2����Gd#Gş@O�w# B\H|gⒿxDWV蔘dx��4f"�� 6�}����r��^>���8pJ�;[�e_�`Ǹɭ&.�EiUI_j00sik&uϰqy4f$Dj0�;}`>h5ۘ,do`)k$$z wͶ������_:Z<PL��9_p.(DX>lJ~��B$����/<{4@xEaLza)Oʼn.@+4U-O@pg $��з���� ����%G��4Ct:9=dm-Y)_��uaHud��4526HX2Nm q}r#&[lD ?·grM$AVBI:6qxO\IpfeRd|E|z.׫q��Z_7L85Ҧ��y�B{ \!JG1yo7{ HL~ sP<ld S91Z��`bE�03��|p7=P)@]ԧs3K*9镛e!&\tcKTO0'��+&gNKKM 7nK۾�U,zoQm�pA���fj5,$_n�g@.U* ΄1#뎷����(4�������cQKQS}jh N�d hc��0CyQ &8ܽWSrG //d?_W�$-  h`ㆨ��������7��������]Km 'A܅FyaULud(�3aig�61W.x|Zn�d)PS^=g@̀|W��H/�uK�kBjㇼ ^NwF:#_{/�{9̬�lg+FlEjdX<����]4Q3 l=i[]l0JKKvB/S6A[U&y,`yR *Lo Uu`| jB_�?4/M^L��. f(z/~@*2SN 䔲αvF1ݨnڷe;OQqezhlU5^O,<ŌC~�<֙`: C@@`Tc$ x`׳p�M=CB^a:8mMI�l1\of EEjz |0]͔OrخXd$"wY0XS;$5y *VlC'*:@̦<��[-!]2Tא uR2 4,[B̴%oa-_cAK-}?ہ@9��7j.w5-g��Yc)T:<A5BB< /tD�]D,t̪\da<x._ `<�4zb8b���� }FZNj4����whgb TZ:Ridm2ؑ`prhq�o a%n:<�KAsnw��Zg^ vn,oS)|ӑU(������!ˣ`�0iBwKv^JQA}=R]?���������an�O (� d��^կۿAa�3TFUf}q^pun`"D}^\,9wQ r��{��dK1a><ho~U {8.li[��NxLf\~ZNӨm+O0% F�GD[vTt{Dk���� �3}TRm@ wldå��@_-� Hy�4������Yx�"/>%��7Vh0]�L5UoP 0y̦����^rX: @do4��Rs^|;qeXv1&d�����#JPˎМ𵹀W\۫6�>S���������m�# Y����� ؒ}^O�Ģ = iPP1̲8ga�FNإ}J@>`.<a�S�A ����Ē�������m+7�K$zڹ�2�!-2�?T!d�ԫN!@+0Z`,\ ����R���h���� ��z$[:ׁ�|ĥbe-o���� ��,t0��SF��ܔ����1�|F潦?l���4rp �|0N�\B!(Hn K4Σ����9$BH &�����ԯ ����\0�����������t}~svco:b[5ʳ?A/~2`c� �g)�'h<m� L,.7���������������kR�|s����L/9J �����8ݎ}@dQwB,"_8=ʄ/'`Z3w\�!"NyI9 r}x���7]5f?6)T5~:DL��+KIh�c%'IgnO/H `zhQbw��:f��FT؎nY;- ���`|ɭ�*4*�efiBq]D Ec:��<ÃھX}B$A}98aCp��|O��� B  Hei׳.m\ț9c�_%ipJY $?p@Y!OGIyQom|$Źn$g**r�)a:A�!n!��;iU&ܒj*.v ja.h6 �n�H ]��� ;�q4��'�0a����@A�$W���� �?P􈛌w `ZS'He&�JO�({�>]�XH[lIVsfc;@��ҷ*[HP(p(4xgC�ILqэkaxkK3D#: ęV~Ӎƚ|��xl �L]f<g`spJI|^<y@Ho2 =TD#Ԣq0!hǢ[/s���Hٺ[ &ޙ����UN& –8����y�*yg>'iS Yx)�Bsz/UudI ؀(��uS/-�JyMfWS[_da#cx_ZEe'+]]eNh7ҡ}? Gt)C���d}a;X ۈ ���f K8.SdP)53ūO��{`1CS��GAx-���pI>,DjCpac��)]=����kw+8`!ڋb=>_+�$Oʠ�f x.,�UST!u�HgoCa1x$Ӭ \WK@cU#�`ttC N�k%�HIJ-M^!\�}^���e"��ND�@zN4|Xr\ d,DXڮU#kL���=���|fr��������V �s۳~yDx+OH0�e���#a�6!``<Ā>v����y����:A\�$� 8:;œH@ß<����7��t:J a� Ѯ!$@oEIL /l M͝>�|_q2gxϵzZ|R��>ftL/3>E�BMwJԥ^mN�PUD���eLDSq�J#k,���� n(%KѤ<.j��ѾeC?G03M��>^jVTS1u:%�XBQdtIUZt���%`-QX7 M-E,+SIb۷/cDwobu]5nǿr=���(qa",A04`ҡ]A>�g [uw@%L{lS9B=>L�� P ##x�o^B�/W? "M`(G��!�|N]p6}5}y0su1_u��V����BɊ��1Ó{v�;� BJ<2 :pC+^kW|rMb(( h1I $ ��BR=A?n4]�70 x\3V/5b=vq-i $�a8e\��;�r<,L4(��  �]'�˜ƪ9<u@0\EcNXR6m�6(UM3��̇s�ʭv.Ѻ� p7X������������� |gS cGpwLr v�.�� ,zQB|�l ^T��pFW } ��8f ����Z��qQv 8KԢ2�x.%� &xZkpN討]��V�HQ���D���y|w&;\�����2���V}j�A=ʶ���@m�Û*YB* ���$����cm ����H��Mc��� EҼ=B�[X�����T�� 7��[F%���ꑶ L(>�cwh#h �P�فk����|f[9��R7 ���[=1�$rG xŰ'NI rP2I}j(7,��4ƼfX7L{@3���|3��p���ޕ3i���>='<{mϱ��gvPy+vIbk Dآk �8�Ch �KeNF^9��N����p@loJ{3W(3m8qD; `ք_|T G&@=xi:RL 0���`\��b%h9X D!3<rL/Dpj�Ujt΁I VoxjhdatŻ7tn5\A.B(�=h�ƺ *q"yw,M +bt#,شd¦cdW8n&]"4\H7I>U5 _9ƈ o7W�W>E3"h\�% ?�䵙e/6�4 ʼAbˈq�4�0_*WXq/J'~u/\6 e_OzyqQpjiJ<v0L�a& B /;9\d4D Iוֹ0�~:Q]2uh:.Ydfc7v^5 j/C-SBk��wĹ5��g8�.\;:_��lݾ&zm%e%FM�,,@���D��%�t8d�Qr�XJ HPBĶ?>L9x7#�t;�7UQh|@1��Ch?VP9pB�*�v�iCk &a`n~o*"��& +�>P���T����DXދG����t����2��(�>":P�/](h�D ʍ���~��Y��p@<��I 3�Dx1OA l404dyfooW MDI ZM�lA̚<`@"�;/+P#c�[y3J-Txf+-$BA1]E,�3\����dcjdDDd��tJ+ k4$H�3@(����������������O(����� i\Xz�%�tԥ��l�,G~[�T?�������,E0 (ck| [~Y��hV:t��(�-n|A coڙ�LD eܤanzL@n/m+#=��U"�\}�(=��������1����2UB ��Pj{1��c d+|2 ������#uusES$Ti0��`��� F\E@NE@B{j\=0!AiRz O(R+~Rj��L��MǺDrY4&�y_}na8�KW]lX&3W�P?L0_������dUZdD"@R������������$v\�������G~��8:ߪL T/-ԐϱM8;�=ywP�*Z���� t��� +�TWLW)(%[H6�4a<����~�RG� ,S܆pLߪf8�>P0ѭmT9Hڃ��D/n}˜liv7Wyg&D#bKGp'T}��Zl*EL50d$k_wn��4M���"A�\ ZPu�X4���}9pHٺWŽE�B HaTqh TC.`@2 Az3^[NEJy)ιA��X�){u���m��(TrBMԩyhĆ0 B΅&)ӎ^ndpbRM]5\5eC�zOn" &}#/G\H_2p'ƚ^;"s(DAxt18ʚ+��\<B8;U#+e0 W��us#��{P�H5��j7?16!;+"qgz9i:�,����w"��@e ��<n4]՝�<“fwwMo#���PsZF9xm)կijŭ`T-Jee7(xr!㋪@ӏH��A̡BU ɓm7j~� />��&%I���`J]��T�$Y��d8�[Y.1Z J5l#���AsF)"K%/Ys Ń!v���sU`(Odmk9Z<  #F����96`>2JT*:o7n�s��#���1Yw@80[AL3qCSQOF["Zȸ~g ˩*"YtC8H3[Z\^K()'<2 !$R샘_�V_eN`gL!fs` �1��-uLuth}|�4J��0���F` 0 lV \f|�0K5@�]�Eq>ra1g. B.jXu n^:Ε���|f�N9f- H lX[scN|F% rgGbc m tx- �h"���`��he$�l`; EZ~zb���W5�9~Ķt`Lvm�L:o ���F�%]&49dx"n,돎[B)3��8&PF=P9ˢ�Crm���\gYwøt*�k$/,QB�P<t91cJ׆jmIlr=RI$�~-kRz��ر����& �x @;i>}Eᬯ,a]K{G^I%AqژA�gxj{&/P 1 n������$Ԣ:"� 7�^ �D]_ ��|cX�b[X�jV1o����@ "������\3LG�@gV2_r:.afo0Ū ~=c G�xLܻ *���FŴv'WjtFfmE9\Icشj�Z-DaQ/~P==Kk}\qyYq7B񤍗&7,ʃt&Ef9ڻ8/Mp�ݼ$sĠBȞ�LI2׼w)N ~To2“j4$!E�\9���un4>� չ��R��ri��������p}-�qW t��84D\ԑhLDIIFXts.(AiѶ%�0U���-ٺt4Ϭ9ZB��ӝpt9U=$>`3;� )x~����1/��xO0<��P_�grir��l@=� @~/*W %-cyu,Hp__0t,ex ���-1$ǝ YR9�d;qT"X.wMwZZS|� � !Zڇ嘄J]a[)! Qa<.3zr0=[bMHwj^9+mq£r9DC1p$Eb �$ΤnDIߦNBVYZED ���� ���S5ojQN9A���(L ���D��U�yADHrv{g�k����qq IJ\Gg6Q,(O�!k4|>!o" VmO^{< ZtD[ W�8" _ 7v Lz&��@�udٝ��������F'��@R�ؕ��2*z���ٌ�`z����@N<T�,iOut�& ���@];����<,~�#P=�\׳�< ���� 0>��)���u;ࣜb${33o ��dX����o5 ����pqə'���������������38}�W|$��,BC�T��ݍV|��<����Ć �������� ���lKE��� ߶������>S�N? uv ��Tz\o���-O $ixd����L���� ������#<k)@0gBW.a]3h(q*M[~dU#����P����X��Q!�of&끀8c�&�c$v@X޸6#�d-;�@U{G(�;q'W����I��4\gBo{Yc�����\�����&uy?n"XK*L<3nN��$�gxcGbRӗʩP ;x{4�i9?-jdT.2?WeIGs (&6;dK7��In" 6Q^K<UmGXͧ:vBbp J|>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ޫ L�hP*Fv';j3 *pm5>(p�q �{�\ԯ+�= 8M@X$_�lL<<�gj q?p5<��D2;b� `�8ڂ!rKZ �����s<@��o@~ �&W����ly��15z;��iU�������,^�,kohJ!͠pJ ������hyQ#;�#K�B Ai� 'u1;D@5$zN\(���0T)wC.']v��XVm@fŏR�x;�=a`3O#�����=M�3KC!8�3���-q� ��Tf#�����Pj � sNXh�Q/ix���V"de���H�����l%HB"]m}f}WY^do愫F ��P>n48e_�ܻU 8Vu>_(; :P2"% R = ��,z��7b Ԓ������νZ! .%~6|��7,2�K!_vUU�w R�(]bp| d}K6-B3==)�814��ưPaF���PI{)A^5���(;�[531@6 <D4[\sKqe].K1KpFڼdr m]R"aE(Fۘ]D�%@nlj�DP|'���h��Hޮ7`�%q:����3g��U�g-րŨ,~I(F:y���d8 ��knwPQ G�'HlIOzZqh@G"&<�����3: �<SdRf�pH}YA=̀l ߂XS ���W��2�'<?y)��i����,����@ox��&:pcP�]da xv&.(@y�{'�KԨ&ݫxŪ?tL$��1�s���������P�"h˝<0 btVM܁Bu4u$*c<Hbv(EK�uJ ����XA���W;I>([^1�Ӿ*>��i��������p��������fc�n8 ~3���ޣX��8T��������X/��wy:����^:\6ia ���(>Y��h-<���`? ��ԕtL�7΄e��� !��W0igi!�H�q��e�����~n�Apcb]|�� VB��s=^hX2(@0 d4@ X0;j,|,��̓ՄY�GsȤ4_{5 \,@8�$)(1,6U%sytFx2Z_p����@oՌ2SlZRzCK,��]D_����E%p{V �#��=8�J}(�pGwa1=~� dǫ��W}HMj1 r:ą'NkX\E���%��.���� ����8��������1��#58 mUx v���W�D]��P_bbTzjd<OS7vnï:���_S��Pk",W#WD{{ Wgh,` lIp`+5#D<ۯ)6FS$wHD �|g]`;�Ƚ Facb?̴+KO>yQ#$rlͭy^T^'F$|<*?6րc��� ��<>Y_AB{BR`��}Sc}J��>U.�,3}O,�"H!:��Yw ihU2vI���V��Z2\-���>)`y4g|hosһ\u9:ߵ!pR\7p\f/ o>gk"> Q=�y# @]HY�7;dn41lb|^F[,6i������o^L/ca<��Zd.3Ȝ츝+a60LzNBcEYņ1sW|:0z1h2^(e6I5|lU83WϢ�� ���kW7W%�� dmx,H;">גj^2}('n7�8,6[/Kh ǧp]./���,ZK�p�Y �Thy {\��(3M;��i�����ZCB�������k{�hϠ�츣-f"*;*㥳҇A{7K='iQӹ.=]\ 6z ��y( ����� J3ugw�D >um_[SzASCNc\�Mu���[#h!�9ahP���ܣKqڴpw8;wOu_�h̘Gm4�}*ԤL*DcVK# �?�4NP.X��񡕷ߡSkYBĸ�@yb:PO0t;QOl � �C)xv_c0+W N:$�a��zR+ V60q���@MJ{41u`KM�*縝!�������btejok��,~�DA!Guo�C0$vg?zH679a!z���0Ɛ��7�j���{y䠮Wݫ/b,�� a������� љflV*�~̝441Î,i{ iA{{}f_(VȻ~3E:,H3uVO> a\20��H$ K z2"8bI28dLG@8WA7UD3L2]�IȀZ& @����&��<ZlJ�dJ{ nP O)uMt4he-3 K(9J.�s�<w(M5S~$x.6S!'HnS JPz+1Ww5vT t�Ik!); ogze1�LLMO(7o��^����?4�<#$X^Z0Q �Hܫݤq7�phJZ+Qc̏ohU? inxdxV8+F��x�)>lp-2.J||;\=���������c��<����a7Wʮc4-B��j�"R�ν�xYxdp<#N0`Pb�GITj�T"C �V/~ʟk0^u8�6[0:nE��������"�P:~뛫wm%��P^:��HW,������0��v��Pa'cKn�8)Tx�sOW̧yn1ٕNf`伊 H�x/t0U���Ӕ2F�5XRǁ�������QrFY0j:�S33���4u����f��c�4��������cv�%nDQYk>EZA� t�#sG��J?��pUg�7& ���O%a��Ff[˒��������������������d>D��Ͳ7a]%�T/Hh& y�i*K#Ut!,i��|厉����ȥ�8Q������_�����X�8 ��������=��/Czc(|hɮbcr)f4 H+O*(ּi���NBcEg̀#�>Dmz ZZ��; �X �X~*�`y=x $1Q0F'Ys}n\ �ȟr ��K9c�� Xpqھ;Tp]cU@ G40VxQEy-Z a^�O��L���}^�� <d1!�ń���H{vD�� YRh,w ^BY0�9!EϠLܒ1Kq?t]}I ZIEahkd=L 3SS��ܦ(e5��X�5Z�K ��?%E�n����x �M\xVpK0;o9]`-=L#^(]⢽f�|I����q%2��`T N)ǝhIHCV2)�&i[e~1퇜PfZs*M yR׀ehe;yqex׀i����Ȋ��#ʦ9wk[)-wΛ0���^����<E����t��o.;��3i~��l,ԓgX%p@?a zZLN/DNI7��lD%ɩ4�\'���� ���` ���� ��Z(|n%۟_Fcތ�����aCK۱ �vthZ%z,�Ɨ:P�p��DLB5�O<Y��o^a>kz%�BpX}ζ8څ6(Xy¤ �~A˴ ��lKT/�$kڭanM5ʙwFqkB f#hd9B766>�i>e. 5{`=B|L��8{J`Eh)AhM- ,LF ȦsOUT̸C-xa^i��Z?'2$Bn<ba*vY!q@gNMg2J��fIIرR��Wߨn$FX,RҘ6Rai<``Mbj\mAMO��0H +nY g=ݺBt (~�G?KX|u[F7î/ '�H12\󔍫ޘZ�Uz@o?)8#t8bd�X4ft4a!cQV;e@.Mx$!� jq޿P}.�lW?9q|:*31u(465@D! e#DFUl ����bȀ�����I9oftΔ0#I]̮1"N̦ �hy�&nxPWz3`msx$}76pBF#;�0}7mS�P�������f�EL}dkͤ2cg> n�K���������D ��x:#@ (D"+3Rt�&a`Y/ (��;r��sCQ��Di. CE7[wlo$:p ?D`N'vA`PC,OPP(��������7Ȝ –?i_l4`�RH}<PE˒;Bί j��� ���� �>cУ��KVL2&:(1� "f iQ G+41m'+*7} WL09C��� ��||%^p쵝6 {5KOO5L�,��������{Ki��}=���lr���Zn̙ �9mx@K���̓�,lNJ-E������������ g%!pܖF_;Z�wĈ�S�/]PO*Ɓ��\]j�~Ħ��������}[eIeT|_a*|fG@L 捰`<1$ T7ac���D����#g.e|t`��|J�9y$0_�H�l'���*z��H"~�zZQ�0�P���� }����z%����������l.v 02 PLd{n v(���ƕO`>W������������������MĊo:�N���EcNۄ-l��Ĕ\?D���bdzФ,]&��/T1oFIxwx#�Ĉ9{,n���<([ ��_3p ex�6 $@u op�3j=2 eKBP-<c@O~>S ���k/�K-83A\CY��� N�#H����T69¦FK{۱XHv�}Ag_ZWEC\ nGD߁ ,<< E-��C�ۭTv⻎MS^LH�����āM?7 �zӱgWQs%vnPD[r}*sv_,!ȶc+py5N  �Ur���1e\�^K��,cwHi9Pg6�,A70O'f+%肐(2>G�фs�ź����� �@aa��� LY=gɒnϲZd"Q:zjllնrwu�Y >LYV�\59p�$GtD�0I8rؐ ߲9bXZgg���1HT ���}+ ��Jq+H`D}ηV\zs){L8extOB{4!phW`F(~X_V qt%{so� S(Y$o@,Z"�` �~m[xU��������l�3[�[�E%:_׶o A*��`[Gg��Tq_1 !/puJd0NKRpb9IF�� H pr ���-�,�g���G]b5asp7~5A��� ID��phhKRLsDŽ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[`sh�p����e���\g�������uN6$iZ�{+�2&n��/̈́niU��������P'j6���,9O�_ާ)C0���x����XJ _ ;fL^|s $ M "6␨y(�hAc舰@",mHy4 Ca��J:?\qdO,1P�d19Aɻo�8ɦ ���>�[EZ$N�7! ��ۺo����DO{i_`vaqJn r7���CGCe&(�uSF �>RO t= 7RH�*$N��{9#*g�bq��|0w�r�:wS<kup4<)d���L*]*(w|D qm qE` |_d�|,"��yD�Xw�ݨd=M6�Ld|e�d ԩ?6c$T{l"4Y: /:v~��(������șU���vF�D9���SgޟBZtL<&C<8 ifu ҢLf_�=>y4) ی2~��?qNI/*~BJ;Q)T>�:(G,+ <ҷW��LMdz���C Xc%8�������`oL��`րzҟ �|*K%,�5��V��iKƎ ��X'̠ �6(v<vpPa�� �MuYI}s��$��������<���a�`w$�A!e]�%�ۥa ��<&:Cr��= _#_��lȑ#��]����Y,tX ֣́fo3�8L7gNA���@�&���U���`Y^$~ܜbp F�8����u8g4{[_$�҉~O44Ud׻JxNq�A����@������wW�nt--8R!ᡶ<?ܒ1p��J���-��tB����!sW0FȕXc8�`C�� }����S}f��| \���� �4f%��q7 5e&��yd�����,ǃ,��0! 1���>8.�� n����@ �rlN��B �@v�LqI^b47/ncX>!edh �3G ��xH@ �bHOFPS5��rE������� LSxj{~O;ph$PadO#Lјm:6�x���"R@H%{~+���"A ABmJצ ~D 3Chv;<g&RtNR�pZE|iʁ ;VK.E%Gl<_<d ���L\�t[yW_u҅2gg4ju&0�g-i%-m�@dAjKa]{+u)Ǒ5 0(XόTRk͹T79=�چjYdӕ�Réo%�QmWaO��(8%RE}%;XI5gz�j~ȝ* 4|m���yPǩ{KBLY?WPW =#J-#ctw`8dpeu;�vI YLVa\H"~2, ǩVI oI'=k f�f�.7��bHt1Bh�\Ks�\ h�&y(wHuF x+Y�)ҥS_b&9MA��d<#L%��&�#"rʹMȒj*|B 5����G36J_1;�ڈqTǚt �ȐK[ �탗~[.��x+%ë�C|7,c�ַ~��֕��0!���� ����t���� ���/`!�� `�ȝ�hϝ9p��� m&N����@LhV�]��XaԈQ" �U]dַ,TL1dB LW( ^-0 �KgxۥٯX]S6w| /Zl$wX FPf ڪ48q ��@Vӝz>9b و&Ex?�īFm������������ ��"�(@��������W׶4o_(xTO,)��<?�g �8,u���;����# ��\f T!/��~H4v����XWE&Y1������~�uad�>G7:g�lp:Ы"1&�F $zcx������������qW]��8̮*]�Ul>-T}�Ģ���ӱ}$��l���?OL+cu�qil 3.!7Kf}�H/����{F�vƶ`z53-Yv~LBEl=.c?ٙxb8}=md��ֹ}��ʏHYg �פJ{`0΃#kɒ+�\} ��% e~$ ,���Њ �� c1GP& L ����������\3��8;�0K5���0Thk lx\Q6K`fh˜?f*[Al}9d,/���9O6���,���08��c5ep4Yay�����؉T0�`��x�(;Ïwē�<�lԛ�� @v]zc�xL$*<O0*ME2kJ!���q:D5ɡR��!ЎϺn���Z?k@T[Rr^Oz�PS���� : ?! 4d��) br�IBΨ(Þjt4I4تӹzr&O1� kE փ3DL���� ���xgՆc$~qkR{x�0�g˛/IS%@� !B�B?�3'�zUD=8K.[^-%l_0 %d dcBq<dDDWwS6΁#p(te;TklFq$Hd[n8m�xx��U�-f��vy�ÛiM ųC5T/?ͦQ,j2:_ �j�������_F��</t�`MU"J`"d68 rqcK;�`Xq+;<I8���5b-h}29GT Y!��l����L;^ {V+`��'��<XP��T.w'm����XV������˽._4(n׬l`F��� [puqΜ7��M|��瀥=�GEW"uzkR��S��p"�K,IjxLJ?C|U"����[����������x}��ywphLmi @X8,3*)YM8j?]"`?^[\=>(:!M#NDBYTj>:h`1ĤZ� t).3bI8A i~�8< wHS,O�#��@����\J$@^H#lN,�K����A@���|tɼmqH ^Y&h ^_ٍ,֟J-ŠwM0u)<zT<P`JI!ťExbw SnA٥0*4eFH�朹^3kȽ,j ���+�i)xxE7�9d U-niFC,ff�'L��T >$��)4K<kMZeeiS`CMyu#n/e��e 7\Q����7K7!%U�meQ�Xh7!j/`2*Z+ڙ�He3ML�ɺx1H٬.�+���ey&Ng]fPъ.U#hy  ΂ 30dzs/0= u 0RuOX ׭.�����HRf�b����U.�ao�~1FN��#=��(�:)���� ����ƥ4 �r[_f��1p٧X1tRl!ԛ�X���W���񤌾i<ך.М3y$tҡ;ԗYڡ kcsEGq)^-JEZV7 x[#9_Ȅ\tTVB?IO?Bv%�$HKxjD�P|'o�C)fw=fb W�'a��� 06͠qc2=v-�hk���l:(ny�J�� -L::B}A MB౶**5@e����L0dC^pj���2 Gmu *o &yfZ;!=2q[����*eKi3�hY$����2B:�y=w y I�1\���?_�=�| @~sr%KMux�t cYZ n#=x<OX6���`'~9g584+NC]ӬQ/Bܺ�-4�61>ǐ֓RM˨YW4� jdB33k|:ǘ4vr\ܞb:�H$K:$9XJi0ѻ` @yO�~x=f�$ȲK8����ps:3Ii{���V3����S���t�n�RiEM$W2ѱL�����|37�PkBX-\C��@958>ip0\;mӝq'-/-ϟ$!ΐTXn_|im xu $|�BU=���|F,�/-�p%=���Y�,iT���J7�8 `��Dd1SU4� ��0�' ���,%Aa�.&Zl,M��?�@u'�b����g���8w�(+ _I7ٟ܀p�S����\\����r��r������������ T��WYZ7~��L.f����0�1��Dh����'����������.V��9������Q,>v2�Fb��[n�@ ���QPxUPw, �,���� ���3c@8h\i>KJ_q!lQ'��{JY /1 �_f~ �Mo5RLm��XjGٌ �J­@dk!= 㣣O����8To�; `dTV]�����Iv��榇"M`3���������+ &,' Z])mUz>Akz��t ����U���OB]/qR����GG-nw? �~W,g/@���TSVZg*�aG>5# Lܑ~ � �{ 4 Y}J6B@ |_Y&,9X�0[3oQ/ W:VַFI.Ii:sZ~W崑%3v#}KǕb]VQ7}+���~(ma>0>OLj-.»8T;y? NV% hjI!j#k q2mZ;����8��8K3W_>ݻ<T8Ij:c�U[M�:>Yհռe㸶.tҖb{&'�C,���^Ymد;>H��y9յ%`�j������\3�0���0r/ͤCIqMx#4jŘ���r18mᐢOla ub%S^nk$670h6�OQv@?QU+;X>Hh�mäp�����$\ |_l7B0��"P�`:lQ-k~5LU_͑j��p�� wD,뗝sF֬8���?p[gG��XYi se9L����'�DS79��Ц9���Q����hġ#஛BDh[J�l{ԭ ~k`�M}/� )�%9I�|(hl?#� ��N^�P^W=Cx ��N|U6KGp1��p7,a�BQUqoz`]&9ۯ$S��cM��uxl���2K"S�M�\Fm���h}��N+VIp'!n[@t*�s��Q�m�B����"3�q"+sΡ8#8'#faXj ���Ld|] u$4-|^X'lwe�ֿ=WW)}8�� S+tiS���!W t:HD5QK.D%�UHA��� e��5acnn�(�ib<Qڥ��oa �p?|ť<ʭL�NBݪ<_qj _h�݃5����{/h<����kUȒ4p X ��< �� �0kNhcVJCd˧��ݯd07OoIY8w[$r X2t`ߑ|C% ��O8h:Y$U@��Pz<%���΀J�)��� FiP��tFsz?=K��VP���3*c5_J ԘCOg4N\Ky 8U$*F@ !sr��� p���a2�)(�FD(n[��K֎s��ڻ`�x���P2S74f*ɔ�����w)�����|ܒPIOpjGK/S0b~Zj��&Lx�sػ\quZC �s�T4$J�x���$G�������Jft7h >ؚ 㮀v?sϐ!Ҍ~evYV))կ%n@fz-\ʍ\�s)C{���JiNYTJ�hRU9A p��0w������������S<ў |s��$��P.`3��C���It)}p5ea3/8;����=�P$dt���l +�cZd���,m��~:��CpPnӭ����X�� ; *�\�lnxZ��$��������mDUQY��ܿ;P�Tص��'o^}1->�4ؙc5?s+x0p8u%U^iԞ%@.W]5\srN8ED]n.(;2,M@4]Ƒ. S`jӽ'4k!`=JE[3W�UhBR2cz����w�$T.�(α'$��� ���x0����Ԫ��NU@pdo'�|@#RHc875*]{h��8 ���7��������1����������������u<;;} @��vJ����g�;@�|/�=3(ڼP¶(\wZ_+3g`/@$R3� S4 _eb&|�'{1F+HQ)'Td�SHn3*vmKˍb̨Q& ESAbPwۓ-<eaJh?\Ke6m�jYI�y` `qi�`���M >M�no:~��|ahYx�c41� `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��;����c����D"�����/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׶<D� /M@P]�b� ߡ�KZF.,I߈$#OQ!�0s}(ŗwmKGD=�PQˎ%vt߆a*hdT�������APETAGEX��������������������������Year�2004�������Track�02/10�������Title�Silence�������Genre�Silence �������Artist�piman�jzig�������Album�Quod Libet Test DataAPETAGEX��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0231862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/data/silence-44-s.flac��������������������������������������������������������0000644�0001750�0001750�00000143330�00000000000�017513� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fLaC���"���y�+ B�zbܷH2ĺJ�� ���reference libFLAC 1.1.0 20030126������album=Quod Libet Test Data ���artist=piman ���artist=jzig ���genre=Silence���tracknumber=02/10 ���date=2004 ���title=Silence��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0231862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/data/silence-44-s.mp3���������������������������������������������������������0000644�0001750�0001750�00000040000�00000000000�017273� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ID3���� TIT2��� ���Silence�TPE1��� ���piman�jzig�TRCK������02/10�TALB������Quod Libet Test Data�TDRC������2004�TCON��� ���Silence�TIT1��� ���Silence�TLEN������3000�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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:TVuw0QlKJ48'ދ}D9<!cW=vEFbJd/z��� 0�����9� ���\E7i*of81CQIxD1,Q,<_/m u,V)JȆݕZkU d6SB�@�� 0������7 ��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��� @0���P@�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!-UPYoLdgt�A� �����4 ���j6VӔ*{۟8^(rm&^HXRFKA"Դð"j#:* dmv��� 0������2�`��̯ar-Xʱ+84ΕT1XqǸQs醘–ݩKe+ ]S*cRduuA��@ �"����- ���|Au�Oހom61W�Ϩp9 Xѵ9}$KS<Ӹ啇Bd|`��@�� 0������5 iud5'2haµ2$!/&p4  vZc9frdf�@�� �����;`@��M93bRqό]͹(u2"*+bխǘ?C\(tsKըV6']9[h;s=PdqA��  �����.�`��B2ELv<FT!ϩ$%smNwzj ` L$`SqcbdoA�� �#���= ���0F?xņ^aW+5B.cHyV)Bބҩ4U sYz!㏋]ja{ֳ`6pd^A`�� ` �����9�`��pKPlw4i= [qUJ1*rv_\VjE."ذ쐆+ lґn`ddA@�� @ ��@�=�`��ƺ#kQqU)8YкQI4 wUk.M R 5;Y;Rdz���� 0�����; ��� EzQuVTqW9v ^ر}N~HX|\6JyyNg0Udu���� `@������+�!����E5Nb2@m 9HFG.9WlutBihU K֭3N2 1o - #{SdfA���`0����3 ���zǦ^Tk QMI(M@@εxs 4uk=DP~53FW`Tx[<dzA��� 0�����1`���ʣ#AMoc.ʪIKn5P45+8?emלYww1q@$T)q.d\B�`�� 0������;�`��MBp*Pɫ֊iN7*d^D| aҟ(F~h[zQHͭHiy"dǏsA�`��  �����7�`��Ezv*S{^[byU k C'-[VHVQO?UBQQW̉M (7fApbŲ1w Yd͏iA���0������7`���04B4U[d7&?%sْ6|G|1/k{&]i˥)Ghl6>6dgA���  #&��<� ���(krqt))G yN Jlz C)Ňʹ3*79xdrA���@������3 ��h(Uƚ,r ET7_۰}L)!!I;Ifw=p^S _do����0������-�a����mWIn qѭ =gy+0V̪'L9 (ֵHsoZkklh0,T>d��@���#�A���9`���Y̎\fmy$'@WHbFbVyၢڌqel) g jd�����c�B(���G�`@�z'8jF@, ZY&&BrVI킡g?]}vwo:-[<R`dyA��0#8�@�8`��dI*T ؒ@τ(!rP:tTPU[аu~&$>8VJd� ���A`�?� @1i2iy/9q]UB Lː8bF@SX2r˫w~xyd���� ������C�`���wlx:iL)_d(fcSIKi&=A׳mR_|(ed@����B<@?�`@��t ;L&jVy#<Njkߒn_h=V瘦LcZ$Cd}��� #&P)DD`@��R]sq%k֢9KݗE~ A<t֨A䅥/4ZzMK,z2dA���#8@�? ��˽{<l|?hu>3|2mbb6STÙ vm <e(d6>*Ld���� ���B\�@Hx('p( i^ZÝNF 9<o!d}T\e-BdA��` �"�`�A�`@��qA!ր(}y V4<Gt3yM{G׻k+:lg%M&dwA��� #8\�L� @v틨>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@�@ #8���I� @��N*Ne<}^qG_Q./My};(Bs.&Rd~��@�� ��8��N �c]Zx)jm6Dle(At: w)SEt4\95h{uOAQ !dmA��� #8h��H� @ :IgނYY;* }ܶlIr.;Ww{F=/ =MCdA���  #$ ���I� @��eG&/j7 (ʚ_](y9 b(.hRS⡋ k>,FXjqPldA��� 0���T��J� @��&Tִw&igE2l]Hkuu%ԉ45Լx,Yd����` �"����F� @�NJ(ʞPmUF@*vJC7wl;x`v'.X"eg81d@�"8��D @���.o&Sdɭ"+]"'סyh ...lP)C>AXSjHtXd��A�#&B$���F�`@�!aκ^Y%ϵC([uB7kCb]Ej)Zy iA&=*+isOd~����� ���D����I� @��R<6N-/ۀ;,?'jYMʃBBŦ^OJViMdA�0���\�J� �qnat9B QzU .*4Ir9<uof~ub+<ɔC-);Od~A��@0����?`��HB\)KmUE m \XcU)RJbQ"\(<:>X(Y_ed���` �� @�E� s-^8ysK!qVd:@(BR)`7,s8Caf%&\M ҙd����@��c�B$���<`���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 hqqZUdA������P`J @\t-{onAŚ[Zzw])SL"0_:y?RƤpo%owxRid�� ���(@�@ ���;o-)dy2U zBfQ ԲH׹'Զ0,fG6R̙TTR7d@�� ��BD��H @��9 0vPW6ANufm( r-x5ZuY#nʽ̎b@dA�@�� `���8�L�`@��၃d�bD-|r$$XJP-Yȓ29>IT7bkȏ)J:ud�@��@��$���I� ��jA/._Z0XY\J5*ck qΕk73}MUߺǨQ X duA�� ���A@�H`@�=k!g\/d,fg19ԭ <H,!y!vp"v1bInMsw>׿td������"�B @�H @�/Mc2G~M Pj]4iu`pAPB]1/75A�R%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����� ���H��L @�޻?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�"8��E�`�ަ8XAC�,"= ^f\ܙ܌BqN!wDS/spㅫ/!>ǰSmdxA��� ���<@�> @ߛȂg~ԗul~Vd?d|V*d4\2|W$ad����B8�I� v|ԑV5A\v ډ׋eTdJKO<VJ~䇿JdA��� ���8���E ���>MA¬G^̟^dcz1KH=xH ^%PY0.Th`<x#~ ʬ wd@�����B `�B� ���o#gio1?UsOG_K脓̊&X+_6)HuKF<> 6xadA���`0�����8� ��EpjDJ < kJ5#nSd)[G; aT1F_6><rǐWd@"�B���F ���8Der*8jCC;!n6XU2RRͦda+(ymJXd��@��� ���Ah���F`@��0˘wXՖ IЂR*Z֔t}jLTJP([ <7+!At ʡ4d� �"B,��J�`@��UKXZd#al%w>͸8{㥍WK2OP6A ), 5Kd���� 0���H��J @DYH,츹p -$=4`|v OuI$6J_zQ}_є_[dy�A���D`K� @QozV:ySԀ]N�Ǐ̋r9IiVMM}=Ġ23[ޔS?d��� ���4`�>`���:wyIM6M ($ P{A* y1h) 6)1yKRdA����b�T��C� @���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���  �c�h`E�`� �k�k.¨�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�@��`0���T���E`@c=Xҁy.)"o9*Su(YH!5>,8{!:Uф"c|*"H.Qdw��@��@�� � J �W*D>ռU oCZѬسEiQ<c;Y̱U׶%�^jXՌd�����$���=� ��\3[^mB#*,Q8ni&.IcƲ>@y9\9B&ٛK{Nq]hd@��`�b�B���J`��GC:2RI`<sh 2,hᅡYk/Pv,1U:HMA])FdA���� "8p�L� @0qQ8f6pHbCTV_? myK O/-?H:4B1dz��  ��p� `N� ���sCI;( ?B$@O&5unk5KX~r>P|n+d��� `0#8�`R�IՏ3VU6jȵĝ p)]?Ic*1CMEqH$:V'J[rd���` #���3`���I4+%/ ^JS#I %R$B.1uH +h7=P^uW"d@�c�B����A ��x5kS'AV(ߗ]<~]fa X"Qt"2ˤLy7DjZd��� #&D��H`@ 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���� 0��t�`N`�=2�(~Pw3iS:Qz (vmaFZ|V.5kC%RQ$ʪIdvA��� �#�`�J`�Rmqr>V*Ċ5 7 ikE,r+eg/8aeadwA��0���l��P`�Æ"*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(<rMUp %9ڐ<y)B*UCR?ʊ0˕ `EId��� �#� @@F� @�Ih&+-צ+iVTHR�^5KH~/-O>͓ %c*d����` ���8��B�`@��� 5ٗybr_p~ vE&:ئcRyIs*/6DbQ4=>Ӏ'duA��� #8 ���I� ��,c$1* )NW*Pj*Kc 44۳P]ԕ 8eq d @  ���A���D @ƥ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]Id�����c�BT��J`���1MM<ZܥaC(q�3DsɸIav06ƙ0oJ9ᵇކp$@'di����C�d��L ���&D?{jzmTװ{s6A*"=jMN-J(VI+mds����0@�h!BG`@�[ ͂jZ dNx= nKc_g09ׂDrK0SPdA��� ���A���:� @֊ G%\Q .pe䞖T>HM 6ܣfOwo @h=ad@�#�A`�G`@��`'`DISa1Kw{z ÚbId]^7gzo G m *d@��"P`H �WRAw%LAME3.93LAME3.93d��@��(��>�`��dA�����B ���C�`��dlA�`�� ���,`�C�`@�d@#�A���D`��d@�`�"8A@�9 �d���#�B����A�પd��i������ �����������4���TAGSilence�����������������������piman�������������������������Quod Libet Test Data����������2004�����������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0231862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/data/silence-44-s.mpc���������������������������������������������������������0000644�0001750�0001750�00000003641�00000000000�017365� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������MP+���\gg��Йs4}>|n"vKd"墲*{eiy\=sy4g/cX@Occ{҄-y^g2<DGjQ(5 lYR1ElŤ.<*0ZP>;ZK'?I%.]$Q(w%3V�I9_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 i�m;IZX\^&ЖV*UAޮhn ȇYQ|8VM3yll mS33a)IqeZ9[f[-+gրOE uG&WG5&6|_{;V]sϤL/O} ۚ\%1b- ZU̓RT}:pFg+i}WiY<l[.cSfZzglnw= <S*b<zPz_v[o۞*ӈ{z=vpgf*Sjg禮ؑ#xs{RYo7$ Dp29|շvZ!#^% yyӤmnM<<g~ΟӞ3sϟg39{ϺaI%|Lq! `Y^H> �y럻+)2n$pմs9doZ���W dǩdoz۶mےcpz_UUU]?Vt.\tپpkU`__G뼪j$ҤLT<UU~r�[U5]ţK BUUuVAP~��:APETAGEX��M�� ���������������������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.229712820826APETAGEX��M�� �������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0231862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/data/silence-44-s.ogg���������������������������������������������������������0000644�0001750�0001750�00000017136�00000000000�017366� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������OggS���������>1n����@vorbis����D������ɯ������OggS����������>1n���*־Cvorbis���Xiph.Org libVorbis I 20030909���)���rating:quodlibet@lists.sacredchao.net=0.0���album=Quod Libet Test Data ���title=Silence ���artist=piman ���artist=jzig ���genre=Silence ���date=2004���tracknumber=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ʣ<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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0231862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/data/silence-44-s.spx���������������������������������������������������������0000644�0001750�0001750�00000057556�00000000000�017436� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������OggS���������'����ǑrPSpeex 1.1.12�����������������P���D��������������������������������OggS����������'���0���Encoded with Speex 1.1.12������album=Quod Libet Test Data ���artist=piman ���artist=jzig ���title=Silence ���date=2004 ���genre=Silence���tracknumber=02/10OggS��n������'���+-]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]tN��mC�_mm/mmmmUՅ]]]]XUՅ]]]]\ֵtNkmE_mm�/mmomUՅ]]]]XUՅ]]]]\ֵtN��mW�_mm/mmܡm%UՅ]]]]XUՅ]]]]\ֵtNFS_mm�/mmwUՅ]]]]XUՅ]]]]\ֵtNq�m`3_?%/mm�mmUՅ]]]]XUՅ]]]]\ֵtNa�m}�_mmcmҵ0?omUՅ]]]]XUՅ]]]]\ֵtN<m�_mm/mmmUՅ]]]]XUՅ]]]]\ֵtN�mP_mm@/mmhUՅ]]]]XUՅ]]]]\ֵtN(խa_'@mmUՅ]]]]XUՅ]]]]\ֵtN�m}�_mmثtbmmUՅ]]]]XUՅ]]]]\ֵtN(mmB_jȯmmsmUՅ]]]]XUՅ]]]]\ֵtN@�ma_o/mm[AmUՅ]]]]XUՅ]]]]\ֵtN�mn�_mm/mmUՅ]]]]XUՅ]]]]\ֵtN_"mt"_jVm mmUՅ]]]]XUՅ]]]]\ֵtN,�mj�_mm/mmo5UՅ]]]]XUՅ]]]]\ֵtN�m^c_m@/mm(m[mUՅ]]]]XUՅ]]]]\ֵtN_Dg,_mUՅ]]]]XUՅ]]]]\ֵtNpm]_m/mg8տoUՅ]]]]XUՅ]]]]\ֵtNZ�md#_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Յ]]]]\ֵtNt�mx�_mm/mmUՅ]]]]XUՅ]]]]\ֵtN1�mk_mm/mmѠmmUՅ]]]]XUՅ]]]]\ֵtN[�m@_[m/mmڎmUՅ]]]]XUՅ]]]]\ֵtNmFmR_mm/mmޔmUՅ]]]]XUՅ]]]]\ֵtN'�mW"_mm@/mmmUՅ]]]]XUՅ]]]]\ֵtNFm#_m/mmUՅ]]]]XUՅ]]]]\ֵtNC�mu_mm/mmXmmUՅ]]]]XUՅ]]]]\ֵtNm\�_mm@/mmmmUՅ]]]]XUՅ]]]]\ֵtNrp�_mm/mmmmUՅ]]]]XUՅ]]]]\ֵtNcmOʀ_mmm@mmUՅ]]]]XUՅ]]]]\ֵtN5�m_mmA/mРmmUՅ]]]]XUՅ]]]]\ֵtN8�mu_/mmLmmUՅ]]]]XUՅ]]]]\ֵtNz�mR_o@/mm�mmUՅ]]]]XUՅ]]]]\ֵtNPc�mU_�/mumUՅ]]]]XUՅ]]]]\ֵtN �j�_mmfm$OhUՅ]]]]XUՅ]]]]\ֵtNY�mV_m/mmߋoUՅ]]]]XUՅ]]]]\ֵtN�mp_mm˯mkmUՅ]]]]XUՅ]]]]\ֵtN(mU�_mm/mm�mmUՅ]]]]XUՅ]]]]\ֵtNq:kH�_mm/mmܠmmUՅ]]]]XUՅ]]]]\ֵtNp�mI_lm/mm mmUՅ]]]]XUՅ]]]]\ֵtNZ�mq_?m'/mmcomUՅ]]]]XUՅ]]]]\ֵOggS��������'���B-]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]tNH�mi#_@/mm`mmUՅ]]]]XUՅ]]]]\ֵtNP^ԿZQS_mgpmUՅ]]]]XUՅ]]]]\ֵtN1�ma_ikAUՅ]]]]XUՅ]]]]\ֵtN_oڵ@/mm mmUՅ]]]]XUՅ]]]]\ֵtNH�mv_mm@/mmҞlmUՅ]]]]XUՅ]]]]\ֵtN��mc_oow�/mހmmUՅ]]]]XUՅ]]]]\ֵtNK�mr__mۅmmmmUՅ]]]]XUՅ]]]]\ֵtNk�mj_mm�/mmmmUՅ]]]]XUՅ]]]]\ֵtNp_mm�/mm`mmUՅ]]]]XUՅ]]]]\ֵtNbI#_m/ٱWmmUՅ]]]]XUՅ]]]]\ֵtN+.O�_mmu/m mmUՅ]]]]XUՅ]]]]\ֵtN7�ms_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Յ]]]]\ֵtNE�mT_mjҿmJmmUՅ]]]]XUՅ]]]]\ֵtNsFs_mm/_mUՅ]]]]XUՅ]]]]\ֵtN*ԿR_mm"mm×UՅ]]]]XUՅ]]]]\ֵtN�mp_z'YmӬ5oUՅ]]]]XUՅ]]]]\ֵtN=�mq�_mm/mm߀mmUՅ]]]]XUՅ]]]]\ֵtNwmE_mm/mӭmmUՅ]]]]XUՅ]]]]\ֵtN<Xֶo_mkmUՅ]]]]XUՅ]]]]\ֵtN0jx_oѬ[텝UՅ]]]]XUՅ]]]]\ֵtN>�mo_mom:mUՅ]]]]XUՅ]]]]\ֵtNP`Կm~_omoUՅ]]]]XUՅ]]]]\ֵtN�m[�_mm@/mmmmUՅ]]]]XUՅ]]]]\ֵtNfη]�_mm2/m|Ӄ'UՅ]]]]XUՅ]]]]\ֵtN'�mq_mm@/mm٠mmUՅ]]]]XUՅ]]]]\ֵtNmX+_m[m�/mm@mmUՅ]]]]XUՅ]]]]\ֵtNb�m~�_mm/mmҗ[mmUՅ]]]]XUՅ]]]]\ֵtN�m[�_mm/mm�mmUՅ]]]]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@/mm�mmUՅ]]]]XUՅ]]]]\ֵtN3mՐ3_m/mm`mmUՅ]]]]XUՅ]]]]\ֵtNl�mJ_m[m/mmՏUՅ]]]]XUՅ]]]]\ֵtNQ�m}�_mm�/mm[mmUՅ]]]]XUՅ]]]]\ֵtN�mo_mm`mmUՅ]]]]XUՅ]]]]\ֵtNJTӶS_ml @/mڀmmUՅ]]]]XUՅ]]]]\ֵtN~�mw_mmMmmmUՅ]]]]XUՅ]]]]\ֵtN2UI�_mm/mm,[m[mUՅ]]]]XUՅ]]]]\ֵOggS��O�����'���r&:-]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]tN mp#_mo/mm׳mmUՅ]]]]XUՅ]]]]\ֵtNB�mv�_mm/}WmmUՅ]]]]XUՅ]]]]\ֵtN'Կmp_m�/mm۠mmUՅ]]]]XUՅ]]]]\ֵtNpm~Vmm/mm@mmUՅ]]]]XUՅ]]]]\ֵtNP�mn�_mmCdmmmUՅ]]]]XUՅ]]]]\ֵtN7�mq�_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Յ]]]]\ֵtNv�mh�_mmomUՅ]]]]XUՅ]]]]\ֵtN*�mz_o/mmmmUՅ]]]]XUՅ]]]]\ֵtNh�mx?_m/mm mmUՅ]]]]XUՅ]]]]\ֵtNc�mJ_m[mg/ZmmUՅ]]]]XUՅ]]]]\ֵtNNmq_/UՅ]]]]XUՅ]]]]\ֵtNq�md_mm@/mm mmUՅ]]]]XUՅ]]]]\ֵtNukR_M�mmUՅ]]]]XUՅ]]]]\ֵtNk�ms_o/mm mmUՅ]]]]XUՅ]]]]\ֵtN{Կ_mm0/m[ mPmmUՅ]]]]XUՅ]]]]\ֵtN1�mn�_mm/mmї[mUՅ]]]]XUՅ]]]]\ֵtNFm[_/mlmUՅ]]]]XUՅ]]]]\ֵtN'�my_o@/mmPUՅ]]]]XUՅ]]]]\ֵtNrFKX_mm/mmm5UՅ]]]]XUՅ]]]]\ֵtN�mQ�_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Յ]]]]\ֵtNR�m~_2[mٯmkm@mmUՅ]]]]XUՅ]]]]\ֵtN@�mu�_mm/mm_mڵUՅ]]]]XUՅ]]]]\ֵtNu>ˀ_mm/mmmmUՅ]]]]XUՅ]]]]\ֵtN�m@_mmͯmdmmUՅ]]]]XUՅ]]]]\ֵtNC�mj"_m/mm mmUՅ]]]]XUՅ]]]]\ֵtNl�mzH_mmmmUՅ]]]]XUՅ]]]]\ֵtNG�m\#_m/mmmmUՅ]]]]XUՅ]]]]\ֵtN&οm�_mm�/mmmmUՅ]]]]XUՅ]]]]\ֵtN9mkN~_mmUՅ]]]]XUՅ]]]]\ֵtNs�mn_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Յ]]]]\ֵtNb�mx_m_G/m`mmUՅ]]]]XUՅ]]]]\ֵtNJ�ms�_mmHmm!տUՅ]]]]XUՅ]]]]\ֵtN�m_�_mm/mmoڕUՅ]]]]XUՅ]]]]\ֵtNF][_m/mmvmUՅ]]]]XUՅ]]]]\ֵtNP�moj_m@/mmHUՅ]]]]XUՅ]]]]\ֵtNI o#_/mmCUՅ]]]]XUՅ]]]]\ֵtNzԿ^_/UՅ]]]]XUՅ]]]]\ֵtN�mX�_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Յ]]]]\ֵtNC�mh_mmCZHmmUՅ]]]]XUՅ]]]]\ֵtN5ֶm_6m!/Ƿm͝UՅ]]]]XUՅ]]]]\ֵtN9�T�_mm@/mm mmUՅ]]]]XUՅ]]]]\ֵtNo�m@\%@/mm#oUՅ]]]]XUՅ]]]]\ֵtNj�mn�_mmׯmmѠmmUՅ]]]]XUՅ]]]]\ֵtN5�m}_mQm mmUՅ]]]]XUՅ]]]]\ֵtN`_mm/mm�mmUՅ]]]]XUՅ]]]]\ֵtNxI_mm!/momUՅ]]]]XUՅ]]]]\ֵtNW_mmٯmmmmUՅ]]]]XUՅ]]]]\ֵtNBԿO_o5@/mm֠mmUՅ]]]]XUՅ]]]]\ֵtNu6V�_mm@/mm'mUՅ]]]]XUՅ]]]]\ֵtN#㏀_mm�/mm�mmUՅ]]]]XUՅ]]]]\ֵtNi�mR_mm:@mmUՅ]]]]XUՅ]]]]\ֵtN:VB_mۯp WmUՅ]]]]XUՅ]]]]\ֵtN@ֿ_m�/mm,mUՅ]]]]XUՅ]]]]\ֵtN&6_Vm/mmܐUՅ]]]]XUՅ]]]]\ֵtNPX�m\_j呯hUՅ]]]]XUՅ]]]]\ֵtNdοV�_mm/mm`mmUՅ]]]]XUՅ]]]]\ֵtN_m H_/mm݀mmUՅ]]]]XUՅ]]]]\ֵtN|Os m|S_6m@/mmڗmmUՅ]]]]XUՅ]]]]\ֵtNP�ml_Q[mK`[mUՅ]]]]XUՅ]]]]\ֵtN�m\�_mm/mmmmUՅ]]]]XUՅ]]]]\ֵtNwmOʀ_mm/mm`mmUՅ]]]]XUՅ]]]]\ֵtNs�mE_mm@/mmmUՅ]]]]XUՅ]]]]\ֵOggS��0�����'���m,-]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]tN�mh_mm/ҶmmUՅ]]]]XUՅ]]]]\ֵtN>�mz~_o@/mmUՅ]]]]XUՅ]]]]\ֵtND,_m/mlmmUՅ]]]]XUՅ]]]]\ֵtN%F#_/mmԀmmUՅ]]]]XUՅ]]]]\ֵtNS�mI_/mmmUՅ]]]]XUՅ]]]]\ֵtNL�m{_mmkm-@ mmUՅ]]]]XUՅ]]]]\ֵtN�ma_mm@/mmҗ[mmUՅ]]]]XUՅ]]]]\ֵtN,~܀_mm@/mmmmUՅ]]]]XUՅ]]]]\ֵtNcoƀ_mm/mmzomUՅ]]]]XUՅ]]]]\ֵtNm�ma_mm/mUՅ]]]]XUՅ]]]]\ֵtN8�mp�_mm/mmހmmUՅ]]]]XUՅ]]]]\ֵtN|mY#_mڵ1mmUՅ]]]]XUՅ]]]]\ֵtNgfZ_jbگmmUՅ]]]]XUՅ]]]]\ֵtN�m~,_/mmmmUՅ]]]]XUՅ]]]]\ֵtNgS_mo*ȯmmUՅ]]]]XUՅ]]]]\ֵtNE�mx�_mmQ/խa?mUՅ]]]]XUՅ]]]]\ֵtN'�mi�_mm/mmܗmmUՅ]]]]XUՅ]]]]\ֵtN�mO�_mm/mm@mmUՅ]]]]XUՅ]]]]\ֵtNmO,_om/ZUՅ]]]]XUՅ]]]]\ֵtNX�mu�_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Յ]]]]\ֵtNj�mU_mmm`mmUՅ]]]]XUՅ]]]]\ֵtN"�mh_mm/mmW[omUՅ]]]]XUՅ]]]]\ֵtNFm �_mm/VmmUՅ]]]]XUՅ]]]]\ֵtNMX�_mm/mmmmUՅ]]]]XUՅ]]]]\ֵtNr�mu_mڵ/mmUՅ]]]]XUՅ]]]]\ֵtN)mx_mm/mmUՅ]]]]XUՅ]]]]\ֵtN�mb�_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Յ]]]]\ֵtNI�m�_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Յ]]]]\ֵOggS�z�����'���F]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]tNZ�mH_mMmk�mmUՅ]]]]XUՅ]]]]\ֵtNucG[m/m܀mmUՅ]]]]XUՅ]]]]\ֵtNP6NӶmK_mmqf[jVڵUՅ]]]]XUՅ]]]]\ֵtN�mf�_mm�/mm@mmUՅ]]]]XUՅ]]]]\ֵtNI�mw_mm�/mm`mmUՅ]]]]XUՅ]]]]\ֵtNR�m}�_mm@/mmԠmmUՅ]]]]XUՅ]]]]\ֵtN6?F_mm<mmݨmmUՅ]]]]XUՅ]]]]\ֵtN�mV_mm?/mJmmUՅ]]]]XUՅ]]]]\ֵtN.mmӄ_mmUՅ]]]]XUՅ]]]]\ֵtN �mR_om`mmUՅ]]]]XUՅ]]]]\ֵtNc�mk�_mmïmKmimUՅ]]]]XUՅ]]]]\ֵtN�mU_mm/mmo7UՅ]]]]XUՅ]]]]\ֵtN�mQ_mm/mm mmUՅ]]]]XUՅ]]]]\ֵtNz,_m@/mm@mmUՅ]]]]XUՅ]]]]\ֵtNU�mH_m[o/mm`mmUՅ]]]]XUՅ]]]]\ֵtNkF|�_mm/mmI}UՅ]]]]XUՅ]]]]\ֵtN%6m`_mm@/mm@mmUՅ]]]]XUՅ]]]]\ֵtNe6mk@_mmmRXoUՅ]]]]XUՅ]]]]\ֵtN,�ml_w[o&/@mmUՅ]]]]XUՅ]]]]\ֵtN-ԿmX�_mm/mmmUՅ]]]]XUՅ]]]]\ֵtNZ�mt?_m/mV@mmUՅ]]]]XUՅ]]]]\ֵtN(mh�_mm�/mmߨoڕmUՅ]]]]XUՅ]]]]\ֵtN 6M_mm�/mmܠmmUՅ]]]]XUՅ]]]]\ֵtN֚J�_mm/mm mmUՅ]]]]XUՅ]]]]\ֵtNk�mK_V糯m�mmUՅ]]]]XUՅ]]]]\ֵtNRa_mm/mmڗ]mUՅ]]]]XUՅ]]]]\ֵtN"mKj_`mmUՅ]]]]XUՅ]]]]\ֵtNBp_ůmm۫mmUՅ]]]]XUՅ]]]]\ֵtN[�mo_mm/mmmmUՅ]]]]XUՅ]]]]\ֵtNh�m@_mm@/mm`mmUՅ]]]]XUՅ]]]]\ֵ��������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0231862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/data/silence-44-s.sv8.mpc�����������������������������������������������������0000644�0001750�0001750�00000001007�00000000000�020076� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������MPCKSHQo@�RG ��������EISOW���APyR)fdc=eTM4Ǔ52Γ^-薂J40`i _Ɔ>L|A[_a@@=Y.]?j'5ؗh̙# <L05hGnK 0%rǚ@% 01+$脫CQ�])S?_,ɞ1D,֮W4,+ӆ\gk_̣A%i_׃M0{AP$d ܣ#&*O�VOZu~Gi q-<im2ͥa{>eO_pJ 2h * Sݗ׎ndosKi/-/gNO�E:f,K-sKR~AP*{_4=Ueи~Zٝ H4gST5 SE�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0231862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/data/silence-44-s.tta���������������������������������������������������������0000644�0001750�0001750�00000235274�00000000000�017407� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ID3�����TDRC�����2004�TALB�����Quod Libet Test Data�TRCK�����02/10�TPE1��� ��piman�jzig�TIT2��� ��Silence�TCON��� ��Silence������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������TTA1���D��z�)RLZ��RZ��Z��'��` _��������������� �������������������������������������@� ��������������������������������������������������������������@����������������� ��� ��������P���������������@����������@���(@�� � ������� ��������P@�� �����@���������������� ���� ��(����������(��� �P�� ��������P(���A��@!������ ���� ��� (�HB%�%B ��D���@��A����������PPP�`�(`�����P@I�P�P������������P(�@�������T�C��@�!PX @a� �����@A����&���� d(0�0 ��L ������������� ��@&" �E�(EaPtP`L���LT� ���E��P[������2`����0�������`������e����e��$@Y ��ˀ ���d���0lr1���I�&a2����`������*�� e������e��TI��LR6 �e�0��������&P �� �e�Q[����0 `�*��������&������`��eT�`e���0 ������` ����e�2�*��0 ������P6 ���0 ������e����e�@��� eP6������LB52���������P�L�� `R\!� ��&�@�`���`����(��� �&�P�2����jL`�ʘ�e�e� &�����Ap�0 ��P ������0�������Pe����L�� ��� �����$�e�0 �� 0WRI��(1a�(���I �dP6L� �C�� ��eS �����I������IL�0 Pm�2lj T����@6�L��A�  ��@5�� 0 ���@1���&(���I��&P0PF5&6$ ���(T������0��`�0�!L`� @Y5�������ʀ2�j��d0$����P)��ee!L2j�`V �@0P$0�L��L�e�3(l@�T���&e��L��ʀ2�`(cB����(eP �����L� L2 ���&@5 ���PV@5�՘���@P��( �2p'!M `������ �����I` ʨ��jE e �( � $����P�! a�`�P6\6'` ���*� �e@���eTC����@�T � ����P�@A�0����`k*aj�P6 C�2���� (����`!@ �0 CH`@(������ �&0Y���� ��2�P���L`)�����j@Ym #C1��($ �������(������ ��� �<���& (S`rɐ00 ��`�00 f �e���PF2j%L5&����P2��a�$@x!R2TP������`” ������'���0 �������&af�0�LA�PV6 C`�d���2�ef&$S!L�! L2l&I������T d& 0$�������0�����A�� a3 C���( aC �� (ʀ0����A�� abʨ`@�! �������� ��(��AJ������ �����*V-� ����� ��������x&a`Ն0@��0�����T �0�0 .� �����a( OQca��! A`L��`j ���� �@\m$�&a��A���(������0!yõ2@9aTl���\��0! Pa&a�L��������@6Sa��IՆ0e�I0$ a�eCLj#a0 � 6\m&eCjL2d�Ae����Pa(=̜ ����- y���( @5�0�� �a ���d�$ a A23��P�$Px�2&'I�� R6L2@! ��0WIx�P)0�P)0�՘dL�.d!L��0$3�Ax6u{�0��Pa����` Pa��������` CH$ Cr$Lep9 ddM��2 d0��pf�A L`j6'S[ɐ &$3����x8<$O5&gAI�PF5D0�2<'3  �����@6!L������eh 0d g&a0 C�A2C0��I1WIfH0&a�۬$2Hf��0eaA2C2HfB$3\MƩ@sj.r3a'dj�*aN<C���PL jC yS! @fN23(Y �mI"0 @$3d\$p2(0jF L��&0 rmd&��@$@ٓ!��� �f0 ��%0a$ aL&a83�&a83d3�� 0uIf!y<3'pm&C9 s5!L2 A��P69<a&gV d&��!Ppx8 �� ��(0S0IL�ʆ9g����LIL�9IF9I@"0��(0Ix8L&@f������A L$L����&7N A'0a83$ g& <O���`t>@pfRa298$$��\md& !0 3C<Pm$$$ 灘D���2HL�&arF rQ&&~֖̜@X��A2\M !g&���0 3�����&ŕ!e &C�&arf093PTd̄ ���0 3I�La&g&Lhd$393��d&g&PIQF&a+o)�Wb P Ù A2 j2uy��L 2L`|m d!L�d&g& ���0'$Hfr2ə �Pa @!A�0 3��2 3/<ʮf2d&咙s�䩏;9AJ4��F2$MKy `reG'�&ə��ᓧ!L232(f9G������`lO MNq!$'&��Ro9m9J���L.{5GT$Dd&'�������$393�����2yΙ !a�ZkkC!TPcAjfڮ�$393���I3��������D$Նd����0LXL'CjCxIjcΜ#!�fCޤ<M"cEC�����`LL ����(0\0\a�dx>v &Pae�sِ32O29 �3`393�� 3932C���(0 (sِ!L2C��`LL�L_z83 �1W{ ��0sfG� ����ˆs'A��������PA!��2��030sfC(0�&dR3?*V'3.0�`LL�0�`LL�������"!�F@PF�j 3a&g&eLL��00L0m0��@V M 3 $arf������d@ ?LL������03sٜmɑhE$ j$<����&��rf�e$<2sL"�2�����e3?G- �B��*Vl8<HxfrFF29�PFC� 393`<<L"��0jgC >[�T0_#P  O"@�&Ϝ?ơ���$#E@593` y'�&HxȄarf@8g�@ ZAC��ˆs~03`.{nYoMjbO1Ih`1HxHIyGʔSo �) *P[$Rf����0ayQA֖I����� 5C03'09y2sddp ��eEϜ3 3j@����`LL��ly8y+ 2,19����&kLq@��*sIms>A0wX՟)y&�9<�e31VE�BʂǾ��0fRTQE���|HF$p W6��!DTE`6syjD��L2GWA`p3g 3� 3k38���PFa,�2rxC�`91G@�*:L9�PV9aʨogY&y �`99@�� -'93���(#gϸVU��a''�(#0a愙9}Th ����@9<0 3���ԍ99 G�sp>!-a@mYTa1hc@f�M*"�`9H9zpH1V*"�0 V{sO*B��cA3g#3j 0s&��� 3��ϸH|8 �jTj�PFg8g&��f|au#HF|1��`朧�����@F�@2b 3gN0)?xUi10 �j��������Lxʮ8͢ 2B͙�L9̉����(#�fy&����@9<dv&y�F X5B�@3(bD@3'`̙��@9<L9�&|`@dppŪ!UG�Q,f<Kb 38"ky5;0 ����*c T��0a?qU#�@5u)2(ja='Cc$ Fx��fy*�șt;<P9<�P|C̜z �P9<��������v&DI3���`2·*.#Rgl;Ҁ` *,�d�Pԍ*(0C|mO>8����33@KX5B�B& -@�'̜3HfN��0a?:NَZ5 ���$#23���&68P6uC"F08<3ϙ9mcT8�������(#�3 sSC9aΜ�����&|15B����H|ꪣ1h`A:8U#77Ta@�,C}C��!���0gfU" ���fy*���X>YF�7=h��,H9<33kGc!����������9)sN�PU#Z/wi@��d+VBD GcPa@0V"3u�����@9<!���V9a�90ảap9Yi9$/w` 91�0F¤vvT!��PD̜��<�@F:Xe *زKPĪ *����F?gOZ=0R9fq]�b�BQ#9j޲ !b0mLErV2"Ӟ5�cPa@�BUqs �TPul€` %WI��f> �&Z9$����$#O VcPSvcaĪ)��aŪ�� 9c@3Ta@�� kTPFGle5HAԤɁ"T{$X 3, @c€�sx�����0X��PX!��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?Q��0bPe\!0*Y]u����z:kWX51t !I� |j"V��P9@@|j�����q,ޭ5z˂00b���8Y\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@eBT1�F!rh=fע,H�BjCFa@c up:F L+1@����s!pp:F@1ƥǸjDc�������U.F����`q:Uq@08jfb@@#V�2I7U�����s9 �HVy@̧F�PI~V����Lx3.v*E@#VO9��P*FŚ~e*D���e3?��*v-!n3ŀB>�T_݁W|U)SU����dE@F`RMKc������*XuUA2ƨ �. hqa( :B����@c4PW}��0Zq@e:x4U¡8b1i���0����,p�bExY �����G]1q3wiBWLt1+-U:VQjBj���aq@�H8!uXx��@c|spr1jDS.<\ZA����@2QXc]z !��d#s�q.�񔍺!X5B�`CF��� ������u*~jE ��V�����R8" u#X1b1ZXcTXu#V0b)FĪ#��0ƫ>UG�������d.��T/ĊUhĪ#���@2Q���`1 �`QGisAxueP+����"vz�0b1 #FD:B!XuW}ejĢbغB4"ZCVbĪ#��cXWP+4Zq@Eօj�`6u<$��ª#c�����(ZǏx@��`q������1*jq fU 놮8bF}YUZpuQ8 h *Vz"b`ݿ^ǃDH(вA0Z11Պ��Ʒ ?LЪ1` ���1��PQGh٨/)F\uDcvWQ8[w>������@F)T#P->���HVX1ԊVQ1�w?E�P,���UG#C8PD#uSp@��0�18̙[!C-:úl}AěfRa8 ���P[X8V �,C[Q8 ��c Ke�EUG������q�$cq@@G#z Bj]UǨ9]j��XZq@��1 ���$bQu����@Z������ uiv jq1 @Oٳkǵ����������R85pu���c���QWjPxG\#pB(.A٬Q/:@����@(:ЈƤP+���cq-;_Hň=h Z eYX�@(V!���Fak;ή I���rX+��j1 ��������dG]PQnp@0��TUG4���ԭ~UG�� 0U#d !�ưVa8 ��R7 1B�Pţ�cUG(v׊�c9 � ,����8"����ԭO0Ckq@���W!� ���5j#�p�c��TT/��������?> @P֏ǶQI)aX+�p#c+~UG���PW!���Pţ������d����8����@2.U±�:<&Y,���@ l"H W!�1�����8����Rt^Z)U^g򺆩‚P:.]W�LkEP���� uG���� uO^:B��DUG kŁa2 Z6֗~DafUa`+N!k  *R0 ��cX+ uſǰI ��P \u�����$82g]-z6~{wĪGȲA�����@88 ��v=õƈ=/cmg*e/A+f&$$W!����Z�d<B ���PcE6~џ ���XEϰp�,h����8Tz xMl1Z�����4;��@Qq#29�6RƸen=HT#d֊�2EZq@�������@iF= ߺQW��nb@o Z��a8 ���8,Zq@aҳ8D�b8W$����Y X8i8в֭B �WcUX1p������ jc\2Ep8 ����@8F]u*:B���QqiZӬVP !�,:k!��G-L��8p8Z8d!v]r<`D������(Qu:B�����u#  ƈ^T�ٱȴp�an]rV!XA֊ !^xĊb \u�����Hሗ~K#qb0rX+�,ZcUGr��������:.qq@�HQ�ԭK?��QqS&��`֊`�����:C8f?_r"�`1&aR �� =&���JW!DĮƀP4ƈW �� fZ+4BZGq[D >A�í  :a8 ���Haq@p6T;a8 �ūZ Bq#8p���@E]<Ł���]z<$��a-z1���>^.J ��0!:B���dG]l 1�1x@eX+���><ZQN.v ����+EAe���c!*pu�������Qq�qFD#d֊Egz|�����������P. Xq@���:.���5QXqK?eưV`,^8uUG�_*:$Ue[I/6K$�p*Xqe@t_0�����0`)99@cXk ����PS֯gkAE\ ʀ�@(\u� ޺c2,�ZcD#֊��qiVkʼn ���L6;UC,Zq@���?`D^,H������jq88Mz\u*\uu?TRZq1G8pA����KCF]:B@Y ��� W֊a8 �@~PX,cX+�Bq#dY-㡫��!  P4U9d k0Kc#��� zv4'$a%nY %����������1 e!���N}���Q۳p8 ����@88 XDZ��Rqaή]C^H�Z1ezc$�){ ��,Zq*<jm@T�l+;] 1bhX/A��������@?ho@P€d z- +0]!��m6_rBBARk4 ��Z,Zq@�� u<-k!dbʪ^l������:q@��R4;+����|z��Lk�Ԩ :B�B0�� ���l ���Q- - �DNJ�RDZQ8𪃲:zj����HNJ)ƈWİV�2]��TW+:N1 hT ���^u��QqUG��������5c!��5«@ŁW8#�@(|z���Xq@���@E]|�� Y}݅z|UUh( h���`֊���F]|�겻B� a_X8D (z=rY"���:158#�@=;��b!P<5h7aPX* %�0�����:#�*/�������"x %`�*�Z,Z`֊Zƈaw c`:N5Y㠊 {`Y#*h6SfW=U � ���� uG!*F |zŁWfܸ.:he �������H����d<zAuU�õ� z^۳Zƺ�������G�Pu=BcV<@�z� ^۳x-z�Ƭ+| $�0�1,-ZGpx@���@Eu=B��cV|H^յ����W]9,Ӡ@K�KCsVh�������@dLC b%Z7+P@o{CxOt���\r&�@I+4�, 2R(Kf^l m[5' Zdi Jf0%Yl  6H��`L&ӲC^a ,6� i��MK@���%LPPvԶpM,6�1x[` ¶ RRSrk ����8G������Rk<�ŁW=Bt]������(QaVhN޶$�$hL^$���� 64K@������ 0-m ��@P/= $��0eI�0R+'+AѮFԘ0���� fв t]꺢gj�����BcDt�����PQ��������HqKʵ %M  ư,P0`��@PQz��1 u<OQp`8@��ٯ%�(-1\1+������:>(1�U ŁW=B���� (<ǵŁQtV=>BCFs&Aka� V@���0eRHXa E=W�aZ@� (  @ AErQi@���KNtDaZaZ� ���=ӿ.I�` [e Chia��������iIi¥LA0v2à0�HdV:B���p͎kK`xK ail��1P%='U�����@EU����d<>r2���r06,opƕؘ֖p=ņ 2&����� 2ò Qh%i�jg}g �p-i8UA8Z,ed!%$$������� _:WRþ3(P% ��8Z\.qZ@��������P'MKaZJ`iZ@���ƴ,iB++.d�`L˒Ro`�����ư,i` .7,[dH-L ����@09 �����@Ppѐ.e „K��XiNVf ,a����L1ZZ0ۮXW ��������*/cLж.6�( -&r$$� $���� ( MI-L ��@Pp)SJCPvG]q���K@$ ZBI@̘6<������ 0-npeP� .eRN'XYka����� 2%Mi �r �(eI�cZ! <P� #vl.6���m�����Dƴ ���D)M���� lP°iyii2`DqV E&֊��` 5����Jԋe"eI�Жa +oh2ٍm;L&�����ƴ,i���„Kw [!f ���Aa¥LA�����il `1\)xVFޭ4㤵0Y`p) � $����å $�nvL��TL���� 2*Vm逢ƈZMxX3I$���QW=B���@HK�,LpT ITs0�⤵0��Ŵ,i����@IK� }6|6|d4f ���\iJmAՆul���,eISh/K` $@Fl6�X Kxp{-1.p [vL��l`ih4�YbC(4f �ˆm7: $ U @���  i]mKzM z_ڐ�Hhr������ІPJ�@2iyii�����cX4A��cX4A�� l0b r �p(_VA[vIr��0ee1 ��ư,i���hNM�������Pb �� (CaY�������(Ulր%LJ+:B0@|hXD 4f � .6lia�����cؖ4A�\biT,;ކv57m7p" ��@{M`P{��( �����cؖ4AA9&����T/ 6e$��00�(a܊@h- m&۪9Z@���@aؖ0(m � (L`M$���0mI�a( [ ������ mK 2˵Z"`bl!Q]d2і; 8YZ@'K uܰ|=KXKzl8lia��@X1I$*m f^mGl[e ��� D��a[+[ bؖ4�@(/ i&����X ے&���������J*[8CP(W9j� wr\֦d��a E 6I!=H�������ʆK9!(Lv  n6! ���`1may9nw@0[ZLD�0ae �wU_(LR�\l"!.6�������� 2�������J(ndpr8d76bF⬁D 4&.6�������ʆ[90mI����Q-MH 0^�������(lC&ʁ���������%$��Z&�` ے&((LiHfP(؜l- �@ n6��0F{KtLpMH9Z@�H`6f ����1lK ��������B8NC�cZ0Q3(4�����c4A�ak0M$��„Wnh:/- ��������@ն>P�`1lK� vb ������ n�1,ჼD��,VR ukhp�[9LTa0`i)QM$@B3(4��Ű-i�X ے&��&\dwж0� 4%l"�����Ű-i -Lp*7,[a�8l- ���Jp+ ����� Es[APex]������PpXha`ia� '(�Y7' Km ��Ű-a��A:L4lY+ ���% &I .6���@(iZ4 wm)�H�Ts0��������������@T M� S{ne"8�,rR[9 l-Ll0&�P-/vDL @F\l"�bږ4��Ŵ-ѹA6������@T e [9���i[B ʁ�������@I!p&����bؖt���8,�@([wN-F0Le5\h`Zh[@������t _^Ʃ&K"XL"��&DbɾX-K@�����ö`H������iۆN � �% ����� q؆  l(g߶�`[4C i,i�0r ���������@Ib 0ʂԺpY@&H .6ٲAi+@@ .6����Bce; Lp Cm0$P,K@����� pM ����pM �@NK:�(%djQEs-i���@(ရb,CUs-i�������Br8$DBUlX~{Zx����@Cyi�eI#L�� N M"2��������p[2���@([9������8lá`XH �ŰmY 6 ö���B0IAscӥ���������,muϠQٲ���������LP(�aۆ99† |ML$8X4��Mp`ۛ2:% 2! % �@Fd"�@(�/2�b[H�����`1l0%"2l{`8X4����t-<A�Aۆ'y i,)lYҠ4X4�Mpsstit& �����bڮmK9e{ &D�eIdit& �������iۆ B @�������ӧrvvcö@q�@(H�ö���J8E �����(\Yl[�A �J8;\~a7wJD�P0esܮsTU2�����J86- "dt0\cpit&79Lp�'˒2& �="D˒�������()C���PR8E ��B {`=2ತA= Am)ZyR������%B nda�@qƆmK��bڶ4An2!M% ��%p+d"��Ŵmi=6H n2��� plY ���%"PhL$@U4(v Fу{Ke .,d��H,K0[4��5H+-rö`L$�������%Cbږ4Mp&x%s79ٰ]Nk7H�BjN[$����B @��,mˎ鶤AhrLZD��BIYl�2& ����`I�ޕئE>- 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_`m�����bld/2�����xBIx���}$t0E&� K4b- ��@(7hya0(NzI0VH���@qrY����`1]1ݖa������Axކ#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 $2��Pl0Y5Ǝ$%jv6"!I^d"����@(ZY` C($/2X8ȋL$��e0���nξ VXT{)\ai ������ذmtJPA -L"�Eia$/22 7l[Za/d[Aa-1-��������@(餗v:U Z1/9Y8ȋL$��������� gܗ LI���%&`[������ i/ vXQa  ��Y8ɋL$��b-Cx, P�vކ�����p٦A؇(� IkYfWh��@V� d%T]g"; Ha����������"^`4dvvA$l$��������re æ)�����0M�X m:48ɋLFy�����,ձryDq- �@FrM$�E&{������`1\i��@(78}DqrKAҭ E �Y8ȋL$����������� ��jt& �,6Mbe\4�������jM ���Iov]LRWYD0��������D5N4��������(CD$r. ,A 2 b�d /0������� MOD�d /0��X caH"�����Io8Y %m^iӲd/b"��� y'2 ©\ 7H�����ݒl ��� a5H��t:6l}$h �d /2�����e&����blA������%v%p7:W]lJ8ؖvc"([8#�����Y8ȋ:m&)���tH�2 A^`"��%&�����������ZtT)p e��� tľ\`J"m77\.าPZd ���J: &�*$/0��� o ::D6݀3Ă #���-"uLnE`;~ @��m������pڦI,6:/U��������f)-}F����M򎛖] ����mnd���Iv�ti*/0����� t^a�% n0 ��,2 b���M� tW$-2HK����r$Odd�����*L%;&ݱr&%+)} IL×)D �����*w����@qRdSE���nKvLn0��P;~>@AѭMU\a��� e ��'*M x H$�Y0dd����`aTQ&������Io8.2Lb�2Lb�����������(NGFcr[2LPaS y/  ]0]\".7D-` �����bxLK{Jo6����Pҩcp[I ���,6Lb�d`/0!^ʳBPZdaoidaFeZ�������AI'"? 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 "s����S{[��`1ܶaS\a0þa(pe88Ld��2Lɾ2 p^nɤA*FCѠn$_(Efb��8T$bibFϵi [@qrYarYarYI ���, &8,1e& '{ ����� pd.p4W^)c_QR8Gb�������X m���Jz(_(^P(`"����+ E2��BIF)MD@N��� &2��* p7�����, hi 4zh{GU$BÙFXn !d_XE&AFE0,$e�����)Ӄ}#G6a �����T23�f :n������A Д2��bm : d�dt7��G"9 .6I$ ��������� (‹Md���vT| i-'H(Ⱥde&1����pۆILq>7C3�p^[$��������������� al LI @qrY Z80L$N� �^@������/}E ��G$LqLD`스(Cy1D 1:������/و"A,U4vMl!m@@B v022������a 21222��@P ibӊ;$zE%XKF@�ƙW(1����EeR`Q 4goi6 !������%</0�������v6,Q\AAF�2:Ҿ, KD��hb;H�hb;H���X6A4XtY&*6J $������B  $�Jx(_`"� & 6M"��dt7����� (| M�@(ipfs"dt77wK3a���d4 5 X₎jd@8XtY&BF{`U29nA`����+CE[R.i }QlA!%h@��d�a���� t-L`4(.h`\�ɢL$���8YtY&Ee"�Pam$6M"��� P����bmнVq}IMY0m%3f9<xS$P;-���ࡶœ���@%D$dI~ NaWHpmA`�U2BF���d4 de���, NEe"@FdD�Ja՛(�����������A[2 V]`e8VͩDL�ѨYMȈ�����06 i 0`"jEB������@ٻ(qAwQ I̊$I�hb$#�������� ��@&�������xx7�(6U2A H�&ԜeD@q6MNm&m&.Б]bH"���dt/0 ������C&�����������Pr[mY i_YD��������B a~M| ò|bo @y!/@I!��d2*.Ht$ڐuD���������J @�20m$�������, .cY&[e"����dP};H{Q$ P �(Nn]6e�P;%:ʊ��@qABg:` ���@,MF$ `.������"x(@qXuY&�����b0t$8yUCi�'mD���� P�� 3|," ��rwNJ_*IB�����:_Q$bEB�����'.D�������@{fp�(N6]������������PY4Xr&1��� ��S'@(ɾ .im&���4I2\/Ib@v$8tY&���@Ez*_@ ��X /4���@(} ����������Zةi$�%< (^i��˵[v or-</p QܶiP����p(_hn-) �����vH6m$Bʗ0CR8}A  ����������`1l�@ v8x(_@���������% N8z=M{GF@�d Q0P `D������� $����XL/pj���@2RxoI tbv ���'.D���������@]> 6Q$�� @����@Aإ Jqje"�Meb@/4PlA&q,q+��Pl,���`T| ��v<2�����d2�b3b(�� FŮ4opqİH(S� d3I!��@</#m<B7,D�������2�24���2;̚ ��� �(6UѨ`R\���p;8 ����UeJSl,���tcO_ N 2��T ݽ8<i*WPK&£;a7HHf"'[s!]UE[IIPܖP~a3 �нetL{[I�δ_Y P.4��������()<7( VUlUŎi/H����������,-]e"�@L( XU٠Yףr~ro$3`pQW%I����(N۬~hnHF"I�������� (}����]w/Ad"@"ݥiAG񚅈�@ �������� (AqC9VU ��P,��0 * |ShmKw�������������������������������������`@�������� ����������������@�����@���������������������� �����������������D�@�����������@��R����� ��� ������� ������(@���H � ��� ��P��P@�P@����P@� �P @��P @��P @@��@A@����@A@@����� � ������ �������(@���(��"��� @�P2@( �����"@����� �� P������@EP����<$�����``�(�������@ ���&� (�����I(�L��`.P&`P@� (@�L0�TL��$� `&�� �)&��((��L� L�����L���\���& �B$���$PHQ�I@(�BT�(@Q���I����D���2���$��0I���������������$e�P�L���I��������`������(�&��$Tc��&�$��$�����e��@��L��@Y��P$ )*!@ L0�ʀ2�ePm����I`������I��&T�2P&2�`0���I��2`�2����ee�C��(���2����������&P `B�����0I�@YCj��e����`B���A�������0 �0 @@Y��P&�0 ���$L\ �P�����L�����\a&A��2��(+��&)���������2��(&��@�@��`������$Pm����(c���(c� e@��e�����e�����L� ������������P� ���Q����e��P��2$����������������eL�j���P$ �0 0)j��e�LP�������P��P����PV���0�`�j�0(���@@�20������!����jS7 e����e�e�����@�����s5&00@��ˆ ��`�`C@5 &�2*Q 0l@��LB��&�(C���$���02���2�&�I�d������@P�LR���$e��Ap�( �e�$e�PP�eL���e�������L�`��I����� ����@m�0�0 L2���L���`2����&`�j���$@���(�Le\F2 A�0L @!�$�L`e .0 C��I�����$ a������IfHsjC��@5&@���������P��2�22��!Ce�������� ��&a3 C��tld��I0@�ˆ0� ���P$LS L�” <!�0��La�� ��&�����A!<02���PF0����e��e0@����@R[jL�� @�@e�e@������PF3 LIfr$ L`O�”A1 ��P�����������L&�0�P 沙Dl  @sd2!LPF�l�`I2C�(+� &�& ː& $@P�2��P �& L0ʠ����P�L`Ȑ!0x&a���������&a&j0 3@���I.@ epe&�0! ��������e�e���ee��@0�( @����&aȐB�`�&a0 C��(@L6� ��� Vʊ `�Ɠ̐2���2! 0 I������02�Pa&a���0 C�'g&a�� @m\mH2dH9:m��I:6 ���eTcLL2e<9$ ����eʘd&a(-a1AƄ TI0 C�� �Ax30!��&n2@P@F2Ԇ0���(0�C2��PaA��ʨ�(+3aC�<'L���ef������`$aIp� ����Pa(0O\ !$ I�0�ȀIxrx������ ��2�!C2! ���A����&a� aq51!ruI ����&aL'0�0!< !3''gd̤2�C�tpj! a��eCjf $e$Sa�$�� ������C�If������ef` a�1aP pe#=H2Lt&a'[0d0@��=-?\l <$@��d��LL C2&gjsxr����j#@0 ��� 'Ϝ@y0�� W{o$L0��L! Pa�'a �0! �A8 Ʉ2Hpm0epf��(Pm8<&@d�@f�0l83$L&a�����L L �C9 ̜ L „!<A53�(0��(d&���Tb p9 ���L&������@Y� �A2 px8L��������2H2��-��`&xrxB!LS a���L&2 3A2��(dd\mg<9HAmrMdo0&�� v0b C�� �`Bm�������@$C v 3 �0A�\6I�`CO<Lj#0aAB!�P[&�L`L2 &a@e2���23���fns0 � L 2��0!3�&aL�(0��& �������eCI3' A0 ̄2d&��L�3��Ifrf����� ���Ն���2CdgN3�&>-h�~83I0a3� ���2C����lIfNmpmZ4Yѓ;} ��� ���2ld& �L`rfe 沙 Qm8pF9Yo3Hǜ@f̜D�(0\Ɯk'5@H�����Ajeo<&����Pa&��@m Lj6�e _$S8sĄ0a0�� �@Ն\ouc& ���\6� R$M & ���L83$<93WdA ����ee!�lL2a&�0ɄI�@0������j<uc30[2s�Pa&��PL ̤l83ϟzC  0���L`8R!eE3`Ùp90�� ����d0a3sI � � 93&g&��frMadI0(3�`d&�L<EzHI����d&gd&g&���$393$39:e�C�(2HfSo$Zs'g&Pa&<GJ$ ���P!3O208 �AY ������2HfB$3- �fy�0a&gm� A �����A3<G�P!LL��0<S��0Af'yr�&p$C&<$DS6u3sI21`LΨA��s'̵6L2s13&3&$39� ��&03��`R6C� rmde���-z�Pa&L`rf��PT+K`323�mW |#��B0�(0& 3g&������� H`rfRa&ɇ���������frfef��Pa&���Lə09h$Cl>30�Ljxe L09l9g&�L$m���L5HjAx R3 !���|<Gx2HH  3930sF7&y 2 LL2�l>BxY�� .{8<*9(�Hf39Ph��� 3\7 <L a&' pGR[.#ᙃD��� ٧Y<s0LW� 393(#!�e9DE4bHx 393- σM"�0a&g <&$ 3j$<�rf��Ly9!LФO>I�������(#!���vL���0m��� <� <ժZ3?s&(#am'm A�2j 9r5&y`LL�Y[2,<9������P٪c\C�*C[z" ΐXɁ�0 I.)(;d��Hx&L��ʸZM6"frX[<g���LL�2eg��@y�(#g�ə 0\?��� r<��6rx&�m|`��PFkK0L�PVL�!|x>պ#(��`LL�03Cə ��������frf39303�0sݞ ��!���Lə ��P6̫}<0g 9h@��$#���& v<bDfI?9I��0sA0aL"�0\ۓ�I DM&<yK660 � ���HF PaXkE�����/{ҍI�fΙՀ2rxH9<2rxaP;<8VaHŐ2@&̜ə 3 3hEh�� 3&v08Lɡ-׆,w0x2H4�����PF����(#Lə @9<�&<Cۜ;x0 �����`朧�&<<|V48< 3 3k38`Va=#�ad83��Lx8X!�$#?3gI��`Ǣ<D`.6c` *E �����C 6!ik=U��ƠY-;Ġ€@2b!L&-|pU11v)b@U$`&1s&�(#PF?ayΧ.BDM"DHז<8�~p@��HF 1Aoc! d\Q:�j!$6 $#dD��fy&����PF(#9OE9<�����0ϳc,q@�Bs���*y/����`1c��@qU#�1X�kzjYlB���YA֖z<��@œ'!3����&3s3�������2𳎑fRa@ɈÃ`23gNÏ9��a9O�dd,;gR`1hp!�eeϵ�BQ(933<z"����ʸn59 &!30sL���(#'A93H=Gΰq@Ơ! 47"��HFa"B;59�IPa9dD0fA3gp28uÏF8j��@:ƪ2'd 3'��0m>�*L>GlTa@�����d9穠lɧֈŠD"3�(#_dD�f}Id<Μ����0sγ���PF|5B��`\ӬT6 -UDZ,BC����T#":@ �am$͉�!0aE|g%̉����� 3'393&1�fyXR&������*y'A#ԨAq@�@2rxO<$�0F .l٨_ !*eRa@���$#|���*RWx����T!̙�%QnMBH^��`g"ed;z0 �����P sΣ >bƣQ̜���0sΑr� F5 zX�y?8 4)bD Vb����$#s+u 10 Jpu<bUʤ€���!ÃP̣p@�̈B�ɈQ?�ٺ#V��!Pw\������(#����PVP~~"FȚ`& I�!����&̜C�z`,VcB5C���`4 ��QUt%U#��ԨF���:b }* @m)g=%:WijThEZ#!���j5B0yj�X��̙sX#$Ȝ#!0snxJ�̜9��0y?8�EDrxxfQ *�F��`̜T� Z# !�� IT*;-@(#$3|Pu"��PFϜ9s!S#(3'am8Pw .fqC�cPa@:ACFBdI2s"�|F2���0s2G:{]c�ˆ ����TCf�?W<V ��@2`�$c �TxuSPP?YAj@ ��cHwV%D@�,�Ro秳G- �����U1q� #0 �����Tn|fQC#**L(~TCk #N L4��P9<0x#V 2Iz߲aa��aAl����1`X 5���ֿ? e�` U`bzV # X:pkU!��` U!c+ V5C���@kP #����@" XPa3ҷ#�;aJ :5*1Ta[6=ò~ R*,C-5CڐA֖ ]!��bĪ1� Uf p�(Fs���q?��������ԨUXC!X5BA4P�S#'lV땞u!�- F,ň�����Pc *x[�੣F@8y<8 �� u+>u:T4b�1c[vCq]1jЈU#ˆU#�����(b]�����Pc\):["`@E@jF�����UX@2�� u1b8Dz�����*XuU:j���������Tpqpc�dPCd b)FЮB2ղ3ˆU#�0agX ˆUj!lG\5B����.�������)"{<HiF 0hW!���H8 c5j �*jj4p@�������jVQ��P Qq`����Pc!�@2Qj �`#,kN80@]a @cVDDCaЮ ��f:Ɓ�Quu(hbxD1E�����q#Vpb�P ��Q+V!����@A-qpA������j:8XZq@@T!h;C) \q@��XZ8 �T:SB��HC#b��10c \AW}lgc-������������1.�RWXh`U p@�,!Tƫcm3C`D]c@Y�0zq` jLQ1b�XZq@��Hg**�����:Ʊ>5��1b������3Oc #V!���d � u�Q+vvKqT%m]J �� ���*n-:ے(X��Bj Y#~]2E���01t C����$c: �1�uDž1 ���� 㨋6>4N3^C¡e Sj%0 � \z@�������P RFڍi6֊#F,ňXf9lN4b��R?4bHU� ƀ`j���P���Pc!�(:` .t@@T 4 k�*TkDDZq@�����HwUPl7o����C54Zqb�Wcc\6H������@z뱮#������d^{�G]eGe��5tx`Ɔ(�������㈇4h Mj�������cu5ja,CxfX+z PjňUG4zBqh Zq@�B�B0Wu!����$cq�*Vz` ���PS~`tG Z1e9ԊP ,Vqh����Rxʎv8,F:H�XZqC:B����� u.ԈW!������� LuY 1 �@TV���jx����zmZq�aB� c>KA0zmB\vʮ "V4@����0;tphᨷJ!0hU �cW! dgۻG, P+�����U:B���z#�Eg+*FV(k;kjѳxغ!RV&H"�����TˆƈjG]�nQW1�1kP+�u=��czgV��4S8 ���*Xxcu W:1v1.!<l ;E'Yai � V �Jahw;ꊇ4p�����*j#Zq�P(֙~ +vEAl�F6X-Ā���Z<� Ap8�ŰB� 4(G��� ucXIHSq3)D hY_k��Zce cuY6`A�!ưV<PDZ3XEȀ1B^Ȁft 8 ֢c���!:q���XƱ#��Xce c@8H]]֊�NqcGٸ~G0�������x#8-Ha�����@Ia;#�eV֊زQs?���X *9a۟=^nFe)Ŭ: �������P:YB b`]Ua8 �u=afvQl�زT]BG$���ưJCW~E ������"cHx Z 㸾qmcv}1D�ڞm8jHHqm@��$�ai�� Z _mTeX+���� l}i<BW!���1#q1���Hgk�eXQW<W!�Q#JJZ+��Dk=2v-U�� k���gV����*⺮xbBTZ1JZGa8 㸾C`bW_6% �Em)OX8 �����-Zq�W[������$4ӯmD��ڥL���ra8 ����:; Z,3=A`%!��,ZqUq:B��������;+�����㨋�RqEUDZ";qE�2vPvW!F,:ׯ,2J,���� jDTIcQqcUG�,Zq@��:n~(4GK\����R4;GJNJ!�0U+\uDŁ(:hT̪hPQ F( VPk3\������5q=mwE@n,Qqઃ�������QWЧ׆!A���Aqઃ֊����vH)],J!�Ł1��@t6V<Ƶ#T8/:@�����Xq@ mcK� p�:BŁ1ۭaD �������� Z+(Pa a,������6* ����HqE�$8%(\u����iv+ҁeX+�B` ١W!�����H�P.W}e QqUG�����������㨋�HZfkWC�����(:.��P.>gtwb@0W `Ċ:B�������8"�������jU?#PJ 8h+:B������H> QqUG@(1٨ ����Ԩ:Bau [p l��� *2Gx=V ��� uvX8 ��Q%�q<͎G%'A)@�*A���X���8����x]_G;&d2E lJ"���P€ $�*a8bŁW=B��!���������d1ٮjUh k��1 cXٱ^PB5B���ŁW=B@^�`,^>N1 KJX"��C[vʂƠq~ɉ �&r�����@T8QDZYC �������Q/u,, ���j -pUtI',����[n0I���% �ZcV ����uB��5,ú2+�2+��!�P.|sC5Tc8n���:6H����X Unh �ҁZ TW$mH����KNd���`1,a��ò � t UcZD@h���q��C[Ae4S�  $���bhK �����p(S2+`���������Qb1,K8ZW<䑖 :fMR6[2Qĵ MQoŕ@�����0UKjc[&���� n.,Kx@��Zk=ȅW-+EH�%C2i $������Aǰ]Tn@0( [H��cXp]6 ���` m%=V�Cka�������Y e0LA������a(XUCNk\le �Łz�1-���{Էch�P8* �Aq$��p[m ix���� E֊ x)T k1e-"�8qR>KMBDh)i ˅`CZ.4) J��h!H���R�` m ֊PLw$ ڄ"le �-a -|[hIX D^hA)0%Y,Q4|�,6��( BR e2,6 i0(A[hPB��@(aVPeX=cB@ 6H����X X1WhΖev:&H������, ��(Q^5u}LI^v���jih!�@TxiW=BzPx#��BqU�>z����ƈoݣ^񠢇,z켓uF8Ί)@֦A �^6Űqj]qð.z����MӲȉ*0���� 0�XLMpY������J ��$qGl4RA/;H�X\C{������� (iX)��ch[z HC 2�( ae���0e d,lm6IL $�kT0��������i*J 6����$r0�cZ0lBW9x��׿ ����� ]v)��06MKH&K�pH 6 @BB H�����UXC�,Yk4�€L ^�"�H,6$Xl �����Dƴ 2�^A}VVլ$ rv8tZ*/@�HP^$���0eIT 2$MRi����� ( )������%+>v0@ư,.6�1�A!].�[ *S��$q9,K X����TpQ�p!�t0RF-- � .e ���\*S` ו�WaY9(4n]`���HphW*/´@1,K@`  ����Aј]cX0A@PpiTJJ� ���*j(c}|*O`Z@ `@aX0$l ��ò ò "�ư,i` ˒&�� ( )��� 2Z6=L¤4U[y %Ե ǥ&T���T]8} %l ��XiJ 0q R'Xa0�p &��@B\l ���h./aR \l QUl� TaT���������%v,lK@0eI*6.�A6����; Bm�0l0�����dsr9 .FoS{q� B 6Hl6������� ��pJS������@d [�cXZ8 \l  ( vFsr#h41[[Ҥ40(MIkaB "!�� �����/c[ ���������\[pJ*a.WXL ������@ KK [RL9 V m"%)/x0i- �8A6bd}З $ s �������PQ?Ɖu�����Y<遊妵- 0-K@���+=^4P)H�e Ӳ  T= e�@aZ0 tt@���LZ{yRk&@h����� (L)0eI���Ș4Aư,i�cڭrVRiC�t]���QW=B�H;li2H��1+K@����҆AҰ���bX4A�����2-}*e ����������jLS[,i���d��PR8) jS�ò �4tBLu9L&�J[ � K ��0R` ��cX4A���% 2��������"K`]zٻp-i��++8^#xM$@.6���0! hHyCY����� fh]4A_2/Ia^2"e �������x�c|L)�������(^(SYP@BFlBIk�������Ԩ���RC_e �bxKy:.6���(N�������PF}[@��h���^ZXZ0�,eIB .6 ˒2l6��,a���B .e �KOt���JZC X }Lm��heul @f&h͆P(. 'Us0���@koa鶡�����1,K@0R$�0a[m6�� (L %MPPpѐD�Ķ7; &���1,Kò ��@b > D�iѶ ƎU Nat+Od3ZcsUaKaZ@@aZ )bH�@1Z蘶0��)kR)@qe ������7K fKcsڲ'D��������Y4-ј,i�Zm/`ka2H`&Г�27- ���1[[An6�[5G[ ������ʆK9���JVۮ��˫]$%p-/vL�������@P‹>F-- ��1lK ��Ll{+ :oiebH��±#N�@7yM$��0lK@��شB?M$��$0͞hSʣj_,1��T r.e"�����bcvL��aM斿52%��@B,,"P�I!Mf ���I5%<nd;mh[@Hh $�� p���p;.- �����8Ʀp���0mI9lK ��„[9&\hҾ}I�HhM$�$4&���c QVXh��� 24����0cMӃl"������34`/@7H����AT.SZhD��0mIAaMf cܴmi���������2L� ( hh 0\^������ ZyĕmiD��iyS}[Eˁͱ*6@HhʃRR&���Rp)L%Ll"�P,K6:Mhe2"��8d� .6( F &˒�H������ 0VA���@b = oi2� .2���a[a&���„Wlh]]6ٲ OJH��a�cےaFOP˒2̖% ����„[9�������1ڇm /6���( ےf �ľ}U!êM"AU�D����������rIƦoA\lK@˒" ��0C(4E&�����@da� 7������D0LPP^&�v-}H�� (p�H�Hn2��AရL$�����fa�m$�AရA�Qo3r˖�P$/rȰۦ$9ؖ!QxH!M&r,K4'ے As걹������Aa­&D��ö ��@P>ЋL$��@P8r9 In2( vKνׂPr,K&Ki& ����%Lxс�,mJA d[ ��``ۗhbn2�(N%mI���m@����������T豂%JBS�����5u4a�S{HxK˒����{`J"�,f{[A X ض������@ICx" �7q,)êe1I�/rd &D���@(z A~QOmgX,KD�����Űm$P/2�����$/Cf�@F$#PTKD�b48M$�@F#rp˒����������Qa �öM&DŰm�a��J8C& �������(\.p������r>ȋLHeI\'yhRm䲤�eI�����m ����@IKxBF#D@q,i������B ����DKyLbض4���UE����m �ö  pЋC{CD������������rI�^t ��ư\"wiŋDlͬ����rE&�2/CVX4`Y@&ɈeI���������"p&�`1l0A����ja+�PA/:!pЋL$UKAh N6- PhL0��PlKD ߮.K&���&D���@N ���Xl_$W`⠪Z\]a⠪V-&)�������p(:E&�x�_ ]Tym!�`Yd= 2M&���2& dF2As7\M"d�U//ТU/id[J0Л$F��AA�hRDZ &xM˖���p˒Pvs"I"���xс��&ꕷ4������p؆ -" .v~IOh8���2:M&����-;ے2a/d9,i����#v!�r56]]mIi0Mvgے2a/ Iے2̶% 8X.H 8% "��mI�������rыA���@I7���J8M �@(79 P@����z*KR� r:؋L$����+V�����J8bo��� pқ$��n���B 'Ɂ����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 L4H���PIo0Aar���pنA�`"������jit:6w۞/@B"(tH�����,˜xL������X.4IX-O�;H�]E"�����p6F\Y \AhH&yDq-Cٶ fےe��������`1<ZDdt/|ɝx!&ĐH,D d2rEѭK{D ���� ��������D5N4I����6,Z0p٦r,p3X'5e0J�ݱ.a#@WI|!3 R$[U `"dt7 U4hpՍI kT(T]g$� f[ ^ 0 L$@F' ϴ : wd3 �Q&+]E"�8ؖa�.0mnv&�ɶ.0ٖa�����bl$J8 6 7;L_\@FSuI����������M/t4@pH������@(7u.0l"94v �&��P1[ -l[A��������D5N4bM�lR4 "�.! /0���Ფd/0������PIo8 o-6J$�@Fy�I^`"���X e ^`" Y]ކbPZd ���X mD���@(᡽L;mv1II֮D+=% "��J8;nZ^ l[A�������MJ8 &PI^(c7v)���������B 'M��,6M%a_6: L$������%m6%�% }/0��� ʕX=L[ d/p8aan4bM�����@FyǶ_d������̶4'Q(m%:;�������`aXtQ$8t]@F8ն,’n0[.'ux` 17  LD o����0\a�X m N{aI"!����Wa'7I;Eـơ(17th&@0&�������XLmD�Ax8do����0]apl0���`1ݭMA��XLp SD�8va{9|0_@B����@qZT ��������hr[4StUieF��@qUQ$�������Z8m$eh o0kbCh o0X8LQ D�0�%[_`"���������@TM� �Tnp7 d �����0\i�����( ��B '},Wbѷ5_= B�'2 "������PC)-<DnzJ7H��, PA(I`"! y):I| eXl%�%`-- "�d o8bO⤫AA`"���Uͻs%&eqrYA {`0, ��beK߶���A`"e��������%÷ ��PI`"��������Q-<l$!tH�PI_`k +,mi.w%=�к5-$MTE B�b o0).3dA`P_T 1 I�P,,٢"����T}l`dVR˸=a B����@���J: L$Te30 8N@LDwL��������tpBf2D�����,$'*KaZ8L$���@Nc;So 1 ����AF@ ddQeYA&almi�� y ��,2 skpd em7~$9+(&n%!����'S*vxY>��r4U-i���%ze`o' 8YTY$B ���������JJ�m; "�m�md/6H�%[3 7ȂXafSr\i���n4����`1ݶ ����o/Cj0}E������D�������� e.E bmA��m; "�XNcso˧H�������������B-<)D����`cm ����JzX^NE&poBI2H,8%i}sae`bJo4������pjvmJ/2��Y% 8, ����m; 6cP$vl&V !MTE(Nt۾@ ��Y8L$����k 7cտV%$PݾYL�����Y0eEE"����E:s%"�����������Qa�StOlI(N.-&���P҃D2 "����B7vzs@�Y8e$����T҃QF`t.(#Qa �(.4L��r ��&�n- &2:ٛ:/4��(jA,i� jm([D������ 0I�����PFkui"ɢ���� K�M ���PC��@(| �tۦA��� t]`J"����������ڿ-2� Ndw(3U¢e��p7@@qN ����$–h���� P�������@&���j<^. ������Q0I%=/6Jv"��]qܒa 5I�����̲KyѪ8](U�@ 2��P,,������$�����ONbV~PFŦ(j ;TKЋb0@j�$$������rmA������^x:7]^N H���N 2 brY2 "�@/P�Tvh),MH lLvUdQѠLpP]D"��P1- .&ϩbLW$����d;H�������,L/ r[V-Ku3Ր,r��������U7D����`qM\yYFe9:7u#(w.;hT�TP"�do`"�����C ���,wk֞}LL(4o������A&4nnj&���@ɦ U&* Tޤs5%!������P e\'&r~3Nf" ��������]J;|(_`"���X_H�@ɭm��+K a5v{h@br[A��@䶌זi���������@ ~(Ŧ6 "���*"C2x~uo- br[A��TLn4����Mm1O*s!�Qn`0nI�����@І*C0- UmE$��TҩZ:7B �����1����� ^2:&/4�����^pjo0p*o0���rd2�Cx ���Yii��*T`t/lNDdo $���������ZzjoLd������ ԾDPCy ap[fW{JfC��SزAivvVR[ I*.C"; 2 bTҡt{ hAcD �������eB-d$QrI6p`S$m0��rP`b����������vT`9l �vIa ��×L@��TCyg���bL�, ������� sG7w(���* ;���Av0����If22"860H�B:طY���@Ex(o0mbp[AJxn"1μtݕD ��T ^mi�*᡼0- ����X-݈FWWXNnK �@KDTCy�������BKO Ld�@-=7�����E[:���Tl1yH T n4����lb'D ���@"1Ld�����^0um)0$//0�&j�����boB< NP������*` ���XN/4‹Ld���������2&2��b\u�t*o0ܖi�*oAb �������������bho T�2 b�����e;Lb�����eHO 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 0��m9:7�@qp[I ����˅o'"0UL3����;7,L @r Meb����*xEHR,6 1��������4,"_.Cy�tpX= 9+ e1{YI,-<7������%=_'<{R Zxho`" MeJ�����C{*^iP,$��Te0Sb6$! $�,xho4 SaB+ D���S{e&1�B Fe/47dj""����� (S{Ú/4�ĂQ"�������������P` ����ծEl�����iyC`We������X޺A&e���m&[ʇI8XUYY�@Ly$b���8XUY�VM2U;ʅٞK\0���@en' %hi+X-ip_P������������0Ɲ]F@�ȂQ0[8ٮHЩt 0p/Q` ��*E4l`Q$5k! ���@e&1P1xYI ���`9|UFe!5&mFnO ��������r6Mb���,i"������, oU0���XvU���X(������� lwܦ������������������������������������������������������ ������������������������������������������� �� �������������������������H�����@��������P�@�P�@��@���������(@���������� ��������( ����( � ����������� �����@����(����@ ��������������@����@!��@@!@@AA����@��!������� R���(�PH�@�D���@��������� �������H�@@(���@E� @��$�� ��$`(�&&)` ��`���0�s P@a��&���� (��LB`(��$�(�������@������(�I������$@ ������I���d�((��$��$@�@A)(��@A���U��(����L��P�� ����`$� &��0��E�������� ( � a. ��@Q������ �� �eL��(c��( ��L��� � `!� ��`(�� �� � &I��\6 0`H�`$��@�L�����@��P���e�������0 L2��\�����f�����2���`&�� ��l@jT���������0�����������������(c2� �`��e�C��� ����1 �e�T��l.0�0 �2`������ʨV� �$�����e�C�$�L$C`r�P�$C���P $��s5N 2���$��ee@IA�� L�P�e�L ����2��S &������e�C��ʆ0�e�0����A5�&�I!���0!� �����C����ՠ��`@P0 O�C���� 0L��� �P @�T�`�0&I�������!��P ��I(������!L�Հ���@�Ԗj��f$�����(�(j� ����LA���0��$���T.d��@5���`�&(C ������`1 ��e I ����0 ������Tc��!��LB��Y0�����PT& @5���`@%L ����&��� T!@�2��( 21 C�`B�����e����@�����@Y�@`@@��������&�A ��(clSap��(���`P6L�`�������e�e��P6ɔ$ e�P[P$ a`���e@2������ �C�&��`��� $$� PI�2��������&�0� Wd&L��PPV �՘�P@YI`��(``��0@՘Y L.�@�0 �Ԩ�0'`�&)Ce��&a�xL�C�j���������Tc @���2��2���Ȑ2@�3I$ a@�e@Y5������eՆ�����&a�0I(������Q 2�d&$ a�&aH�����H0P\!$L�'aOZ� ����IeC��`:Lm!L�@��&aH�Ld�� �(��L2�2��!������B��Pj @WR �(`T՘d�����L�`((T ��0�e�e������� ��������� @&�aL �`p̩m�s5e&��0�����LI�0 CI���@m ɓF `�YTC  a�����0$�����L`TI�Lf0�����L ����6C2$�����0&a��������0ɐ a�21� 0 @ʀ�`0�P&KIP6�&A`��P��������P)3�Q!L@���P��e0�0e!Tc�������2��II����0 C�If��0V L2L2 e00 j �@ ��0 3P 0�L0���@!L\m&, ���0���2�(0������0W0ɐ @ddP6jL�2�C\�� <� 0 dAL&�Lp�����������2�P6 CU A�ʨa'ala0bf2j@f`0�Pa� R �����A��A&a������0'a��@��(0$ ` f��d���0\3Ղ! �0! e$e�� a���2JH�d�LRF���� �# $C.{Nf8A0 Cf������IP dQ T<  e0��0l8$ A ef���`0���0 C�d(M5� KjLʆ0�0 Cj !���`rِ uj3��@2kb$ L“3O�����P6��0 C���� Ս� A2��& gr����2HZ 23����@��A2I y(.0 L a C& A LII($ ��@C1@��\ə'@s2O$2HF ea L���(̈́ˆ!L2df���� &0 ������# 6fee�0!L ��0���pjd,�L``0E$3��&a6d!g(d&0&0l42Hf����L��`3� �j2IlHfBڞ$B* ��I.{0 !9L�j3Ld�A2 5Hf$f8L�2Hfpf�LpA2��&a8$ g&L<j<9 弶sF'� @m!nL0&����L`8eIlsC2b02L��IL�2ȵMj`BI L0��j#eL$Y-/�pəa@̓0g Ù $ gb<s0sVb09<rdb\b�ɇ��@mÓ0sf�A8LT9̨A2�(jL!y�����3y>Mb ���`n3 �@YY W=(��(\$ 0#$32 3_O?X4R e4 *"�����&09V$0C`@ A2I932pfa0WӜ3P|I�Pdre'����e@fș 0g0 lCle?GBE �P1r!@&L�(:y ���P#ၜ���0ə 2��b2&e3'arfL&C6Hf�L`H|3)Cf.O"�@$3��(\$ ��� a8yma̜gL(d&0і(Hms&&GՐeL���� 3je 0��h��@HXF>�9��\L����-LL(dF < � $<$0�����2Hm0���� L2Hf2əPo L�(d&LفkSK6'D0��0�&frfPL�2\''3՘���@\�!<�Ty0(b&'gp <Ԁdmf 5ȵM�����f}jé a&LI����� r��L23jf����gIB�L23�@Yy&�!3O���efB՞`c.1�T0$2+Km8yLb ������!<L y(H$����60����(02ə!ə ���ep̤ C�&<$@PLL���� �03*921Lp0 393����������@�AxJ����@1��0mPsID������������L9'0 "LL�����*9&032چ3s0���032Ho3 93�03��Ifۣ<�dB��ee]H( D�� ��(C�����'|͠ebp귌r}dL��0M-!�Lə LN"�0a&g&��������@YY��&hˇRF%93�`LL`�@kg~򟪀�0QD��-X'b� e����P28ć&&���� uE���`T\y֨��C��03� rf���L3!�Lə epxepx�epx�� g&�Lsf<Q;C�2*B���ȩ[(,XŁQC8Њ���j!�� FU<� NC�\|5*NYh d1px�!Ƀ�ᇡ#PE09��P�����frf.C ��������&<|Аڒ3<x3IC*Yj ܯ ���ʸ~ ��|U�PF 39#Mn%s rCźЊUD��� .-=Xu2"4�Px6"��(#_WTE@9X������dfrf�����(#vdeGDM"�LI0���&\g`&'`LL�`u{h2rX��`¬vfa&g2rxees$ e\c!F*t � EX#VBL"�� 2rx&eL�f΄9HL"�ᙃG8CtĥA6UcD!b&�a9yp�U@G#1Xƈ �0sȩ7 3���e<MDTX"���@2b� 3'<L>k1��j L�0s0<&̜90ả��&̜D�&̜"fN��ۃ# ?k=bcPae51P5BrsdD0 IA���1F:RW!���Lj8 2X+���@0 �PF\s@E&̜9�eOīC�����(8V�$F rU#4C %1X��(#9p0`F������2rxL9����(s[<" 9<5PsaΜ@9s"�0 c����*(Gd5F]Z#d * XGZcj"$3'���`.j@3'f| jO<5B|dD����2ag�fy~C,rZ\Z(�!b]���! #FFTQg T����fy*�����p*"930dmb@�̜!f3B�PFO5rx%93���&̜30s>+|<#H<ՠ�0yN��If 2rx$3sAޠ fWۻ��B,6 С5B1 JҲb:j�� uMd1'f 0 �9D ��`LBfes>q}PZ# !T8�@9<\FBPF�0a朧��$Sy> 9‘vҀ \�@Ö�2IŨ Y5B dўp �ˆA�O<p BUNd AG=F������PAtj d`1Ygu!¡Ck���Q!B�š ���T1Z6!�Q5BD!̉������2�� 3<������Pc<J̙LNnym@0vxLc8<ھvP�T9 ��� '?q �������� >g1gn@i@�����Tht0vUPAam3 #?g` * �8PJ1V1s# �����`9OڒC����.#_eɈB��Tft:{H` * d`@M]XF�ACq1*��R1*)U#����| d���j#FڸnW83j#��9 `ԛ^]ԊJ�1+{ĭX��.k ��@B����@cF20 ���������#,�@��59穀9|u eÃ�9$L-?*@ˠ��0sN!��s�������r v&yC�gU#d `<s"��0ᙏ"aD~u ���T6 `#G8$3'�����@m�d@m|�����f>cձuQ !2If1hp ���� 3T��@I~>c�@!/vUqY�� * �����@Uc0@�U#��@n:* - H1XjA ͟+U#� *,�QU!�0g1!���TP?,^��!D١W}B(aĪ1 )Uk;*�0bU? ����` XT�8j��!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@��c�Ht!Q6k<Z$l $')B� :Ƹ1!�1€��j~*#�!qc\lԅ>5��iɲcq5B���� "u<$�0*Fa_a�ˆU#`lRz˂�@v ui iĭb@!X5B��0b��*xfV����Hx.]q1��1.s+�TQkǐ�0b!X5B��,!,ˢ}) ��:*C���PA뎣#!����dczF���\X1JG�!ĊU#oguрP �����qE�PQU93����ΨzUZ8j� zjgZtTQ pMP#V�B͡Z#�@#V!^x# �0Z1ܵxˎX$��P+aĪ2*9JgP#V����@B��&[#$u<D�ˆUL���fc`� V=ZJg+>!��cGll>VLL���PUG�� ���HFuկW!��VP#V!�!+~Uf/CD1ԊF:B���������@Oz|=XYd B�V:FaĪ#����$cuA@:B�����$c\DKg#  j,|UG�ˆUhĪ#0bF:B����1 �`QG@+nݤK�k=Ŭ!Zی" eXDT6aEgX+!۳ �����!8�j�1u��aĺ=RؚKua2[P+s14FĪ#���*X�cc Vj� T0ba8 ��d#��������PQKgG ^4B����PAkab#4f8a,V���Zw|` YG!d+�����*Xu/hW}k$�!XkT+&jb@�`bx:FaZG���!tW}dc����cq@aZG���"@Y^!�0b#C8 �Ƭjq!ec]Zq@��������H8"dVU0q`8p@�PV#b#�����@Ez::B�����$#:ȡ #uA՞a-{p@�,C-{p@����q��j|zvA*R^0c���Zu#���Hac< V��;{E3a���18 18 �5bĺ=]8u$�����������P��$#:-[ d mp@���0F<#uFi_4EP+X4S8 �������H8"�H8"���H]Ǡ�, !c!c:T ۳Xl1( Y4`Z�C8 _=;$���bZG���q+��eU[}W;) @e'@ AXU����@2Q/iZG@(Fu�DF}TPv4jC,CV ��aĵP@DZCdUigNd$D�PVYJbDz�( jŠ݊C��au{k5k���PQ+u��@Eq����q:B&N�����H8”]HgV��� z` =[ b*=]8YPSvb 4bbZ+4-*h k1����� .��*x��z��!\B��� uS1*B�0'xZ���gZF����*غ c@���Tpc=B��cxE,��k=B����$8ꂌ11+ o!m K9H@an(#X#z�Ъ-{Ԣ SvG�PuH5etw@ʮ3q3zC@`����!#����� z������_xQ zL`+n(��2-펺@cX+��������@2^ �HqX�pŵ>#1=Ut���������@��\8^k2Q(Akc\rV���!qG0egkD�Z-����i '\-sA KahESV0 C!��#oG]���0k=B�����dGXz|,DKHa0h2U����k ���� 2!< kr KH�����"c pV)lw!qG!qG֊ ׊Z ע������HYըǡk=Bm}i! A+9Ly͵}l)H$����0������$8E���P`\!�8xê٨?ZjFh`Y<l � m3ى*J a)G1n( ZF񺤩V � S^1C[qbZе>@)\ P [OBS�H(Q+Ҡ:@�Z�֊xhі( $�chٺ4����@8V<qc]�)\uHe*9Lye@��������VQ8CZ9H�����@W\gqx@0UI*=+@G\A�J5eZ+������dG,�HfGE�qc`Z��p����PQW=4;qDU$�8Z#���c8nl]z ]ABfU��0��T҅m@cֽ+⠻�ሷC_,%㤊�����@2#z3z;` ������zGax@��X�)8pZ�����\Xq@�B8kA[H���Zx@tc~MA+2 `eRM#M���� Cx[ͦA����` ^ &@azLZ%¥ $������1&ʖNb6 maRtP% ]Z!R(tABB:H����a]Q:>i%h�� (ڃȁqtYҁd)Ҡ,e ܲAZB $������&q\le ��bhK̡-��ᶋ�� 8+|xA�,zG}@���Ю�������n'-aB1.$��-a������Qa X bk=ƢgR(4誃@hUG lU ��1�8W:H���������$x  �*xh[H�����"���@E]!��B!Xw\HB8 a@ahKx�����@ź Cĺm9R � ڔ l( $$«0DaPZ$,A0jD 8e:z!0&�6���lYjbҲР4(p&b^_u�eucq&�� (x)V< ������Pz��€MA�������Z�kfk)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ƣV��Bq!�1+欻Ǡ%C[hNˎA ULۄ5@���`1AWCkð�'@  ��(:_SN'�BF 2�������ʂC�X   q6 ,u= %1���`���Rq���$쏯1H-L �����@(qզ �������ԥǠ.q\��HeXo^cX@����������@q<`҂òLA����,W���jK>e G|Y :H\6q uŐ1_����@xNk$�DucZu���,qØ޲QN1YV4n6+ HJ"� [H���X,޻JlUri��� ( Dm ���A!c%��������@dLS @ NwWXx@00hk ��@P)T ���e9 �$aV���Aa֦�#?h+� $�aY%L��+ u��!\xG1\ 6ŁjF�v5kZx@�@bB�����#< ����ԩ_Ѡ4h���% �ò^��8Z���,u��ڲW�������� ?.C0= -0ipF� (LDch[z $���&0jS����*z����������ԛ-L����Ș0A * $�� [; e\d[H����U찴)% KH��0e �����i ����Pq '-YL[; Mm4g/a*p[@U0�(NZ�����Ű,a�����՘rS p) ��lm ,e +X] �bˎ_@@qr¶=L[&e Gm,z ThFCk ��(B8mciZh����R�����&sk K_]ɔl) �������&���D4 e.Lے usRaYŞ`I$%�%X@�����B 6��X zIk,e ����BI)Tm=PH ���ikhNFQeB����PT>ԊNRrMf�������Z:6��X,a@�iYdNB�X4cf۵2HI$���mK@��������j |?pWB��,V0@vB'K�`1-K ��� qLȲx]Lڶ �%X`,e ����^4PNBX]q@�8ZWQ4ઃ����1�����Ԩ-ugz-a���@81M%փ�� T<Z^0,-Zt( Hj��>WH���BG]q]Px��Qk}�S*ҶE"- @�������(lڔZ�����% [&lm"eI1v4)�-*Ĵ`mc4Z+@ `MKH��B&*4b)X@�����`1<Q4_.6PJ- İB)5��% !a+���������DGyA:Wx@�`Z#�@l��%<'��bX�X ������Ca{X ��&2���ð( ��� 0akSB #vQJ @P!et) ���AaF1kp, AZH2uAZ8ZA.e �P @P%L ���ڛ>L6 n!h0à5@�XaX@$4R2���1���P6lm ���_d��ư,1mK@` ˒&����StsER��` &Aa֦ ����i 9[[�@ �ò����ҝ]y1y)T�����X4!��jaZ!Q@�������(^|)�@ Q7ֵ0"^L5(z������������T6m ,eI���՘4A����%6=Х $0h- �c`) ��[t9ZZLX,�K9HJ >ѭ $��$4RPh rL������ 6òIiXa0`ilNZJZ�����U}0Pn5@��0&� jSp`��cXa 6�`L˒&��� v.-Yka ����zMm/vL�e ���i 56zKH@qR�2�������%MP(aUmT.`0V2�Dmt*Ȋ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 �%<p) ��i - BB-4jCTaK���������� ni&OT�(f9mkaB+P`�Q-7; &�� yZ W4@���%M,eI��`1m �Yֶhr%d-=�������%M��nlZ.a�����D5TjS��%M��. ��@���m/4����,eI�ò �X ˒.eBph[H�����):*Akq��Xfka��Gڶi].6����%L�JxR|@��������(^!��|C@ʁ$xM$��Mm ���Ű,i����PRp) ���@Տ4֠ (Lؖd[5G[ Ҡ0����,eI����T/|C� (]C �Ll{+�M$b$ m&l"���@(a¥aY�A/H��P2|�b XI$$4%<-o� �P������QiI�Aa tle"������� 2t� 0[t,eIX ˒bX(RX68a!2qV|LR!2,Gm0\D@Ble"�����Aa]mj0�IԵ%$Jp e � Qv�;nX0Q2��������@dt������"0&\!�a[� (LC„jUlX0��������A��C&r,-L �0&�&\VhkaP-KC�[ ��öY-JH` ے ����¡\a[&��ư-d28[Z@�����[K`[H�qE>PP,i[ ��������"㰤 (L7,00wHE%D���diltdž//�@8YZ@hL$@Y2YғD 'ud 4V&¤4Y D@Fle"��XLے % %@�HhL$@B,0ٕ7-L ��2���%@ˆ.h,KzK;Lv) � _OMR�2r&KP(4 p!$��a��@(a­H������Dp�iPpkŴma�������J(t(2t0�4'_. �����AaM0%=m_������ rIM$���0n6���a�`,\ȩ ōU/m ����3hŴmimas-a����PZ#�����PQ/h ���������A/me `Y$a[H�ö�2���@PBijIL$��!qn g˅1ٖ0`Y¤4X0��� wYeK�H$Lj@ D1l[J4M$�������`1Ea[!UzB6�����㰥Sѡ\´@hKBv8iYfcm#$,K@�Hh]lD����cض!Q&Da>&wk]@ٲ �HhMH@a`-aBƆr..���@Bl"Q,Ka,aB\l .6�����~&��@*vNm5G&��������`ÖNEl"¥Ka,a���ư]M&*4&� \l)mK2��J+:̰M$������@ [9D���� 2gcvnm"��0f 7xƕeasڲ'xdadd.76������p i,i%+2��Z貤f �( &0f Im0ŦPh !&�������0) C(4kMNeI�� v>Ћ8[4���������rML-a,� .6!M%M ���0m&pp&�� eI = EEg˒&����1l01lWaD&pyK�����~<������Aရ4f @P8&��XY^y[=] BΛږ&����@P8VlKaröI��������r4&'y@abNSn27H����� j`0 t�� D8k@Զ4���0AHhP 4: p0YI^l"������[6`4+oj4dY�$4Fm/^,f˒&����� /6bڶ4 aZ  pno��eI�eB��qI.I^l"�� vD������cڶ����Y8l����@Tˎ] Ҁi   n65Hd1[4lY���ưmi�����rK9ö 0�`1,[axyK0P]iz :5'T�����'Ւ&0����B t0&2���@(�����ŴmW` �<E{�_Ҏ{o8Y4A0D ����b-&2Pmov��'˒&0����J8VTqV $0I`br)Ci&���B x ���@N[:Mp '˒&I :F%M`�8Y4��XLۖ&0�����B C(�T=6'Q�Mp ���@Qm%KVږ&0P,Kf `7����ö f`itf7�^K-A<[H _.1��˒&02f n6!Mv� M`@Fl &D�d4./nm"SjD@ d����%)$xM6|;(,[eI�Mp*%M`�������Z ��aZޖa����m8�,mP��@(ဗrar`��N=`6|3��P,KtmK���aۆ ��@(tN=w\�������%›~;�� (ˍ$˒&1�������ʎ SF% P@ öID`ah7;� Mpgے&1�����cض @=V~k(;|;|hzỳ��@BVf ܶ'�.l����1,h F rifh` ����\w8̄,LD ��PtU(9vM,̺*@H:M#Ka ���P,Kے&0��%ف ���`1\4�Nb8ٖ4�������zeAZՆ6L`P^lk R2�P`3\B{y%h$&8ٖ4)N%MŦwe ʅo ,hE0 K�ɶ , T@8ؖ4d /sR[X���Mr ��˒FmK�ے&0�PAn2An6����e`����������J*Tz, T@�/BBܪctm{1Ku��bկT@d4M0{6�������@(ဗr fh�B ؁hے&1����%|XN7@d��8vcvI ^iӲl] nf"# n6�������mM��������P$傗rhyw7lŒT4e(ed��������P$o!�eb�����+LtxyNb��������J8BB ف ����������@ 喞K9��p7%Lb��X m�/2A3haٶD䲤I �h;�˒&12HmeI�LOf2�����X -Mb���������~z3�P1-I0AI3ha����`1\ pYi��J8;,K+/-4���������ʨw%|��eIr:؋Md�������ʉ ��,v ov ��PAj6XՓN!v+Cu@ TlK`[D؁ hR Z���,˒&1�.K���B irIM"Um_pH>H������6LPhdۍ %4�PlK����B D�����@Tˎ]A]Lm��������ʨwy{aXhizyN`�mI�amA0 Yii ��@q-i�6abf���鲤A^ A^d"���2LdM7-!oQA^d"�2:ȋ;F%Mb��������������� a8��`1<-2Q{%%8ٖ4䪗dd/չ֞ś#[aIln$b�i)Q<&0 D��eI��tٲ@������N4Io6��XLm8BIy ��������PRMD����`1]����e(�J:͝C׶4N d�T0���b����o,j4D¡H,DB ���Ȃ$#SafUp V"3M$`�����(N. &{ �����tL3nl���tr)������Z8] `~le1�d\c/h6*diB$6p����������%SZђȃRm&j / /2ٶ 5"����D.Oy Rn ']e`�����d"����J:M2�@_ޢRUd �Y8kVXZ.1m���d /2ٶM;Fm�������%zL"{Jwaf),����� Le&8ضa�͞"3�.DF��������`UD"#���"M&2������NjOR�p dۆ Lqm��� 1i ;'oz㢮 `���������.P0lۆ ����������4PB 'D`1\.ácqm8t9F$�]M`�@&U],2# &mn*0ضa�p7��,M&2�Pڇ22�����`a\ AdB],2Pt]���;P�j38 &]8(St]4X8ț;F*&&b������XLrE-& Nd�@quQ04ٛdd�������`a\J:���������_ʳcvulܢ @qnm3��D8l���@(/2�����()E1۶app,a� y;GvnlLB � f"E`Gp $̂ a�����tZDY84Tȭ)HDX8ț8M&2�Pl0D@ɿ&Ʉ)N.��������AI'}��� t9� tD!Ѡ^Y$Fm&1Pl[v ڇ;YRl!+_)������J:5Z8444D�8ٮ 0! ��'6Lbd o0!Lm��,䥜N���(Nm=I���(f6Lb����NA`"4}[fA^&J.&=w݆U^[7��&&D4�bea`Wp &2������� t DF~ )5Il`,,Ҷ&C����%&2���vɎm& Ȓ&1��ۗ �Y8Ld�����,6;vuH�Xw%"/Bq-ZZ@$HDTcQ!!a��M!dܗ L Z8K9H �, Tqrن%tLl- bi(oeM#W`F�wŜ1���=&D�����l m9���@qmS$FU,6!!9 .0��(Nֆj-0v禗߂���������� (/r{vW`�������E2-.$ ���T[D H76Uܸf$a�����brٲcrۆI �{M\ vIe ɾ,o7g7b ۠ZOUM) H���������Mr&Q"RA^M�TL.0�P y)p i*o �nl/* "dV&"���ParYP@R `Č��������KӦ &b2� QvqM�P da+1 Pat XP@Ą���͕"3�Pabde��0jmRbr٦I ������v&IT #����@h$_`"* _@����bg$*&c6  Ld�@% d,gm���J8E|+O]oK[^@ ���P1l$�����vm������o_)̀Ne^@ \a E2P 'ۀ2vFc�Q(♞ 2d: ������v&brنIanm+2$1����@(ط/I ����`! L5Qd ���͕"3����I&JarI ������VswɨE sm+$WZwf#&("��ParaV|.$2ف ����������etY&�������tb�,ep��@MP 'wOlιk[!žYHDl@B �����"BP '{I '{�e&1���XV_Av\"pǥ2Lb������rn[xHRl!,dor �P~Hdo2 "MA 6xfi)F ̂˖6:'^ZJ���������V{ -/1ui)  'b����������@҃~ ?m`���P<Eeb�������o0dv ) ("�" d���kB/6 "BE ������.@cG7 (��)Q.sWl���v0 `b;)Nu�����������E|\٤NJf*ɄP,J,)ڮ ���������XZHN������x*�`9\C@�����^eE6(do0 SapI �Jxh/d�[:wjob@�������K"���BK @wE"3km-IL>$&j2P '{������������d���Q�0ISr ��������) ���@h|S{[!",}���������D=.��������Pd@&V^uI" `%0�*d_@��������X&P �d_`@�4- m2������BKT nK8i , b����Ndbpۦ Zxhw73����@%;p vI����4@2���t깣͛`&D$0��*}b�����*L^,����`iz 21�������()|9r154 5P^2Q 0tqj]0p$tdlEc�����}Qm]!C��*d_@bpۦ Z88��P d������������^tԹC TM����Gؗ1չ喒E+[H d����@-<8P d���*FV,xu !lXL C D����ij-/Yt<hRUl%= ��@M��������0X/|\D9��������⚭�g��������������������������������������������������@� ������� ����@� ������������������������������ ���������������������@������������$������������ ����(��� ��� ���� ����� �(������@��������� �P@����� �����P��P��@�����P !����@@�����������@A"���@���@ �������A���(��(��������������� P������������"BP��� �P�P!P�d@ *��*H H(�����H@������P��� ��L�„�X�&(@�(&����`�0T �(��&��  0IA���� &� (������������P�*&LB����(�&�����&P�I��`���&JQ���� �$�P�P�s5$�\m�&a�(��RL2���� �� �(�PV0 �e����e�Le��C�d�P!e�L��2��C�� 2����I� (I���� I*�elB����� ���������j#������L�$���0 ��0`����C� aL2�� I�`(!��e�e�P����ML$����m�����L����(`F����(If�������@�P$��Q ���2�l C��`e��������P������l2����L�I��@�����:���e��e�0d�&I� �����s52��&I�1!�C������0��!�Tj!<Wc0l��e�P 2I�����������0dH�P ��ȀI��!�� ��d�P �6�����I��I��!0 ���! ����C���020��QP�P�L�u����`R��$ 0���0�������P6'dL�@�� ���@�@���0 ���@Lj0T++c��jL��L a��j#�$<I�T���0 ��� j����e C�������(!e�`!�� 2����!Cd �0 �$������ ��`��������ʘ( ��`Հ2�ɀjȠ��PV �� ������L2���������T*�L(������L@A@�`ʨ6@� ��`@j aPV������$@ �����2�(2Y2���`2&��e��e��0W9  `���T �L������a2����2� �2A2����&�a�`2WZ `�2S ���aL���e������Հ0 ����������((���d��0LjL�(��`2�2Pj�P���L�� �����������(+��I(P��P[�� �&�a��`�����YQ�e�� ������(��e�C0������0 lrm�a�5������&���e0��ula0�@������� �L�Uj�(�!C ����`0�0 ��&Z �1l�Ls! �!<I$ �� aH&Ð ����0 C�d � aA�0� a�b��(@V����՘d! T{8lڐ* a.a2HT+� @!<!� ��&0j0�����$<9 A @$3����� `��Mj$CjL��� &a$ 0�����0�� 0 *a�����&a2�P0��0�ˆ0ePc2�01%�0 �e�`6O< $<9L.ņ0��eePp��� cl�e0a Ա�05'g&a�!e82CjL���0\6���\mC�� L5�0 C0 #`C`C�j0P,C�! 4��@ )00����Axrf�� 2�a! �C.C �����e���!����dpAd& �LkeCD�`Cjd� aɐ<''a�(0OO�@! e@jm0 C����&a��Ld.�C �j@�\1BmL2SA̤ ���C�� ���0sL��e0ls<t2�0��������2\m̄! A! �$ I����T0� a����Pa`j �0 g&a�` a a0���P � � a0[M6jL2 )#Wl0\6d''�C2eC2=���&a0�(0��0 OO��0\$CuZaa�`��L2�j A�L( ��ef��������IP �����$e$ÔA2SVn2e��2�d�j3L����` IIR$�@ < C��'gVZ- e�� 0!L���\6eIA2p� �������A2 0 PL(d&�L`p�����00���ʘ 1'39L,pmCmHfAmHf��@$3�� |ِ3O&F&A2���p���P1B$3�Nm@f��A2 �Lp����������L`8 0�ʘyr\ ��e<9L`CPO5HfB$S$3����� �PL���(+`�&0&eTc &Sd3S@$3aR6e8L��&0��fN �@m!SG<%O$2Y����� yÙ 0<O0pFdfAp�&0 apFr̜H&2lҊ#ck{@2HfLZ<L�`×MP0a�3�`ep���2H LL͜|F��&arf��Am 6I2��Pep6F`ԀL63P $31'j2s1HfPL�����`&g&��0LL��d&g&�L2���"I><3��\s���063��&ə �eTc!����2Cʘgrk<M"ed&'�՞9 0�d&mr @mM=8@2��0LL�����d&g&������1'ϓmr^`�2jp$3�������(d& � m<I&_$���������`3C`rA2s':6<WD��L`rfesʞ|p @b#g��@s<קlD�Lŀ3399"L��&093d% ��e &093���� ~$P<LN"��@ulr!���PL(|ə A2���ʨ$z;dԘ0ə A z$BH ����@2|fș xyμn( d1c7=8"��PL������ ��� _o3~#I!�e̗=5�鑰hr0H3jGR-XAк8R"1 feh 9arf„Q;7<+7<:&Pd&@$3d<s0jf���ef2a&!Cy&'Ag&g&Y̘������ 3|x2ar���&k{fB8g.L`LN"�ԖdHmf�����PA�PV3( 0932̐3��� 39[NfH�frfL23��93&SFY s0�(��0C7m'eŕMa&2�&n9Ι'��� 3Ifrf$h9����IfrfB�@63s23���`$3dyL"��eqO5 3<ЃO-zr1��0L���eԍI!YDZ*B�����`dYLeǜ0⧹!)AIa&'�28<28> |4B�� 70 HI4Rd@.I��� pS3�28<jpx*�2$�Q32cTE��Pg�����\6W`B�`����H<yPk($B$I@L|3������@ �&yLCfr�� ���&�&<jՔo̙)>ƨ( 0E����Lf9REIfr%RIe&'GʙsfNd K@@DA=9PF��euN\oGc9xqxLЖBFr�&g&C�����`<��*ə ������e&< 39$px"4ehL͆ A!B94 3@0B#"fNŐ�`gLUǨm@ir+��d��TP5FUe3:Bdd1'uky����@ g&Lf��M>CcĠY`E!b&�`Wg{7F("��jT"0ả2rx0 y"<KM:�0a@9<yD(#ޢ@jQ�PFg=*\ZAL@��ƨ, !I�����0a朙�e(#�C3L>k*"`2QK>�ə aC�PF�2rx���̣K���PAU������N`e�F~��������@m,"?qT��Po a��0gOULKDpc G���`,;G�ar<9<��S_#TjƠVPD�A2�z yr`y7��P̙#�`��������PF&<IgByΙ �sf.F�٨€""�sf<5ƪI @9<2rx�ԖdL�0sL2<$9[fp �q e!y&�q5&y&����3���m bPa��0a朙�3 sL��0sL� 32rx��Lv>T��������|�*U8”IƠ€�Q#cU#�� C9 ��0sS����� ���/{"����C0axҡ5B��c5*vͰx`��CoQ5ց""F�`F����C����l䇡cv+a]X`Ú6&R 0F���d`U����@S"�PA9@9<s1rX[rDO�cЖQk<j1`tvX11 C!�1kG-I��!FE���@2R˧ޞӳ1P!�����j#g��!C-96Ül,š,g= J "DHf���0sL��ʸڐ@D���L _ã}"B�� 1.l38y#���Lx XYbz\L����!�lN'>1 9<2rx*�j;pٲ48�2r7�������q5z"F�@R;0so҈֠���FϤ99L@9G����9nZ"bb#0�&̜)Df�������@fyj2oQ� �(#9?cQ5j��0szCU>Zi&1I9g~��*X h�0aǨ[KaY=x�����T95 ��� 3糊`<TvD�Uf<@ɇ ÜTMb<xC10B�gFr����ec,bY rD�(#gfr������� eL�jKœy�sm(�@UcM��$#(#g�����eo^1 �` *RD1��^:�� 1Bn< Fy1!��B<u4(!Dz#!�0Vҁ�L9 ��)kCF4Fx&]c!Ds!D��� 3* 33B���*6��0Ft* ɈB���)1K!�� &3s��~Rv3$ϣt�ˠ�ٸ(����+(0j �@F-h������FUc-@F#95d 1X!@ ����������*jk$#W��@O���fg]VZ#cP�c*P("j��!QزCg<Z#�!D1ny ����q re2p1İ3Vn����j?Oc(D팪 � !�TPX�j2r��zՕfR��'[Z8 aq�ˠ+�@ňk!X\k!����� uન[Qk T$# ~? T8T8����qh]ˆZcd~*���TjA$#?�5~DET8 �!&)'!��Bx2! >P39<4@ xj���T9mkz&!YxPU������������ ux�� ]T���� 1�H1v3, Q4 1 ��\q>LmCF@Ly�nm;0P:n£k}�������>u/|T�BfRY12eqH�زH𐂺EpQ:B���#!X8p��HHk,Yfn=Y2c\k ����@\�@ꈧ҅#���H1Ƶ��RGB�@Zjc?���� c��@ꈃ+ u/)bX ���Haˤ#"rЃO�g�L3)C:P:t!���b1�b1 Xk �������T8�UˆP#C��0;p��� ���PXC���8֭B: �!k<ngc-P ��d���T8�T4;B: �RtXǣ4b1$�xC���@+1B#C��X(�L@PG\_nЅ` e�����W@k]q\#b1������Hxk:C�U`Ł2FB qA+"@ !�1ͮ+UP )օ1B!Xk+"TB[aZ����PBv+B4!6wkC������ "�����1.U:��:1 XnЅ������:k�PC]h p@�ˆ!�aĺp@1S-c1�q`X1c ��P/]�C4S-����\z:C-Z?�Pb-������H",,4w񫝆 ���XZ,mX_i�p�ˠ#1CUͤ+>Ƶ L"j0 pCkC@#:��0Z8 XZxHq\G`�1:Buܺ � ��Ef_1k !�!�aY]40#ԮHt�ˆU1kC�@ ��:1����@2E�$c\Xǐ1�����VZDZl dx}I����A*Fĥ����\8(א�� xq! ��c�QǡJ@ٸ0V{���R1c2ղgX ���XUR ����ԨUq ��������RG|׸4S-eBTX,C-<kC���QCb�P`b[Wz!b-h pC-��늀0VHd bңc����� B"JFu ���q,=tˆcaD])9JgpCDa`=C���0Z1"ふ!DcC_ѭ@T G@#:kC0f*1L_.5B��� 1^j( jP X*FZ���u|H�06CKzE ������qFu X5:FcPD��Hx]8baZF1F]C�F@W{c�����T8���Խ5>u �F07k}J=Gʔ2H ����@#u$Z1ƪ�"Bm6֊Hw` p@@#u 0b] hYѪ������`գFD\Aw+J9�B1JX�������@@<>j@ĵP ��1h67k|H�` 6;2J+p����cfQ/QG���@6����P-%:Ƹ1�eJz{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-< öXz�8> �P&1)~?RHGX��!����q���$c����1Exz!*+J3)S-< ��` @ ���V=+9dC? X,5>V$6Kb]I����,0A���PRiͅHX�� *Ƹ1����H#vW�bԭ<b, 8V _x\K dj����ZcFX����Pָ1Zf*ĀFF\k*%5��@T1���@1ZW|mJe�e���jԪ:� Ύ*@FZIA���TX-0VUv/< C-<ju<p#��j+F\HUz \B(F\ax%P *0��(0AA1Zhĵaa,=@ňkǂW�BH G]#Dau���BXqo#G\u(i_�!1C-< �����&������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0231862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/data/silence-44-s.wv����������������������������������������������������������0000644�0001750�0001750�00000104513�00000000000�017242� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������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��M�� ���������������������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.229712820826APETAGEX��M�� ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0231862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/data/sine-110hz.flac����������������������������������������������������������0000644�0001750�0001750�00000146652�00000000000�017215� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fLaC���"���� @�X"ߌodZb�� ���reference libFLAC 1.3.0 20130526��� ���TRACKNUMBER=1 ���ALBUM=Tests���ARTIST=Quod Libet ���DATE=2014���TITLE=110Hz test track���COMMENTS= Nick Boultbee����e #Z'Z0kA|{.>zy=)zOdblMyx  @mN5%"%@͠l6Kp]=Jl{n[ǘ8< <px@(hA쉖}8 Brȫ3xšBإc0#T:HU4 Tc Hu NPaa!8vA3!qJq bC (cRG$*$xxCِDܲ 1K(|LJjnlQ{-n2n2<IA;c5 M[lLP=@\֒[R6D"ԟ#dd% `\`Y45Mi6o`Yi7 [)yFK٪%QW 1&y̱ # H:V1c8RADY:QaJ!(fcDaJ!aRAGÜXQX;Bv0E3$r BB*ń;x3U"3^QA`Dj{\J $0 !,&k`/%G{Om5dBtOR[Ka5%_0 8&tm6К%>kp|>vxzh,5VigV(3L-APF:YfFa2dxE8VS!9F0è:(:AŁa4Z xw`r@AaT"FIrqRDTUseKuR3L$Q9%SHz(%ǔj;mNx<<.MO-nAboY-i/D&oKzI/[Ѹ H4 ~gi��h`� 筴 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[Ď,<<PBN/i3+]`Xh<ӀiŨmX+[k>6GMr%$פ>I%<P Pm )y>.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&$y�J=p@Ⱥ>]Nɧ 8,.<J xQM 0R%RifIWbEI)hQ:xgc \@wP,'08dCBhR"Q`BA D xDGAŊܬ"I#`P߈~!lbXi5D 8iCqp7}e>Ԭ%-'_] 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վ}m�xYOPk|/Ͱ>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^e5W2<NDUyGYLD[>Nlh1ͪ1HyIe4L8(.M1j5ѥ!c\xPHazISd4ζ4Ab#լJƜ<K7v4xʉ!- 4q*B$PV>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<QgRQīQhK0ӞE7+8EKOc3uMbIZ,8,  $MMFjƊ<ʚCa 0(hQi E$DeŔ)yŐIźcQ<Rz&س uمBBk#\Xp<B>=/$߹QNfOv-n!MeTHҵjaCHjxSQyFm<DrٞSYWQBPȌxp$#uUpEJM+rQhNr&^N%6[=4,|T%/"oW0 Ё rя0  Zxժ$$ jcЀDzq⇎'E%\HA!Bٟ,M,IbH-Гܕem뮐GEGbYđqL[&zz81,d]F'D=AbaH {&IAG^)& #Y[Raμ 9lc4ƣl+"XX\ 1pD  !吜˅ZD ;F ,a짌 #e,q&}!/MF=M%$}ҍ8j+sYDsԔja T<`XP?<`ƫ$HG5O8 W-θzb4{{rPY)h. %DC FULW_v!&.n$Q$Nw44$ch@x89BKuKҖT<a(FD40UZ :ز 4`K40iQ=%)cܞl2}˩h#F 8462n2~^LVF )i$ (Y g_-f% !.Qqے-^OzQ0Y)銾RU{;z%K0.<(Y $a" 8Exh@XA8/n3S0ql.$PsLK ?Jܥ5EJ*,%5UZR)i0eM)=CEg˗k#X ($a%[Ɯ40kYW$aon^~rx&Y'~ↇ †;c+WByㇻ 8CEJp{kPLsJj.г vAb%h@H@Ik!Yy (EYMGN[lܜ{5fYaa{',B=ƑOyVl9vGOFK.HyW*z%^E,Q$$!EZN, S^u8sDVMTefr{*Jc7I!>cJ%u94J4QhℕcJ4 V<xPط0icT- 1{q …-8rzJ!(F\cqG5q%~w}CHK=g YfӉ;OfH<WӗUyA)8́0&{'-0ф<ҒdJ-DJ.Bk4a-!v/L%|b #EŐRQj[/H4SK08$  ÚP@$VsQrT]oNy͒Ac1 6sb3cB`&z + 80$0x%-W,,ǻmźsqead\>7zal묋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><X-DV9cIL(IFL3eID7kNE'5mے$D Q#QMlʄ)ԒfM%E6m䤗$q),I۵nG7#D|xB}Hq9)9ՕKIf[)BMk+B%KRvs;tY#8!FbQLqOo4TvRVnKvK2oISrXҳQ"TvoZ[(1ISrM!DRI$HO؋&;S)ݹe%LM6&$k2ԜFpE9+^m>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= #]RF<B%ʒw)1QJRB AB q !8¨8B AL ¸0CuCANs XvÐR*!J!+0!\TSt3vшUDu璫K.K-WD{u-K@,~~Z/ \l5)'KRO-/=>zZdIKST'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ͥ<Yd -=G r#XM塬[>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<fk-ڨ$Ό䔷_GM1-Lj%G 3:mh+jv;)!Y+]YQR(F}!rzAb)O-e) P .ΘVtr;90pUqT91DAB+5&8ko0PaM lɶБdDpaN5ՒC(6LNMF(eA BqEJh3̔E&8lզ3A@N!Dpb )DB|MȤ‰™uekZߐ,Ζq78@g}cygARˊ^ˆX1vu 3"lL뼳]P't„֑QAƮpkRVIrLդjHEb8 PA; \e! # N5p6ęEQ7Xɨ`BsLG ADq )J;]F;nBXQHZA1bRz#^a,Gg#(™{!{= pW j%c(QȺK׵LV d8cVj4E 3䆡o1dzJ;LqKt{4pCLJZ:{Y~HJ0$%T!nb]w=oOZ)&Bs_]ޘG%1UhY sQgUq[D]+1LVrYVY還*9(PMaS*y%r:~gK76b0usBWP¡n)'"p`!>'%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<UrYU3DY#H"T*1wzk-Ib{氒!ϯPL|5E?:M7rnvRZ~OJSd^u+`&[me)rL^.)l]H,9u=[Ez!FfR#HSSTTr!+; 0+CB3A aG)+B x g@:R ;DXw;%Y҇X"Y]ݕ؉Edu#U-wrKb^33w^&nŨ\Dp|o akNKh[[zWVr&I<m>ө_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"YGx<!gcJCa*΢q9EabT*x)#4t P$)auFc;"Ȏ*t]JdURjDZ5KcHy_&_??M>mu;ҙ|L5>|l>婲Z~X/2^;L<j a7;_&#cgY3=Y Dd!.ZT"y;Y!dv;tCdb c8!Eaw9g92pw82 1NQQ"I 9"(c* )G'yR)ʦY^RHDUj$HK?IcT~mLRkobCa35ǧA(&Wkn`Z0am>O&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-<V>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ʋ<R;-O'e) ץ,EoEm<3+2h&P†8eB(8G5"Q5BSq!FN 8N'%1(ĂVĆQ9(e2#d$&n Dq!)H'$sDQ.))jD'nkgO-;WE:;y]>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[<b;[[˲t՝Ub8ÓVJG#INTrx,,ܝ*|)+IHeDS"7jJj2RFԔedJɲlJБZ""Fd&DLHI Iq!DhEISdLژ+XOI%eoȤYY$N"+t]>ee<KUJ“~_c[,\dQtTT]T)gk2YS."}72Ѯ!@B,#䱫h'$Мb(pEdM2#F "bBRFɛdȚ82dQS4dDp8855pI&+q$II)i$KMt2۲)+<,vs:,}nTV[œ gt טQ"9L(eHVZeJ˔10Y"H֓ItȤ*""DQ!tH)9!#VɍI"&L6Fѡ6DL2BrBq94LМ&)TDSFBs9$NgQg5FR\6#]bThVMtvR!Ir*zˬv}~)g{9AH>rTQuv]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Ū<P\ĻCD,RΕ!*Dxc¥BxTUT,rBP+Q q0U9F9x!`@W4h9 T!H2i ы3)ʅRէ/$ͪa'kϝReso'l˂i;8[yv]7Vؿ'{(ݼ܌~Wʱ+ ό嘧ٷ%s[8&tEe7WPnIhRf>ܱ]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廭&'44P<x0 `ؙ=+7^| Oo| l@7 /5%p pMT pZV<.\7|aw(ˈYKD$`XEr!U$X+SJPeނk<]@IIq=35H13W%F4P)Òs !bW5)䚲I)laE{!4!.؊TQBUs;Wٵ++}Yg0K5H7y3k{+*B,tۋ9pg}W?E'{R1OW?o$;պw^=^jx7}lX0;<vg ʊyԙ Uu(AE&ȡ_KJhSK$-YH-E"C%2"iq-))g*kd\H!$Je"[zq$4גZD"%R{0\ӝTRe  CŅ"b o(Y7ۉq,nSk x-<M{x'P S|z{ҁ<ѮZFZ/6m%"^h>I- `.i-GA6EɭmKZtP{T@Z0z  8M/m}nԼMZ뎜̪VE+]%")H"Xć IhRC<S+(Ge !C$*3@# 8$ D9b FAX#LG#d` hAV)gy,F 1d84=ҔjXOmͦO%G[&KP-N RoNpIq8r*s stuvXw MIm@Ez)d sTynj\zmq&PYܚ]в;DBP? E!_PDB#l0_OjNxj'L{JK2y21% 2r4F "̗!PUJug R(Rš* 8h 5xBD2[;C IR9̢-ȇ$GH@Wk-bJJk/'CK(lZ'qjIM\mnHy3qDv<H - {J Px>l[oA5+Mm$t 8k>q(MX-IjQ7VG+7!HYHX"%Q B%iuX<Xw1e Cs,F&"H+,rأ1c%VRs5hHR2Ӗt)S†s<$_NBĘR<a&-.&c>&۳{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<bTD<+9لX8B,C)֢,ř,r!%nv9%4gKd }v78T<ݳ[ LHHOX@J q3jOx}N|&v%6^%%CHlS&3Q9BTƐI\xW|v%-ߙ8ӖyDiWYYxl=̳T<a;1AvGyTT;+*"vqt;Т dxib)&Gv# vY)n1.{Qk?7Qk6y=S4<L~špq=aA.] )ݮį_AtoYص, <AmCL&  <` g,P1=SJ7[Ffe!dLXQ>*v)s,n`*9v2L;F"ňy QZP"u)EDf2,Wx<SNO3RHBHT<I#ܒ<畲`/'X4 [b ^_\bo& RIA}-|\7ZiL/ol4I,cb$jm5^6>(7?7E}-q- &*y9JD#i rLzUu"JUb)X;t B" b[,8Ф <EPƌ:v+t%h(f2<)* ᠢJh 'QHEXgC8})hǣa=kQn^.vRM.6ζy+œh~^Ƕ Q0^<K д,7x~}pқ8/<a]i!!*\ )9cL^2Șb#xĻ,y',T4Rjhb)Ws ;"EYcuH)TΥ)Hd9XE3"a Ic +TR*]T9,c5D1%,ȳ GL"[YUģjm 'OLLPJ- ]=D3 ݮǸkOEa/yN&RxcZPƱ]iGƐy6儱}O}vj& ,-jE4pPQ,"ݮ̥a2!"#\І$"J#E,D1Pva8B)"hń<uA;Δ2Í<d+:YNeZ3d,BLYަi "tBO" "$pǕ6U,"e_}<'j4PAߴ}\l>ɒs%ԴqO,7zl6] XJ[ <p4  LL-^M7jf1Eni818Mrw5ӈdʶG#E%SRHBU XHrt4H9* *c: D(f: H i #;yE&$BȕNu*D[$<pFvQ5BԵNG@h@XX`& qn&PݥmM~aO o?w RTSeQPMNM"KIHAF5pj1 dzZڴ/<&4J-[?ɌZ[n0"Uج!" B8°88B )@1(.(=j0M(,= 4I,`i'C ab% `G r8 qb08)*V) w+HB{*hW]OuI/-xl$/6E%?Qvj]ۻow~~JF'io,ni`lk^: NfoQu5j$V3;f)!S3QpCOyN5fA90C"b$A&QYFIY%XDJ4E(IFO< $N`y0 ŒqD-'4{jLr{XBKر"$A2R%nBv<_^)NU]:UU9?vjwQ'TݑIdntYmn_~v9_*YyGhxUkZ"WU)PS/HωLmN blC'9s[A)g$B1iӞs4q!idy<,#M($AieAAk1\Yo,B,CH0zE&C^b!=ccq\:[JC'SD_|_mg{JWo|h]} כ'Ŭ6!>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^yoI<c" 8 (‹0M($H9(KM%,X[%=i.i 5aFGiDG#JGoED('ߥSR /\fQuVӫ{_}e>Q;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>My�7 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<A^^POzy= v?[j|$ޗ7I%-A4%iiRZV\ Zƨ G�Yr~ (@L=i~x|x߮ `h}C\iSQ ($a5Ub:,Q&dTI x83’⸄9)A(W X1FpW<aTQp$DB*<r2H(9ņ49!t:* 4bՙY(K[JkRTL`I|lֻ7Եk}ahԒ-.i4 P^t| ^P$[Za_zj ZFf 82ɤx!C7"䝤I8f)KtN;3 !"s10v AF; ,wA 3a(Hӆ<4+%)b 2HW9 4(X4" DhFUg$bi v]?5Z |7|%zMl-k5�ӀlD8H K6Ĥx@״]A87V-Y{T.I_k ZX,Zy1iDh"E$)"RJU0;1 :E#xTA :AX8dX!0$, J B q0 q)B0B ca\*hrôE)sb:$DcUR FUJbfol}I?PiA._xM˒Y0?mBL#'ZKy6>ؙd"Zۢ`/h/~Ij5 0ya8$0xݏf,BU1c<ee8Hb@4) (Q 9D#ss)B!F0*<BAC0S(g9Q TqT#bcZLK+)lF-W&6~`ԉ88=nM_Ő 06m R?D> ~Д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[<a!Fdu1a:CW<L#q)- 1Ri ddD$KD&DZBE IPLID$ TB,H) BE &B""DDp!0X%ID!0HPH""СdD(Y"Sd+YItSR̋|[&֡k 3Tl<8;S2so#9=#iOj9IFW&I2Y1+ *"C" . T 0$R A(D @VJ!"D$DPȐ"$ D( SIp)IIJD"$ &F+ě)d1qh@Dc$ &ŎCi|zYlɮ_TֺQ'HFC e6FDXHM P(XD"�$(Ha@bJ$Y@DL "a`YHBb0bZ)iL&K#""h_e5Zʽz87S1Y(36І<S>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ʌ:fh<Bε#QM,+Fq#”8EAH10S#`AN3P0f AGpba+3)1Aă #)rs xt39]LvS/!B\m'qP3ϗĵA5t5edV֦_r̉tНjV2x+&3ufǿѱ' N9D&mf~ț m%GR#OSl bqRZ ]렦\99,dVJ&>raM$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* & <WDBh&X!C80#4**Gs+!$b qL qCAp0B1pB!#1BB^)2<W K,3H,W2HCSE=YWf8 8H@H@|V-)9vm䊨;Y9X =0_ubwrU]Gp3Q>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+aH<WחByhUw=RiJZ*ZUw|*szyQ,b[(GARr^̗F4mI2v PFGFn#1 ! LbA 0hC aa"(ac B0L!1Bb &1Іlhldfdن(PLL6&T?e>gV~ñ}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`ƐҍkXWF<JgJ;0Eab^$@ĄPøR:B 3KX(+CpDR*)CBPЍ ,R8DŽiv+4i$ ,cN4bkP- ؃D{ݥwI‱Ӈ섘>m-i/\2.o>jjMZEim'@%6\x<Pn-)&ޛ>`&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`c�I5%$\ 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=O<m{$OY].S"vR+*IcrMv&I3IrDq '7jIFLIIMbVJ"IMFq9+42#CRq9)&#vbM hnjA;q)H.LҴi'NIe2ks.k*vo#&T]+,{-S³ϕegCF8@>Z~ة|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<cyXD[D ŐZU+šn"N"(qgEsc(dA3P9NrBPBg)bhBÚ,XF <3HE,f2PT^rT"P1 Bըؼ I (y&Ɛ5ŵPIG?i( "(y$!$p}yF6դ.IZ/Z-`_IEDZ& 8\i4\l?ˏ{ qdAL%SU3vpᆙxT"0(WHĕAWa9"U$Jǂ9 "3☣21 d,* 2DB#D@:´"+‰<)g" 4" SSÆ%dH8 ~ ( U<Aj\K% [^.asm7K/}WȜ/O 0.4ƒ#LFcM`im<4 CjpYPX4ۍz_6!hno RL(Hrƈ$W^d#g,s‰*)A)VЯ)W1!H:Gh!w(1t  HEQ&1qJsBBQH*1Da9%9 )aCFtHacP#,<@FEǡlmZii(=Y`>.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<FK1b&, ,D%ARG #d3,+NC9sd$9#NPX,9w Vr)EHŅ,T1JC c,BDR $({3yƄ RN$ 0D4AcZ%hOpI,> OdiрxP=ĉ( J.~ 0 <hKޖ-$885WDIM.-(jcX䰓Q!E$B]fb; K hqZRG)G)Lw!w(00TXbCW H a`B3APfsA9Q iNA)8:܈1"=L?'2ҞRQ}ZT!&%&F uqPޯSO+LD `zKy%)pj%-KjZ-*rxND^8ВNaZ$' m hYACx=j%ګ"eTPC I :Γ(:IAf :C P2qF@CC H@XrGQHR 0⨥qP"F$V"2 "3E4SHe98$̊i^^z?XYJlxP,poͥMh|u*<ɴM˃6ڻ>Ɂ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)*XPzTmlkjihtgLfdcbZ�X0d$ P1pb.)5ɫvTGa+[YdIcuE#-.ϿBjT*{:cer?0 gb:>fs<BOQ)>լJݑ)C>pc#8DR[bVPMQ*&jȉ!)7#qnDlH"|F4I&&Dؑ( 4D#jJmvN!馩tK]gZΖxY>tZ)1y#YmŞع+~-;<HS Ύ+E׷~G$s,#;nE"]p4R'7q'"s)"Ѩ2BD'Ą G"8N5ABACH7 ɍM94fNͩ7ٹ.Fl57NH)MȻNGf!veQ'_<Qm#Gު,OSVT[g#qI܃lT*:N}Ct:^G'9kL䝬#97DVh8"'+L#`FP8ӆE7#BfN72Q)456D̛2!!A"Qn;%5mL8%DH)%%MZFg501ZtݼKSdE I/gg/g):IBH\ersȤ;[TR<oo}Yo#wQb,!ITaI9h&J"sTȜIM؅ `FQt'BD2R)HƬMn$dْ̈!cSvFHJM PkGS)RvTS$\NJ"ft+ye{#QBmHHA+:lt1tAYN,veeϺNGD(F)-nn֘zekMAƎ2 &Q;LhJ4%%fԌᝈ$6le2!)"b4'djDj&C#r$d2FJK!;r%7%jI[15KNe1LJD: T^e+[VaSGbsr= N3\²tCY>c+*\'!S8LnӘ"C>2FSrjjRnr'N$ČbQ!2fhɑ71")) "ClJnDT%&ۚ)"%"Dht+;Kc9F.aFxoϢܺ rm!\\F<e,!e>l}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<MtgDf:};zC' k1ŤԢgV*^#}sT|yU Y_jgc(}g>+:^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<j>"�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:nMY�8A8>OZk^׷FI@j(>N %p'uk .19<<FERs-YR @5G$ddqP)P9Ep< 4HBcA(SSPDa H DQ`ì"c!"E3ADvE f`PH(<)lZ:іꜾ5_Cy\}VI�сz_6x|I@% m6jMI/YHT5-4>Yi?M.Bp.zOV_--67/'./7epl&1iSrZܚsȾxV" 20#2L ;$qa:A`RBCQE(Thf2äQT hg8GB`(AKMBc"#9Ǝ⢎1&G;Jtr8XQg !��������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0231862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/data/test-2.wma���������������������������������������������������������������0000644�0001750�0001750�00000055106�00000000000�016404� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������0&uf��bl���������3&uf��bl4������� �����t�e�s�t�����������ܫG� Seh�������݀cBl?[FZ������0ܤ@�������#����w<����+���������"��"��z�_.� Sej������ӫ� Se�<��FC|K)9>A\.��������s�k��� e�n�-�u�s���]&EG_eR�������ů[wHgDLz�����������4������D�e�v�i�c�e�C�o�n�f�o�r�m�a�n�c�e�T�e�m�p�l�a�t�e���M�2������ �����I�s�V�B�R����˥r2CiR[ZX�������������������������������0�������"�������N���������)54�I"������������t E˖^ ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@�^P��������W�M�F�S�D�K�V�e�r�s�i�o�n������1�0�.�0�0�.�0�0�.�3�6�4�6����W�M�F�S�D�K�N�e�e�d�e�d������0�.�0�.�0�.�0�0�0�0���(�A�S�F�L�e�a�k�y�B�u�c�k�e�t�P�a�i�r�s����r���]�� ��0u��R ��ȯ��6��������m���*��0W���� ����# �b���@B�G���\�3��� �"���@KL���������W�M�/�P�i�c�t�u�r�e������i�m�a�g�e�/�j�p�e�g���t�h�u�m�b�n�a�i�l����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ێ@ �I�s�V�B�R��������.�M�e�d�i�a�F�o�u�n�d�a�t�i�o�n�V�e�r�s�i�o�n����� �2�.�1�1�2���@Rц1�H�������ARц1�H����%�W�i�n�d�o�w�s� �M�e�d�i�a� �A�u�d�i�o� �9�.�1� �P�r�o�f�e�s�s�i�o�n�a�l���.�1�9�2� �k�b�p�s�,� �4�4� �k�H�z�,� �2� �c�h�a�n�n�e�l� �2�4� �b�i�t� �2�-�p�a�s�s� �V�B�R����bܷ� Sez�������@iM[�_\D+Pÿa�� ��������$�����������b�D����"�����������������""��u{F�`ɢ ���������z�6&uf��blF������݀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�&��`HU�D�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������)54�IF������������������������������������������"���3�I8�������݀cBl?[��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0231862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/data/test.aiff����������������������������������������������������������������0000644�0001750�0001750�00000041504�00000000000�016363� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������FORM��C;AIFFCOMM������@�@ �������SSND��>������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ID3 ��ID3����{TIT2��� ���test.aifTPE1������artistTALB������albumTCON������genreTCOP�����TLAN�����TPUB�����TXXX��� ���TRACKTOTAL��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0231862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/data/test.asf�����������������������������������������������������������������0000644�0001750�0001750�00000025146�00000000000�016233� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������0&uf��bl���������ܫG� Seh�������`Ȩ�@5HCf*������t_ _�������@���� ��������������m���m���f��_.� Se.�������ӫ� Se�����ܷ� Se�������@iM[�_\D+Pÿa�� ���������������B��@������� ����������P�P����������������������@Rц1�H�������ARц1�H�����M�i�c�r�o�s�o�f�t� �G�.�7�2�3�.�1����8� �k�H�z� �M�o�n�o�,� �5�3�3�3� �B�i�t�/�s����B�6&uf��bl(������`Ȩ�@5HC_���������]����x�����PF2� @#�N.: #>Ý@U: *fTZ"-;|r*Di)ûfE����������]w���x�h���P] g- SMzqtbd&ܪnt3Yd%8d(ZZDp&aʴn&X!8xG����������]���x����P&i҄S8AG3'vZjHl>CԲ�Fݢe#i#8|z5LLe:�Rq����������]g��x�X���P)ŪIKX&au_z9ߢuqjw̽M&yL GQࡺ ҅#NEYN����������]��x����P].63 6q'l Ct<A6Ѷ -;"^ ­(:$kW$ωd�����������]W��x�G���P"CVʠ� $78J2$2jʶcJ &P˭ J$&)xYSCI=aF!*$Z* `H#+|����������]��x����PRi#N p�� B$z'Bm9QB#"XuJ$2HÑP Zy����������]G��x�7���Pa6 r,몀ZZ| q)sE[}Ӽ|S O  Tuijw A����������]��x� ���Pmp$ꓞIA"|qڄ.j0>Zq4蚨ɘx+Wp$(^IGV˄\����������]7��x� '���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�ӫ����������]��x����P]E#̺uVhbEyTBd%(8ʁkݞ��MӄO JY$4픘����������]��x����P>(E~]  Meq!VgeIGa=P`G[F9uߥi佡����������]��x�q���PMOƧ *1(h•G2RC [ZY"(ܲ]Ggw0 ȊUq|ht f.DU����������]��x����P"rUQ4Q; bǥrmw*uhmzq ؋2 e*ZT ����������]o��x�a ���PݒR/qOe 5 �^X2 WPW0z�9"*fh$1(*dVM`d quU�����������]��x� ���P P pO=g&j�@XTg3g 'kSz_tUc::xx����������]^ ��x�Q ���Pf\I\H` #ܝ:qt.18ȫt𚳊X4짵˙XJ겹O8P*l����������] ��x� ���Pj 2w CB AYZ.!]Ĥw0QlQ7&tL{v"LMcޤpM[����������]N ��x�A ���PtX%y˻6Z8|5ՔɚtS&CbY^̂%"sguY$FRy / dPuL\ P����������] ��x� ���PE*$SbMV[2D$?,©� �E"2j 5;LMUrV ,kWsZ0����������]> ��x�1 ���PE nXC8Qo�1Yv Cn;f=@cn#. ڢe򫿴`^X}����������] ��x� ���P2X/`ȼ2Q1ld�F2i2xUy.hxV�/~\ ����������]. ��x�# ���PZBDG3�FIJ�¥2b.2an D ´kʘA]9[(uvB9k8����������] ��x� ���P(pdn^`X3`A٫-h8GH PC1q ~z6)~kN0fw IXwz&ڱmM*q8����������] ��x����Per½c/KKyCy݈ AY-XVZe@Iع4V0QIM����������] ��x����Pu �VO1B+)c PnXT04Q#C̾:E~pltrP)ҳr{����������]��x����P-?ciuoa͢Ѓ\٫xUi.Ѣufn7բU6D(g=\����������]��x� {���PQvТ7Fc6re8 C?D"-KkV/DHTfIG+:vx42@A����������]��x�!���PiF+Ċ\΃2%ɲe}؊"@=ts t$r/ $B- `+&Ȣ����������]v��x�"k���PmǎZK?$�]ⴰinoleԚUF*J`Ķ<Ċ7L| .�����������]��x�#���PUzE^6òHXhrF 7LsWP)f4AR1L,J?a "jEqڷFb/uWԡ%;����������]f��x�$[���PYZ(bO6SߵQ69M[ben 쫧 ڦwRztdAC9ZRuq\tF'&@vg`G����������]��x�%���PƆB_0mS>a:J #g ;RwBB$90V$U{Pյ"J!,ꏛ%�:s ����������]U��x�&K���P -0tV @g3]٠J"�(<Ш)=QS|swײ~4PYȋ )����������]��x�'���PQcKD ld͓b!{5U5z(&h mukf2tK}"%arh#����������]E��x�(;���Pm[k5@t]_ܺuuݸ#ᅡ^x5EJ4E<bF68u`.rif[Q,7b~����������]��x�)���P5ԙsA(-Ȣ5H$ 7*�2$,ګ<DqB$"BjtM3����������]5��x�*,���PM>% E)igE~> *Ejf&LY,�VR2$#2E�Pإ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?ku�PZKl/|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Ȝ����������]��x�0���P]FX:lDoo6X$a�%:6C\ϻ:ȳj&-^j4tB(r^����������]}��x�1u���P#ݓ,_ am{Qw vжzDÄ:�Yw UM3Nd҄V_a!Bdt9����������]��x�2���PFd' oঢƠ�> a4&Jݎ@,'9ᮣ"E|qn#‰NMcdXw����������]m��x�3e���PQ!:}Uu Sä1kn|LuҭMSIh4=L8XεmrEprjǭ����������]��x�4���PkZ߼߰Dg'q{Dp<nޝi<3&yrCt&mo"j.%V0����������]]��x�5U���PAoA'�7"FlQ˙f0 7#"%Ϸ骬44< 2 犉[ $=$ҷ'*8����������]��x�6���P<t(iC!H%$1fVPRq)F:ĥ$- @Z�R $`T"W����������]M��x�7E���P]"":!xR�{eb̡ U(Ȓf"% %jqy&X?|' kf HЇ����������]��x�8���PB=r( #M s-12& ҂hM!BU} ^)ĝ.(:uDuItc;����������]<��x�96���PlX2㾳%GiMW2%zJhY%VҍFdY25Ҽn#h6n7 dR5}hY5����������]��x�:���PpU[%nӏO+qth]<5*jnM{Hܲo~0r-Q Kir����������],��x�;&���POLUNot`Y֐\w :?:)H 12p p{@d����������]��x�<���P j�" VӯI :X'ՠ?O *d#nXb_aF DZ*#hĔgj����������]��x�=���P O 9b>(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  ����������]��x�A���P:U,3؟CjakI_2e響! �Eo2tf"5 �XMS!:W€{����������]t��x�Bn���PEBiѝ, .D)JJkwc5�^ZhG r%! QS!buSFWSCL����������]��x�C���PQO)beHw}Ȝ͢F)bEL܈H,鄌s)j5X|T?X1N#zK]& p����������]d��x�D^ ���Pٲ)J �lyCe}WN_K٨B5'*8XYL" Gb����������]��x�E ���P^Q=H)|vkƂutF) idzuځI@ŵ6i¾e=XY&M)����������]T ��x�FO!���PZ`tI*Z.ԮBddK2E4QwPυff%f�5 (Mx10{!k®xg����������] ��x�G!���Pa„Ѩ}wۍ3G`QXt`-λduMS=#&H@iD5*$T/����������]D!��x�H@"���P)6hɉh5,:1Blq뢞I)CRQ�(Nq6>6CwH.3t4j>:vHN����������]!��x�I"���P :>ێ[xunpJtg�"pfj-ү[tM(XӉ����������]3"��x�J0#���P{iˋJ ]uX|ԋz@M0;WtV!5f':%h r%=*Yl{\����������]"��x�K#���PV^'R%(+3Ћez t04krYO9ы7kkDpl9ڤ&7 Btۨ_����������]##��x�L $���P42Bs  }Ak#Y*tvkb2;tM26^`Y6u>fB@����������]#��x�M$���P!X\$ W2w&$8Ҁ S&xtm0A#С4)9#P ?z����������]$��x�N%���PM"`f&H8UY^M底_PqM]Ԫu b\"Pxi*Țuf%DE1����������]$��x�O%���P1FѪW}EYdH PNjʬ vBTAӐYf)%:q � % [(`B3i@D����������]%��x�P�&���PR D5� P] D�RaQh=˱D)pYN L=QJ.GcN{4����������]{%��x�Qx&���P/zEqkt5x y+*qe1 Vb^:G}Lq Z2uwF bJ T����������]%��x�R&���PR*uȗx^ ȓyQK)"U� &-[1 eKCT:׃\V *E\d<s&Dy����������]k&��x�Sh'���Pv ]қ  cǔ2t3Q7KǮa*[6r) Q7 '|AS! H'����������]&��x�T'���P2"XK`]I: �4i p(M@J<ٲco2^ U}"_6����������]['��x�UY(���PBX (AU,yJS (ejp�J9;kd@&UAJvȋtȪ.o8ÿm����������]'��x�V(���PM_JunwzT%$ �iJfCb)6jSirBE=L'5!*SN>D����������]K(��x�WJ)���PQ#9ZfAT؞kaY /t}Al-�.Q ga-"%ߚ XρlS& ����������](��x�X)���P%2;t4oRxt\D9.FPE5;1rl{E{s(F켂en%ywh ;c3����������];)��x�Y:*���PB຅b#@q=/ soLB,DҬ ӵl<o2^*,Z7.ƾvl?tXdY>����������])��x�Z*���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׼������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0231862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/data/test.lnk�����������������������������������������������������������������0000644�0001750�0001750�00000003226�00000000000�016241� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������L��������������F�� ���KjKj g,�'�-��������������������PO :i�+00�/C:\�������������������R�1�����B8�Windows�<���:B8*����������������������W�i�n�d�o�w�s����b�2��'�Y>+ �explorer.exe��F���@ O@ O*����������������������e�x�p�l�o�r�e�r�.�e�x�e������F������������-�������E�������������C:\Windows\explorer.exe���C�r�e�a�t�e�d� �b�y� �R�e�l�a�t�i�v�e�P�r�i�m�e� �.�.�\�.�.�\�.�.�\�.�.�\�W�i�n�d�o�w�s�\�e�x�p�l�o�r�e�r�.�e�x�e��d�a�t�a�\�b�i�n�\�q�u�o�d�l�i�b�e�t�.�e�x�e�!�%�S�y�s�t�e�m�R�o�o�t�%�\�s�y�s�t�e�m�3�2�\�S�H�E�L�L�3�2�.�d�l�l�����%windir%\explorer.exe�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������%�w�i�n�d�i�r�%�\�e�x�p�l�o�r�e�r�.�e�x�e����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$��������� ��CBg (#������ �����1SPSXFL8C&mm����������.���S�-�1�-�5�-�2�1�-�3�0�9�8�6�8�7�4�2�-�1�7�2�0�0�3�6�6�1�3�-�2�5�3�1�4�5�6�4�2�4�-�1�0�0�1�����������`�����X�������xy-pc�����������n cqG#^AF�'n cqG#^AF�'������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0231862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/data/test.m4a�����������������������������������������������������������������0000644�0001750�0001750�00000011764�00000000000�016144� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ftypmp42����mp42isom��mdat��libfaac 1.24��B� 2�G!�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�#��#moov���lmvhd����ELII�_���������������������������������������������@���������������������������������iods�����O��ttrak���\tkhd���ELII�����������������������������������������������������@�������������mdia��� mdhd����ELII��D�~�������!hdlr��������soun���������������minf���smhd�����������$dinf���dref���������� url �����stbl���gstsd����������Wmp4a���������������������D�����3esds����"���@���� �� b��� stts��������������������stsz����������������� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ���(stsc�������������,��������������� stco���������� ����I����� ctts���������������������� #udta�� meta�������!hdlr��������mdirappl�����������ilst���!too���data�������FAAC 1.24���#ART���data�������Test Artist���----���mean����com.apple.iTunes���name����iTunNORM���jdata������� 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000��covr���_data�������PNG  ��� IHDR���������Ԛs���IDATxc|�� Xo����IENDB`��/data��� �����JFIF��d�d���C�    "##! %*5-%'2( .?/279<<<$-BFA:F5;<9�C  9& &99999999999999999999999999999999999999999999999999���"�������������������������������������������������������������������� ��?���jfree��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0231862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/data/test.mid�����������������������������������������������������������������0000755�0001750�0001750�00000010100�00000000000�016216� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������MThd������`MTrk���4�XXXXXX� Tempo/TimeSig�Y���QR�X�/�MTrk��~�bbbbbbb� aaaaaaaaaaaa�?���C_`C��C_`C��C_`C��?_H?��F_F��C_`C��?_H?��F_F��C_@C��J_`J��J_`J��J_`J��K_HK��F_F��B_`B��?_H?��F_F��C_@C��O_`O��C_HC��C_C��O_`O��N_HN��M_M��L_L��K_K��L_0L�0D_0D��I_`I��H_HH��G_G��F_F��E_E��F_0F�0?_0?��B_`B��?_H?��B_B��F_`F��C_HC��F_F��J_@J��O_`O��C_HC��C_C��O_`O��N_HN��M_M��L_L��K_K��L_0L�0D_0D��I_`I��H_HH��G_G��F_F��E_E��F_0F�0?_0?��B_`B��?_H?��F_F��C_`C��?_H?��F_F��C_@C��C_`C��C_`C��C_`C��?_H?��F_F��C_`C��?_H?��F_F��C_@C��J_`J��J_`J��J_`J��K_HK��F_F��B_`B��?_H?��F_F��C_@C��O_`O��C_HC��C_C��O_`O��N_HN��M_M��L_L��K_K��L_0L�0D_0D��I_`I��H_HH��G_G��F_F��E_E��F_0F�0?_0?��B_`B��?_H?��F_F��C_`C��?_H?��F_F��C_@C�0>_0>��?_0?��<_0<�0F_0F��E_0E��B_0B�0J_0J��I_0I��E_0E��H_0H��F_0F��B_0B��?_0?�0>_0>��?_0?��<_0<�0F_0F��E_0E��B_0B�0O_0O��J_0J��F_0F��D_0D��?_0?��;_0;��8_08�0>_0>��?_0?��<_0<�0F_0F��E_0E��B_0B�0J_0J��I_0I��E_0E��H_0H��F_0F��B_0B��?_0?�0?_0?��@_0@��=_0=�0G_0G��F_0F��C_0C�0P_0P��K_0K��G_0G��E_0E��@_0@��<_0<��9_09��E_`E��E_`E��E_`E��A_HA��H_H��E_`E��A_HA��H_H��E_@E��L_`L��L_`L��L_`L��M_HM��H_H��D_`D��A_HA��H_H��E_@E��Q_`Q��E_HE��E_E��Q_`Q��P_HP��O_O��N_N��M_M��N_0N�0F_0F��K_`K��J_HJ��I_I��H_H��G_G��H_0H�0A_0A��D_`D��A_HA��H_H��E_`E��A_HA��H_H��E_@E��Q_`Q��E_HE��E_E��Q_`Q��P_HP��O_O��N_N��M_M��N_0N�0F_0F��K_`K��J_HJ��I_I��H_H��G_G��H_0H�0A_0A��D_`D��A_HA��H_H��E_`E��A_HA��H_H��E_E��/�MTrk���Piano 1� Roland SC-55�?���>_`>��>_`>��>_`>��:_H:�>_`>��:_H:�>_@>��F_`F��F_`F��F_`F��F_HF�?_`?��:_H:�>_@>��J_`J�`J_`J��J_HJ�I_I�I_0I�`D_`D��D_HD�B_B�B_0B�`?_`?��:_H:�C_`C��:_H:�F_@F��K_`K�`K_`K��K_HK�I_I�I_0I�`D_`D��D_HD�B_B�B_0B�`?_`?��:_H:�>_`>��:_H:�>_@>��>_`>��>_`>��>_`>��:_H:�>_`>��:_H:�>_@>��F_`F��F_`F��F_`F��F_HF�?_`?��:_H:�>_@>��J_`J�`J_`J��J_HJ�I_I�I_0I�`D_`D��D_HD�B_B�B_0B�`?_`?��:_H:�>_`>��:_H:�>_@>��@_`@��@_`@��@_`@��<_H<�@_`@��<_H<�@_@@��H_`H��H_`H��H_`H��H_HH�A_`A��<_H<�@_@@��L_`L�`L_`L��L_HL�K_K�K_0K�`F_`F��F_HF�D_D�D_0D�`A_`A��<_H<�@_`@��<_H<�@_@@��M_`M�`L_`L��L_HL�K_K�K_0K�`F_`F��F_HF�D_D�D_0D�`A_`A��<_H<�@_`@��<_H<�@_@��/�MTrk���GGGGGGG� XXXXXXXXXXXX�?���:_`:��:_`:��:_`:��6_H6�:_`:��6_H6�:_@:��C_`C��C_`C��C_`C��B_HB�:_`:��6_H6�:_@:��F_`F�`F_`F��F_HF�D_D�D_0D�`@_`@��@_H@�?_?�?_0?�`:_`:��6_H6�>_`>�`C_@C��F_`F�`F_`F��F_HF�D_D�D_0D�`@_`@��@_H@�?_?�?_0?�`:_`:��6_H6�:_`:��6_H6�:_@:��:_`:��:_`:��:_`:��6_H6�:_`:��6_H6�:_@:��C_`C��C_`C��C_`C��B_HB�:_`:��6_H6�:_@:��F_`F�`F_`F��F_HF�D_D�D_0D�`@_`@��@_H@�?_?�?_0?�`:_`:��6_H6�:_`:��6_H6�:_@:��<_`<��<_`<��<_`<��8_H8�<_`<��8_H8�<_@<��E_`E��E_`E��E_`E��D_HD�<_`<��8_H8�<_@<��H_`H�`H_`H��H_HH�F_F�F_0F�`B_`B��B_HB�A_A�A_0A�`<_`<��8_H8�<_`<��8_H8�<_@<��H_`H�`H_`H��H_HH�F_F�F_0F�`B_`B��B_HB�A_A�A_0A�`<_`<��8_H8�<_`<��8_H8�<_<��/�MTrk���Piano 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_@2��2_@2��2_@2��2_`2��2_`2��2_@2��2_@2��2_@2��2_`2��2_`2��+_@+��+_@+��+_@+��+_`+��+_`+��,_@,��,_@,��,_@,��-_`-��(_`(��-_`-��-_`-��-_`-��)_`)��-_`-��)_`)��-_`-��-_`-��-_`-��-_`-��-_`-��)_`)��)_`)��)_`)��-_`-��-_`-��-_`-��-_`-��-_`-��-_`-��'_`'��'_`'��'_`'��'_`'��)_`)��)_`)��)_`)��)_`)��-_`-��&_`&��-_@-��)_`)��)_`)��-_`-��-_`-��'_0'�0'_0'�0'_0'�0'_0'�0)_0)�0)_0)�0)_0)�0)_0)�0-_`-��)_`)��-_0-��)_0)��-_0-��/�MTrk����HHHHHHH� ZZZZZZZZZZZZ�?���C_`C�`C_`C��C_HC�X=_`=��=_H=�C_`C�`C_`C��C_HC�X=_`=��=_H=�C_`C�`C_`C��C_HC�X=_`=��=_H=�E_`E�`E_`E��E_HE�X?_`?��?_H?�E_`E�`E_`E��E_HE�X?_`?��?_H?��/�P�PĞJ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0231862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/data/test.mp2�����������������������������������������������������������������0000644�0001750�0001750�00000015620�00000000000�016154� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������h�ϥΧwm�c浰c[EZvlbt873mrֶN34>E~Vu,[i.V %`WFbɐsM ێ(ծޓvo~1<e~֜��$I3~x~8ߍ4ԕ eCYMۣt2$7\ 0M#[96Ge7XMy\Od֗Nx$GvM豭4v{Z ��H"7}~ӓHӾd[mmSX+Q5MiC &d)*pcRQkeqriiPҵ|ƕ"67KvG^؀־kZ>7oZkZtɕ>d jgs_-�I3~:}獕SU>AS R#Euc5i8PՃ)v&p!K-P1sT҉$zK$GܻYvs#cFpgⵌaaf n״g+^:si5t��57~8~ jD�%ܭJˇ@ _$$G|Sĵ86re(؝D( VnKjvZ\CkMk4kZmz䇗$ִI"3]ߞ7z+FikIh:{olr|٭WܷT3 gI-k]Te vrd- ~G4#T&Ff9Ѥ^7Cq!iaLvSZU��I�5v~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,˵<pѤA-Ypq ca"dCf'" [g$3mߍߝGy<:C%nQtڍ7&U lA\xo2grfmx[@BED|Sg%Ӻ;٢pD)W%jEt}X=gJs+MM`¹jN4k6f]4$H3~6TFVrbe\h7ѤޛX%x65lA  6E)/,5Ь4M#+~M+T5l֒ #REp$kojh n?3*MԕP��H"nyiB٦Ky+ev;+<ufօ1S',ke5bwPyʱ1N~"-l\\5+ij5P)NAkZ&Fc"M6f$30-hƶ3aCP oW(� I3mߎ9l#!:9 W.mӸHsMj6iE|Z`fK+�#dz4е6t4]#M.2!wńkyɞ $x"" t2֬H"n3~ߍ߭ȪZŝb gkkYȷNj<Qv*Bȁk4 冚37gi# +>&J,!F<r3TPIhmja 5hR5 -飘P��͸~8|xh^0[ |#X]y?s7vè|JY&5I앓LWSlkhRm/QIԃȥMzӿ<UC!\GQ鍢i5l3-0hIbYzmxǯ��I"3~9~7sY,mSMNkI9jaNk I�2 mHc 16F6wp2[vulEză@Z$*+qAxykZAIkjM[<UP�3y<}l?QsIm8ME <LcIF"d?&E,G"tnL6SZˌs=/}qԀ6;><kHv< ĭ*9i*wCA H"3}n7߮,Em ʂ MlWJk5M#ƞm*4He9%uUSrZEB^T0Rp I;ksI dDmlV CrhYQ}YzI3ߎ7‑~:tu6%V,#B `Tl;F>9k@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{v��I3۝ێ7I-%Na )v$a.Ў YS�.kW$QlJuIIVOj䥗51RpF;SXt<F6C���I"j3}ߎ8r'F횖^+ ٬ht.en[dٖiH1ɖX̩TUVNUjkZR|cMp ʭ̚ k"46h'9QQ5JM}�3w㍷bgxBr5>ikw."on-K#HMlJIbN=#)* 2󋻃g*^T{"{Âēe1-S[MracOL9$hKòz�"i3n7~/K75С.7HR=KZFQ,JG m{+#v4$uRZL۾k-=8˧M<M ,"s)Q&Fr>e4_{w(�[WfI.387>0NeiMsS)"6›HYN+Dʈy/2W37!M:q*H76T!Dm`2 ֕-U5<J"AnyQ ^v<ژ5`!υj��$H3~8䃃6%~5k73j�97}jV*$j%evFdF+ m7ҺcBl ݽBeR6Cls"ֵw$q{ Ͷ~9ߎRiZe-u;c5ji"[bv%.df3v8؇qWx`8R#Vf]_ _@o{m-M kG)W6gQ*IhM.dD|���Iwn8BݴY֬Es V V W J>SF3b73mgcMlg'%z\'q[C!C&) a% OأqlBK9쐄.n<ѽm!@��3}ߍםلe6ʝ9M%cf}IèK$[-hK8AZ \VăS©њ%f p5i]-a>"<GVBA;fִlҴ$Q39ۊg釘Zne F&B1' i?b7,YO.6v|R)6_(n6reڐ[~5rel ᵮdCĎ2ZG5:mw ٤yw�$H3~9ێ30>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ԍ/5B<fV瑰ᖡ nP>g=͙*^B 3'${~vy2]&Rܐ�����������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0231862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/data/test.png�����������������������������������������������������������������0000644�0001750�0001750�00000000374�00000000000�016242� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������PNG  ��� IHDR���������&���PLTE�~D���bKGD�H��� pHYs�� �� ����tIME#7@K7���iTXtComment�����Created with GIMPd.e���VIDATx��� nH@���������������������������������������������������������������� ����IENDB`��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0231862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/data/test.spc�����������������������������������������������������������������0000644�0001750�0001750�00000201060�00000000000�016236� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������SNES-SPC700 Sound File Data v0.30eE��Game Select���������������������Super Mario All-Stars�����������Datschge���������������������������������������������������25�7000�Koji Kondo�����������������������0������������������������������������������������������������� "�= e������������������!%`+%+tò���@�����2��������������<�<������������ �����������������������������������������������������������������������������0����������������������������1L��������Ja � �������� �������������j��������)����)����������Q�Q����������������������������������������������������������������������������������������� ����� ��������������������������������������������������������������������������������������������������e�;����������� � � ��� �� ����������������� � � ��� �� ��� �������@�������������������2�����nA�A�A�������������������������������������������������������������������0������������2�����n�A�A�A������������������� Ͻ�]��=�=? H?6` ??<]?��S� iMLL�]�EFD\\kk�m8`CC+?.�??????iML \LS`QQ ??_G�G1?== G&?_G&/��u���oʐ?" Ȱ$G(`P`a`\�|ՠ�԰� G^ GEԠԡ aa`a? ? �4 zM�]-ݍ�z+/K|=  m!z!z}\?-G$��o$$(?++(��no����ŀ<́<ł<̃<o�,?<?\??�&�o�&?͐Z�[Y? \_�ZYpY_ Y�_ohhhh0h(o_HF���ԏ�Go�@:@-@:@o`h"hh h hh�&-?�`]o@ HF�oGG$( # ?{ ՁՀաԱKGZhTPB_Y So �__ Wn ?_BB?B@/0��G1 �?" �Ԁ-G$ԑԐp== G�^GD1npd? ? 0011/0 �? 0-(>(>? h? /-G$?�pq/? ?g == G_< T VzRnTTRhdz``fzbnhh`jbZ\zXnZZX^�G1?( == Go - -\ 001o`_`�=$G:M}\]�(8 HH� GI/GNI���=! oQ(1�0oԑ-? P1? @Aoհ? ա? Ա�ձoձ-�ΞDo �XoZ? [YZ? \o�RoT? UST? VoPoա-G$o? ? o/�ՐՁ? -G$�Հ? ՑoՀo��oԐ-? ? o-G$Ձo@? A? Ԁ0011@0A1oJ? �`? �bHoh? iah? d? jch? fo`bHo? ? N? ]y?=`DoM}��dM+(HL`LL���H l?M}?H<m__o-G$&/D0h>G$ ? 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\01�00@h?h)h0m- /# 1-0/A-@/-/G\?/$G `? ? LްD�u/ @� `Ա`ՠHh(/ݍ�?2_qo ?:10 A@??} ?  qp?ްQ`_? mQ�Qz? zoQ`HHY!o� )4BQ^gnswz|}~�������X !++43�,< MlL\=-\acNJHEIKF_e , J *Ver S1.20*���h/ �^���/^������1�o S? /9�(�xC�x�x� 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#:;/7���I=?�ĬōŌ _" oY:�0*:0`?: ]a?}/ a?:hoh9hIh/ ?@?r ?/e@\?o�:Џ D ?@?r�:ĭ:Ĭ-: D ? /�I=?�:0" ]`m?=nm-�,_`(8 HH�l?@I=?/ ]Pm?=nm+�*o-\�?L_]]T?=n+=*o ��� \?( JM?�& ?" �'ĪŋŊo%hh '%&hHo&'� \?�ŊĪŋo'��? ?rJJM?Ī� D? o ? /P?Q?oĪ�( D? o�,?<?\?�&�_`? a`�G_qh_hh_z(%(hhh hLho__耍\?�ŎĮŏo0 /Ex* qD�˯ˮ? /]n ߏ��ĮŏŎ_" o?D?�˯ˮ? 8p?8q??r. 耍\??o ]pm?=nm/�.o耍\?�ŎĮŏo" ?on O ""iD?/#��ĮŏŎ_" p?q??r. 耍\?opp� pp�� pp�pp�jpp��pp� jpp�jpp� jpp��׸pp�jpp�jpp�pp��pp��00pp�jppp�jppp�ppp�pp�3pp� pp���pp�ppp�jp%f#X#$d$"%!q%!!{#{#!E%%%�&��$ [ O wN"cN >#:Dr[S��nnv~n PV=FfwN#+#""t"��#Z!!A$"$#!$p$!!""#####$#K!"("A! !c!ARB.8;V}ZB81D!![ F�F�2F�2�2�2�2�P�TF8*TF8*� 2�� P P:,0�<�� �`F�` 2� � � � ���o�l�2-+(&$!$! �d�88?1)FM#88?1*F88?1)FM#M#88�P� 88 ?1 )F M# 88 ?1 *F *F0F� 88 ?1 )F M# 88 ?1 *F *F0F�F� 7�� T�F�P�`�``�``�``�``�``�``�``�``�``�]� c�ZZ� Z� 'c� �PP� � F� �A� P�(2<FPJFPZdZUPKIFDB@><72-+(&$!$! � <�<0F� F��� �F�<� 0<�0��F� 1� T� �Y� P��8#�8�#��8#�� 8( �8 ��*� x�*� x�*� x�*� x�*� x�*� x��F� &" $! "'"$& " "'"$& " "'"$& " ��O�L� K�F FF F�3T�0�3T�0� � F� � <0� P�� F � <� 2� 2� <�  F� �P� FF$$��     � 0�0 �� �r$$���  �! � r�$$�� � �! � 0��0���T�<$� <�|��T����(2<FPJFA<72-(#� �2�P�<�(��� T� �TF8*�TF8*�TF8*  � 20� (��2� ��2��2����88?1)FM#88?1*FF0#M� �T F88T * *0#�  �#�`�T�(2�&-���� F*� <& .5 <JO6$0� `� F??F*?811#��8� T� � �?��8� � 1�� *� � #� � � � � �l�88��KF�H�F�F�� T�P < (  �T��?�1�#�� � T�#� � *�� � *� Y��1� ��1�8�8�TF8*� * � ** 1 � 11 8 �08� * � ** 1 � 11 8 �08� 8� �48�0��8#�8�#��8#�� 8� 8� 8��M�Y�Y�Y�Y�Y�Y�Y�Y�Y� 1� T� �#� � � A��??�F� F� F� F� F� F� � ##*� � � � � #� � 1� � 8� � ?� �� >� � >� � S� ��F�Y �YYMF?8�*##�FF?8�??81�F$�**1##188??F� 8 �8 �8 �8� n�'n�$� d�d�� 8#� *8��@@6@Q@6@Q@l@MAhABBBBBBCElIElIlIOOOO \;\nnCuCupuux[xÂނTT007vv���jjj/j��&p j@ &� j�  j@jp�&pjj UP�2e2Ler��������1 �z$zB�C ��{4.�����������z?1��@!�zf{?�1����������$] =pBԒO/ 1ӖNԖ 0 ܿ0 :RӖ&1o02/A�4@!>"!?R% `P&-AB�5.$`>#U O_/TT~ҶB0MnNe# NB0/?/3# ?C1��������2#�>! QO"01L+N}1*?C-// /@#/OP A4,*[+k.",<"2�]z]ӣ;l",z,ԕ/P2�<0>/Y.Nz<NĒ*]�M0[]?-z]-?�N LM0zm�<?�>1MM@{]<>��������A1DANC,!A1DAN��������jDDUUUfffzC4C4CDCCzDCD3D3C3vUUDDDC33jTEDD4D33ZweuUeVTUZTUDUDEDDZCT34C$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>-.,=@.%/ ��İ:`дO�E--ĠԵ2/?�N�# M,K? M 0* /1<:/O.l:LlO]a;�"ޠ,= -m[\?N] ��?OO:% /?ÐL0>� -.�ϐ%0�  CL00_>!Ґ !Pр)/�@M P>0,n/� $[�N.�;ҀK?2�pL/"3pD.0..�.p9~1p<NNm !1�p/?�@/�M!p�L �@ ` <N*[p]R!p0 |?NpNp�?`2�"p.`;j-!`<?`0` Jp` /`2n.Pq,`�-`�P"*`1Pk>�P.\N�P>>-L>@a @,\ @"L$@@N#�0,_[_0L=0OM0�l@.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݊�?zE�14->/"/!#&"A51 " ?Q�5` A�Q>`$ GM3?%"/34"Bϊ/*". C?F/C7aA.ъ/�"�� P"e�FR�"WAE?� ﻊ. 30@d�!�$e%.""VA"z D-͊��켊z Sz1BDS3zAv5fU0#EB�z2ˊ.�zDCz435gS4$S!!j%CW-� Ί zBzT?z#!5EC2zECDCjd$2"!z�Uz˾ڭzj#3Rz�"#3D z#$C3Zgc4AC/z2$1z! zj�""z"#Cj5DVEUDz� $z@1j.ɫj/ܙZ!!j�"EfBj#C3FfCj# 3�Vj@W@ʾjjܫZ#/j�5UTj"!#Egej2"#Fj0V@۽j!j캾jj3ESz�4Cj!D2Dj/VAj!j!ۛjj#DDz!��DCj0�#U23j VRj#zj�j�"5Tz!���D3jB�4eB2j!fRjD.zjj4Uz!��TBjA 5v13j �WbjF/zj j4Ez"�DCj0FeB2z41jF>zj ˼j�#4Tz!�4Dj0Fu23z�41jU/z!j ʼj#$Tz"��ECj"Fv2#z�4AjV/z!j˻j�$Tz"��D3jCFv2#z�41jU>zk˻��������D��C eC "�S ��������z�0!-z#%zm@B$Dz"z@�$#""�#�"z!1݊�!T?z=BڜP�!F"B݊U/g,#33"D/DR̚C Da�g?&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 "# CTS2C�3DU0"��$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КEBEA416B�DBE032E1�D1C�D U D!C�3" 41v2 u3 3!�u!!S/" 242S2�""B!! !�#C# D!B1#B3D!zu"2#12 D!zT"3."#C zS!�42�#Dze#C.2�Dzt#0ڰd.B#C zf$1ٯT#.C$C" 2� 2$.24-C#2�1#�$.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"2���������h^1t S.F�!�� 22"CGk CL2Mn"<`2 #0E+m$ݨ@-QN�C"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ޘ> 6O<DZ�.AӨ  ; Bae0oV!.0ܘnC%M9$S%ܘB # RK//  !S4s#5T|1.N!?2#0ޘUR/D!N2._# " A^01*<ΘA%;@dO0��_G ?D̔.&LaB?2�-e?Cި 1$OB�T/.C5/a"4 O"��1.t&>D 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 N3�3� D,!�.Q Bވe1#"B�5= ܈ $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Ј!1�xTlA1"$14 .x N`!2A4x7<"3 xPۯ3NC -x.1Rx6^bxOU 13x%P/xR/3?h0&S2BxO/x/. 0��x$4/h2,6-x 2?-"xB3x"#.F xA x?"!6xc1xO30x/e#x.=xOxR=1x2/x$?0!x62�x6x>"<Rx1/xCxe1x".C1x@ Sx?/�4xQ2xRxS ^x !Px!t !"x /xN!x�Mx"_x#�x$ x%- x Bx>xE 3x"x!$2h,bx!ChTDh?$=h c1h_?h %<RhrTh?1!hV?oh Rh"!rhOF�0PhCd;@h!A0 h.^Qh3 @hC�0 hE >Ch�52h &^h0 hQ00hF."hRhEh-. hn ���h!th-E/d%*hA!h$3�hP1h/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�`X��X$��H31OX!� 2H H!OCHSڰR H  #H ?SH#�3H$OH-A "HB1H>2BH�!0H�/,H AH@3D1!8WA�5 H!% 8# $P8PCH B 8D�R 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�!� 0A0�1@"�/��" ��? ���6 �-��O�2�� 1� 2/1���^ ���! �CB������5D"E�����2#C �� ����"D����!�����B��������2��������������"#DC#4DC������4�3#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 ۿ]N1�A!͐M-n]D%fE;P0@ [\L !.,2`RNN=42_U""@a  0->A"N =C /A�0=ߔ].�1ѐ1/DB� -0---OO.&-DM23/��- 0<O>0M� ],Pl]m /"c`B $D0τn$23?!߄k6C$dF4WT%Ѐ/3]t1">>EcR=O  #EUDS/!?2B�ھ#�41 "tq@It@p $Tt`-1/"tѧOK# -/tL!.p�dtlNpSQڽ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/P�DoPVT"D4@PPDq+4n*/D"@,D N/4N,<D+1.4> >B-0 5 Q!4@4� ?$`< A$- - /S  !�3 _nk@/ .� ���! @����������������������������������������������������������jaͯ jjEFUuCjSݯ jj55VTuDkb͠ �������� *  �,=L��/6Q ?@@>1�= &-^-, >�ܶ>//tA^�,"] .?=O�>� /n2a_1�1NMN!A/ S>λ=_ao1>Ŗ!</� �  ]-;,/>Ѧ;�2K��MJ+%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 _J�OQ泦?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- _ >�<!\[]$ʮΒ1O$. ?߮,UTBb/.]!!O!3�!,-.,?+! %/ ; .& oKaJ$. m�?�N;Q1 C^"$4#A-Tg6 >>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@+P1�EB/N,N/% _B #2!A/OAЂ0/4�˼0�Q҆:#/v AGĶ A1v]Wz<$v+|?>ON?#reBQ$-3v!@J-v!vP-aІ!/r M/v ;T�@"rO�2E0_/��rE!RvO,�v3 v> v"/.v/b0/FQrrͭv3v;"?f?[A�2f! =bϝ›vM�$b/@3fA=bt?f�0L�Mbb%b�Rv\sbRD-޾V O3@3f?f# f>"fM�f@ f!@/bC1$#"fMfA�>2V\< b3V>V=,Nf�RAU3RGT+0əV03CV! 0@V.  V"AVV>AfV1�/1RT��R$V! -4�F:U R�CܼR1�%UCRT� 2V#! V@AVBV"3F`4V A�FrFQ4F0rF GFP!"!V 1!F0t R�3#FrV4FR�2F@q #FBc Fa%V AV3Fb�CV A�V3Fr�#V A�F u FQ3V AV!2Fq3V AF1e Fa#VAF1eFa3V AFAe FQ�2V AF1eFa3V AFAeFa3W A���������,.,1"#"^2�s2"""2""xED4342#"�M�2��!0tqd3"�/xPpR�'$ 2"�$?"�!tBe$5o%Dd$BA# ChPB]C>x�>x-x޳xxd/d ` !hKO\dC4ARBE3dA$>F�h-0OBhA"dDQ dC!A3?hSF O=D�dBAQ$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#B3�x멻ax�!x"A4D"dxCB!Uc"x�1?݈�x413D$5tD22""x�x d1x2"C0!3Dx2TfD@=#hd">@9ܼxx�h!P@x#4U2T2Ux!"!4 xxx#0"2Cx4CCC#1h@!!hhڽɿhAx"231344x4""2��hh̻ hURhV@!%UUSh3EC32!#h4 h˽h�#h$34EEhdT53C#"!X" �= hݭhʽ�h�"3%Dx"3C""h1!hܻh�XACSDTh$433!2d"3hhX%Vh"#D2D3#Ch4!"!"Xά˙X˛ͼX� 2h!"33"433XUUceTT2X��hX!!X3$CTTXTE3Uc333HC32ͽX̽˺Xh!#C34XeWEE333#Hv!ܽXH̬X�33X4$EC4E45XU4"!X۬X̼X2"C3XCDDD33#2HVvVU#2XXH#D3X"DC3TCD3XC321�HܺͻXHX14C33XT4C3533"H#ۻX̻H!H3TEWgfFeHSSC4##""8#H˜H̺X�""34X3$3C323"HE12H̻˺HH#"3CHBDDDUEDeHCST2"�H˻H˻H�3243H3CDDCS338uRD22�8 ͻH̼˼8 5H2FDUUVEeHED4C"!�HHͼ(<!2C83#4D5FEE8vUVeVeUc8P1 ޼H8H!"2C334C87dteDD$"(5ͻ8̻8H�� "##BH3CC433#!8D1!�8ʻ˫˻8��(�!@e5EV82334CDED8cC3C! 8ۼ88�!"C3D8UFFFETDC(dd#18(ʩ( $8##3CBcBS8cD3S22 (8ͽ(��$(BDDcEcGF(DVFcED3A(1�8(."(#4DVTvef(f7GCT3B(� ((޼($"4D(TTTuUsUS(R2" �(ۺ˻((##43(3CBC$2""bC13�((�#46F(33CD3C33Vd3R뭼( �"6#1T2dFFFftdVCE1@0�̬(544$$SCbRCC$!Q@! �1$"CRED64CC3!1��1�A##4%"!22$!!�� 1R%$aE5T5$C3! ���  ���!"#$25RB3$����##D234"3"!43#3$3CTD4RB"�������!! ��ͼۻ����3DEEUUDD42"�����""!�������������������"�����2"!���ۻ���������""#3�2""�������������������������������������������������������������z120ߖB #@%ߚ�?ϊuBc#�@?/�"$4O4p/1�#�0/#@#z/UB102 _5, �=> #sU� 1]?ٚD='An�� =!\Ѫ0 P/ D"3$ Cm 3L Ϛ1%+*G �!B �"2��? 5 ,,/�L4�b00Ѷ���� 5+���/1q/� 3C2JQҺ/.�/Զ00, �2���J��N����@]1N�{>5�/\?4! V�,!����m5"벰 ϻ 2/\1��" #a,� 2�T��� R"!0?0-2/1!�2n�O��o a��C�R"�>PO- ��%.!��. ��,к?���1.N?�k �=D�Ϻ?#?3  B .��^ ��O �*��"�"<�,4ү"[ ]=4���C.��+R2*Ѷ�>c�� �>  "�/�@?_�6, S$��3A�R-!��L�0���l���1� -�/A 2� 3�!� �� �%��� N> P#% 1� #���������l;˴2.>�ߤL!#S�>YQ10!/1ӴO  !/!0SQ?10AC/<"S 0?%dN0Q�/-? ,ӰT#$ݾ ?,`1.o = 0 Q,$?:@"2!3�B� 2/3�2 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<Q�>? 2^"ĥO ?S5C$/,L=20"a /Ӱ 0.MN>-A0@ д=MMM=N@ !�C5!ONQC@!/a0?><=.DD;.M0 B6O!1߰B@ .A/ \=35#+2C"4D?AmN@1�3 Q=а@$B1�C!#� ,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"P�1�>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�������������������������������������!�A�f ̈q���"���"!�����hm$42#BX2ChX@P���hNm t<X HDH4MfE"e5X"A?1H� /H �H H>H1_ H_/SL1D 5*Vx`���DD���4 Z�xb����HB*[X�X� 4DC!!x7z���X2hXA43X336A3@&X. Xx�#CQ,""x2  XXhy] h?! !$N�=6���X?p2 ! 1! +�FfeDC2=��>�bM?��]KD1��x" �� R�h1@xO� C" Q?!*դ-AO�4?&������@>>OA&P/> 41ۻO2!� Na��#O�."!huh̼5�Om%%Etx�!�� N�hH ���>."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<!O Ј!x==, QDx/ -m_ @CD33S%5!x x�t!߻x1ݔ""1  ,do$Mބ, �>^5",">4 !O  N#� @x�\M0?/\ �@ @:t6a?-�!>xRo{*N xox�OK��̈́m_@0�0 >„^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="d�d=<$�T7bNdNdCTd/�ݳh>!?�Md4h?,?d1d^?!O?#Ld.@Tl!d,d hM>X# d =d d"0T"=2 T� TT�1�.X[{dB#! �T?. T;h>,?X@Sd ?�X^n1<.STA3X<-dX.+^h�/ dO TD""4_T<K9</HQ/,T 34$OaTQϰT]`TD3??X# >�T,-OT->!X/OT TL� TT�H>5X<\Z0 H$ ,֑DE#5OX=A-TDJE#bX!�?.D@! D D`?&H�N DC4$D 3@XT "H0;"D@!2T� �D =D H>�MH 40l,H�>OD? �D @#D223D<\D�0H�>,T<?D<k?.H-\1^D4:>0OP4 r<4м-VC8.#4 Ͱ8�4 D�0 #T_�DLmP@Ca .?@P"3#D0=4D24P4.?`8 44�44_0r4D�4QS/2 8*?> ^8?/4�P@0$=޲O4!$^@.$$S_%.aA$M0n�(="4�@ 4O.$E�$_�@$11>N(O�..M(<.-(/$.45/20 $E!#-M<> N�,_�><O�D@R � - � //`.? � ��>@Π��@ 1����!@O"�.��@^!1� ��004B1@20���P���/��������������������5TDD�T4"!��"3C4T�EDDD!�����������!"""""�""���������������������������������������������������������������������������������������������������������������� .<xS2$=� + �2,@5@@/B@Q�b>Dm@,$?"- .4$<˜=A##=ҨϘbE @4?5!"ߘ" R?F  Tb?=?͘s.AgB�Q!! "^ވ^=\"6E=�2!%��$  .� !�BO 5 3.! !2!6!V@5  1.>S�-!2R!�!""�-  =A-ˆ_NG+c3$0S�܈%]RΈ4>!A""#-!3Bߘ"$eWnT�3-P�C"-���Ef7l@A+ >Έ#PCNB� „T�;$2�-<xg!S?2 x`VA; �QC[$0 DA Q߈!W?T?@ @.+@ /" "U 2, 3  $  4-2>Q!Q .3-xU.4$>ވBO@�BO�x�t.ֈN>?E/D2A3C4"" 2$B-Ax2" <x./x&OO!1t@!x4 R�xL~ψ$. xT1@x!$ xT/xF?bx3 40 xV2xO x/߈D !�x$/# x!Ot!6<b�x"$.TxA/x1x� $x `xw /Ex0F >%x/"x"""x4 x@Ccx##1x 2$t%+S x!x^$"0?x%Cx #4x�x04?x_2.CxD2x#h G=x/2h<ESBx%S h@$.RxBhC3hA fS0h2"dSx1 x.x"x1xf x$?!x!�xx`E/x312hE.ݻAht 3!#/xB��"x2%@de_ x"h ?/hQC2!h�"C20hB0`h5?ʮ%h@/6x/"hf?BxSAhC�̺.h=!X#�5 %ah d3!XCEBX@h3.h?ux"Cx1""h#ܿh!��X&N"!hS/4hE1"�Xh�hA3h#2#! hWA6Tx"hQXE@h !�$Bh �%?h !X !h�" h"$ChDACh Ah��X"�.XCD/"! Xug3X&N3hCh��/Xs4 dX�"gBX5?#!�XFXڼ�X>#DHc$e$T/hBX# X2ܻAX�B �Xe 5D2X34?X " X!!H�#33X!�" VQX�5QX#0"XH01X�D3H/6RD?˾H't�H ۼ˪Hd H.EUB2 X!43!X3H3ښ!H/%B!8QEX"  �CHA�HA 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�� .$����� C0���3"!"23������������"# ��!������������������������������������������������������:!":1Jn""J5 J̹&uDJ31 1J�0$JjC fP˼32Z##0�"zTj2j#0zWbj"4�j3!Ί51j"B# �j"3!z�5bj3!!��j�$ Qz"�Z�5SB?���A��Z=#Ue3?��a����j0�342��S!��j/�#E2�FR�j�52"zǚT�jC5�w �j�Df�렪4��j5wz!ڬ%Q��j$Vz!��ۚE/��jP�Dz" ܚ50�jO4{# ����.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ê�� <<2���2 )� Ɍ Ɏ ɐ ɑ ɒ Ɏɓɓɓ Y _ Y _ Y _i Y _ Y _ Y _ Y _n )A ɓ ɕ ɜɜɜɜ ɜɜɜɝɝ ɝɝ$A ɜ ɝ ɤɤɤɤ ɤɤɤɤɤ ɤɤ$A ɗ ɘ ɡɡɡɡ ɡɡɡɡɡ ɡɡ$� ɨɠɡ ɨT ɪɭ ɴ ɯɭ$� Y _ Y _ Y _������j����`������`��� j@������������/��������/����������������<��F ��� ,���������������������������������������������������������������������������������xid6(������ �Nintendo����0��j�3�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0231862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/data/test.vgm�����������������������������������������������������������������0000644�0001750�0001750�00000005105�00000000000�016244� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Vgm A ��P��6�����M �����������<��� �� u����� �����������R(�R(R(R(R(R(R"�R'�R+R01S04R17S11R2RS21R4PS4TR50S5PR64S6PR8RS81R90S9RR:XS:RR<0S<QR=1S=0R>4S>0R@S@RA,SARBSBRDSDRESERFSFRHSHRI"SIRJSJRLSLRMSMRNSNRPRSPRQSQRRRSRRRTRSTRUSURRVSVRRXSSXRYSYSRZSZSR\SS\R]S]SR^S^SR`S`�Ra SaRb�SbRdSd�ReSeRf�SfRh�Sh�RiSi�Rj Sj�Rl�Sl�RmSm�Rn Sn�RpSp�RqSqRr�SrRtSt�RuSuRv�SvRx�Sx�Ry Sy�Rz�Sz�R|�S|�R}S}�R~�S~�RSRSRSRSR?SRSRSRSRSRSR/SRSR�S�R�S�R�S�R�S�R�S�R�S�R�S�R�S�R�S�R�S�R�S�R�S�R2S+RS2R*S+RSRSRS-R�R�R�R�R�R�R<SRS<R,S<RSRS@RSR(R(R(R(R(�R(R@S@RDSDRHSHRLSLRASARESERISIRMSMRBSBRFSFRJSJRNSNR+�R(�R(R(R(R(R(RR05R8rR4TR<FRPRXRTR\R`Rh RdRl Rp�Rx Rt�R| RRRRR@#RHRDRLRR(�R#R-R(OPPPPPP�PPPPPRtR15R9rR5TrR=FRQrRYRUrR]RaRi qReRm rRq�Ry rRu�R} RrRRrRRA#qRIRErRMRrR(rR"rRR(rRqR25R:rrR6TR>FrRRRZRVrR^RbrRj RfqRn Rr�Rz rRv�R~ rRRrRRRB#rRJRFqRNRrR(rR#rR/R(rS<qS01S8RrS4PS<0rSPRSXSrSTRS\SrS`Sh�qSdSl�SprSx�StrS|�SrSSrSS@qSHSDrSLSrR(rS#rS-R(tS<S11S9RrS5PS=0rSQRSYSrSURS]SrSaSi�qSeSm�rSqSy�rSuS}�SrSSrSSAqSIrSESMrSR(uS*SR(tS<S21rS:RS6PrS>0SRRSZSrSVRS^SqSbSj�rSfSn�rSrSz�rSvS~�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$R<qR(rR(rR*RrR(rR(qS#SrR(rR(rS+S-rR(qR(rS*SrR(aR(uR(tR(a R(�rR+rRR(rR(rR*qRR(rR(rR+rRR(rR(tS*SrR(R(uS+SqR(R(uS+S-rR(aU PPqPaPPrPaPbPbPaPPaPbPPrPaPbPbPaPPaPbbPPrPaPbPbPrPPaPbPPrPaPbPbPaPPrPaPaPPqPaPbPbPaPPaPbPPrPaPbPbPaPPaPbPPrPaR(�rR(uR(rR(qR(rR(rPaPbPaPPaPbbPPrPaPbPbPuPPrPaPaPPrPaPbPbPaPPaPbPPrPaPbPbPaPPaPbPPrPaPbPbPaPPaPbPPrPaPbPbPaPPrPaPaPPrPaPbPbPrPPaPPrPaPbPbPaPPaPPrPaPbPbPaPPaPPrPaPbPbPafGd3 ������C�h�a�o�s� �E�m�e�r�a�l�d�����S�o�n�i�c� �t�h�e� �H�e�d�g�e�h�o�g���0000000000000��S�e�g�a� �M�e�g�a� �D�r�i�v�e���00000000��M�a�s�a�t�o� �N�a�k�a�m�u�r�a���-NQgckN��1�9�9�1���-�D�J�S�W�-������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0231862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/data/test.wav�����������������������������������������������������������������0000644�0001750�0001750�00000005614�00000000000�016255� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RIFF ��WAVEfmt �����+��+������fact��� ��data ��~~~~~~~}~~~}~}~}~z}~~|{}z~~~y{|ywx|yx|}}}|~||sqrqplosmmoqvsnotw{}|toohdgggefnu~{|wuookflnou{y}|swqolegijsxxz|rrwroghmnq~~xu{yrkkqux{v{wwwnrvx~x}przstoqytuwv~}knljuqvy~s{zzzikhetqt{x|xx{jkfeutpyvzzykjekvpr|z{}tnhgtvu{xx|tommutwzvvu~iinvvnw{yypqsuzrs{szwnvwwtp{~us|rm~zxpo|~xkr}p|}vj||zqrvw|}~qu}rmptt{zvzwsqm|uzy||y|uqqw{{{rwrp~xwqgyumg}{p}kmmj{ptsurszt|vrolifoph`|nbrq:wrb^kglflH\|jtvPvzxrLf|rvl^npeHZzdȇcy_^RGFseȋ}el_XJXGƛ`ƍqbxmdEkiLkkda~uKKU[nj_{i{hvf?pcJdžc|`nbZOCVRrhɷxU`YVPUNƧWЕai|ulIULy̳aٞcxswgD]BoroԼfVYMV[GWodsL~rO^mNj]}̗^VcN\|qR҄_bzjS\NcʣYTy|YNdcOir͢TYWXvznH\häSZ_O_}sCzrSlTjO`pyAldzϜMpFV|yjN}h`W^Osz|xPqPjIaIiUXǎMӈIxNVw|FcmxP[Ln}mej]c\^rzZ{sk`]Upxsn^yu\fS`PqzfT~paaLYsnveuoxZb[xyxhvfvX_Tqoq~w}^nQa}sibkr`o{Jkbeyv~z{]ziczq~ur`rX[o{vun\\epqquezkYvpqvwqxXpgVppo{qqaVWKntqyragWS_xjorqbǁTYYqorrovvoTmsQi{wwzoVsSf^{v}}hck_y{{yv}xspjWvqV|jqor}qtcw_iduok{{h^{riy~u}xzZf^[wtz{ozyelg\uek{qtyv{`Zk`{}pjs|{ze[q]rl{}uugy\qb|uu{y~xwtl`x]ypnztvyy{nfxYhnvw~|wynuh~stx|||goj]wqpopyhwvi\yxWiins{tqxj}gektbkwrpryx{}re|`z~khpsrpszzsptbrpbnuqmt{}suouftxpprxnrquztqqqvxxy{tpqpulpuxxr|}~usrt~vot|wpyyrn~rtu~xvurt|ysx}}xtqsxxrpru{{x}vvoy}poyytv|~~}w{q~koyvmt{vtz|{xqx|tv}}z|{vsxz{yzxu}ystxwxyx{~~{tuxrnstruz}~}zwwttutsv~~~~}}yxwwvuw{zx~}}{~xw{|z{}|}zxzz{{|~}}|z{||{|~~~~}}~~}}~~~]LISTf���INFOIPRD���foobar2k-album��IART���foobar2k-artist�ICMT���foobar2k-comment��INAM���foobar2k-title��id3 ��ID3���� TXXX���G��C�U�S�T�O�M�_�N�A�M�E���f�o�o�b�a�r�2�k�-�C�U�S�T�O�M�V�A�L�U�E���COMM���,��eng��f�o�o�b�a�r�2�k�-�c�o�m�m�e�n�t���TIT2���!��f�o�o�b�a�r�2�k�-�t�i�t�l�e���TALB���!��f�o�o�b�a�r�2�k�-�a�l�b�u�m���TPE1���#��f�o�o�b�a�r�2�k�-�a�r�t�i�s�t�����������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0231862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/data/test.wma�����������������������������������������������������������������0000644�0001750�0001750�00000105162�00000000000�016243� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������0&uf��bl���������3&uf��bl4������� �����t�e�s�t�����������ܫG� Seh�������CO;J)rJX������9.@ �����������<������������� �� ����_.� Se������ӫ� Se���FC|K)9>A\.��������s�k��� e�n�-�u�s���]&EG_eR�������ů[wHgDLz�����������4������D�e�v�i�c�e�C�o�n�f�o�r�m�a�n�c�e�T�e�m�p�l�a�t�e���L�2������ �����I�s�V�B�R�����t E˖p����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������˥r2CiR[ZX��������������������������������������� �������.��������� ު|O(Uݘ"�����������������#DIANEpT���������@�^P���������W�M�F�S�D�K�V�e�r�s�i�o�n������1�0�.�0�0�.�0�0�.�3�6�4�6����W�M�F�S�D�K�N�e�e�d�e�d������0�.�0�.�0�.�0�0�0�0��� �I�s�V�B�R���������@Rц1�H�������ARц1�H�����W�i�n�d�o�w�s� �M�e�d�i�a� �A�u�d�i�o� �9�.�1���$� �6�4� �k�b�p�s�,� �4�8� �k�H�z�,� �s�t�e�r�e�o� �2�-�p�a�s�s� �C�B�R����aܷ� Ser�������@iM[�_\D+Pÿa�� ���������������a���A�� � �����*�� ��u{F�`ɢ �����������6&uf��blv������CO;J)rJ ���������]����U���� ���� ��% "" w=  ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������]U��U���� ������AA����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������]��U���� ��+��(��AA����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������]��U���� �� ��8��AA����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������]U��U���� �� ��H��AA����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������]��U���� ��+ ��X��AA" w=  ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������]��U���� �� ��h��AA����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������]U ��U ���� ����x��AA����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������] ��U ���� ��+����AA����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������] ��U ���� ������AA����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������]U ��U ���� ������AA" w=  ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0231862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/data/test2.lnk����������������������������������������������������������������0000644�0001750�0001750�00000001034�00000000000�016316� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������L��������������F��� ���J1yJ1yJ1y�����������������������B�@�2�����(EA{ �AEE0~1.TXT��&���(EA{(EA{����&.�t�x�t���������$������$���5����������d������������ ����C:\Documents and Settings\test\Desktop\??.txt�C�:�\�D�o�c�u�m�e�n�t�s� �a�n�d� �S�e�t�t�i�n�g�s�\�t�e�s�t�\�D�e�s�k�t�o�p�\��&.�t�x�t������� �.�\��&.�t�x�t�&�C�:�\�D�o�c�u�m�e�n�t�s� �a�n�d� �S�e�t�t�i�n�g�s�\�t�e�s�t�\�D�e�s�k�t�o�p�`�����X�������xy-fcf85a601536�[]SK)\(0%ܾl7�'$[]SK)\(0%ܾl7�'$��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0231862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/data/valid_feed.xml�����������������������������������������������������������0000644�0001750�0001750�00000012614�00000000000�017361� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="UTF-8"?> <rss xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" version="2.0"> <channel> <ttl>60</ttl> <title>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 ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540386.0231862 quodlibet-4.4.0/tests/data/with-id3.dsf0000644000175000017500000000217300000000000016702 0ustar00lazkalazkaDSD {\fmt 4+data ID3TIT2 DSF title././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540386.0231862 quodlibet-4.4.0/tests/data/without-id3.dsf0000644000175000017500000001013400000000000017426 0ustar00lazkalazkaDSD \fmt 4+data ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540386.0231862 quodlibet-4.4.0/tests/gtk_helpers.py0000644000175000017500000000103600000000000016521 0ustar00lazkalazka# This program is free software; you can redistribute it and/or modify # it under the terms of the 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 ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540386.0231862 quodlibet-4.4.0/tests/helper.py0000644000175000017500000002107000000000000015471 0ustar00lazkalazka# Copyright 2013 Christoph Reiter # 2015 Anton Shestakov # # This program is free software; you can redistribute it and/or modify # it under the terms of the 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 from io import StringIO from gi.repository import Gtk, Gdk from quodlibet.util.i18n import GlibTranslations from senf import fsnative, environ 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 = 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(environ.items()): if key not in old: del environ[key] for key, value in old.items(): if key not in environ or environ[key] != value: environ[key] = value @contextlib.contextmanager def capture_output(): """ with capture_output() as (stdout, stderr): some_action() print stdout.getvalue(), stderr.getvalue() """ err = StringIO() out = StringIO() 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, **kwargs): """Creates an empty file 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 fd, filename = mkstemp(*args, **kwargs) os.close(fd) yield filename 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)) ././@PaxHeader0000000000000000000000000000003200000000000010210 xustar0026 mtime=1614542835.18547 quodlibet-4.4.0/tests/plugin/0000755000175000017500000000000000000000000015136 5ustar00lazkalazka././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540386.0231862 quodlibet-4.4.0/tests/plugin/__init__.py0000644000175000017500000000313600000000000017252 0ustar00lazkalazka# This program is free software; you can redistribute it and/or modify # it under the terms of the 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 ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540386.0231862 quodlibet-4.4.0/tests/plugin/test_albumart.py0000644000175000017500000000236300000000000020362 0ustar00lazkalazka# 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() ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540386.0231862 quodlibet-4.4.0/tests/plugin/test_bansheeimport.py0000644000175000017500000001014700000000000021412 0ustar00lazkalazka# 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 sqlite3 from senf import fsn2uri from quodlibet.formats import AudioFile from tests.helper import temp_filename from quodlibet.library.libraries 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) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540386.0231862 quodlibet-4.4.0/tests/plugin/test_brainz.py0000644000175000017500000003242100000000000020036 0ustar00lazkalazka# 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") ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540386.0231862 quodlibet-4.4.0/tests/plugin/test_clock.py0000644000175000017500000000207500000000000017646 0ustar00lazkalazka# 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() ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540386.0231862 quodlibet-4.4.0/tests/plugin/test_console.py0000644000175000017500000000203200000000000020206 0ustar00lazkalazka# 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.formats import AudioFile from quodlibet.util.songwrapper import SongWrapper from tests.plugin import PluginTestCase AUDIO_FILE = SongWrapper(AudioFile({'~filename': "/tmp/foobar"})) 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() ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540386.0271862 quodlibet-4.4.0/tests/plugin/test_cover_download.py0000644000175000017500000000272300000000000021560 0ustar00lazkalazka# 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() ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540386.0271862 quodlibet-4.4.0/tests/plugin/test_covers.py0000644000175000017500000000245400000000000020055 0ustar00lazkalazka# 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 senf import fsnative from tests.plugin import PluginTestCase from quodlibet.formats import AudioFile class TCovers(PluginTestCase): def test_cover_path(self): song = AudioFile({"musicbrainz_albumid": u"foobar"}) song2 = AudioFile() # missing Soup if "lastfm-cover" in self.plugins: cls = self.plugins["lastfm-cover"].cls self.assertTrue(isinstance(cls(song).cover_path, fsnative)) self.assertTrue(isinstance(cls(song2).cover_path, fsnative)) # missing Soup if "musicbrainz-cover" in self.plugins: cls = self.plugins["musicbrainz-cover"].cls self.assertTrue(isinstance(cls(song).cover_path, fsnative)) self.assertTrue(isinstance(cls(song2).cover_path, fsnative)) if "discogs-cover" in self.plugins: cls = self.plugins["discogs-cover"].cls self.assertTrue(isinstance(cls(song).cover_path, fsnative)) self.assertTrue(isinstance(cls(song2).cover_path, fsnative)) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540386.0271862 quodlibet-4.4.0/tests/plugin/test_custom_commands.py0000644000175000017500000000447500000000000021754 0ustar00lazkalazka# 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", library=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) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540386.0271862 quodlibet-4.4.0/tests/plugin/test_duplicates_browser.py0000644000175000017500000000376300000000000022460 0ustar00lazkalazka# 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() ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540386.0271862 quodlibet-4.4.0/tests/plugin/test_fingerprint.py0000644000175000017500000001406100000000000021100 0ustar00lazkalazka# 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'}]} ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540386.0271862 quodlibet-4.4.0/tests/plugin/test_html.py0000644000175000017500000000234700000000000017521 0ustar00lazkalazka# 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(" # # This program is free software; you can redistribute it and/or modify # it under the terms of the 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 @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: 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) while Gtk.events_pending(): Gtk.main_iteration_do(True) 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") ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540386.0271862 quodlibet-4.4.0/tests/plugin/test_mpris.py0000644000175000017500000002114000000000000017677 0ustar00lazkalazka# 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 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() while Gtk.events_pending(): Gtk.main_iteration() 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 ././@PaxHeader0000000000000000000000000000003200000000000010210 xustar0026 mtime=1614542835.18547 quodlibet-4.4.0/tests/plugin/test_plugins/0000755000175000017500000000000000000000000017656 5ustar00lazkalazka././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540386.0271862 quodlibet-4.4.0/tests/plugin/test_plugins/pickle_plugin.py0000644000175000017500000000141400000000000023055 0ustar00lazkalazka# 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() ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540386.0271862 quodlibet-4.4.0/tests/plugin/test_prefs.py0000644000175000017500000000261700000000000017674 0ustar00lazkalazka# 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 ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540386.0271862 quodlibet-4.4.0/tests/plugin/test_query.py0000644000175000017500000001155500000000000017723 0ustar00lazkalazka# 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)) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540386.0271862 quodlibet-4.4.0/tests/plugin/test_randomalbum.py0000644000175000017500000001042200000000000021047 0ustar00lazkalazka# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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)) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540386.0271862 quodlibet-4.4.0/tests/plugin/test_rbimport.py0000644000175000017500000000503000000000000020403 0ustar00lazkalazka# 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.libraries 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) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540386.0271862 quodlibet-4.4.0/tests/plugin/test_replaygain.py0000644000175000017500000001363300000000000020710 0ustar00lazkalazka# 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) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540386.0271862 quodlibet-4.4.0/tests/plugin/test_seekbar.py0000644000175000017500000000124600000000000020166 0ustar00lazkalazka# 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() ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540386.0271862 quodlibet-4.4.0/tests/plugin/test_songsmenu.py0000644000175000017500000000506500000000000020573 0ustar00lazkalazka# 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) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540386.0271862 quodlibet-4.4.0/tests/plugin/test_style.py0000644000175000017500000000502700000000000017713 0ustar00lazkalazka# Copyright 2015 Anton Shestakov # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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" REASON_DOT = "PLUGIN_DESC should be a full sentence and end with a '.'" skip_plugins = L('pickle_plugin') fails = [] for pid, plugin in self.plugins.items(): if pid in skip_plugins: continue if not hasattr(plugin.cls, 'PLUGIN_DESC'): fails.append((plugin, None, REASON_ABSENT)) continue desc = plugin.cls.PLUGIN_DESC if not desc.endswith('.'): fails.append((plugin, desc, REASON_DOT)) skip_plugins.check_unused() self.conclude(fails) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1614540386.0271862 quodlibet-4.4.0/tests/plugin/test_synchronize_to_device.py0000755000175000017500000012741100000000000023154 0ustar00lazkalazka# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0271862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/plugin/test_synchronizedlyrics.py���������������������������������������������0000644�0001750�0001750�00000003270�00000000000�022516� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0271862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/plugin/test_test_plugins.py���������������������������������������������������0000644�0001750�0001750�00000001015�00000000000�021264� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0271862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/plugin/test_titlecase.py������������������������������������������������������0000644�0001750�0001750�00000003013�00000000000�020521� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0271862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/plugin/test_trayicon.py�������������������������������������������������������0000644�0001750�0001750�00000007111�00000000000�020377� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0271862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/plugin/test_viewlyrics.py�����������������������������������������������������0000644�0001750�0001750�00000003477�00000000000�020762� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0271862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/plugin/test_waveformseekbar.py������������������������������������������������0000644�0001750�0001750�00000003434�00000000000�021736� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2017 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 Gst from quodlibet.library.libraries 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0271862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/plugin/test_website_search.py�������������������������������������������������0000644�0001750�0001750�00000003151�00000000000�021536� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000032�00000000000�010210� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������26 mtime=1614542835.18547 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/quality/����������������������������������������������������������������������0000755�0001750�0001750�00000000000�00000000000�015330� 5����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0271862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/quality/__init__.py�����������������������������������������������������������0000644�0001750�0001750�00000000370�00000000000�017441� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0271862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/quality/test_flake8.py��������������������������������������������������������0000644�0001750�0001750�00000002602�00000000000�020113� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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)]) errors = o.getvalue().splitlines() assert not errors, f"{len(errors)} error(s):\n".join(errors) ������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0271862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/quality/test_mypy.py����������������������������������������������������������0000644�0001750�0001750�00000001406�00000000000�017740� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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. 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)) assert Path.cwd() == root.parent, "MyPy must be run from project root" out, err, status = api.run([str(root)]) assert status == 0, "Failed mypy checks: \n" + "\n".join([out, err]) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0271862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/quality/test_source.py��������������������������������������������������������0000644�0001750�0001750�00000010767�00000000000�020254� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2014, 2015 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 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_DIR 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_DIR))[0] @pytest.fixture(params=list(iter_py_paths()), ids=prettify_path) def py_path(request) -> Path: return request.param 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]) 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0271862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test___init__.py��������������������������������������������������������������0000644�0001750�0001750�00000003331�00000000000�017010� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0271862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_appdata_files.py���������������������������������������������������������0000644�0001750�0001750�00000003424�00000000000�020050� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0271862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_browsers___init__.py�����������������������������������������������������0000644�0001750�0001750�00000004405�00000000000�020741� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the 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.audiofeeds) 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_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.audiofeeds) 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0271862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_browsers__base.py��������������������������������������������������������0000644�0001750�0001750�00000016440�00000000000�020255� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2006 Joe Wreschnig # 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 os from gi.repository import Gtk from quodlibet.browsers._base import FakeDisplayItem as FDI, \ DisplayPatternMixin, FakeDisplayItem from tests import TestCase, init_fake_app, destroy_fake_app, mkstemp from .helper import realized, dummy_path from quodlibet import browsers 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() 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() 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_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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0271862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_browsers_albums.py�������������������������������������������������������0000644�0001750�0001750�00000017356�00000000000�020476� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 functools import cmp_to_key from gi.repository import Gtk from senf import fsnative from quodlibet.browsers._base import DisplayPatternMixin from . import TestCase 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_artist, 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_artist, [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): while Gtk.events_pending(): Gtk.main_iteration() 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0271862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_browsers_audiofeeds.py���������������������������������������������������0000644�0001750�0001750�00000003665�00000000000�021321� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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.config from quodlibet.browsers.audiofeeds import AudioFeeds, AddFeedDialog, Feed from quodlibet.library import SongLibrary 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 = AudioFeeds(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_feed.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() ���������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0271862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_browsers_collection.py���������������������������������������������������0000644�0001750�0001750�00000007156�00000000000�021343� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0271862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_browsers_filesystem.py���������������������������������������������������0000644�0001750�0001750�00000001461�00000000000�021365� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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.browsers.filesystem import FileSystem from quodlibet.library import SongLibrary import quodlibet.config class TFileSystem(TestCase): def setUp(self): quodlibet.config.init() self.bar = FileSystem(SongLibrary()) def test_can_filter(self): for key in ["foo", "title", "fake~key", "~woobar", "~#huh"]: self.failIf(self.bar.can_filter(key)) self.failUnless(self.bar.can_filter("~dirname")) def tearDown(self): self.bar.destroy() quodlibet.config.quit() ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0271862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_browsers_iradio.py�������������������������������������������������������0000644�0001750�0001750�00000012126�00000000000�020450� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the 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 quodlibet.util import is_windows, is_osx from tests import TestCase, skipIf from quodlibet.library import SongLibrary from quodlibet.formats import AudioFile from quodlibet.browsers.iradio import (InternetRadio, IRFile, QuestionBar, parse_taglist, parse_pls, parse_m3u, download_taglist, STATION_LIST_URL) import quodlibet.config from gi.repository import Gtk quodlibet.config.RATINGS = quodlibet.config.HardCodedRatingsPrefs() 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") 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) @skipIf(is_windows() or is_osx(), "Don't need to test all the time") def test_download_tags(self): self.received = [] # TODO: parameterise this, spin up a local HTTP server, inject this. url = STATION_LIST_URL def cb(data): assert data self.received += data ret = list(download_taglist(cb, None)) run_loop() assert all(ret) assert self.received, "No stations received from %s" % url assert len(self.received) > 100 # TODO: some more targeted tests def run_loop(): while Gtk.events_pending(): Gtk.main_iteration() ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0271862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_browsers_paned.py��������������������������������������������������������0000644�0001750�0001750�00000042424�00000000000�020274� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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 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 _wait(self): while Gtk.events_pending(): Gtk.main_iteration() 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") self._wait() self.failUnlessEqual(set(self.last), set()) self.bar.filter_text("artist=!boris") self._wait() self.failUnlessEqual(set(self.last), set(SONGS[1:])) def test_filter_value(self): self.bar.activate() expected = [SONGS[0]] self.bar.filter("artist", ["boris"]) self._wait() self.failUnlessEqual(self.last, expected) def test_filter_notvalue(self): self.bar.activate() expected = SONGS[1:4] self.bar.filter("artist", ["notvalue", "mu", "piman"]) self._wait() 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) self._wait() 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") self._wait() 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() self._wait() 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0271862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_browsers_playlists.py����������������������������������������������������0000644�0001750�0001750�00000033074�00000000000�021232� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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 senf import fsnative, fsn2uri, fsn2bytes, text2fsn from quodlibet import app from quodlibet import qltk from quodlibet.browsers.playlists.prefs import DEFAULT_PATTERN_TEXT from quodlibet.browsers.playlists.util import PLAYLISTS, parse_m3u, \ parse_pls, _name_for from quodlibet.qltk.songlist import DND_QL from quodlibet.util.collection import FileBackedPlaylist from tests import TestCase, get_data_path, mkdtemp, _TEMP_DIR, \ init_fake_app, destroy_fake_app from tests.gtk_helpers import MockSelData from .helper import dummy_path, __, temp_filename import os import shutil from quodlibet.browsers.playlists import PlaylistsBrowser from quodlibet.library import SongFileLibrary import quodlibet.config from quodlibet.formats import AudioFile from quodlibet.util.path import mkdir from quodlibet.library.librarians import SongLibrarian from quodlibet.library.libraries import FileLibrary from tests.test_browsers_search import SONGS 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) 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) 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) self.failUnlessEqual(len(pl), 1) self.failUnlessEqual(pl[0]("title"), "Silence") pl.delete() class TParseM3U(TestCase, ConfigSetupMixin, TParsePlaylistMixin): Parse = staticmethod(parse_m3u) prefix = b"" class TParsePLS(TestCase, ConfigSetupMixin, TParsePlaylistMixin): Parse = staticmethod(parse_pls) prefix = b"File1=" 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 = FileLibrary() 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.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")}) def setUp(self): self.success = False # Testing locally is VERY dangerous without this... self.assertTrue(_TEMP_DIR in PLAYLISTS or os.name == "nt", msg="Failing, don't want to delete %s" % PLAYLISTS) try: shutil.rmtree(PLAYLISTS) except OSError: pass mkdir(PLAYLISTS) init_fake_app() self.lib = quodlibet.browsers.playlists.library = SongFileLibrary() self.lib.librarian = SongLibrarian() all_songs = SONGS + [self.ANOTHER_SONG] for af in all_songs: af.sanitize() self.lib.add(all_songs) self.big = pl = FileBackedPlaylist.new(PLAYLISTS, "Big", self.lib) pl.extend(SONGS) pl.write() self.small = pl = FileBackedPlaylist.new(PLAYLISTS, "Small", self.lib) 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.bar.destroy() self.lib.destroy() shutil.rmtree(PLAYLISTS) PlaylistsBrowser.deinit(self.lib) 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): while Gtk.events_pending(): Gtk.main_iteration() 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) self.bar._rename(0, "zBig") self.assertEquals(self.bar.playlists()[0], self.small) self.assertEquals(self.bar.playlists()[1].name, "zBig") 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) # deletion of playlist tracks def test_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): pl_name = u"_€3 œufs à Noël" pl = FileBackedPlaylist(_TEMP_DIR, pl_name, None) pl.extend(SONGS) pl.write() new_fn = os.path.splitext(text2fsn(pl.name))[0] + '.m3u' new_path = os.path.join(pl.dir, new_fn) os.rename(pl.path, new_path) added = self.bar._import_playlists([new_path], self.lib) self.failUnlessEqual(added, 1, msg="Failed to add '%s'" % new_path) os.unlink(new_path) pls = self.bar.playlists() self.failUnlessEqual(len(pls), 3) # Leading underscore makes it always the last entry imported = pls[-1] self.failUnlessEqual(imported.name, pl_name) def fns(songs): return [song('~filename') for song in songs] self.failUnlessEqual(fns(imported.songs), fns(pl.songs)) @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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0271862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_browsers_search.py�������������������������������������������������������0000644�0001750�0001750�00000011207�00000000000�020445� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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 senf import fsnative 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 # 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.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): while Gtk.events_pending(): Gtk.main_iteration() 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): self.bar.destroy() quodlibet.browsers.tracks.library.destroy() quodlibet.config.quit() �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0271862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_browsers_soundcloud.py���������������������������������������������������0000644�0001750�0001750�00000005372�00000000000�021365� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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 TestCase import time from quodlibet import config from quodlibet.browsers.soundcloud.api import SoundcloudApiClient from quodlibet.browsers.soundcloud.query import SoundcloudQuery, convert_time from quodlibet import const from quodlibet.query import QueryType from quodlibet.util.dprint import print_d 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 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0271862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_cli.py�������������������������������������������������������������������0000644�0001750�0001750�00000001476�00000000000�016030� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0271862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_commands.py��������������������������������������������������������������0000644�0001750�0001750�00000007156�00000000000�017063� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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 TCommands(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) 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("rating 0.5") self.__send("rating +0.01") self.__send("rating -10") 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) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0271862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_config.py����������������������������������������������������������������0000644�0001750�0001750�00000005114�00000000000�016517� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0271862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_desktop_files.py���������������������������������������������������������0000644�0001750�0001750�00000003441�00000000000�020106� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0271862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_errorreport.py�����������������������������������������������������������0000644�0001750�0001750�00000006324�00000000000�017643� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0271862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_formats___init__.py������������������������������������������������������0000644�0001750�0001750�00000013546�00000000000�020554� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0271862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_formats__audio.py��������������������������������������������������������0000644�0001750�0001750�00000123761�00000000000�020256� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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 import shutil import io from contextlib import contextmanager from senf import fsnative, fsn2text, bytes2fsn, mkstemp, mkdtemp from quodlibet import config from quodlibet.formats import AudioFile, types as format_types, AudioFileError from quodlibet.formats._audio import NUMERIC_ZERO_DEFAULT from quodlibet.formats import decode_value, MusicFile, FILESYSTEM_TAGS from quodlibet.util.tags import _TAGS as TAGS from quodlibet.util.path import normalize_path, mkdir, get_home_dir, unquote, \ escape_filename, RootPathFile from quodlibet.util.environment import is_windows 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"}) class TAudioFile(TestCase): def setUp(self): config.RATINGS = config.HardCodedRatingsPrefs() fd, filename = mkstemp() os.close(fd) self.quux = AudioFile({ "~filename": normalize_path(filename, True), "album": u"Quuxly" }) def tearDown(self): 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 [Unknown]" % 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): self.assertTrue(self.quux.is_writable()) os.chmod(self.quux["~filename"], 0o444) self.assertFalse(self.quux.is_writable()) os.chmod(self.quux["~filename"], 0o644) self.assertTrue(self.quux.is_writable()) 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_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_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'}, (('foo',), (), 'bar')), ({'album': 'foo', 'labelid': 'bar', 'musicbrainz_albumid': 'quux'}, (('foo',), (), 'bar')), ({'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_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)) ���������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0271862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_formats__id3.py����������������������������������������������������������0000644�0001750�0001750�00000057744�00000000000�017643� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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'])) f['lyrics'] = u'modified lyrics' f.write() f = self.KIND(self.filename) self.failUnlessEqual(f['lyrics'], u'modified lyrics') 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0271862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_formats__image.py��������������������������������������������������������0000644�0001750�0001750�00000005551�00000000000�020233� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0271862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_formats_aac.py�����������������������������������������������������������0000644�0001750�0001750�00000004632�00000000000�017535� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0271862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_formats_aiff.py����������������������������������������������������������0000644�0001750�0001750�00000002074�00000000000�017714� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0271862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_formats_all.py�����������������������������������������������������������0000644�0001750�0001750�00000004652�00000000000�017563� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0271862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_formats_apev2.py���������������������������������������������������������0000644�0001750�0001750�00000015464�00000000000�020033� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0271862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_formats_dsf.py�����������������������������������������������������������0000644�0001750�0001750�00000004135�00000000000�017563� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0271862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_formats_midi.py����������������������������������������������������������0000644�0001750�0001750�00000002427�00000000000�017733� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0271862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_formats_mod.py�����������������������������������������������������������0000644�0001750�0001750�00000001566�00000000000�017573� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0271862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_formats_mp3.py�����������������������������������������������������������0000644�0001750�0001750�00000003737�00000000000�017515� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0271862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_formats_mp4.py�����������������������������������������������������������0000644�0001750�0001750�00000012731�00000000000�017510� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 import mutagen from tests import TestCase, get_data_path 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")) ���������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0271862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_formats_mpc.py�����������������������������������������������������������0000644�0001750�0001750�00000003300�00000000000�017557� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0271862 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_formats_remote.py��������������������������������������������������������0000644�0001750�0001750�00000001634�00000000000�020303� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_formats_spc.py�����������������������������������������������������������0000644�0001750�0001750�00000002532�00000000000�017573� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_formats_trueaudio.py�����������������������������������������������������0000644�0001750�0001750�00000001603�00000000000�021005� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_formats_vgm.py�����������������������������������������������������������0000644�0001750�0001750�00000003311�00000000000�017573� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_formats_wav.py�����������������������������������������������������������0000644�0001750�0001750�00000002675�00000000000�017613� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_formats_wavpack.py�������������������������������������������������������0000644�0001750�0001750�00000002013�00000000000�020434� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_formats_wma.py�����������������������������������������������������������0000644�0001750�0001750�00000015521�00000000000�017574� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_formats_xiph.py����������������������������������������������������������0000644�0001750�0001750�00000047176�00000000000�017773� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_https.py�����������������������������������������������������������������0000644�0001750�0001750�00000004533�00000000000�016420� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 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 @skipIf(is_linux(), "not on linux") class Thttps(TestCase): """For Windows/OSX 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() request = session.request_http("get", url) request.send(None).close() for url in self.BAD: with self.assertRaises(GLib.GError): session = Soup.Session() request = session.request_http("get", url) request.send(None).close() ���������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_icons.py�����������������������������������������������������������������0000644�0001750�0001750�00000001331�00000000000�016362� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_image_support.py���������������������������������������������������������0000644�0001750�0001750�00000002126�00000000000�020130� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_library_librarians.py����������������������������������������������������0000644�0001750�0001750�00000015132�00000000000�021125� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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.util import connect_obj from quodlibet.library import SongLibrarian from quodlibet.library.libraries import Library, SongFileLibrary 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)) while Gtk.events_pending(): Gtk.main_iteration() 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) while Gtk.events_pending(): Gtk.main_iteration() 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_library_libraries.py�����������������������������������������������������0000644�0001750�0001750�00000062124�00000000000�020756� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the 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 gi.repository import Gtk from quodlibet import config from quodlibet.formats import AudioFile from quodlibet.formats import AudioFileError from quodlibet.library.libraries import (Library, PicklingMixin, SongLibrary, FileLibrary, AlbumLibrary, SongFileLibrary, iter_paths) from quodlibet.util import connect_obj, is_windows from quodlibet.util.path import normalize_path from senf import fsnative from tests import TestCase, get_data_path, mkstemp, mkdtemp, skipIf from .helper import capture_output, get_temp_copy class Fake(int): def __init__(self, _): self.key = int(self) 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)) while Gtk.events_pending(): Gtk.main_iteration() 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)) while Gtk.events_pending(): Gtk.main_iteration() self.failUnlessEqual(set(self.changed), {2, 5, 8}) def test_changed_none_present(self): self.library.changed(self.Frange(5)) while Gtk.events_pending(): Gtk.main_iteration() 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], 5) new = self.Fake(12) new.key = 100 self.library.add([new]) self.failUnlessEqual(self.library[100], 12) 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 %d" % 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(range(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 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) while Gtk.events_pending(): Gtk.main_iteration() 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 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")) in_song.sanitize() out_song = FakeAudioFile(str(other_root / "out file.mp3")) # Make sure they exists 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!" 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() 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() 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_metadata.py��������������������������������������������������������������0000644�0001750�0001750�00000007703�00000000000�017040� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_mmkeys.py����������������������������������������������������������������0000644�0001750�0001750�00000001531�00000000000�016556� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_operon.py����������������������������������������������������������������0000644�0001750�0001750�00000056473�00000000000�016572� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 senf import fsnative, path2fsn, environ from tests import TestCase, get_data_path, mkstemp 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) self.failUnlessEqual(s == 0, command_succeeds, msg=repr((s, o, e))) self.failUnlessEqual(bool(o), stdout_not_empty, msg=repr(o)) self.failUnlessEqual(bool(e), stderr_not_empty, msg=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) def test_permissions(self): # doesn't prevent reading under wine.. if os.name == "nt": return 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") 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))) def test_remove_all(self): if os.name == "nt" or sys.platform == "darwin": return 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() self.assertFalse(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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_order.py�����������������������������������������������������������������0000644�0001750�0001750�00000003764�00000000000�016376� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_pattern.py���������������������������������������������������������������0000644�0001750�0001750�00000060266�00000000000�016740� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the 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')) 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'', u'SortA2'), (u'Artist3', u'Artist3')}) pat = Pattern('<artist> x') s.failUnlessEqual(pat.format_list(s.h), {(u'Artist1 x', u'SortA1 x'), (u' x', u'SortA2 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'', u'SortA2'), (u'Artist3', u'Artist3'), (u'Album5', u'SortAlbum5')}) pat = Pattern('<~album~artist>') s.failUnlessEqual(pat.format_list(s.h), {(u'Artist1', u'SortA1'), (u'', u'SortA2'), (u'Artist3', u'Artist3'), (u'Album5', u'SortAlbum5')}) pat = Pattern('<~artist~artist>') s.failUnlessEqual(pat.format_list(s.h), {(u'Artist1', u'SortA1'), (u'', u'SortA2'), (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 ', u'SortAlbum5 SortA2'), (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 Album5', u'x SortA2 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' Album5 xx', u' SortA2 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 ', u'SortAlbum5 7/8 SortA2'), (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 ', u'7/8 SortAlbum5 SortA2'), (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' Artist1', u'SortA2 SortA1'), (u'Artist3 Artist1', u'Artist3 SortA1'), (u'Artist1 ', u'SortA1 SortA2'), (u' ', u'SortA2 SortA2'), (u'Artist3 ', u'Artist3 SortA2'), (u'Artist1 Artist3', u'SortA1 Artist3'), (u' Artist3', u'SortA2 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_player.py����������������������������������������������������������������0000644�0001750�0001750�00000031706�00000000000�016554� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_player_gst.py������������������������������������������������������������0000644�0001750�0001750�00000021442�00000000000�017425� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the 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 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.sv8.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") 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_player_xine.py�����������������������������������������������������������0000644�0001750�0001750�00000001766�00000000000�017602� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_playlist_menu.py���������������������������������������������������������0000644�0001750�0001750�00000004351�00000000000�020141� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 quodlibet from quodlibet import qltk from quodlibet.browsers.playlists.menu import PlaylistMenu from quodlibet.browsers.playlists.util import PLAYLISTS from quodlibet.formats import AudioFile from quodlibet.library import SongLibrarian from quodlibet.library.libraries 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 PLAYLISTS or os.name == "nt", msg="Failing, don't want to delete %s" % PLAYLISTS) try: os.mkdir(PLAYLISTS) 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) self.added = [] def tearDown(self): self.lib.destroy() self.lib.librarian.destroy() quodlibet.config.quit() def _on_new(self, _, playlist): self.added.append(playlist) def test__on_new_playlist_activate(self): main = qltk.MenuItem('Menu') menu = StubbedPlaylistMenu(self.SONGS, []) menu.connect('new', self._on_new) main.set_submenu(menu) menu._on_new_playlist_activate(main, self.SONGS) self.failUnless(self.added, msg="No playlists signalled") self.failUnlessEqual(self.added[0].songs, self.SONGS) self.added[0].delete() ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_plugins___init__.py������������������������������������������������������0000644�0001750�0001750�00000012436�00000000000�020557� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_plugins_cover.py���������������������������������������������������������0000644�0001750�0001750�00000030170�00000000000�020131� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the 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 Gtk 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 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() def run_loop(): while Gtk.events_pending(): Gtk.main_iteration() 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_loop() self.assertFalse(found[0]) handler.plugin_enable(dummy_sources[1]) manager.acquire_cover(done, None, None) run_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_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_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_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_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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_plugins_events.py��������������������������������������������������������0000644�0001750�0001750�00000006612�00000000000�020323� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_plugins_playlist.py������������������������������������������������������0000644�0001750�0001750�00000015540�00000000000�020660� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_plugins_songsmenu.py�����������������������������������������������������0000644�0001750�0001750�00000016074�00000000000�021040� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_po.py��������������������������������������������������������������������0000644�0001750�0001750�00000026146�00000000000�015700� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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 from tests.helper import ListWithUnused as L import os import re import pytest try: import polib except ImportError: polib = None import quodlibet from quodlibet.util import get_module_dir from quodlibet.util.string.titlecase import human_title from gdist import gettextutil QL_BASE_DIR = os.path.dirname(get_module_dir(quodlibet)) PODIR = os.path.join(QL_BASE_DIR, "po") def has_gettext_util(): try: gettextutil.check_version() except gettextutil.GettextError: return False return True class MissingTranslationsException(Exception): def __init__(self, missing): msg = ("No reference in POTFILES.in to: " + ", ".join(missing)) super().__init__(msg) @pytest.mark.skipif(not has_gettext_util(), reason="no gettext") def test_potfile_format(): with gettextutil.create_pot(PODIR) as pot_path: gettextutil.check_pot(pot_path) class TPOTFILESIN(TestCase): def test_no_extra_entries(self): """Works without polib installed...""" with open(os.path.join(PODIR, "POTFILES.in")) as f: for fn in f: path = os.path.join(QL_BASE_DIR, fn.strip()) assert os.path.isfile(path), \ "Can't read '%s' from POTFILES.in" % path @pytest.mark.skipif(not has_gettext_util(), reason="no gettext") def test_missing(self): results = gettextutil.get_missing(PODIR) 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(PODIR) 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) messages = [ "'%s' (%s)" % (e.msgid, format_occurrences(e)) for e in fails ] self.fail( "One or more messages did not pass (%s):\n" % reason + '\n'.join(messages)) 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 """ terms = ( 'AcoustID', 'D-Bus', 'Ex Falso', 'GNOME', 'GStreamer', 'Internet', 'iPod', 'Last.fm', 'MusicBrainz', 'Python', 'Quod Libet', 'Replay Gain', 'ReplayGain', 'Squeezebox', 'Wikipedia') ok_suffixes = ('_', '.org') fails = [] for entry in self.pot: for term in terms: if term.lower() not in entry.msgid.lower(): continue i = entry.msgid.lower().find(term.lower()) if entry.msgid[i + len(term):].startswith(ok_suffixes): continue if term not in entry.msgid: 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: @pytest.mark.skipif(not has_gettext_util(), reason="no gettext") def test_pos(self): po_path = gettextutil.get_po_path(PODIR, self.lang) gettextutil.check_po(po_path) def test_gtranslator_blows_goats(self): with open(os.path.join(PODIR, "%s.po" % self.lang), "rb") as h: for line in h: if line.strip().startswith(b"#"): continue self.failIf(b"\xc2\xb7" in line, "Broken GTranslator copy/paste in %s:\n%r" % ( self.lang, line)) def test_gtk_stock_items(self): with open(os.path.join(PODIR, "%s.po" % self.lang), "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 [ b'media-next', b'media-previous', b'media-play', b'media-pause'], "Invalid stock translation in %s\n%s" % ( self.lang, 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) messages = [ '"%s" - "%s" (%s)' % (e.msgid, e.msgstr, format_occurrences(e)) for e in fails ] self.fail( "One or more messages did not pass (%s).\n%s" % ( reason, "\n".join(messages))) 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(os.path.join(PODIR, "%s.po" % self.lang)): 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") for lang in gettextutil.list_languages(PODIR): testcase = type('PO.' + str(lang), (TestCase, POMixin), {}) testcase.lang = lang globals()['PO.' + lang] = testcase ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk___init__.py���������������������������������������������������������0000644�0001750�0001750�00000011231�00000000000�020041� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk__editutils.py�������������������������������������������������������0000644�0001750�0001750�00000003523�00000000000�020454� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_about.py������������������������������������������������������������0000644�0001750�0001750�00000001100�00000000000�017406� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_bookmarks.py��������������������������������������������������������0000644�0001750�0001750�00000003127�00000000000�020277� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_browser.py����������������������������������������������������������0000644�0001750�0001750�00000002241�00000000000�017766� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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.browser import LibraryBrowser from quodlibet.player.nullbe import NullPlayer import quodlibet.config class TLibraryBrowser(TestCase): def setUp(self): quodlibet.config.init() def test_ctr(self): from quodlibet.library import SongLibrary from quodlibet.browsers.albums import AlbumList win = LibraryBrowser(AlbumList, SongLibrary(), NullPlayer()) win.browser.emit("songs-selected", [], False) win.songlist.get_selection().emit("changed") win.destroy() def test_open(self): from quodlibet.browsers.tracks import TrackList from quodlibet.library import SongLibrary widget = LibraryBrowser.open(TrackList, SongLibrary(), NullPlayer()) self.assertTrue(widget) self.assertTrue(widget.get_visible()) widget.destroy() def tearDown(self): quodlibet.config.quit() ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_cbes.py�������������������������������������������������������������0000644�0001750�0001750�00000010607�00000000000�017224� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_ccb.py��������������������������������������������������������������0000644�0001750�0001750�00000004771�00000000000�017044� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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 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) while Gtk.events_pending(): Gtk.main_iteration() 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) while Gtk.events_pending(): Gtk.main_iteration() self.failUnless(c.get_active()) # ...and inactive config.set("memory", "bar", "off") c = ConfigCheckButton("dummy", "memory", "bar", populate=True) while Gtk.events_pending(): Gtk.main_iteration() 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) while Gtk.events_pending(): Gtk.main_iteration() 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) while Gtk.events_pending(): Gtk.main_iteration() self.failUnless(c.get_active()) # ...and inactive config.set("memory", "bar", "off") c = ConfigCheckMenuItem("dummy", "memory", "bar", populate=True) while Gtk.events_pending(): Gtk.main_iteration() self.failIf(c.get_active()) �������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_chooser.py����������������������������������������������������������0000644�0001750�0001750�00000004536�00000000000�017756� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 senf import fsnative, getcwd 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() == getcwd() ������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_completion.py�������������������������������������������������������0000644�0001750�0001750�00000002666�00000000000�020467� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_controls.py���������������������������������������������������������0000644�0001750�0001750�00000001704�00000000000�020151� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_cover.py������������������������������������������������������������0000644�0001750�0001750�00000003340�00000000000�017422� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_data_editors.py�����������������������������������������������������0000644�0001750�0001750�00000001565�00000000000�020755� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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 TMultiStringEditor(TestCase): def setUp(self): config.init() def test_no_strings(self): mse = TagListEditor("title") self.failUnlessEqual(mse.get_strings(), []) self.failUnlessEqual(mse.get_title(), "title") mse.destroy() def test_defaulting(self): defaults = ["one", "two three"] mse = TagListEditor("title", defaults) self.failUnlessEqual(mse.get_strings(), defaults) mse.destroy() def tearDown(self): config.quit() �������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_delete.py�����������������������������������������������������������0000644�0001750�0001750�00000003332�00000000000�017547� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_edittags.py���������������������������������������������������������0000644�0001750�0001750�00000011273�00000000000�020114� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_entry.py������������������������������������������������������������0000644�0001750�0001750�00000010402�00000000000�017442� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_exfalso.py����������������������������������������������������������0000644�0001750�0001750�00000001261�00000000000�017745� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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.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() �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_filesel.py����������������������������������������������������������0000644�0001750�0001750�00000013126�00000000000�017732� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_getstring.py��������������������������������������������������������0000644�0001750�0001750�00000002731�00000000000�020315� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_image.py������������������������������������������������������������0000644�0001750�0001750�00000005137�00000000000�017374� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_info.py�������������������������������������������������������������0000644�0001750�0001750�00000002317�00000000000�017242� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the 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 app from tests import TestCase, destroy_fake_app, init_fake_app from senf import mkstemp 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 = 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_information.py������������������������������������������������������0000644�0001750�0001750�00000006754�00000000000�020645� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_lyrics.py�����������������������������������������������������������0000644�0001750�0001750�00000004153�00000000000�017614� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_maskedbox.py��������������������������������������������������������0000644�0001750�0001750�00000001135�00000000000�020261� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_models.py�����������������������������������������������������������0000644�0001750�0001750�00000035155�00000000000�017600� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_msg.py��������������������������������������������������������������0000644�0001750�0001750�00000001755�00000000000�017102� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_notif.py������������������������������������������������������������0000644�0001750�0001750�00000003111�00000000000�017417� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_paned.py������������������������������������������������������������0000644�0001750�0001750�00000013345�00000000000�017401� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_playorder.py��������������������������������������������������������0000644�0001750�0001750�00000007050�00000000000�020307� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the 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) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_pluginwin.py��������������������������������������������������������0000644�0001750�0001750�00000004574�00000000000�020332� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_prefs.py������������������������������������������������������������0000644�0001750�0001750�00000001467�00000000000�017433� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_properties.py�������������������������������������������������������0000644�0001750�0001750�00000003641�00000000000�020504� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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 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]) while Gtk.events_pending(): Gtk.main_iteration() def test_removed(self): self.test_twosong() self.window.hide() self.library.emit('removed', [self.af2]) while Gtk.events_pending(): Gtk.main_iteration() 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_queue.py������������������������������������������������������������0000644�0001750�0001750�00000003517�00000000000�017436� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the 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.order.reorder import OrderShuffle from tests import TestCase 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 test_save_restore(self): player = NullPlayer() lib = SongLibrary() lib.librarian = None lib.add([DUMMY_SONG]) try: os.unlink(QUEUE) except OSError: pass q = PlayQueue(lib, player) q.get_model().append(row=[DUMMY_SONG]) q.destroy() q = PlayQueue(lib, player) model = q.get_model() assert model.values()[0] is DUMMY_SONG 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_quodlibetwindow.py��������������������������������������������������0000644�0001750�0001750�00000001674�00000000000�021534� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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.qltk.quodlibetwindow import QuodLibetWindow, PlaybackErrorDialog from quodlibet import library from quodlibet import player from quodlibet import config class TQuodLibetWindow(TestCase): def setUp(self): config.init() def tearDown(self): config.quit() def test_window(self): lib = library.init() pl = player.init_player("nullbe", lib.librarian) window = QuodLibetWindow(lib, pl, headless=True) 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�00000000033�00000000000�010211� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������27 mtime=1614540386.031186 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_ratingsmenu.py������������������������������������������������������0000644�0001750�0001750�00000004201�00000000000�020635� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_renamefiles.py������������������������������������������������������0000644�0001750�0001750�00000030543�00000000000�020603� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the 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.libraries 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_scanbox.py����������������������������������������������������������0000644�0001750�0001750�00000000616�00000000000�017744� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_searchbar.py��������������������������������������������������������0000644�0001750�0001750�00000002047�00000000000�020241� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_seekbutton.py�������������������������������������������������������0000644�0001750�0001750�00000002310�00000000000�020463� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_songlist.py���������������������������������������������������������0000644�0001750�0001750�00000022361�00000000000�020152� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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.songlistcolumns import SongListColumn from senf import fsnative from tests import TestCase from quodlibet.library import SongLibrary from quodlibet.qltk.songlist import (SongList, set_columns, get_columns, header_tag_split, get_sort_tag) from quodlibet.formats import AudioFile from quodlibet import config class TSongList(TestCase): HEADERS = ["acolumn", "~#lastplayed", "~foo~bar", "~#rating", "~#length", "~dirname", "~#track"] def setUp(self): config.init() self.songlist = SongList(SongLibrary()) self.orders_changed = 0 def orders_changed_cb(*args): self.orders_changed += 1 self.songlist.connect("orders-changed", orders_changed_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): s = self.songlist s.sortable = False s.set_column_headers(["foo"]) s.toggle_column_sort(s.get_columns()[0]) self.assertEqual(self.orders_changed, 0) self.assertFalse(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_header_menu(self): from quodlibet import browsers from quodlibet.library import SongLibrary, SongLibrarian song = AudioFile({"~filename": fsnative(u"/dev/null")}) song.sanitize() self.songlist.set_songs([song]) library = SongLibrary() library.librarian = SongLibrarian() browser = browsers.get("SearchBar")(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)) 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): self.songlist.destroy() config.quit() �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_songlistcolumns.py��������������������������������������������������0000644�0001750�0001750�00000010321�00000000000�021544� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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 gi.repository import Gtk from senf import devnull 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 class TSongListColumns(TestCase): def setUp(self): quodlibet.config.init() def tearDown(self): quodlibet.config.quit() def _render_column(self, column, **kwargs): view = Gtk.TreeView() model = PlaylistModel() view.set_model(model) song = AudioFile({"~filename": 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 = create_songlist_column("~#added") self._render_column(column) # column reuse triggers warning somwhow column = create_songlist_column("~#added") self._render_column(column, **{"~#added": 100}) def test_length(self): column = create_songlist_column("~length") self._render_column(column) def test_filesize(self): column = create_songlist_column("~#filesize") self._render_column(column) def test_rating(self): column = create_songlist_column("~rating") text = self._render_column(column) self.assertNotEqual(text, "0.67") column = create_songlist_column("~#rating") text = self._render_column(column) self.assertEqual(text, "0.67") def test_bitrate(self): column = create_songlist_column("~#bitrate") self._render_column(column) def test_basename(self): column = create_songlist_column("~basename") self._render_column(column) def test_pattern(self): column = create_songlist_column("<artist>-<album>") self._render_column(column) def test_artist(self): column = create_songlist_column("artist") self._render_column(column) def test_people(self): column = create_songlist_column("~people") self._render_column(column) def test_bpm(self): column = create_songlist_column("bpm") text = self._render_column(column, **{"bpm": "123"}) self.assertEqual(text, "123") def test_initialkey(self): column = create_songlist_column("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) d = datetime.datetime(year=1999, month=5, day=1, hour=23, minute=11, second=59) stamp = int(time.mktime(d.timetuple())) column = create_songlist_column("~#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 d = datetime.datetime(year=1999, month=5, day=1, hour=23, minute=11, second=59) stamp = int(time.mktime(d.timetuple())) column = create_songlist_column("~#added") text = self._render_column(column, **{"~#added": stamp}) self.assertNotEqual(text, "19990501 23:11:59 PLAINTEXT") ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_songmodel.py��������������������������������������������������������0000644�0001750�0001750�00000037245�00000000000�020306� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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.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_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 = PlaylistModel() 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 tearDown(self): self.p.destroy() �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_songsmenu.py��������������������������������������������������������0000644�0001750�0001750�00000011345�00000000000�020326� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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.remote import RemoteFile from tests import TestCase from quodlibet.formats import AudioFile from quodlibet.library import SongLibrary from quodlibet.qltk.songsmenu import SongsMenu from quodlibet import config import quodlibet.player def an_af(i): return AudioFile({"~filename": "/dev/null", "title": "http://example.com/%0d" % i}) class TSongsMenu(TestCase): def _confirmer(self, *args): self.confirmed = True return False def setUp(self): config.init() self.library = SongLibrary() 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 = [RemoteFile("http://example.com/")] 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 empty_menu_with(self, plugins=False, playlists=False, queue=False, remove=False, delete=False, edit=False, ratings=False, show_files=False, removal_confirmer=None): return SongsMenu(self.library, self.songs, plugins=plugins, playlists=playlists, queue=queue, remove=remove, delete=delete, edit=edit, ratings=ratings, show_files=show_files, removal_confirmer=removal_confirmer) 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_tagscombobox.py�����������������������������������������������������0000644�0001750�0001750�00000002716�00000000000�021001� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_tagsfrompath.py�����������������������������������������������������0000644�0001750�0001750�00000002244�00000000000�021005� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_textedit.py���������������������������������������������������������0000644�0001750�0001750�00000003606�00000000000�020143� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_tracker.py����������������������������������������������������������0000644�0001750�0001750�00000007312�00000000000�017742� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the 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 tests import TestCase, mkdtemp from gi.repository import Gtk from quodlibet import config from quodlibet.formats import AudioFile from quodlibet.player.nullbe import NullPlayer from quodlibet.qltk.tracker import SongTracker, FSInterface from quodlibet.library import SongLibrary 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 do(self): while Gtk.events_pending(): Gtk.main_iteration() 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) self.do() self.p.emit('song-ended', self.s1, False) self.do() 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) self.do() 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') self.do() 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) self.do() 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.filename = os.path.join(self.dir, "foo") self.fs = FSInterface(self.filename, self.p) def tearDown(self): self.p.destroy() shutil.rmtree(self.dir) def do(self): while Gtk.events_pending(): Gtk.main_iteration() def test_init(self): self.do() self.failIf(os.path.exists(self.filename)) def test_start(self): self.p.emit('song_started', AudioFile({"woo": "bar", "~#length": 10})) self.do() with open(self.filename, "rb") as h: self.failUnless(b"woo=bar\n" in h.read()) def test_song_ended(self): self.p.emit('song-started', AudioFile({"woo": "bar", "~#length": 10})) self.do() self.p.emit('song-ended', {}, False) self.do() self.failIf(os.path.exists(self.filename)) def test_elapsed(self): self.p.seek(123456) self.p.emit('song-started', AudioFile({"~#length": 10})) self.do() 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 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_unity.py������������������������������������������������������������0000644�0001750�0001750�00000000641�00000000000�017455� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_util.py�������������������������������������������������������������0000644�0001750�0001750�00000001333�00000000000�017261� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_views.py������������������������������������������������������������0000644�0001750�0001750�00000021316�00000000000�017444� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_window.py�����������������������������������������������������������0000644�0001750�0001750�00000004565�00000000000�017625� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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 TWindows(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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_wlw.py��������������������������������������������������������������0000644�0001750�0001750�00000003713�00000000000�017121� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_qltk_x.py����������������������������������������������������������������0000644�0001750�0001750�00000004211�00000000000�016551� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_query.py�����������������������������������������������������������������0000644�0001750�0001750�00000055717�00000000000�016435� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the 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 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 TQuery_is_valid(TestCase): def test_re(self): self.failUnless(Query('t = /an re/').valid) self.failUnless(Query('t = /an re/c').valid) self.failUnless(Query('t = /an\\/re/').valid) self.failIf(Query('t = /an/re/').valid) self.failUnless(Query('t = /aaa/lsic').valid) self.failIf(Query('t = /aaa/icslx').valid) def test_str(self): self.failUnless(Query('t = "a str"').valid) self.failUnless(Query('t = "a str"c').valid) self.failUnless(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): self.failUnless(Query('t = tag').valid) self.failUnless(Query('t = !tag').valid) self.failUnless(Query('t = |(tag, bar)').valid) self.failUnless(Query('t = a"tag"').valid) self.failIf(Query('t = a, tag').valid) self.failUnless(Query('tag with spaces = tag').valid) def test_empty(self): self.failUnless(Query('').valid) self.failUnless(Query('').is_parsable) self.failUnless(Query('')) def test_emptylist(self): self.failIf(Query("a = &()").valid) self.failIf(Query("a = |()").valid) self.failIf(Query("|()").valid) self.failIf(Query("&()").valid) def test_nonsense(self): self.failIf(Query('a string').valid) self.failIf(Query('t = #(a > b)').valid) self.failIf(Query("=a= = /b/").valid) self.failIf(Query("a = &(/b//").valid) self.failIf(Query("(a = &(/b//)").valid) def test_trailing(self): self.failIf(Query('t = /an re/)').valid) self.failIf(Query('|(a, b = /a/, c, d = /q/) woo').valid) def test_not(self): self.failUnless(Query('t = !/a/').valid) self.failUnless(Query('t = !!/a/').valid) self.failUnless(Query('!t = "a"').valid) self.failUnless(Query('!!t = "a"').valid) self.failUnless(Query('t = !|(/a/, !"b")').valid) self.failUnless(Query('t = !!|(/a/, !"b")').valid) self.failUnless(Query('!|(t = /a/)').valid) def test_taglist(self): self.failUnless(Query('a, b = /a/').valid) self.failUnless(Query('a, b, c = |(/a/)').valid) self.failUnless(Query('|(a, b = /a/, c, d = /q/)').valid) self.failIf(Query('a = /a/, b').valid) def test_andor(self): self.failUnless(Query('a = |(/a/, /b/)').valid) self.failUnless(Query('a = |(/b/)').valid) self.failUnless(Query('|(a = /b/, c = /d/)').valid) self.failUnless(Query('a = &(/a/, /b/)').valid) self.failUnless(Query('a = &(/b/)').valid) self.failUnless(Query('&(a = /b/, c = /d/)').valid) def test_numcmp(self): self.failUnless(Query("#(t < 3)").valid) self.failUnless(Query("#(t <= 3)").valid) self.failUnless(Query("#(t > 3)").valid) self.failUnless(Query("#(t >= 3)").valid) self.failUnless(Query("#(t = 3)").valid) self.failUnless(Query("#(t != 3)").valid) self.failIf(Query("#(t !> 3)").valid) self.failIf(Query("#(t >> 3)").valid) def test_numcmp_func(self): self.assertTrue(Query("#(t:min < 3)").valid) self.assertTrue( Query("&(#(playcount:min = 0), #(added < 1 month ago))").valid) def test_trinary(self): self.failUnless(Query("#(2 < t < 3)").valid) self.failUnless(Query("#(2 >= t > 3)").valid) # useless, but valid self.failUnless(Query("#(5 > t = 2)").valid) def test_list(self): self.failUnless(Query("#(t < 3, t > 9)").valid) self.failUnless(Query("t = &(/a/, /b/)").valid) self.failUnless(Query("s, t = |(/a/, /b/)").valid) self.failUnless(Query("|(t = /a/, s = /b/)").valid) def test_nesting(self): self.failUnless(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): self.failUnless(Query("#(t < 3*4)").valid) self.failUnless(Query("#(t * (1+r) < 7)").valid) self.failUnless(Query("#(0 = t)").valid) self.failUnless(Query("#(t < r < 9)").valid) self.failUnless(Query("#((t-9)*r < -(6*2) = g*g-1)").valid) self.failUnless(Query("#(t + 1 + 2 + -4 * 9 > g*(r/4 + 6))").valid) self.failUnless(Query("#(date < 2010-4)").valid) self.failUnless(Query("#(date < 2010 - 4)").valid) self.failUnless(Query("#(date > 0000)").valid) self.failUnless(Query("#(date > 00004)").valid) self.failUnless(Query("#(t > 3 minutes)").valid) self.failUnless(Query("#(added > today)").valid) self.failUnless(Query("#(length < 5:00)").valid) self.failUnless(Query("#(filesize > 5M)").valid) self.failUnless(Query("#(added < 7 days ago)").valid) self.failIf(Query("#(3*4)").valid) self.failIf(Query("#(t = 3 + )").valid) self.failIf(Query("#(t = -)").valid) self.failIf(Query("#(-4 <)").valid) self.failIf(Query("#(t < ()").valid) self.failIf(Query("#((t +) - 1 > 8)").valid) self.failIf(Query("#(t += 8)").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"}) 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): self.failUnless(Query("album!=foo").search(self.s1)) self.failIf(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) self.assertAlmostEqual(ineq_time, not_val_time, places=1) def test_repr(self): query = Query("foo = bar", []) self.assertEqual( repr(query).replace("u'", "'"), "<Query string='foo = bar' type=VALID star=[]>") query = Query("bar", ["foo"]) self.assertEqual( repr(query).replace("u'", "'"), "<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") self.failIf(query.search(song), "%r, %r" % (query, song)) def test_empty(self): self.failIf(Query("foobar = /./").search(self.s1)) def test_gte(self): self.failUnless(Query("#(track >= 11)").search(self.s2)) def test_re(self): for s in ["album = /i hate/", "artist = /pi*/", "title = /x.y/"]: self.failUnless(Query(s).search(self.s1)) self.failIf(Query(s).search(self.s2)) f = Query("artist = /mu|piman/").search self.failUnless(f(self.s1)) self.failUnless(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"]: self.failIf(Query(s).search(self.s1)) self.failUnless(Query(s).search(self.s2)) def test_abbrs(self): for s in ["b = /i hate/", "a = /pi*/", "t = /x.y/"]: self.failUnless(Query(s).search(self.s1)) self.failIf(Query(s).search(self.s2)) def test_str(self): for k in self.s2.keys(): v = self.s2[k] self.failUnless(Query('%s = "%s"' % (k, v)).search(self.s2)) self.failIf(Query('%s = !"%s"' % (k, v)).search(self.s2)) def test_numcmp(self): self.failIf(Query("#(track = 0)").search(self.s1)) self.failIf(Query("#(notatag = 0)").search(self.s1)) self.failUnless(Query("#(track = 12)").search(self.s2)) def test_trinary(self): self.failUnless(Query("#(11 < track < 13)").search(self.s2)) self.failUnless(Query("#(11 < track <= 12)").search(self.s2)) self.failUnless(Query("#(12 <= track <= 12)").search(self.s2)) self.failUnless(Query("#(12 <= track < 13)").search(self.s2)) self.failUnless(Query("#(13 > track > 11)").search(self.s2)) self.failUnless(Query("#(20 > track < 20)").search(self.s2)) def test_not_2(self): for s in ["album = !/i hate/", "artist = !/pi*/", "title = !/x.y/"]: self.failUnless(Query(s).search(self.s2)) self.failIf(Query(s).search(self.s1)) def test_case(self): self.failUnless(Query("album = /i hate/").search(self.s1)) self.failUnless(Query("album = /I Hate/").search(self.s1)) self.failUnless(Query("album = /i Hate/").search(self.s1)) self.failUnless(Query("album = /i Hate/i").search(self.s1)) self.failUnless(Query(u"title = /ångström/").search(self.s4)) self.failIf(Query("album = /i hate/c").search(self.s1)) self.failIf(Query(u"title = /ångström/c").search(self.s4)) def test_re_and(self): self.failUnless(Query("album = &(/ate/,/est/)").search(self.s1)) self.failIf(Query("album = &(/ate/, /ets/)").search(self.s1)) self.failIf(Query("album = &(/tate/, /ets/)").search(self.s1)) def test_re_or(self): self.failUnless(Query("album = |(/ate/,/est/)").search(self.s1)) self.failUnless(Query("album = |(/ate/,/ets/)").search(self.s1)) self.failIf(Query("album = |(/tate/, /ets/)").search(self.s1)) def test_newlines(self): self.failUnless(Query("a = /\n/").search(self.s3)) self.failUnless(Query("a = /\\n/").search(self.s3)) self.failIf(Query("a = /\n/").search(self.s2)) self.failIf(Query("a = /\\n/").search(self.s2)) def test_exp_and(self): self.failUnless(Query("&(album = ate, artist = man)").search(self.s1)) self.failIf(Query("&(album = ate, artist = nam)").search(self.s1)) self.failIf(Query("&(album = tea, artist = nam)").search(self.s1)) def test_exp_or(self): self.failUnless(Query("|(album = ate, artist = man)").search(self.s1)) self.failUnless(Query("|(album = ate, artist = nam)").search(self.s1)) self.failIf(Query("&(album = tea, artist = nam)").search(self.s1)) def test_dumb_search(self): self.failUnless(Query("ate man").search(self.s1)) self.failUnless(Query("Ate man").search(self.s1)) self.failIf(Query("woo man").search(self.s1)) self.failIf(Query("not crazy").search(self.s1)) def test_dumb_search_value(self): self.failUnless(Query("|(ate, foobar)").search(self.s1)) self.failUnless(Query("!!|(ate, foobar)").search(self.s1)) self.failUnless(Query("&(ate, te)").search(self.s1)) self.failIf(Query("|(foo, bar)").search(self.s1)) self.failIf(Query("&(ate, foobar)").search(self.s1)) self.failIf(Query("! !&(ate, foobar)").search(self.s1)) self.failIf(Query("&blah").search(self.s1)) self.failUnless(Query("&blah oh").search(self.s5)) self.failUnless(Query("!oh no").search(self.s5)) self.failIf(Query("|blah").search(self.s1)) # https://github.com/quodlibet/quodlibet/issues/1056 self.failUnless(Query("&(ate, piman)").search(self.s1)) def test_dumb_search_value_negate(self): self.failUnless(Query("!xyz").search(self.s1)) self.failUnless(Query("!!!xyz").search(self.s1)) self.failUnless(Query(" !!!&(xyz, zyx)").search(self.s1)) self.failIf(Query("!man").search(self.s1)) self.failUnless(Query("&(tests,piman)").search(self.s1)) self.failUnless(Query("&(tests,!nope)").search(self.s1)) self.failIf(Query("&(tests,!!nope)").search(self.s1)) self.failIf(Query("&(tests,!piman)").search(self.s1)) self.failUnless(Query("&(tests,|(foo,&(pi,!nope)))").search(self.s1)) def test_dumb_search_regexp(self): self.failUnless(Query("/(x|H)ate/").search(self.s1)) self.failUnless(Query("'PiMan'").search(self.s1)) self.failIf(Query("'PiMan'c").search(self.s1)) self.failUnless(Query("!'PiMan'c").search(self.s1)) self.failIf(Query("!/(x|H)ate/").search(self.s1)) def test_unslashed_search(self): self.failUnless(Query("artist=piman").search(self.s1)) self.failUnless(Query(u"title=ång").search(self.s4)) self.failIf(Query("artist=mu").search(self.s1)) self.failIf(Query(u"title=äng").search(self.s4)) def test_synth_search(self): self.failUnless(Query("~dirname=/dir1/").search(self.s1)) self.failUnless(Query("~dirname=/dir2/").search(self.s2)) self.failIf(Query("~dirname=/dirty/").search(self.s1)) self.failIf(Query("~dirname=/dirty/").search(self.s2)) def test_search_almostequal(self): a, b = AudioFile({"~#rating": 0.771}), AudioFile({"~#rating": 0.769}) self.failUnless(Query("#(rating = 0.77)").search(a)) self.failUnless(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] self.failIf( list(filter(lambda x: not isinstance(x, match.Union), tests))) tests = [inter & tag, tag & tag, neg & neg, tag & inter, neg & union, union & union, inter & inter, numcmp & numcmp, numcmp & inter] self.failIf( list(filter(lambda x: not isinstance(x, match.Inter), tests))) self.assertTrue(isinstance(-neg, match.Tag)) true = Query("") self.assertTrue(isinstance(true | inter, match.True_)) self.assertTrue(isinstance(inter | true, match.True_)) self.assertTrue(isinstance(true & inter, match.Inter)) self.assertTrue(isinstance(inter & true, match.Inter)) self.assertTrue(isinstance(true & true, match.True_)) self.assertTrue(isinstance(true | true, match.True_)) self.assertTrue(isinstance(-true, match.Neg)) def test_filter(self): q = Query("artist=piman") self.assertEqual(q.filter([self.s1, self.s2]), [self.s1]) self.assertEqual(q.filter(iter([self.s1, self.s2])), [self.s1]) q = Query("") self.assertEqual(q.filter([self.s1, self.s2]), [self.s1, self.s2]) self.assertEqual( q.filter(iter([self.s1, self.s2])), [self.s1, self.s2]) def test_match_all(self): self.failUnless(Query("").matches_all) self.failUnless(Query(" ").matches_all) self.failIf(Query("foo").matches_all) def test_utf8(self): # also handle undecoded values self.assertTrue(Query(u"utf8=Ångström").search(self.s4)) def test_fs_utf8(self): self.failUnless(Query(u"~filename=foü.ogg").search(self.s3)) self.failUnless(Query(u"~filename=öä").search(self.s3)) self.failUnless(Query(u"~dirname=öäü").search(self.s3)) self.failUnless(Query(u"~basename=ü.ogg").search(self.s3)) def test_filename_utf8_fallback(self): self.failUnless(Query(u"filename=foü.ogg").search(self.s3)) self.failUnless(Query(u"filename=öä").search(self.s3)) def test_mountpoint_utf8_fallback(self): self.failUnless(Query(u"mountpoint=foü").search(self.s3)) self.failUnless(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): self.assertRaises(ValueError, Query, u"foobar", star=["~#mtime"]) def test_match_diacriticals_explcit(self): assert Query(u'title=angstrom').search(self.s4) self.failIf(Query(u'title="Ångstrom"').search(self.s4)) self.failUnless(Query(u'title="Ångstrom"d').search(self.s4)) self.failUnless(Query(u'title=Ångström').search(self.s4)) self.failUnless(Query(u'title="Ångström"').search(self.s4)) self.failUnless(Query(u'title=/Ångström/').search(self.s4)) self.failUnless(Query(u'title="Ångstrom"d').search(self.s4)) self.failUnless(Query(u'title=/Angstrom/d').search(self.s4)) self.failUnless(Query(u'""d').search(self.s4)) def test_match_diacriticals_dumb(self): self.assertTrue(Query(u'Angstrom').search(self.s4)) self.assertTrue(Query(u'Ångström').search(self.s4)) self.assertTrue(Query(u'Ångstrom').search(self.s4)) self.assertFalse(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): self.failUnless(Query("#(length = 224)").search(self.s1)) self.failUnless(Query("#(length = 3:44)").search(self.s1)) self.failUnless(Query("#(length = 3 minutes + 44 seconds)") .search(self.s1)) self.failUnless(Query("#(playcount > skipcount)").search(self.s1)) self.failUnless(Query("#(playcount < 2 * skipcount)").search(self.s1)) self.failUnless(Query("#(length > 3 minutes)").search(self.s1)) self.failUnless(Query("#(3:00 < length < 4:00)").search(self.s1)) self.failUnless(Query("#(40 seconds < length/5 < 1 minute)") .search(self.s1)) self.failUnless(Query("#(2+3 * 5 = 17)").search(self.s1)) self.failUnless(Query("#(playcount / 0 > 0)").search(self.s1)) self.failIf(Query("#(track + 1 != 13)").search(self.s2)) def test_numexpr_date(self): self.failUnless(Query("#(length < 2005-07-19)").search(self.s1)) self.failUnless(Query("#(date > 2005-07-19)").search(self.s1)) self.failUnless(Query("#(2005-11-24 < 2005-07-19)").search(self.s1)) self.failUnless(Query("#(date = (2007-05-19) + 5 days)") .search(self.s1)) self.failUnless(Query("#(date - 5 days = 2007-05-19)").search(self.s1)) self.failUnless(Query("#(2010-02-18 > date)").search(self.s1)) self.failUnless(Query("#(2010 > date)").search(self.s1)) self.failUnless(Query("#(date > 4)").search(self.s1)) self.failUnless(Query("#(date > 0004)").search(self.s1)) self.failUnless(Query("#(date > 0000)").search(self.s1)) def test_ignore_characters(self): try: config.set("browsers", "ignored_characters", "-") self.failUnless(Query("Foo the Bar - mu").search(self.s2)) config.set("browsers", "ignored_characters", "1234") self.failUnless(Query("4Fo13o 2th2e3 4Bar4").search(self.s2)) finally: config.reset("browsers", "ignored_characters") class TQuery_get_type(TestCase): def test_red(self): for p in ["a = /w", "|(sa#"]: self.failUnlessEqual(QueryType.INVALID, Query(p).type) def test_black(self): for p in ["a test", "more test hooray"]: self.failUnlessEqual(QueryType.TEXT, Query(p).type) def test_green(self): for p in ["a = /b/", "&(a = b, c = d)", "/abc/", "!x", "!&(abc, def)"]: self.failUnlessEqual(QueryType.VALID, Query(p).type) �������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_query__match.py����������������������������������������������������������0000644�0001750�0001750�00000010043�00000000000�017727� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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.query._match import numexprUnit, ParseError, NumexprTag from quodlibet.query._match import NumexprNow, numexprTagOrSpecial, Inter,\ True_, Neg from quodlibet.util import parse_date from quodlibet.formats import AudioFile from quodlibet.util.collection import Collection 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): self.failUnless(numexprUnit(10, 'seconds').evaluate(None, 0, True) == 10) self.failUnless(numexprUnit(10, 'minutes').evaluate(None, 0, True) == 10 * 60) self.failUnless(numexprUnit(1, 'year').evaluate(None, 0, True) == 365 * 24 * 60 * 60) self.failUnless(numexprUnit(3, 'k').evaluate(None, 0, True) == 3 * 1024) self.failUnless(numexprUnit(3, 'megabytes').evaluate(None, 0, True) == 3 * 1024 ** 2) self.failUnlessRaises(ParseError, numexprUnit, 7, 'invalid unit') def test_time_tag(self): time = 424242 song = AudioFile({'~#added': 400000, '~#mtime': 410000, '~#length': 315}) self.failUnless(NumexprTag('added').evaluate(song, time, True) == 24242) self.failUnless(NumexprTag('length').evaluate(song, time, True) == 315) self.failUnless(NumexprTag('date').evaluate(song, time, True) is None) self.failUnless(NumexprTag('added').evaluate(song, time, True) > NumexprTag('mtime').evaluate(song, time, True)) def test_date_tag(self): song = AudioFile({'date': '2012-11-09'}) self.failUnless(NumexprTag('date').evaluate(song, 0, True) == parse_date('2012-11-09')) self.failUnless(NumexprTag('date').evaluate(song, 424242, True) == parse_date('2012-11-09')) self.failUnless(NumexprTag('date').evaluate(song, 0, True) > parse_date('2012-11-08')) self.failUnless(NumexprTag('date').evaluate(song, 0, True) < 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})) self.failUnless(NumexprTag('length:avg').evaluate(col, time, True) == 270) self.failUnless(NumexprTag('added:max').evaluate(col, time, True) == 19242) def test_numexpr_now(self): time = 424242 day = 24 * 60 * 60 self.failUnless(NumexprNow().evaluate(None, time, True) == time) self.failUnless(NumexprNow(day).evaluate(None, time, True) == time - day) self.failUnless(NumexprNow().evaluate(None, time, True) == numexprTagOrSpecial('now').evaluate(None, time, True)) self.failUnless(NumexprNow(day).evaluate(None, time, True) == numexprTagOrSpecial('today') .evaluate(None, time, True)) self.failUnless(NumexprNow().__repr__() == numexprTagOrSpecial('now').__repr__()) self.failUnless(NumexprTag('genre').__repr__() == numexprTagOrSpecial('genre').__repr__()) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_remote.py����������������������������������������������������������������0000644�0001750�0001750�00000002552�00000000000�016550� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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 fsn2bytes, bytes2fsn from . import TestCase, skipIf from .helper import temp_filename from quodlibet.remote import QuodLibetUnixRemote from quodlibet.util import is_windows 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") ������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_session.py���������������������������������������������������������������0000644�0001750�0001750�00000001671�00000000000�016741� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_soundcloudFile.py��������������������������������������������������������0000644�0001750�0001750�00000004420�00000000000�020230� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 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.online = True self.favoritings = defaultdict(int) self.unfavoritings = defaultdict(int) def _on_favorited(self, json): super()._on_favorited(json) def put_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): cl = self.client song = SoundcloudFile("http://uri", TRACK_ID, False, cl) 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(cl.favoritings[TRACK_ID], 1) self.failUnlessEqual(cl.unfavoritings[TRACK_ID], 0) song.write() self.failUnlessEqual(cl.favoritings[TRACK_ID], 1) def test_unfavoriting(self): cl = self.client song = SoundcloudFile("http://uri", TRACK_ID, True, cl) self.failUnless(song.has_rating) self.failUnlessEqual(song("~#rating"), 1.0) song['~#rating'] = 0.2 song.write() self.failIf(song.favorite) self.failUnlessEqual(cl.unfavoritings[TRACK_ID], 1) self.failUnlessEqual(cl.favoritings[TRACK_ID], 0) song.write() self.failUnlessEqual(cl.unfavoritings[TRACK_ID], 1) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_soundcloudLibrary.py�����������������������������������������������������0000644�0001750�0001750�00000010422�00000000000�020754� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 config from quodlibet.browsers.soundcloud.api import SoundcloudApiClient from quodlibet.browsers.soundcloud.library import SoundcloudLibrary 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' TRACK = { u'reposts_count': 134, u'attachments_uri': u'https://api.soundcloud.com/tracks/193910405/attachments', u'video_url': None, u'track_type': None, u'release_month': 3, u'original_format': u'mp3', u'uri': u'https://api.soundcloud.com/tracks/193910405', u'label_name': None, u'duration': 3944440, u'id': 193910405, u'streamable': True, u'user_id': 313827, u'user_favorite': True, u'title': u'Banging Techno Sets :: 098 Kerstin Eden // 03-2015', u'favoritings_count': 882, u'commentable': True, u'comment_count': 39, u'download_url': u'https://api.soundcloud.com/tracks/193910405/download', u'label_id': None, u'downloadable': True, u'last_modified': u'2015/03/02 22:32:30 +0000', u'waveform_url': u'https://w1.sndcdn.com/Ugov31icy2XG_m.png', u'sharing': u'public', u'description': u'Banging Techno sets :: 098 ' u'>> Kerstin Eden // Timao \n' u'fnoob techno - http://www.fnoobtechno.com/radio', u'release_day': 2, u'purchase_url': None, u'permalink': u'banging-techno-sets-098-kerstin-eden-02-2015', u'purchase_title': None, u'stream_url': u'https://api.soundcloud.com/tracks/193910405/stream', u'key_signature': u'', u'user': {u'username': u'Kerstin Eden', u'kind': u'user', u'uri': u'https://api.soundcloud.com/users/313827', u'permalink': u'kerstineden', u'avatar_url': AVATAR_URL, u'last_modified': u'2016/02/25 14:21:56 +0000', u'permalink_url': u'http://soundcloud.com/kerstineden', u'id': 313827}, u'genre': u'banging techno', u'isrc': None, u'download_count': 2062, u'permalink_url': PERMALINK, u'kind': u'track', u'playback_count': 23656, u'license': u'all-rights-reserved', u'artwork_url': u'https://i1.sndcdn.com/artworks-000108682375-q4j7y6-large.jpg', u'embeddable_by': u'all', u'bpm': None, u'state': u'finished', u'original_content_size': 157768013, u'release_year': 2015, u'user_playback_count': 4, u'release': u'', u'tag_list': u'"kerstin eden" eden nimmersatt abstract frankfurt Techno', u'created_at': u'2015/03/02 22:31:30 +0000'} class TSoundcloudLibrary(TestCase): class FakeClient(SoundcloudApiClient): def get_tracks(self, query): self._on_track_data(None, [TRACK], None) def __init__(self): super().__init__() 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("dummy search") songs = list(lib._contents.values()) self.failUnlessEqual(len(songs), 1) s = songs[0] self.failUnlessEqual(s("artist"), "Kerstin Eden") self.failUnlessEqual(s("date"), "2015-03-02") self.failUnlessEqual(s("~#download_count"), 2062) self.failUnlessEqual(s("~#playback_count"), 23656) self.failUnlessEqual(s("~#favoritings_count"), 882) self.failUnlessEqual(s("~#rating"), 1.0) self.failUnlessEqual(s("~#playcount"), 4) assert int(s("~#bitrate")) == 319 def test_artwork_url(self): lib = SoundcloudLibrary(self.FakeClient()) lib.query_with_refresh("") s = list(lib._contents.values())[0] self.failUnlessEqual( s("artwork_url"), "https://i1.sndcdn.com/artworks-000108682375-q4j7y6-t500x500.jpg") ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_unisearch.py�������������������������������������������������������������0000644�0001750�0001750�00000015357�00000000000�017245� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_update.py����������������������������������������������������������������0000644�0001750�0001750�00000000637�00000000000�016541� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_util.py������������������������������������������������������������������0000644�0001750�0001750�00000106545�00000000000�016241� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the 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 senf import getcwd, fsnative, fsn2bytes, bytes2fsn, mkdtemp, environ 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 fsn2glib, glib2fsn, \ 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, expanduser, 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 . import TestCase, skipIf from .helper import capture_output, locale_numeric_conv 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 = 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(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 = 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(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>") 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(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"], 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 = 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) 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): 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)) v2 = glib2fsn(fsn2glib(v)) self.assertTrue(isinstance(v2, fsnative)) self.assertEqual(v, v2) 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 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)) �����������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_util_atomic.py�����������������������������������������������������������0000644�0001750�0001750�00000004737�00000000000�017575� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_util_collection.py�������������������������������������������������������0000644�0001750�0001750�00000056340�00000000000�020451� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the 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 import os from collections import defaultdict from os.path import exists from xml.etree.ElementTree import ElementTree import pytest from senf import fsnative from quodlibet import config from tests import TestCase, mkdtemp from quodlibet.formats import AudioFile as Fakesong from quodlibet.formats._audio import NUMERIC_ZERO_DEFAULT, PEOPLE from quodlibet.util.collection import (Album, Playlist, avg, bayesian_average, FileBackedPlaylist, XSPFBackedPlaylist) from quodlibet.library.libraries import FileLibrary from quodlibet.util import format_rating config.RATINGS = config.HardCodedRatingsPrefs() NUMERIC_SONGS = [ Fakesong({"~filename": fsnative(u"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(u"fake2.mp3"), "~#length": 7, "~#added": 7, "~#lastplayed": 88, "~#bitrate": 220, "date": "99", "~#rating": 0.3, "originaldate": "2002-01-01", "~#filesize": 202}), Fakesong({"~filename": fsnative(u"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', []) FAKE_LIB = FakeLib() def setUp(self): self.FAKE_LIB.reset() 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_playlists_featuring(s): with s.wrap("playlist") as pl: pl.extend(NUMERIC_SONGS) playlists = Playlist.playlists_featuring(NUMERIC_SONGS[0]) s.failUnlessEqual(set(playlists), {pl}) # Now add a second one, check that instance tracking works with s.wrap("playlist2") as pl2: pl2.append(NUMERIC_SONGS[0]) playlists = Playlist.playlists_featuring(NUMERIC_SONGS[0]) s.failUnlessEqual(set(playlists), {pl, pl2}) def test_playlists_tag(self): # Arguably belongs in _audio songs = NUMERIC_SONGS pl_name = "playlist 123!" with self.wrap(pl_name) as pl: pl.extend(songs) for song in songs: self.assertEquals(pl_name, song("~playlists")) 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") lib.add(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 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 TXPSFBackedPlaylist(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, "%s.xspf" % (name,)) def test_write(self): with self.wrap("playlist") as pl: pl.extend(NUMERIC_SONGS) pl.extend([fsnative(u"xf0xf0")]) pl.write() assert exists(pl.path), "File doesn't exist" root = ElementTree().parse(pl.path) assert root.tag == 'playlist' tracks = root.findall(".//track") assert len(tracks) == 4, "Hmm found %s" % tracks assert tracks[-1].find('location').text == "xf0xf0" ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_util_collections.py������������������������������������������������������0000644�0001750�0001750�00000010772�00000000000�020633� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_util_config.py�����������������������������������������������������������0000644�0001750�0001750�00000027153�00000000000�017563� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_util_copool.py�����������������������������������������������������������0000644�0001750�0001750�00000006562�00000000000�017612� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the 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 from gi.repository import Gtk from quodlibet.util import copool 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): for i in range(100): if self.buffer is value: return Gtk.main_iteration_do(False) assert self.buffer is value def _assert_never(self, value): for i in range(100): Gtk.main_iteration_do(False) 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_util_cover.py������������������������������������������������������������0000644�0001750�0001750�00000022046�00000000000�017430� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# # This program is free software; you can redistribute it and/or modify # it under the terms of the 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") # Should match f = self.add_file("[a-2].jpg") assert path_equal( os.path.abspath(self._find_cover(self.song).name), f) # Should not crash f = self.add_file("test.jpg") assert not path_equal( os.path.abspath(self._find_cover(self.song).name), f) 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" ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_util_dbusutils.py��������������������������������������������������������0000644�0001750�0001750�00000011170�00000000000�020324� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_util_dprint.py�����������������������������������������������������������0000644�0001750�0001750�00000002112�00000000000�017602� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_util_environment.py������������������������������������������������������0000644�0001750�0001750�00000001361�00000000000�020653� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_util_fifo.py�������������������������������������������������������������0000644�0001750�0001750�00000004326�00000000000�017236� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 import print_d from quodlibet.util import is_windows from tests import TestCase, skipIf from quodlibet.util.fifo import 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(OSError): write_fifo(fifo._path, "foobar".encode()) fifo.destroy() ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_util_i18n.py�������������������������������������������������������������0000644�0001750�0001750�00000013401�00000000000�017064� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the 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 senf import environ 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(): environ["LANGUAGE"] = "en:de:en_FOO:nl" fixup_i18n_envvars() self.assertEqual(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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_util_json_data.py��������������������������������������������������������0000644�0001750�0001750�00000007365�00000000000�020263� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_util_library.py����������������������������������������������������������0000644�0001750�0001750�00000005717�00000000000�017764� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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, expanduser 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 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 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_util_logging.py����������������������������������������������������������0000644�0001750�0001750�00000003463�00000000000�017742� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_util_massagers.py��������������������������������������������������������0000644�0001750�0001750�00000011422�00000000000�020273� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_util_modulescanner.py����������������������������������������������������0000644�0001750�0001750�00000011560�00000000000�021150� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_util_path.py�������������������������������������������������������������0000644�0001750�0001750�00000012722�00000000000�017246� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the 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, environ from quodlibet.util.path import iscommand, limit_path, \ get_home_dir, uri_is_valid, ishidden, uri2gsturi from quodlibet.util import print_d from . import TestCase is_win = os.name == "nt" path_set = bool(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): def test_main(self): assert ishidden(fsnative(u".")) assert ishidden(fsnative(u"foo/.bar")) assert not ishidden(fsnative(u".foo/bar")) assert not ishidden(fsnative(u"foo")) 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(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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_util_picklehelper.py�����������������������������������������������������0000644�0001750�0001750�00000003745�00000000000�020766� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_util_string.py�����������������������������������������������������������0000644�0001750�0001750�00000001150�00000000000�017611� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_util_string_filter.py����������������������������������������������������0000644�0001750�0001750�00000002220�00000000000�021155� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_util_string_splitters.py�������������������������������������������������0000644�0001750�0001750�00000012206�00000000000�021726� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_util_string_titlecase.py�������������������������������������������������0000644�0001750�0001750�00000012261�00000000000�021653� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_util_tags.py�������������������������������������������������������������0000644�0001750�0001750�00000002076�00000000000�017251� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_util_tagsfrompath.py�����������������������������������������������������0000644�0001750�0001750�00000014604�00000000000�021012� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_util_thread.py�����������������������������������������������������������0000644�0001750�0001750�00000003227�00000000000�017561� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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 from tests import TestCase from gi.repository import Gtk from quodlibet.util.thread import call_async, call_async_background, \ Cancellable, terminate_all class Tcall_async(TestCase): 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() while Gtk.events_pending(): Gtk.main_iteration() call_async_background(func, cancel, callback) Gtk.main_iteration() while Gtk.events_pending(): Gtk.main_iteration() 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() while Gtk.events_pending(): Gtk.main_iteration() def test_terminate_all(self): terminate_all() �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������././@PaxHeader��������������������������������������������������������������������������������������0000000�0000000�0000000�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_util_thumbnails.py�������������������������������������������������������0000644�0001750�0001750�00000007506�00000000000�020464� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_util_trash.py������������������������������������������������������������0000644�0001750�0001750�00000004331�00000000000�017430� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This program is free software; you can redistribute it and/or modify # it under the terms of the 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�00000000034�00000000000�010212� x����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������28 mtime=1614540386.0351863 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������quodlibet-4.4.0/tests/test_windows.py���������������������������������������������������������������0000644�0001750�0001750�00000003652�00000000000�016751� 0����������������������������������������������������������������������������������������������������ustar�00lazka���������������������������lazka������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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") ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������