pax_global_header00006660000000000000000000000064131142761060014513gustar00rootroot0000000000000052 comment=9fcafbd292aa0e432f68587ef02448f90e5bd40f pnmixer-0.7.2/000077500000000000000000000000001311427610600132035ustar00rootroot00000000000000pnmixer-0.7.2/.gitattributes000066400000000000000000000003411311427610600160740ustar00rootroot00000000000000# Default conflict marker size is 7 which causes some of the headings in # markdown files to trigger git diff --check: 'leftover conflict marker' # when the heading is exactly 7 characters long. *.md conflict-marker-size=100 pnmixer-0.7.2/.githooks/000077500000000000000000000000001311427610600151105ustar00rootroot00000000000000pnmixer-0.7.2/.githooks/pre-commit000077500000000000000000000044051311427610600171150ustar00rootroot00000000000000#!/bin/sh # # A hook script to verify what is about to be committed. # Based on the default pre-commit hook ('.git/hooks/pre-commit.sample'), # with additional checks for PNMixer. # Called by "git commit" with no arguments. The hook should # exit with non-zero status after issuing an appropriate message if # it wants to stop the commit. # # To enable this hook, place this file into ".git/hooks/pre-commit". if git rev-parse --verify HEAD >/dev/null 2>&1 then against=HEAD else # Initial commit: diff against an empty tree object against=4b825dc642cb6eb9a060e54bf8d69288fbee4904 fi # If you want to allow non-ASCII filenames set this variable to true. allownonascii=$(git config --bool hooks.allownonascii) # Redirect output to stderr. exec 1>&2 # Cross platform projects tend to avoid non-ASCII filenames; prevent # them from being added to the repository. We exploit the fact that the # printable range starts at the space character and ends with tilde. if [ "$allownonascii" != "true" ] && # Note that the use of brackets around a tr range is ok here, (it's # even required, for portability to Solaris 10's /usr/bin/tr), since # the square bracket bytes happen to fall in the designated range. test $(git diff --cached --name-only --diff-filter=A -z $against | LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0 then cat <<\EOF Error: Attempt to add a non-ASCII file name. This can cause problems if you want to work with people on other platforms. To be portable it is advisable to rename the file. If you know what you are doing you can disable this check using: git config hooks.allownonascii true EOF exit 1 fi # If there are whitespace errors, print the offending file names and fail. if ! git diff-index --check --cached $against --; then echo "Please fix whitespace errors before committing." exit 1 fi # If the man page was modified, ensure the date was updated as well. man_file=$(git rev-parse --show-toplevel)/data/man/pnmixer.1.in if ! git diff --cached --diff-filter=M --quiet --exit-code -- "${man_file}" ; then cur_date="$(date +'%B %Y')" man_date="$(head -n1 $man_file | cut -d' ' -f4-5 | tr -d '\"')" if [ "$cur_date" != "$man_date" ]; then echo "Error: the date in '$man_file' needs to be updated and should be exactly:" echo " '$cur_date'" exit 1 fi fi pnmixer-0.7.2/.gitignore000066400000000000000000000005351311427610600151760ustar00rootroot00000000000000# compiled *.o # temp *~ # ycm .ycm_extra_conf.py .ycm_extra_conf.pyc # generated /data/desktop/pnmixer.desktop /data/man/pnmixer.1 /src/config.h /src/html /src/latex /src/pnmixer /src/Doxyfile # i18n /po/*.gmo # cmake /build/ CMakeFiles/ CMakeCache.txt Makefile cmake_install.cmake # release stuff /pnmixer_signify.* /SHA256* /*.tar.gz /*.asc pnmixer-0.7.2/.travis.yml000066400000000000000000000021431311427610600153140ustar00rootroot00000000000000sudo: required services: - docker language: c env: - CC=gcc WITH_GTK3=OFF WITH_LIBNOTIFY=OFF ENABLE_NLS=OFF CMAKE_GENERATOR="Ninja" - CC=gcc WITH_GTK3=OFF WITH_LIBNOTIFY=ON ENABLE_NLS=ON CMAKE_GENERATOR="Unix Makefiles" - CC=gcc WITH_GTK3=ON WITH_LIBNOTIFY=OFF ENABLE_NLS=OFF CMAKE_GENERATOR="Unix Makefiles" - CC=gcc WITH_GTK3=ON WITH_LIBNOTIFY=ON ENABLE_NLS=ON CMAKE_GENERATOR="Ninja" - CC=clang WITH_GTK3=ON WITH_LIBNOTIFY=ON ENABLE_NLS=ON CMAKE_GENERATOR="Ninja" before_install: - docker pull debian:unstable script: - docker run -ti -v "`pwd`":/pnmixer debian:unstable sh -c "apt-get update && apt-get install -y clang cmake doxygen gettext libasound2-dev libgtk-3-dev libgtk2.0-dev libnotify-dev ninja-build && cd /pnmixer && mkdir build && cd build && cmake -DWITH_GTK3=${WITH_GTK3} -DWITH_LIBNOTIFY=${WITH_LIBNOTIFY} -DENABLE_NLS=${ENABLE_NLS} -DBUILD_DOCUMENTATION=ON -G \"${CMAKE_GENERATOR}\" -DCMAKE_C_COMPILER=\"${CC}\" .. && if [ \"${CMAKE_GENERATOR}\" = \"Ninja\" ] ; then ninja && DESTDIR=`pwd`/install ninja install ; else make && make DESTDIR=`pwd`/install install ; fi" pnmixer-0.7.2/AUTHORS000066400000000000000000000001631311427610600142530ustar00rootroot00000000000000Julian Ospald El Boulangero Nick Lanham Lee Ferrett (OBMixer) Paul Sherman (AbsVolume) Rob Eberts (volumecontrol) pnmixer-0.7.2/CMakeLists.txt000066400000000000000000000032111311427610600157400ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.0) project(PNMixer) ## cmake modules set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/") include(FindPkgConfig) include(GNUInstallDirs) include(PNMixer_macros) ## version and global project vars set(PNMixer_VERSION_MAJOR 0) set(PNMixer_VERSION_MINOR 7) set(PNMixer_VERSION_MICRO 2) set(PACKAGE_VERSION "${PNMixer_VERSION_MAJOR}.${PNMixer_VERSION_MINOR}.${PNMixer_VERSION_MICRO}") set(PACKAGE "pnmixer") ## options option(WITH_GTK3 "Use Gtk3 as toolkit" ON) option(WITH_LIBNOTIFY "Enable sending of notifications" ON) option(ENABLE_NLS "Enable building of translations" ON) option(BUILD_DOCUMENTATION "Use Doxygen to create the HTML based API documentation" OFF) ## packages required across multiple subdirectories if(ENABLE_NLS) # find gettext programs find_package(Gettext) FIND_PROGRAM(XGETTEXT_EXECUTABLE xgettext) IF(XGETTEXT_EXECUTABLE) MESSAGE(STATUS "Found xgettext: ${XGETTEXT_EXECUTABLE}") ELSE(XGETTEXT_EXECUTABLE) MESSAGE(FATAL_ERROR "xgettext not found") ENDIF(XGETTEXT_EXECUTABLE) endif(ENABLE_NLS) ## subdirectories add_subdirectory(data) if(ENABLE_NLS) add_subdirectory(po) endif(ENABLE_NLS) add_subdirectory(src) ## additional global targets # indent-code add_custom_target(indent-code COMMAND "${CMAKE_SOURCE_DIR}/cmake/scripts/astyle.sh" WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}") # indent-xml add_custom_target(indent-xml COMMAND "${CMAKE_SOURCE_DIR}/cmake/scripts/xmllint.sh" WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}") ## install git hook execute_process( COMMAND "${CMAKE_SOURCE_DIR}/cmake/scripts/install-git-hook.sh" WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}") pnmixer-0.7.2/COPYING000066400000000000000000001045131311427610600142420ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . pnmixer-0.7.2/ChangeLog000066400000000000000000000110301311427610600147500ustar00rootroot00000000000000Entries are sorted chronologically from oldest to youngest. Starting with PNMixer entries are labeled with release version. version 0.7.1: - Improvements: - Handle cards without mute switch by graying out the switch - Replace deprecated GtkTable with GtkGrid - Translations: - Use modern 'gettext' instead of 'intltool' - New translations: Serbian - Build infrastructure: - Switch from Autotools to CMake - Make the build reproducible - Simplify travis build and only build on debian:unstable version 0.7: - PNMixer went through a major rewrite ! The new code share little with the previous 0.6 version. - New translations: Croatian, Dutch, Simplified Chinese, Ukrainian, Vietnamese. - Icon theme is now more restrictive and more usable. The user can choose between the system icon theme, or the PNMixer icon theme. - Volume change improvements: - 2 steps are configurable: normal and fine. - They apply to every way of changing volume: keyboard, mouse, hotkeys. Before, there was still some hard-coded steps here and there. - Fine-grained (decimal) steps are now possible. Some USB DACs need such fine tuning. - Volume popup orientation is now configurable (horizontal or vertical). - Debug messages are now available using the `-d` command-line option. There's no need to rebuild PNMixer anymore. - Build infrastructure: - new rules `indent-code` and `indent-xml`. version 0.6: - GTK3 support (use './autogen.sh --without-gtk3' to use GTK2 instead) - Notifications support (use './autogen.sh --without-libnotify' to disable) - New translations: Italian and Russian - Tooltip is more informative - Improvements in build architecture: - Travis support (used by GitHub) - Doxygen documentation added to the code (type 'make doc') - 'data' split in sub-directories, populated with Makefiles.am - use 'intltool' instead of 'glib-gettext' to handle translations - desktop file is now translated and part of POTFILES - Better handling of USB soundcards that are unplugged: - A notification is sent - Another soundcard in the list (starting with the default) is opened, so that PNMixer is still usable and useful - If USB card is re-plugged afterward, one should click 'Reload Alsa' in the popup menu, so that PNMixer selects the USB card - Lots of bug fixes version 0.5: - Bug fixes (including but not limited to): - Infinite loop if pavucontrol isn't installed - Draw volume meter on different sized icons - Better error handling - Allow changing of volume meter color - Move to using GtkBuilder for UI specification - Add HotKey support - Add .desktop file so PNMixer will show up in program lists version 0.4: - Numerous bug fixes including (but not limited to) - fix stuck volume when vol is at max - gracefully handle an unexpected sound system crash - Add option to draw a meter on the systray icon with the volume level - French translation (thanks to Matthieu Bresson) version 0.3: - Allow selection of Alsa channel/card - Track volume when it's changed externally - Deal with cards that have fewer than 100 steps - Start using translations and add a German translation - General code clean-up and bug fixing version 0.2: - First release of forked project, adds: - Volume adjustment with the scroll wheel - Texual display of volume level in popup window - Continuous volume adjustment when dragging the slider (not just when you let go) - Use system icon theme for icons and use mute/low/medium/high volume icons - Configurable middle click action - Preferences for: - volume text display - volume text position - icon theme - amount to adjust per scroll - middle click action Thursday 03 September 2009 - Changes from the previous version; - This application now interfaces with ALSA rather than OSS as the oss mixer device will not allow access to theu range of the Master volume channel in future versions of ubuntu. - As interfacing with ALSA slows the application down, volume changes now only take affect when the scale is released. Friday 28 August 2009 - Initial version created/realesed based on the code from AbsVolume, which was written by Paul Sherman and Rob Eberts. Changes from the previous program which have taken place include; - New UI similar to gnomes mixer applet. - New callbacks such as close/hide when focus is lost. - Mixer now uses the master control to enable compatibility with pulse audio as well as alsa. - New Icons which indicate if mute is enabled - Program now calls pavucontrol rather than alsa mixer but this will be configurable in future versions. pnmixer-0.7.2/HACKING.md000066400000000000000000000076231311427610600146010ustar00rootroot00000000000000Hacking ======= Table of Contents ----------------- * [Getting Started](#getting-started) * [Design Overview](#design-overview) * [Coding Style](#coding-style) * [How to Contribute](#how-to-contribute) * [Tips and Tricks](#tips-and-tricks) Getting Started --------------- At first, be sure to run PNMixer from the root directory, otherwise it won't find the data files. cd build ./src/pnmixer To switch on debug messages, invoke PNMixer with the `-d` command-line option. ./src/pnmixer -d To run PNMixer in another language, use the `LANGUAGE` environment variable. Beware that the language files used will (probably) be the ones installed on your system, not the ones present in the source. LANGUAGE=fr ./src/pnmixer In order to build the documentation, be sure to have [Doxygen](http://www.doxygen.org) and [Graphviz](htpp://www.graphviz.org) installed and have configured `BUILD_DOCUMENTATION=ON` in cmake. Then run the following command to view the doc. x-www-browser ./build/src/html/index.html Design Overview --------------- The lowest level part of the code is the sound backend. Only Alsa is supported at the moment, but more backends may be added in the future. The backend is hidden behind a frontend, defined in `audio.c`. Only `audio.c` deals with audio backends. This means that the whole of the code is blissfully ignorant of the audio backend in use. `audio.c` is also in charge of emitting signals whenever a change happens. This means that PNMixer design is quite *signal-oriented*, so to say. The ui code is nothing fancy. Each ui element... * is defined in a single file * strives to be standalone * accesses the sound system with function calls * listens to signals from the audio subsystem to update its appearance There's something you should keep in mind. Audio on a computer is a shared resource. PNMixer isn't the only one that can change it. At any moment the audio volume may be modified by someone else, and we must update the ui accordingly. So listening to changes from the audio subsystem (and therefore having a *signal-oriented* design) is the most obvious solution to solve that problem. Coding Style ------------ This is more or less kernel coding style. Try to match the surroundings. For automatic code indentation we use [astyle](http://astyle.sourceforge.net/). Please run `make indent-code` if you want to indent the whole sources. To indent the xml ui files, we use [xmllint](http://xmlsoft.org/xmllint.html). Please run `make indent-xml` if you want to indent the xml ui files. ### Naming conventions for signal handlers Gtk signals are usually tied to a handler in the ui file. Therefore there's no need to explicitly connect the signal handler in the C code, this is done automatically when invoking `gtk_builder_connect_signals()`. Signal handlers are named according to the following convention: `on__`. Please stick to it. Signal handlers are NOT static functions, therefore names may clash in the future when adding new signal handlers. To avoid that, either make signal handlers static (this involves more fiddling with `gtk_builder`), or change the naming convention. ### Comments * comments are in doxygen format * all functions, all data types, all macros, all typedefs... basically everything * comments where people read them, so preferably at the definition of a function ### Good practices * use const modifiers whenever possible, especially on function parameters * if unsure whether to make a function static or not, make it static first * use unsigned ints instead of signed ints whenever possible How to Contribute ----------------- * [pull request on github](https://github.com/nicklan/pnmixer/pulls) * email with pull request * email with patch Tips and Tricks --------------- * if you use vim with [youcompleteme](http://valloric.github.io/YouCompleteMe/), you can use the following [.ycm_extra_conf.py](https://gist.github.com/hasufell/0a97cc13de3ef2f061bb) pnmixer-0.7.2/MAINTAINING.md000066400000000000000000000075501311427610600152720ustar00rootroot00000000000000Maintaining =========== Table of Contents ----------------- * [Releasing](#releasing) * [Translating](#translating) Releasing --------- When we enter RC stage... - ensure that version in `CMakeLists.txt` is the right one - translations should be updated (see below) - RC releases can be created simply with git tags (preferably signed) For final releases, we want to create an archive manually, additionaly to the tag. This is to ensure that we have an persistent archive for a given version. The procedure looks like that. export tag=v0.7.1 git tag -s -m "Release ${tag}" ${tag} git archive --prefix=pnmixer-${tag}/ --format=tar.gz -o pnmixer-${tag}.tar.gz ${tag} sha256sum --tag pnmixer-${tag}.tar.gz > SHA256 gpg --armor --detach-sig SHA256 gpg --armor --detach-sig pnmixer-${tag}.tar.gz signify -S -s pnmixer_signify.sec -e -m SHA256 unset tag Then upload the files `SHA256`, `SHA256.asc`, `SHA256.sig`, `pnmixer-${tag}.tar.gz` and `pnmixer-${tag}.tar.gz.asc` to the GitHub release page. Translating ----------- When a new version of PNMixer is about to be released, we need to inform the [Translation Project](http://translationproject.org) so that they can update the translations. The TP just needs to know where to download an up to date archive of PNMixer. This archive must contain an up to date POT file. The TP is considered as our upstream when it comes to the PO files. Our job is to provide them an updated version of the POT file before each new release, and their job is to provide us with freshly translated PO files. There should be no exception to this workflow. We should never modify the PO files ourselves, and we should never accept translations from another channel than the TP. In order to update the POT file, one has to run the following command from the `build` directory. make -C po update-pot # Then commit the new POT file The procedure for announcing a new version of PNMixer to the TP is thoroughly described on the [maintainters](http://translationproject.org/html/maintainers.html) page. In a nutshell, send a mail to , use `pnmixer-.pot` as the subject, and include in the body the url of the new PNMixer archive. So, let's sum up the steps to follow to update the translations. - update the pot file, commit. - tag a new version (don't forget to bump the version where need be), commit. - push the changes and the tags. - have a look on the GitHub release page, copy the url of the `tar.gz` archive. - send a mail to the TP with this url. Please note that the TP will process a POT file only once, so another submission must use a newer version. To know about the current translation status, visit the [pnmixer textual domain ](https://translationproject.org/domain/pnmixer.html) page on the TP. Whenever translations are updated, we (elboulangero) get notified by email. The latest translations can be imported back in PNMixer at any time, using the following command. rsync -Lrtvz --exclude=ru.po --exclude=zh_CN.po \ translationproject.org::tp/latest/pnmixer/ po/ # Then commit the new PO files As you can see, we exclude two translations. The reason is that I accepted these translations as solo patches some time ago, and afterwards got in touch with the TP about this matter, which resulted in having the two languages marked as external. Nobody will update it on the TP side, and our local versions are newer, so we must exclude it from the rsync. We can live with that, but if the authors of these two translations don't show up to provide up to date versions, we should get back in touch with the TP and try to sort that out. Ultimately, we want no exception of this kind, only translations from the TP. Anyway. After importing translations, don't forget to: - update the translators list in the "About" dialog. - update the `ChangeLog`. - if new languages have been added, add them to the file `po/LINGUAS`. pnmixer-0.7.2/README.md000066400000000000000000000121631311427610600144650ustar00rootroot00000000000000PNMixer [![Build Status](https://travis-ci.org/nicklan/pnmixer.svg?branch=master)](https://travis-ci.org/nicklan/pnmixer) ======= Table of Contents ----------------- * [About](#about) * [Download](#download) * [Compilation and Install](#compilation-and-install) * [Distro packages](#distro-packages) * [Manual](#manual) * [Icons](#icons) * [Translation](#translation) * [TODO/Help wanted](#todohelp-wanted) * [Known Bugs](#known-bugs) About ----- PNMixer is a simple mixer application designed to run in your system tray. It integrates nicely into desktop environments that don't have a panel that supports applets and therefore can't run a mixer applet. In particular it's been used quite a lot with [fbpanel][] and [tint2][], but should run fine in any system tray. PNMixer is designed to work on systems that use ALSA for sound management. Any other sound driver like OSS or FFADO are currently not supported (patches welcome). There is no *official* PulseAudio support at the moment, but it seems that PNMixer behaves quite well anyway when PA is running. Feel free to try and to give some feedback. PNMixer is a fork of [OBMixer][] with a number of additions. These include: - Volume adjustment with the scroll wheel - Select which ALSA device and channel to use - Detect disconnect from sound system and re-connect if requested - Bind and use HotKeys for volume control - Textual display of volume level in popup window - Continuous volume adjustment when dragging the slider (not just when you let go) - Draw a volume level onto system tray icon - Use system icon theme for icons and use mute/low/medium/high volume icons - Configurable middle click action - Preferences for: - volume text display - volume text position - icon theme - amount to adjust per scroll - middle click action - drawing of volume level on tray icon Source and so on are at: [fbpanel]: https://github.com/aanatoly/fbpanel [tint2]: https://gitlab.com/o9000/tint2 [obmixer]: http://jpegserv.com/?page_id=282 Download -------- Latest version can always be found at: ### Verifying a release tarball Releases can be verified via [signify](https://github.com/aperezdc/signify). Get the [pubkey](https://github.com/nicklan/pnmixer/wiki/signify_keys/pnmixer_signify.pub) and [verify](https://github.com/nicklan/pnmixer/wiki/signify_keys/pnmixer_signify.pub.asc) it against the GPG key `0x511B62C09D50CD28`. Download the static tarball and `SHA256` as well as `SHA256.sig` into the same directory, then run: ```sh signify -V -p pnmixer_signify.pub -m SHA256 ``` Alternatively you can just GPG-verify the tarball with the detached signature. Compilation and Install ----------------------- The best way to install most software is via your distribution. Only install manually if your distribution does not provide a package. ### Distro packages * [Debian](https://packages.debian.org/search?keywords=pnmixer&searchon=names&suite=all§ion=all) * [Gentoo](https://packages.gentoo.org/packages/media-sound/pnmixer) * [Exherbo](https://git.exherbo.org/summer/packages/media-sound/pnmixer/index.html) * [Arch Linux (unofficial, in AUR)](https://aur.archlinux.org/packages/?O=0&K=pnmixer) ### Manual CMake Options: - `WITH_GTK3`: Use Gtk3 as toolkit (default on) - `WITH_LIBNOTIFY`: Enable sending of notifications (default on) - `ENABLE_NLS`: Enable building of translations (default on) - `BUILD_DOCUMENTATION`: Use Doxygen to create the HTML based API documentation (default off) First, make sure you have the required __dependencies__: - build: - cmake - doxygen (when building documentation) - graphviz (when building documentation) - gettext (when building translations) - pkg-config - build+runtime: - alsa-lib (aka libasound on some distros) - glib-2 - >=gtk+-3.12 (or >=gtk+-2.24 when disabling gtk3) - libnotify (when enabling notifications) - libX11 - runtime suggestions (PNMixer can use a full mixer): - alsamixergui - gnome-alsamixer - xfce4-mixer To __install__ this program cd to this directory and run: mkdir build cd build cmake .. make make install Icons ----- Icons are a slightly modified versions of the icons from Paul Davey's "Umicons Volume 2" icon set. You can find his website at: Translation ----------- PNMixer is translated through the [Translation Project](http://translationproject.org/). If you wish to make or update a translation for PNMixer, please get in touch with the relevant team on the TP. Solo translations won't be accepted. You can visit the PNMixer page on the TP at . TODO/Help wanted --------------- - [Move away from deprecated GtkStatusIcon?](https://github.com/nicklan/pnmixer/issues/81) Known Bugs ---------- - On panel sizes of 21 and 22 pixels, the volume meter offset can be messed up (gtk3 only). This seems to be a gtk3 bug, not a PNMixer one. Also see [issue 136](https://github.com/nicklan/pnmixer/issues/136). You can also skim through the [issue tracker](https://github.com/nicklan/pnmixer/issues?q=is%3Aissue+is%3Aopen+label%3Abug). pnmixer-0.7.2/cmake/000077500000000000000000000000001311427610600142635ustar00rootroot00000000000000pnmixer-0.7.2/cmake/Modules/000077500000000000000000000000001311427610600156735ustar00rootroot00000000000000pnmixer-0.7.2/cmake/Modules/PNMixer_macros.cmake000066400000000000000000000010671311427610600215670ustar00rootroot00000000000000# symlink the given files to the corresponding binary directory in case # we do out-of-source build macro(symlink_to_binary_dir _files) foreach(_file ${_files}) get_filename_component(_filename ${_file} NAME) file(RELATIVE_PATH _rel_syml "${CMAKE_CURRENT_BINARY_DIR}" "${_file}") if (NOT EXISTS "${CMAKE_CURRENT_BINARY_DIR}/${_filename}") execute_process( COMMAND ln -s "${_rel_syml}" "${CMAKE_CURRENT_BINARY_DIR}/${_filename}" WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" ) endif() endforeach() endmacro(symlink_to_binary_dir) pnmixer-0.7.2/cmake/scripts/000077500000000000000000000000001311427610600157525ustar00rootroot00000000000000pnmixer-0.7.2/cmake/scripts/astyle.sh000077500000000000000000000003471311427610600176160ustar00rootroot00000000000000#!/bin/sh which astyle >/dev/null || { echo "'astyle' is required, please install it"; exit 1; } sed -i 's/[ \t]*$//' src/*.[ch] astyle \ --style=linux \ --indent=tab=8 \ --align-pointer=name \ --suffix=none \ src/*.[ch] pnmixer-0.7.2/cmake/scripts/install-git-hook.sh000077500000000000000000000003541311427610600215000ustar00rootroot00000000000000#!/bin/sh if [ -f .githooks/pre-commit ] && [ -d .git ] && [ ! -f .git/hooks/pre-commit ]; then cp -p .githooks/pre-commit .git/hooks/pre-commit && chmod +x .git/hooks/pre-commit && echo '-- Activated pre-commit hook.' || : fi pnmixer-0.7.2/cmake/scripts/xmllint.sh000077500000000000000000000003461311427610600200030ustar00rootroot00000000000000#!/bin/sh which xmllint >/dev/null || { echo "'xmllint' is required, please install it"; exit 1; } for file in data/ui/*.glade; do mv "${file}" "${file}.bck" xmllint --format "${file}.bck" > "${file}" rm "${file}.bck" done pnmixer-0.7.2/data/000077500000000000000000000000001311427610600141145ustar00rootroot00000000000000pnmixer-0.7.2/data/CMakeLists.txt000066400000000000000000000001671311427610600166600ustar00rootroot00000000000000add_subdirectory(desktop) add_subdirectory(icons) add_subdirectory(man) add_subdirectory(pixmaps) add_subdirectory(ui) pnmixer-0.7.2/data/desktop/000077500000000000000000000000001311427610600155655ustar00rootroot00000000000000pnmixer-0.7.2/data/desktop/CMakeLists.txt000066400000000000000000000013421311427610600203250ustar00rootroot00000000000000if(ENABLE_NLS) add_custom_command(OUTPUT pnmixer.desktop COMMAND ${GETTEXT_MSGFMT_EXECUTABLE} --desktop -d "${CMAKE_SOURCE_DIR}/po" --template ${CMAKE_CURRENT_SOURCE_DIR}/pnmixer.desktop.in -o ${CMAKE_CURRENT_BINARY_DIR}/pnmixer.desktop DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/pnmixer.desktop.in") else(ENABLE_NLS) add_custom_command(OUTPUT pnmixer.desktop COMMAND cp ${CMAKE_CURRENT_SOURCE_DIR}/pnmixer.desktop.in ${CMAKE_CURRENT_BINARY_DIR}/pnmixer.desktop DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/pnmixer.desktop.in") endif(ENABLE_NLS) add_custom_target(desktop-files ALL DEPENDS pnmixer.desktop) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/pnmixer.desktop" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/applications") pnmixer-0.7.2/data/desktop/pnmixer.desktop.in000066400000000000000000000007141311427610600212510ustar00rootroot00000000000000[Desktop Entry] Name=PNMixer GenericName=System Tray Mixer Comment=An audio mixer for the system tray # TRANSLATORS: Search terms to find this application. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! Keywords=alsa;audio;mixer;sound; Exec=pnmixer TryExec=pnmixer # TRANSLATORS: Do NOT translate or transliterate this text (this is an icon file name)! Icon=pnmixer Terminal=false Type=Application Categories=AudioVideo; pnmixer-0.7.2/data/icons/000077500000000000000000000000001311427610600152275ustar00rootroot00000000000000pnmixer-0.7.2/data/icons/CMakeLists.txt000066400000000000000000000001411311427610600177630ustar00rootroot00000000000000install(FILES pnmixer.png DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/128x128/apps") pnmixer-0.7.2/data/icons/pnmixer.png000066400000000000000000000362301311427610600174230ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aËsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÛ &‡êQiTXtCommentCreated with GIMPd.e IDATxÚí½y”dW}çù¹÷í±eäVKÖ¢Z¥ªR©VIhA ˰= #l#™Í¸Û½Îé±§{¦—évgÆæôpNÏð‡ÍÐîÅà¶lc·wÆ $Õ¾ï{eeVÆñÖ{çû"•ÊÚ„ åïœwbxñ~ßû»¿ý‹´H‹´H‹´H‹´H‹´H‹´H‹ô"ñ½üñm|pMµjý=ß;,KD–-ÚaOÕ¤û…àyËǾüGŸ«/²éû>ò¡W«ò_xžX¡h Zk¤4§¤©e‰3iÊWm[þi§­þâÏþâs×Yö:Àº5S+ì=>nýS­!Ë Óm[¢Ñd©FkÖù ”¥\H3ý{åŠûÙßùߨ³Èº×!Ö­yqÙrû×&'íŸSÊ0wtÔÇó-,[@ˆ4SÄaF¦Ä±"ËB˜÷#ˆ<×þR«ÿû¿ÿÿýõ" _GxË›˜‡’$[¦TG}Æ'T¦Í3ÙfKˆ¢Œ(Êèt¢0ƒNSñ_]×ú·_üÒo.J„WHÖwãG6¬û€œ«Ò;wíJ„ÐÌ2½\­úFôkÈ¡˜¦šn7¥ÑQ™&(8xžE¥â6Ò’d©"Ë´’-Rê>ôÐCÁ½w;|dO{‘¥wGöwãG”2;ºm!ÓT[¤%Ì‚$QÌÎvÄ4ÍȲ )%¶%p]›‘Ñ•²ÇĤM¥âÑlD´Z1iªFêµðŸ !Ÿù±w=óÙʈóÙßú­_?»ÈÚרÕð¶zÜn·ÒO&©ZbIA¹âaY \›nÓlvÉTF–¦¨,%Mb¢(&ŒBêsz½)%Aà‚ÀF+Mk@W<™&ê'7mÞ9¾aÃŽ‹Çï½¾Èâ×^²ûôºÝäç³LOHKR©¸X– Ž3õ{ïÝÆÌÌâ8@+MØxž…H²4¡ÓéÑiGĉ¢Tò¨ŒxHK…)*­)+¥Ÿ’§ï¹gÛäŽ>rdOk‘Õ¯Œm­Ú6ÿHk]’RP®¸H)ètBF««¸÷Þí:ôJEÅ’K–)‚À!SšJť׋èõ"¢(E)Á=÷¬Äóv‡$VH) ¶ÃchýãÛ·?¨7Þ»ãÈÑ£{£E–ßHò»ùcå²\ Œßø¬Æ¶-îßò iš’$±A¦%p] Û)HÓ !ZkÒTS*Ûhréâe.^¨ócïzšýÔ{Y½f‚$ IÓ¬oV®ívãÿ;K³¯½ç=ϾÿVç·qýÄÆõ‹à;D›6íØ¡µú°RÏ·)—]Ò4e||)÷Þû&®\¹Àñãûq=DZð\ ;ƒ²TS(8t:1‚4ØŽ V»‚¦Ç3Ï|˜·¾õq.]ºD»ÝC Ëø`©VúýÛ¶í^²eË®o>¼§÷r u¿˜«ZÀw‚yÓâ(ûi¥4Å‚C±è¦)Û¶í`¤²š“§ŽpæÌ1 E4Q‹qœ¡”ÌÑé$XRbÙ6K–Œ.žçròä)<È£>ÊO¼™íÛ7Ñé4¸páiª‘R"d‰zHkýCëÖn?pò例Ãç7W;¤¿›Ì߸þâ{ ¶ï*Ö¬¹Mšª¸®E¡à)ÅÃ? ºÂ‘#û¹|ù Žã ¤Àu%Ijœ?¾oÑí¦H–-ñ=ß·ÑZ`Û6Apùòe¾õ­o±lÙ2¶mÛÎC=Èò©1._¹@½Ö$B ´f9è§غKLNnýƹóûÕ÷ââ¿$Íw٠ص:NÒg”FøžC¡h£5¼éᇰí2ûöíczú<Aà[h­IR…emKÂ0Åól¤ß÷p]ó)%…BV«ÅW¾òºÝ.›7ofóæÍlß~?õÚ W®\EeF»”R8Zë§´fÇæM;ÿìĉ}ÝE+à;Dë×þ„\¹b¿ùñ{æjWŸ£H .A`cÛ’‰ñ ¤‰Ç‘£û¸råÀèè(õzO}êSüò/ÿŒñOþÉÿÄö÷R*ñi„@´[ñ?‹£ä¿ÿÔ‡>þÀ¢x•é}?þiÙåg/œ;µ¼Ñ˜£:ZSS+±íIæ®×8~b/Ji„8ŽÌ žg‘eFá˔¶I’b;Î t|+êKƒS§Nóþ\·ÄûÞ÷^”ޏ|åqb\ϹÏ`uš©÷ïÚõàŃ÷\”¯ÕQ*Ý•«Ö“$ Ýn‚pùòe’$Åõ|lÇCimB¾©F`rG…)¶ i’aÛ’n7¢Ýî BÉ·"rŒŽV°ì”ßþüçø•_ù5xà!ž~ú'˜˜ð2OKej¢ÕŒÿã»ìÙ¾€W‰žþÐãJ©¬µbÅlǦ×MBÒhÔð|m»Ø–h4fB€ei’D!-HS³úMÚ˜¦Óí’¦êŽ@ ”ƲlFFJ\¼t’÷ï~ ×-ðñ„•«FB¡ù6ƒ€ì_ýàS?ókï|dzr¯EaX :2N§ÓCe‚z½Žm‡‹E\ϼ7‰3¢8A A–)Ç"M ¢0AJˆ£„v»‹w÷W´ßóɲˆÏ|æ3œ0, ¾øÅ/²wï^>ùÉO2µ¢Ê蘛»žI¬¦fgz¿õó?ÿw&p7îà‰%—@4M- ¢22J¯—Å/^¦P€Õ÷LñÈ#ï@kõR™˜†0L‰¢ )L&Pß3¨5ضƒÖÍFçÛ>O!Að¿ñÌÎ^çãÿ8¥’ÃØ˜——« z½tçìLﳟøÄßqp‡tíZMeY– ËW¸e¹´[ —.]&ŽCîY]bÓ¦Œ/%M“—L±TÓë¦har•Ò8¶ÌC’$6+¿ÙhÓnwo(ºë@Jɧ?ýiªÕ*O?ý!OS©8(¥s$?ÚiÇÿjwHS+üÐvŒHÒHY²dívÄåKWùË¿ú+&& Œ—©V'Q*»áóYf@` Fw *ÓhãÂ%:.Ýnü2«ànÉqÚí6¿ú«¿ÊîÝ»yç;~×7éj*4›Ñ/=ûì'~êµÊäë? _3ðürìØVCkÃB&ÜwßJ<·H£ò¿ý'NeË–å”JUcíÝhØ‘¥Šf#&Ë-i™·9Žm*ŽææÄqúmK‚ 8sæ ŸùÌgxï{ßË®; ϳ•¢¡v=ü÷?ó3ŸxÓkú5€þá]™çÚ  ÛíG“KŠlÞ¼žV+¡ÙŒøýßÿ}â¤Ášµ÷ yÉïÿ’)gŠF{Ý”NË„„5+gt&h­HÒ„Ú\}`6Þ‰/ o6ö·Ë²RR.—ùÊW¾Â¾ð>úѱví=TF$Žc ©L©‘V3üìû⣓¯5îŸ8õyýš1{ôÝo©l¯×g¹~ýcã#ÕõZ™™:Bftºuvîx3ÇOœ¢V»–ÛÿÆ3g;VºKRE%¨Ì8‡Œ«X£µ@ š0L ïŽ|FÁ“/»•Râ8àþûïç­o}’_|ÈèõLÍ‚RzĆ·¼õÑßyá…ç5¯úžà=ïùéõAPz{£>Ç\m†±ñžgQ(ø\º8 :ããclXÿÇŽí§RcjÅkÖLR*û‹…¢C¡àäÉ¡‚81Î!)ó±c¼†Y–eP(ø·eY70½ôŸÓZsôèQ~ôG”•+W²ÿ¤%éõ2@ ”ÚŒáÁƒ/~m7¡öOÿÙ²Ú\ô“íN“Ù¹kŒV}, ‚À%M×çjŒŽ–˜›»Ì–Í;Q*À÷|ÞûãϰeËN–/»åËïcù² ”J£‚מ (ºØ¶ME1M5ŽcÑëÅø¾‡ãXÜ ýÞâÿ¥~"O"µ©Õj\¹r…÷½ï}X–Í©SÇPJ…R ¢(}rÇ·ö:´çØ" ðÿ±77}¤ÛéX³³ÓT«ýo-2{­I/ ±mh¶fؽë)Nž>†ãøþŽP©Œ1>¾œU+ïeÍšm¬\±™±ñ• iâ8 9‹2¤„n7¢T ^€¾Óhë޶m,˶íÁã3gÎ`Yïz×»èözy¢©1U¥2KÕSïÝùåãÇ÷Î,`=¸ûGB!ÜŸMâ¨<}õ"•Š‹_°Qyî_¥\äü…kxžMµÐÀºµ»9}úË–­Ìó3²,E婽APbÉäJÖ®ÙÊŠ©ûðýQÜ",˲-¢0&Œ’}'ÒK æüÕÞgvÃ[‚mÛGé¼—‘Þ¦´èž;¿ÿo¾ï0>v¿¸üÍ׿¤ÿå¿üç_¾ÜxhúêElGS*¹!i·Û„aHš&XÒDû $ ™™™eã†|ã¹?ç[ßúKÚ™ê¡2ð=›v;cÛö)ÖmgéÒŽ#èvcÒT²bj«Wo¡×‹hµ®‘eY.ÚÅ >†…Ð?椯NOOsåÊÞò–·pï½÷qêÔQ®Ï6ȳÒ)åcÅ–?¾rõà•ïkÜ óûô¾÷}ts»¼ýêÕ ¤iÌØx€‚N§C’$X–íHâ8ÁvlŠÅµ¹kD±dÇöGyî¹?çÅ¿ÎáC{Øà9ž{îk:üaÔ&ìET*>k×M²bEǵh·"¤ôÙ°îÊå%\½zŽZí:žç¾ÌSØñ} +} +¶msúôi~øaÖ¬YÍÁƒ{i¶¢~ó3Ç÷äºM÷íþ­ã'ö.êë×>ºiÉÒ%ïžž¾DETGÇ¢Óé¦éࢻ®ñëû¾O¡èqîÜi–-]Ï=÷läôéÃ$©"ÍRâ8¤Ñ¨Ñív8sæ4W®\åúõ–ëÖ-aÕêQ´‚z=d|bеk¶233Ë¥Kg ÷`ø~õ÷÷ÿáÕ?¬8J)9zô(k×®eóæ-4›5NŸ>=оšuk7qôØ^¢0¶Mí mÛ”ËE„€F£çyT«#!èõBææ®32b±úžeôº Õê &'Wræìq²¬; Ùþó½ƒ}_B? dÛ6.\ Ûíòö·¿ƒ½û^¤× ‰B…”‚$Ê6·»ÙµS§ö}ë €OúßéŸû¹¿·óÚôÜCÍfrÉgt´@’¤„a8XqÊ–mÛt:6çÏ_dûöÇq,›c'`YMF¯Q.WŸþvP©T°,ãq¬ÕêdY‡û·®&ËÀ’UV­º“'’¤\ǽaÞ †•Åþ0U´,‹C‡±zõjV®\ɉÇPJ’$&hdIžxë“ñÅŸŸ}ÃàïþݸìÒ¥Ú»kµ‚Àel,ívû‘ÛÂxž‡RŠ(бm „´›»w¿•«WÏ1=} Ïs€ŒN§Ç’%¸®‹”&W0 C …¶m£µ¦Ñh233ÍÖÖày.aÏæž{6sâäQ::AÁGð’êrë¿ôiÿþý<öØãÌÌ\#I{ôzýŠ#í¥©^{ÿ–‡þËáÃ/ê7,ÞûžLµ;чæ®_ñmFÇ|„0ÊT%Í·ŽãÇ1išá8’zc–Ri ÷Ý»#G÷Ðëuq=—n·K–eŒá86–e†!ív×uq]w 'œ¿põë—R­Vh5÷¬ÞÄñãGHÓžçâeVB”J)Ò4½fî¤ÓépõêU¶oßÎŋ籛n'1ñ‰Xm Öу_<ø†ÀÇ>þI' ùÈìì´“f)£c>Žc8ú²¿÷öW¡é˜’¦¶­™aãÆ]”Ê#9º×Äîm‹n§G¦,Y2ŽeYxž‡”’^Ïtˆ ‚`À¨S§N±lY™+–ÒiIV­º—Ç tˆm;/Sü†Wý ´Ö} T*’¤G+“ÉlJÚïòÉÇ?÷üóßŠßøÔ§þuxmºóì•+Ó#Q12âS(¸Äq|ÃEŽÑ÷oã8Î_WÄI›^˜²cÛ\¿~… Î`;¾oÓht±mÉää¶í V’$„aˆã˜çÒ4åôé³LL˜Z¹Œ^ס:²”c'öbY†™ÃÁ£~öPš¦@öWÿps !çÏŸgÉ’¥$I”û:LcšªIÇ–³ûö¿ø·oH¼ç=ïñzçï^»6;…!žoÚÂg™¹°}m|8H3ßô2âYÓh\Ãu+lºwÇŽï§Ýj<„€N§‡Ö099Žëš|×5Á ^¯‡Rj`uœ>}–jÕeÉ’¥h=‚ïW8qr/Y–`YÎ ¢xÕ3RJšÍ&ZkªÕ*`ÚÛ†ÝÔ¿¦zó“O>þ[Ï?ÿ­îqœîp݉¿/„°z]Óê¿:êV¸bÀ¨a o­S®];ËøÄ=¬Zµ‘cÇö‘¦ ¾ç ¥ ÙìÕj×uV…”’$I@H’„C‡1±¤H¹8A±°Œ4É8rìÐê†ß– Ý[ ív›õë׆Ž#èõRÓ-S#ZéÊÁC{þð €6ðÊÕ™^¶ln !*Ï3Š^_胠¿¢úA˜0 ÌA–õ¸6} ëw³dÉ Ù›7‹2ï©×Z)X²dÇq€êwÇ\¼x‘ÙÙëœ=sšõ–ŒŽ®¦Ñ¨séÒñ¼JX ¶„þJû} ë FƒB¡ÀÔÔÍfǵétâ~uÓ®w}󸉽§Þ0xÿO|HÎÕz¿ÚjÔV•Ê#†ÂÆ÷-ŠEû†¡}ô}ïýU˜¦é`7à°‰ãíö}ì)l»Â‘Ã{‘BâäE#®+òl†3¦“$afæõz›éé9Î;ƶm‘²Â’ ÓY¬ÝžÄ@BõÝÁÃÅÃy‡}$IÂÜÜ6l4Ÿ••iÂ0ò„ˆ"µµ\Úò¯NŒßذaÓQ”þ¯Y–ÙIS)U‘Ò,FG=@Óh„„aF8y`Ƚ!eÛ¶mšÍæ@"‰aÑj×év¯ñà®§Ð8œ8q¥AàÄŠ¹Z“(L˜˜Á²ìíÞív™››C)͵kM°åK§Ù²e+èK–¬äÀçÑÚ0?Š¢H‡·ƒù–‚én–™FQÊêÕ«i4j‡nÇ$¬º®XÖëªã—.Ü÷†ÀêÕ÷ÿ¬Rꦹ¢:2Ž›‘qrßþ¾À¶­ï/yžú¤Ð–””Ëàe²4¥R)P,Z„aô²\?=«_9Ü/ÝŠãØ4™¦0Äqljõ ÃŽo£ÓérúÌQ,ÛÆuL‡Òv»C­ÖÄum\Ï¥ÕlÑj5h6;ÄqHšHjõkLLT(—39¹‚VëçÏŸa#…@ ˆ¢hМr˜ñÃ’ I’üü"ÆÆÆÃÐä=Æq”á8bíÆ ;Ï?±wÿ÷5}lÛûÓT}DÞ5ÜìùÅÒB@+–-!M£¼«—õ²,]ÇqÁ—8ŽadÇqH’Ä4žPÐéÖÐD<ðÀ[©×®sáÂÙœIfPE«Õ1I(qH†´Z]´VÌ]oã8f)ŽãríÚV¯Úˆ´J¬Z5ÅÙs¸r¹Nšš-ɲÅÀƒÙ·0†u!Ìë–%i5[”+|ßC)“òÖë&äÎχ&'øíóç÷·¾/ðŽwü¤£”þ•Ò+…€ññ~švŠV.år…n×$pŽŽèõÂSµM;Yk`´ÛÆŒ ÈBÁG A&$IFœ4±¤b÷îwR«ÍréâÇíçìÑíFÔë¤TDQ†šf£ƒËD‘FÊŒ0j±rÅ}øþãc%^Üó-´–8®…熧iJÇ7Xým¡ï70SRlª##„a„ç™|Èn7©V÷ðá½ôšÀÆõãc÷ÛsµCwÕkË–Íoc~ÉHFcKzaŠcKâ8¥T2Úy»19YÂum’$}™#¨¿ô/´éû›"„QæúSGâ8¥Ý–Û·ÿ ×f®pùòüÀÅ’¦Ô¼Ýéõ"â(!ŽSâ$Îݹ¦!¥çt:ש,%ÆX²dŠFã.\2úG>Ç Ÿ)”eI’Eq¶ˆþÿh·Û¤™&„0Pã(#Ž*Ó[wîxèK‡í¹öšÀøØý°çj‡²;ýÌCþ¤=2býJ–° PtÃŒ°—aY!´v)WªÄqdT*Žc\·Ãvû°?À²,¢(¢ÛíöÛ0 mäL+º!»h »¶ÿ —.ŸcfæAàÇR›Z•’eŠ$Éò‚S•kê½°ÅÊ›Q™dË–U8ðB>üÒô+°mù²ˆaÿœn´J¥AiI¤8®E§¸a¨J'Nîûo¯YÌÕq7àƒãiãIDAT̘Z¾õ-~ ÿ BH ø¾CšwüJ3…ë Úí.ãcK°¤é îùAPÀu\‰zyd®ï2n47øë“$!Ž”Jql›f«‡Àf×®§8þÍælì1íg\·¯p¾Ä4)Q”˜BÚ¦Xœ TgbbÛîpúÔI‚‚O+²¼g€mßxi_žDJ·°%=GbÛ¥4½^Še±qÓ}~þØñ=sßI|[åáw;akjÊ~·Ê´†BÁ!Ž22eÄ¢V&Æ›73{Çuˆ#M£žÐë™ü€R©tCEϰËutttðúÉœ&³x®VG©”Ë—®s}î(ÍÖeÞû¾OP)/§Ñhc&™«8™é2ï7 …1 {F)½xñ0hÅÕ«|ðIFª#(¥p=´êvôàs¼Ì*èÏFA§Ó¦6×ô¨Žúx¾RºàyüìkZ ¼›™7ïÿ‰Ÿ-¦Yúi­E¥)—]£9G¹Ý,%Y¦(ÍF“±±¥Ø®K·“P.Û¹¸, "yÃ?ú"×qÆ 0Ó‰ãØD‘RG4|?¦Œ±uëc=¶F½Ž´|ß´£µl3ÖVë¼=}îì±,›(î01¾† Pbbrœn·Á™3§ Ûîç ˜s3‰+:„ƒÎ§¡e€Äõ||¿Ÿp"è´´Ö7¬ßùŸNœØÛ~Mànhýº?žfÙÇà8V® åÁ…¹0JkÇÆvQ˜11¾”8ÎÈ”©ü‰ã„BÁ€ ïŠ6ŽãØt Ëô}MÜó’D“$1½^—V«‡í„”KËØ´i§N¦Ýiã:Ò’o R ”6ÙÉfa†ã „pY¾|““>¥b•ƒ÷ užòeI3ÅTA¦ÈKÖÅ Ÿñ°HR ÇöPÚè8¾oÅa˜–ª£nýÀ=_y]`×ÎËRŸ |k½éïgSñi4"„¦%<ý!ÒšjÕ§Óix#”J%šM*.ŒEP,þõaôM-­õ ºg^7 'Ç" ™ÇívËî±téF6nÜÆ‰ãûhuºhÕÏÈ<×6]Èèg%…,]²JÙcíº)8M£q°±mËhø›(Ê-ìŒbøR”PkM™þ†–%Ib›RÉD/Ç(„i¦î{ðÁG>wàÀ Ýלp§´t™·ªP°ÓÊhå¾g£y{3TXfÐ@£S*YÌ^¿ˆÇv˜žî‘e­Mi¼äÂí_о“ÈótÛÆ÷}¢(z™èt:7$|ôC­qM ³èõB´Ñ„ÜsÏN–L®àô©CdYJ¦*KZ¦!•6 '’D‘&!,V¬Ø@±(€“'Ž'íA“mKâÈxúLð(Ÿtg(M¾eexžIƒëõJÅ"~`’SÐÐjÅø¾µêíïxâ7¿ùÍç’×%6Ý·óŽ¢l›”Ë–¦”ÛµèvMKx!òmÀ<0{cÞó/IºT«X¶C·£T«>I’àûþ éa}u»]”Rø¾?pƘò,‡0Jp]iô˘xíN$iaɘûî{˜±±e\¸p’$‰‘–ñ#$‰"Ž ã“$L8zÕª{)—=FGKœ=7ÃÌÌ9£/`¦ÅI†ï“VJãú{Yî…„°— Æá¡H‰xÆŸ ÝnJšªI×µìÙó¡×ž}æKÛäWA5‚‘'/à#e0Æ#0ŒÁ4…N3MšÆÆóJHË¡Õ2LéÏ.Š7$bJ)qÃto!lœM‚ë³<ÏÔHË$Îε Ã:®±bÅF&ÆWrýúU’$ÊŶ~©&å8¨,eÙÒUŒŽM06î13rþÂsa¥DHP™©aHSÓÍÔ²i¦ÒÁL2Õ¹n‘7ÂV.Å¢›["¦/"B,yê©ÇÿÃsÏ=§_WX·nÇOiÍA µ ðm E‡FÝ ‹ùR˜¡Mýl!En&Ä8®"Mm|¿@«•à¸&qDkS:Ö—RÊ?ŒFnÛöÀKèº6ZéAÿ@)Y^^^¯w©×g‰¢ë e&'W“)EuRJ+£ZR‚€ (²bj-ããÝŽàÜùStÚu<ß!o…ëÚƒYÆ*ѹØ7¥ÃÒŒ³Íd&„¡&<<ßÂu,z½”8Ê–Šöo¿ðÂó×_7xh÷‡¥K'?­‰W*¥°-ÓW¯P4+YkÆû%…¤Pt |›L™þ>h‘OÉÐ$t;M²Lã{:m3=¤Xz©l»¿êMñH4¸à®k Jz½^žgèÐíÆXŽDef€ÌÍ·(Jh6;4uª£.¥âåò8Qæñ{3×X)…e›pðŠXº¬ˆÓÓuΟ;A©ìÚË»®E’¨<‹I‘e:— ¦Ó¹év®ñ}ì… –eº¦?‚ ÝNlÛ–3û÷¿ø•× ¶Þÿ–7mÚ²ö_diš{ó,J%£œÅ±"ÍŒ‰å:6kÖŽ35U¥2âS.»f0´‚81#cãHåf_( ±mŸ(2>øbÑüN§;Èèv{´š1ŽcaY’ ðó­!#I!SšN'Âól#}´QÚTJgtÚ=”Ê7%ê¥Ò$BÚÄQÛrŒûXJ’$bùòuŒV˸ž¤Û‘œ:}¥SlÛ˜tI>ë¨ßcز¤™d ã+@š¶v±ixe×óÌx]GÒí&Dq¶ú‰Çýì‹{ž^X¿îáÛ¹sÝãJÙ~»Ý$I6"פMÄ=k&+˜²l<Ï¥Tò©V|ßFe:Ÿ÷kößRQ1W«¡µ Mm¢ÈtqÉÜÜ\žâ¥i5c¦§[¡ISA±è3w½…ãØ¤©­L(V†€ÀõŒ4‰“„z½Gš(–, Òª‚ B’&˜~ׂ,K™œ\ÁøøŽah1;{…«W¯ ¥…ç»>Ž®k&žš fŠc µ·5zOàY„aŠmyÛ6Ñ;tÌ/XGöí{qÿk×@ô]Ä#•MGÖoXvʲü÷i­étš8®…ï;ı"NãcE¦¦ª¹ýËP!¦ã¸”ʪUŽ(Έc´$##צgó0°EJJå€BÁ¦Õ2¹Å’G«•ÐëD(ÒhĤYF½Ö@é,/Û±òÆ…+MzI’R«õè´Ãü»-Ò,Ãs‹Ha†\$qL©XaÍÚõTGê×c2•qæÌQ²LeÎ’y“iiïØZ@å PjçÚ9àMσ `ƒ„°—ÒëfËÖ­ÝñNžÚ—½&0¸ru_üÄ?<.…ý¬ëxôÂB˜´—(ÌÐJ³|ªJ©ä¸á‚Ðá¸u´@±è…)­fŒíX¹Ë4¤Õj†1aÏÆ±ƒ\94×§\ñ¹~=DkÓá[ ßwèv;XVîoÈ'“ö‡RXRä­çlÒ$¥ÝŽi6zxžMu¤€ë ÀFZ&£'MÆÆ–°~ýRjµÛö9sö(IçsœÁä4Õ¸žÌKẒ0T=úÊ`J–šVú¾oã{6½nJ’¨UBÈÿ~âäÞ ¯ +àM?¹Úu‚g,ÛHÓ„6Ε ¦¦ª¸®7füÌ‚”Aà16V$˳׻ …‚CeÄ¡6W§ÕjÇ­‹¹‡1Ãu%¥¢‡eKêõ.å’‹ãúxžOš&DQŒçšñôBbt i¦‘¹"ìå’£Þ%Iª£Å’‹ëJ,éÑét8~ü W¯^¦Û‹(—Æèv[LO_D+3ìʶ$Ž-IRëZyE‘ÂqMDǑı±l[E™RHéâ86Å¢C³£•"ͨ:µïO^¸÷ÞÇÇGª•Ù¶--i\¿®«L7a19YÎ ìÓ;¿e«eYŒ—LJx#¤ÛM)—*#Ff³ž×á—ˆ"‹(Jñ<# Šf#6N"Ï¥P(aÛ‚^æÊ£EklGây–ñúņQ£¶Z]j53èjl¬HeÄòÒTpáÂΞ=ÁÅ‹'ÑZÑí¶Ñygsi <¿¯ù‹¼*Hãæ +}¿€çÛFèÏBJ4BØJNžò–!+7oÚýÇŽï^ó)ß§îY½ü×sK¶å¤K–TMâ’¥ËÊ7TÞ§€/Ô·Ï„år`ÀãIjs!•Škæ GŠv»I§ÓÀqlY¦Ó…N;Æu“E¤eQ«‡ùð)×qФD‘eë8’,ƒn7% ³ÜO‘'¡HÓŒz½E½ÖÁ¶l&– °-KzyvRË4“T „(½&jaŽ“o;¹¦Æg µñ‰¸ž$ŠZÓµZõŒG2ÎF\Ï~îÈ‘=G_ó8wþ…ÎOüÈžçßgYV"ÍX15I±8Âú K)•ÊA€çy¸®;H§š¿%ô~$Ͳ%Õj׳™¾ÚƲ$®k2k:íˆV»ŽR ÅâB´ÛíV2Ð ‚Àcé²"…b€ey—òžÉÍ‹2:ybÚÄð¤)‘Ë8Ž™›kÐl†‹K—–ñ};OwÒT0i•‘¤Fšxž=ˆ]ô£ÆÑ×E™2)ŽÌg,Ù¯—´Z1å’sðÀ¿úºˆ¬\ùàÔŠKßÖ8®K§Q,ØŒŽ• ]—B¡@¹\¦R©066Æèèèà¨T*‹E …¾ïòMnF¡àcÙ6FøÒ³Yªév»tÚ \Ï£P(#¥K‰<•’$šBÑcb¢Ää’q&&«¸ž…íÊe pŒ-nË~1'*¯E”Ò˜¥½^™kuzaB¹0>^¤PtÂB Çñs¦¦¨Ìä:hŒ¥Ñ|e@-ÒAç¹½nŠ2…ãáy6ÍfŒ”¢~èðÞÏ¿.ð®wýÈ•‰‰ecåY–…ëxDqÊè¨G±h:„öK¶Çžç™þ€……Bb±˜7[Û„mÛ¹»Õ¢Z5–B§›L[߈óv;¢Ñ˜C©ßp=×õAÛtº ss]êõz#¤ÛÑ =„´ñ\‰¸xžÇÈHj5 P4 °¤ N:Sy„_Ñjv™™iÄ)…Àcl¼€ï™ð±myfЩ”(­‰Â¥e`Y ¥‘Ž®kLRKš Y·›€Î3Œ´E±ä§P”¹+Vlûõ³g÷'¯y|õkVø¡'î/•ƶ)•å›}‚ÀÅÌÜÞ~/Ÿù»‡õƒþ­ã8ô=æ½fÕ”Ë>Z)ºÝß·0]^4µÚÍV0Vˆëy‚"Žã‘eš¨Ÿgd™EKZ­ˆF½G»“’$`Y…¢G¹äS*ùø‡˜à ˜$•z½ÅÌLƒV+ÂvlF*>AààºRºØ¶‹íØ$IFØKÐJ£4yB)¹À Îîvb¤Ø¶K¹\ T6irI¢F:mýå \|-@Ì;8þêµ'ßòCÏJi‹~1G’8LL¢ç+}óÃù€( ƒÆQ}Ašš´¬bÑÃó$­¦Q”GÇ\ÇD ¯_¿N½6C§]'Ž#\×ÁqŒT0Á!ÓÇǶlÇÃÎOâ(¥×Kèt³…Äy`Ȳp=—RѧT)äÕ>!µZ‡N7Á`Ò‰‘p.ŽäÛƒÌ\)vL™ùˆa˜â¹…RÇõ °mA»• µ’Ý®üÛ ÷ïy-@ÜâµÚ•óB”ÃuëVmóÜRIe¶c>+VŽÝνÕÔŽáœ:“tiS(eÚý-!MM`¡àÒlEt; ££¾1ãXt»1ž—ÑlÖ¨7fh6ëtº]<×gùòÕdYR‹ãžv×ñ¼ OHõŒ°×¥Í4Ó$5õ½nJ/Lˆ“ÌhíŽM¹`ÛÝnD»Ý£Ùè¤)Å¢M©äQ(8ø¾‹c»x~Ç pË2~‘b¡L±XF`ÌÒjÕ3Óš1RZt»õ+.ûƒïúÌ·¸ß¿µyúÔùƒÇO¼ðGÛ·=øT©46¦•"I5ã%ÆÇ+ƒðéBóz:†3ƒûºB?;È4^0™j5@)E§“à8&»Çq$q¢QʶÆF—²nÝf–-Y¿°ç¯~íþà·þÇcÇöüεk÷O_½t¼×ë¶AÛŽã$¿`»®gI)y˜'w M¨·Ÿ<Ò Ó<ë7OÿÒQSoth6ÃÜaÂ㥢ƒm›À“ç™ÿâ:(W&&33ÉúJ I¢Ã Ï~NëDßkv—L|¥ï—·‘óŸGJ×UJG7®ßü÷áß~©XŸŠã©© [XB¿ñB?«w~Öïpã……Ú³ô3€[­ssst:Aóé4M8~v^ {à¸%ÆÇ–²bj åÊÇŽíî÷~ï7?}øÈ·þp ˆ¸ŽãŽxž‹•¥££÷—Ë£kKÅꃞ¬u·d[VA›Š“¤’O6!«1C¯•ꂆ…íXØŽƒëß?qDp]™Ó1aäF#2> ×£V¯}ã¯þêKkªœš[Ìüv0Ÿ±ò&âþVÏI!¤­µª?ðÀƒOýƒ¿ÿ+ÿɶ¼JœÄìܵœ©©ij˜†¦ZwxœËpš÷0óçwîS®]¯×©×ë4›-tü¹|©G¥2†ï21¾”Ri„³çþò—ÿã¯ÿí7þ⯲,‹€ gºÎoU†4¿óC!Dø…jÆ*•ÑûŠÅòÚr©º¹TÙæ¸nÕ¶)¤4Ш~öR^ 3e€‚¤Åõý–”¹©9´òõ4 O=và—?ðÙ!¾ 3_¿ÚC·Ã"¾Xóž[è¾5´õ4ÜýÄ»~áþͧ…°‹¶¥Ùpï+W–‘ÁAW¼ìz¡9?óÛ³ô»võß[«ÕÃ.žçÓi;´Ûž[ X*ÒjÏÖþø?ÿ_þè¾ð»½^§‘3^ 1]-„ù÷3 É(l9ŽSqÝ ¥¥Ry£ï–yžW-Ë÷¸n°Á²²eÙž%„#mÛÓÚÌ<ÔJVy~¤Ä’–´–D A’¤+W.þç'÷ÿoÆÌ•\Ré¡óán$xJž5tkçGŸ¹Ö<0X7Kÿ=͇|ËüÂ/üòÿåØžF÷¬á¾McØ–8I²,4‘nʸú¯õýÅ¢O§“q}VS¯+\×£Ó¹ÞÞào¾öÅ/~î·Ï;s:g¼5Áú ¸Ùû†ï§CÀH†^wlÛ):ŽW²,+0[JéÇöV iùž[qÝB%M»Zé$µ,ßQYš*Fa¯{øúÜì_¶š­ÓZ§Z“p“óºcˆW°ú­!æ;C·Öìy˜ÏøaÉÐ~ó›ÿ‡g?öÑ_úù‘‘ªÓl¶qذ¡Êød)¡Ïà$IÇp›Öáßw ‚"õ:\ºØ# 5qÒì~íkø§úgÿõËçξ0tîzèXˆÁÙ-^¿“ûóoÓy[Jÿ6ç‰#¥tlP©RI YöÒwJ_,­UfÚã©ô&ëU€X`ÕÛ€—‹ g öM¤¼ÉsÒ¸‹7lúÀ>üÎ7?öî§ÒLÈ8©V]V­*31ibð¦€Rç­Úú+?¯D›Z,!ð\—nWpîl—fS#P|íoþà›_øÏüöùó§Ïä¿ßïB¹ÐE[ˆq·’ ú€pÛÖY,„%¥´¥RY"¥-…°¥â¤Ý6ôÝ${¥ wiòYC¯Ï|oÚÄ-ô„þû yä­üÔ‡þáû׬Þ4•fE!žK–ŒùضÀó­Á°'Sü‘’Ä)q8–ÌÍ%ÌÎÎD'Nì;ýå?úÏ_{î¹?ÿF®¸YùŠ• 1Dßô-Vùít“[“=ôZ©ÌÿÕÙTRónçKƒÛnß.üüX7[íó}öqU(ǶnݵáÑG~hÇ®]Om]âÅQL’F 4¾k™.b¹¹E®¢(dïÞ¯_>yjÏÑ¿ùú¿pîÜÉK¹r&s¤C¾8·“w*ôM@²ÐV¢ïFBÌ{.[@ ¤óž×¯&ļ½à X 1~T}æ»ùÑÿŒ75µfå›ßüŽ­ozøm÷­^½qÜ÷ B)òÁ‘&?Ðó\êõÙî±ã{/}å+¿øk_ûÓÃqÖç)dñÐJn€á ̼•t; ¨;·É¯IaLà,YàsÃÌÏn!Ô« yô¥À°Äà& ˜€aô¿ß˲«Öo]5µbíÔêUëFFG'=×u:IöìýÆô‘£{/_¼xöZÎh=d–õ€ž2ºZ«ÞXˆ±¯T?x5ß¹‚ó²ïÉn‚a½à–ÛÀÝ€!Ø9“ü¶gEPÜB Ü Î<cØâðsÓÍwN"@˜3¾ t€Žm–VY#Sñì<³ìf àÌ¿SfÏTö s³mèVRàŽ·ûÐ÷5Ï߃’y{û°™ãÜbÕÏ÷+¤CG_Œ¹C&!¤ Â1«X×@ع‡05®£§ÿg;@Dœ¦a:œgré;8ÔmðJúí<¯ïÖÔ»Ùwù~5$úŒvCö™hiÜâûÿüm /Yìyæ¥8Z+{X´ÐF5Vó”ÜèŒÑïe \¼;a¾ºCåðN¿’ïç6‡¾[é~7–Ù<ÆëyÞ/{ž ØÄÖÅ|ç’3ï9{žRɼU¯nâ`™è¤7q©ÞŠêHnˆÛævJèBæç«*†¿0[@:$CL `xå³€°æ1z¾>q3`-$¢³%Ù-& ]dnÁˆù+òN{' (pw*¥Ô ~Õ0Ÿábè‡û+3»ITðv‡\ ¦0Ì|kÀ“X ú&Úò­öÌ….Ø0I]u‡[Ë­˜Ë]>¾T¸mdP¼Bæ‹Vñ|Ï<1Í-òne\ȼ"ÉmVò*Kwsá¹&Þîþ­^ç.¾o!iÅHÁ·G·b°X൅´Ðço•]$nÂ|qÑ~'ÿYßfkà&Ž•[=ÖwpNú6·wòùÛ}çwwÂÐ[ý–¸Ék·Ê,·ø7‘·û¿â6›;xýNÞûí¼v·çpGI!¯îæ{ï„iâ6@¯à?ˆ»ü¿ú.ߎYâ6Û¾‹óà.~—ï¾Ýßß×o÷Ü+aΫ„!“ô•~ö»Æ˜ï5‰×ØÒ¯ÒgÄ·ËÈ7 ¾ÛÿQ³H‹´H‹´H‹´H‹´H‹´H‹´H‹´H¯;Ú¸þrñ*,^ÈEZ¤E¦ÿ7&'Šf)b‹IEND®B`‚pnmixer-0.7.2/data/man/000077500000000000000000000000001311427610600146675ustar00rootroot00000000000000pnmixer-0.7.2/data/man/CMakeLists.txt000066400000000000000000000003061311427610600174260ustar00rootroot00000000000000CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/pnmixer.1.in ${CMAKE_CURRENT_BINARY_DIR}/pnmixer.1) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/pnmixer.1" DESTINATION "${CMAKE_INSTALL_MANDIR}/man1") pnmixer-0.7.2/data/man/pnmixer.1.in000066400000000000000000000020741311427610600170430ustar00rootroot00000000000000.TH PNMIXER 1 "February 2017" "@PACKAGE_VERSION@" .SH NAME pnmixer \- a mixer for the system tray .SH SYNOPSIS .B pnmixer .RB [\| \fIOPTION\fP \|] .SH DESCRIPTION .PP \fBpnmixer\fP is a simple mixer application designed to run in your system tray. It integrates nicely into desktop environments that don't have a panel that supports applets and therefore can't run a mixer applet. In particular it's been used quite a lot with \fIfbpanel\fP and \fItint2\fP, but should run fine in any system tray. \fBpnmixer\fP is designed to work on systems that use \fIALSA\fP for sound management. Any other sound driver like \fIOSS\fP or \fIFFADO\fP are currently not supported (patches welcome). \fBpnmixer\fP has been reported to work well with \fIPulseAudio\fP, but we lack feedback on this matter. .SH OPTIONS \fBpnmixer\fP follow the usual GNU command line syntax, with long options starting with two dashes (`-'). .TP .BR \-d ", " \-\-debug enable debug messages .TP .BR \-h ", " \-\-help show summary of options and exit .TP .BR \-v ", " \-\-version show version information and exit pnmixer-0.7.2/data/pixmaps/000077500000000000000000000000001311427610600155755ustar00rootroot00000000000000pnmixer-0.7.2/data/pixmaps/CMakeLists.txt000066400000000000000000000004321311427610600203340ustar00rootroot00000000000000file(GLOB png_images *.png) install(FILES ${png_images} DESTINATION "${CMAKE_INSTALL_DATADIR}/${PACKAGE}/pixmaps" ) ## make running 'src/pnmixer' from the build directory work ## since pnmixer looks up pixmaps files from a relative path symlink_to_binary_dir("${png_images}") pnmixer-0.7.2/data/pixmaps/pnmixer-about.png000066400000000000000000000362301311427610600211010ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aËsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÛ &‡êQiTXtCommentCreated with GIMPd.e IDATxÚí½y”dW}çù¹÷í±eäVKÖ¢Z¥ªR©VIhA ˰= #l#™Í¸Û½Îé±§{¦—évgÆæôpNÏð‡ÍÐîÅà¶lc·wÆ $Õ¾ï{eeVÆñÖ{çû"•ÊÚ„ åïœwbxñ~ßû»¿ý‹´H‹´H‹´H‹´H‹´H‹´H‹ô"ñ½üñm|pMµjý=ß;,KD–-ÚaOÕ¤û…àyËǾüGŸ«/²éû>ò¡W«ò_xžX¡h Zk¤4§¤©e‰3iÊWm[þi§­þâÏþâs×Yö:Àº5S+ì=>nýS­!Ë Óm[¢Ñd©FkÖù ”¥\H3ý{åŠûÙßùߨ³Èº×!Ö­yqÙrû×&'íŸSÊ0wtÔÇó-,[@ˆ4SÄaF¦Ä±"ËB˜÷#ˆ<×þR«ÿû¿ÿÿýõ" _GxË›˜‡’$[¦TG}Æ'T¦Í3ÙfKˆ¢Œ(Êèt¢0ƒNSñ_]×ú·_üÒo.J„WHÖwãG6¬û€œ«Ò;wíJ„ÐÌ2½\­úFôkÈ¡˜¦šn7¥ÑQ™&(8xžE¥â6Ò’d©"Ë´’-Rê>ôÐCÁ½w;|dO{‘¥wGöwãG”2;ºm!ÓT[¤%Ì‚$QÌÎvÄ4ÍȲ )%¶%p]›‘Ñ•²ÇĤM¥âÑlD´Z1iªFêµðŸ !Ÿù±w=óÙʈóÙßú­_?»ÈÚרÕð¶zÜn·ÒO&©ZbIA¹âaY \›nÓlvÉTF–¦¨,%Mb¢(&ŒBêsz½)%Aà‚ÀF+Mk@W<™&ê'7mÞ9¾aÃŽ‹Çï½¾Èâ×^²ûôºÝäç³LOHKR©¸X– Ž3õ{ïÝÆÌÌâ8@+MØxž…H²4¡ÓéÑiGĉ¢Tò¨ŒxHK…)*­)+¥Ÿ’§ï¹gÛäŽ>rdOk‘Õ¯Œm­Ú6ÿHk]’RP®¸H)ètBF««¸÷Þí:ôJEÅ’K–)‚À!SšJť׋èõ"¢(E)Á=÷¬Äóv‡$VH) ¶ÃchýãÛ·?¨7Þ»ãÈÑ£{£E–ßHò»ùcå²\ Œßø¬Æ¶-îßò iš’$±A¦%p] Û)HÓ !ZkÒTS*Ûhréâe.^¨ócïzšýÔ{Y½f‚$ IÓ¬oV®ívãÿ;K³¯½ç=ϾÿVç·qýÄÆõ‹à;D›6íØ¡µú°RÏ·)—]Ò4e||)÷Þû&®\¹Àñãûq=DZð\ ;ƒ²TS(8t:1‚4ØŽ V»‚¦Ç3Ï|˜·¾õq.]ºD»ÝC Ëø`©VúýÛ¶í^²eË®o>¼§÷r u¿˜«ZÀw‚yÓâ(ûi¥4Å‚C±è¦)Û¶í`¤²š“§ŽpæÌ1 E4Q‹qœ¡”ÌÑé$XRbÙ6K–Œ.žçròä)<È£>ÊO¼™íÛ7Ñé4¸páiª‘R"d‰zHkýCëÖn?pò例Ãç7W;¤¿›Ì߸þâ{ ¶ï*Ö¬¹Mšª¸®E¡à)ÅÃ? ºÂ‘#û¹|ù Žã ¤Àu%Ijœ?¾oÑí¦H–-ñ=ß·ÑZ`Û6Apùòe¾õ­o±lÙ2¶mÛÎC=Èò©1._¹@½Ö$B ´f9è§غKLNnýƹóûÕ÷ââ¿$Íw٠ص:NÒg”FøžC¡h£5¼éᇰí2ûöíczú<Aà[h­IR…emKÂ0Åól¤ß÷p]ó)%…BV«ÅW¾òºÝ.›7ofóæÍlß~?õÚ W®\EeF»”R8Zë§´fÇæM;ÿìĉ}ÝE+à;Dë×þ„\¹b¿ùñ{æjWŸ£H .A`cÛ’‰ñ ¤‰Ç‘£û¸råÀèè(õzO}êSüò/ÿŒñOþÉÿÄö÷R*ñi„@´[ñ?‹£ä¿ÿÔ‡>þÀ¢x•é}?þiÙåg/œ;µ¼Ñ˜£:ZSS+±íIæ®×8~b/Ji„8ŽÌ žg‘eFá˔¶I’b;Î t|+êKƒS§Nóþ\·ÄûÞ÷^”ޏ|åqb\ϹÏ`uš©÷ïÚõàŃ÷\”¯ÕQ*Ý•«Ö“$ Ýn‚pùòe’$Åõ|lÇCimB¾©F`rG…)¶ i’aÛ’n7¢Ýî BÉ·"rŒŽV°ì”ßþüçø•_ù5xà!ž~ú'˜˜ð2OKej¢ÕŒÿã»ìÙ¾€W‰žþÐãJ©¬µbÅlǦ×MBÒhÔð|m»Ø–h4fB€ei’D!-HS³úMÚ˜¦Óí’¦êŽ@ ”ƲlFFJ\¼t’÷ï~ ×-ðñ„•«FB¡ù6ƒ€ì_ýàS?ókï|dzr¯EaX :2N§ÓCe‚z½Žm‡‹E\ϼ7‰3¢8A A–)Ç"M ¢0AJˆ£„v»‹w÷W´ßóɲˆÏ|æ3œ0, ¾øÅ/²wï^>ùÉO2µ¢Ê蘛»žI¬¦fgz¿õó?ÿw&p7îà‰%—@4M- ¢22J¯—Å/^¦P€Õ÷LñÈ#ï@kõR™˜†0L‰¢ )L&Pß3¨5ضƒÖÍFçÛ>O!Að¿ñÌÎ^çãÿ8¥’ÃØ˜——« z½tçìLﳟøÄßqp‡tíZMeY– ËW¸e¹´[ —.]&ŽCîY]bÓ¦Œ/%M“—L±TÓë¦har•Ò8¶ÌC’$6+¿ÙhÓnwo(ºë@Jɧ?ýiªÕ*O?ý!OS©8(¥s$?ÚiÇÿjwHS+üÐvŒHÒHY²dívÄåKWùË¿ú+&& Œ—©V'Q*»áóYf@` Fw *ÓhãÂ%:.Ýnü2«ànÉqÚí6¿ú«¿ÊîÝ»yç;~×7éj*4›Ñ/=ûì'~êµÊäë? _3ðürìØVCkÃB&ÜwßJ<·H£ò¿ý'NeË–å”JUcíÝhØ‘¥Šf#&Ë-i™·9Žm*ŽææÄqúmK‚ 8sæ ŸùÌgxï{ßË®; ϳ•¢¡v=ü÷?ó3ŸxÓkú5€þá]™çÚ  ÛíG“KŠlÞ¼žV+¡ÙŒøýßÿ}â¤Ášµ÷ yÉïÿ’)gŠF{Ý”NË„„5+gt&h­HÒ„Ú\}`6Þ‰/ o6ö·Ë²RR.—ùÊW¾Â¾ð>úѱví=TF$Žc ©L©‘V3üìû⣓¯5îŸ8õyýš1{ôÝo©l¯×g¹~ýcã#ÕõZ™™:Bftºuvîx3ÇOœ¢V»–ÛÿÆ3g;VºKRE%¨Ì8‡Œ«X£µ@ š0L ïŽ|FÁ“/»•Râ8àþûïç­o}’_|ÈèõLÍ‚RzĆ·¼õÑßyá…ç5¯úžà=ïùéõAPz{£>Ç\m†±ñžgQ(ø\º8 :ããclXÿÇŽí§RcjÅkÖLR*û‹…¢C¡àäÉ¡‚81Î!)ó±c¼†Y–eP(ø·eY70½ôŸÓZsôèQ~ôG”•+W²ÿ¤%éõ2@ ”ÚŒáÁƒ/~m7¡öOÿÙ²Ú\ô“íN“Ù¹kŒV}, ‚À%M×çjŒŽ–˜›»Ì–Í;Q*À÷|ÞûãϰeËN–/»åËïcù² ”J£‚מ (ºØ¶ME1M5ŽcÑëÅø¾‡ãXÜ ýÞâÿ¥~"O"µ©Õj\¹r…÷½ï}X–Í©SÇPJ…R ¢(}rÇ·ö:´çØ" ðÿ±77}¤ÛéX³³ÓT«ýo-2{­I/ ±mh¶fؽë)Nž>†ãøþŽP©Œ1>¾œU+ïeÍšm¬\±™±ñ• iâ8 9‹2¤„n7¢T ^€¾Óhë޶m,˶íÁã3gÎ`Yïz×»èözy¢©1U¥2KÕSïÝùåãÇ÷Î,`=¸ûGB!ÜŸMâ¨<}õ"•Š‹_°Qyî_¥\äü…kxžMµÐÀºµ»9}úË–­Ìó3²,E婽APbÉäJÖ®ÙÊŠ©ûðýQÜ",˲-¢0&Œ’}'ÒK æüÕÞgvÃ[‚mÛGé¼—‘Þ¦´èž;¿ÿo¾ï0>v¿¸üÍ׿¤ÿå¿üç_¾ÜxhúêElGS*¹!i·Û„aHš&XÒDû $ ™™™eã†|ã¹?ç[ßúKÚ™ê¡2ð=›v;cÛö)ÖmgéÒŽ#èvcÒT²bj«Wo¡×‹hµ®‘eY.ÚÅ >†…Ð?椯NOOsåÊÞò–·pï½÷qêÔQ®Ï6ȳÒ)åcÅ–?¾rõà•ïkÜ óûô¾÷}ts»¼ýêÕ ¤iÌØx€‚N§C’$X–íHâ8ÁvlŠÅµ¹kD±dÇöGyî¹?çÅ¿ÎáC{Øà9ž{îk:üaÔ&ìET*>k×M²bEǵh·"¤ôÙ°îÊå%\½zŽZí:žç¾ÌSØñ} +} +¶msúôi~øaÖ¬YÍÁƒ{i¶¢~ó3Ç÷äºM÷íþ­ã'ö.êë×>ºiÉÒ%ïžž¾DETGÇ¢Óé¦éࢻ®ñëû¾O¡èqîÜi–-]Ï=÷läôéÃ$©"ÍRâ8¤Ñ¨Ñív8sæ4W®\åúõ–ëÖ-aÕêQ´‚z=d|bеk¶233Ë¥Kg ÷`ø~õ÷÷ÿáÕ?¬8J)9zô(k×®eóæ-4›5NŸ>=оšuk7qôØ^¢0¶Mí mÛ”ËE„€F£çyT«#!èõBææ®32b±úžeôº Õê &'Wræìq²¬; Ùþó½ƒ}_B? dÛ6.\ Ûíòö·¿ƒ½û^¤× ‰B…”‚$Ê6·»ÙµS§ö}ë €OúßéŸû¹¿·óÚôÜCÍfrÉgt´@’¤„a8XqÊ–mÛt:6çÏ_dûöÇq,›c'`YMF¯Q.WŸþvP©T°,ãq¬ÕêdY‡û·®&ËÀ’UV­º“'’¤\ǽaÞ †•Åþ0U´,‹C‡±zõjV®\ɉÇPJ’$&hdIžxë“ñÅŸŸ}ÃàïþݸìÒ¥Ú»kµ‚Àel,ívû‘ÛÂxž‡RŠ(бm „´›»w¿•«WÏ1=} Ïs€ŒN§Ç’%¸®‹”&W0 C …¶m£µ¦Ñh233ÍÖÖày.aÏæž{6sâäQ::AÁGð’êrë¿ôiÿþý<öØãÌÌ\#I{ôzýŠ#í¥©^{ÿ–‡þËáÃ/ê7,ÞûžLµ;чæ®_ñmFÇ|„0ÊT%Í·ŽãÇ1išá8’zc–Ri ÷Ý»#G÷Ðëuq=—n·K–eŒá86–e†!ív×uq]w 'œ¿põë—R­Vh5÷¬ÞÄñãGHÓžçâeVB”J)Ò4½fî¤ÓépõêU¶oßÎŋ籛n'1ñ‰Xm Öу_<ø†ÀÇ>þI' ùÈìì´“f)£c>Žc8ú²¿÷öW¡é˜’¦¶­™aãÆ]”Ê#9º×Äîm‹n§G¦,Y2ŽeYxž‡”’^Ïtˆ ‚`À¨S§N±lY™+–ÒiIV­º—Ç tˆm;/Sü†Wý ´Ö} T*’¤G+“ÉlJÚïòÉÇ?÷üóßŠßøÔ§þuxmºóì•+Ó#Q12âS(¸Äq|ÃEŽÑ÷oã8Î_WÄI›^˜²cÛ\¿~… Î`;¾oÓht±mÉää¶í V’$„aˆã˜çÒ4åôé³LL˜Z¹Œ^ס:²”c'öbY†™ÃÁ£~öPš¦@öWÿps !çÏŸgÉ’¥$I”û:LcšªIÇ–³ûö¿ø·oH¼ç=ïñzçï^»6;…!žoÚÂg™¹°}m|8H3ßô2âYÓh\Ãu+lºwÇŽï§Ýj<„€N§‡Ö099Žëš|×5Á ^¯‡Rj`uœ>}–jÕeÉ’¥h=‚ïW8qr/Y–`YÎ ¢xÕ3RJšÍ&ZkªÕ*`ÚÛ†ÝÔ¿¦zó“O>þ[Ï?ÿ­îqœîp݉¿/„°z]Óê¿:êV¸bÀ¨a o­S®];ËøÄ=¬Zµ‘cÇö‘¦ ¾ç ¥ ÙìÕj×uV…”’$I@H’„C‡1±¤H¹8A±°Œ4É8rìÐê†ß– Ý[ ív›õë׆Ž#èõRÓ-S#ZéÊÁC{þð €6ðÊÕ™^¶ln !*Ï3Š^_胠¿¢úA˜0 ÌA–õ¸6} ëw³dÉ Ù›7‹2ï©×Z)X²dÇq€êwÇ\¼x‘ÙÙëœ=sšõ–ŒŽ®¦Ñ¨séÒñ¼JX ¶„þJû} ë FƒB¡ÀÔÔÍfǵétâ~uÓ®w}󸉽§Þ0xÿO|HÎÕz¿ÚjÔV•Ê#†ÂÆ÷-ŠEû†¡}ô}ïýU˜¦é`7à°‰ãíö}ì)l»Â‘Ã{‘BâäE#®+òl†3¦“$afæõz›éé9Î;ƶm‘²Â’ ÓY¬ÝžÄ@BõÝÁÃÅÃy‡}$IÂÜÜ6l4Ÿ••iÂ0ò„ˆ"µµ\Úò¯NŒßذaÓQ”þ¯Y–ÙIS)U‘Ò,FG=@Óh„„aF8y`Ƚ!eÛ¶mšÍæ@"‰aÑj×év¯ñà®§Ð8œ8q¥AàÄŠ¹Z“(L˜˜Á²ìíÞív™››C)͵kM°åK§Ù²e+èK–¬äÀçÑÚ0?Š¢H‡·ƒù–‚én–™FQÊêÕ«i4j‡nÇ$¬º®XÖëªã—.Ü÷†ÀêÕ÷ÿ¬Rꦹ¢:2Ž›‘qrßþ¾À¶­ï/yžú¤Ð–””Ëàe²4¥R)P,Z„aô²\?=«_9Ü/ÝŠãØ4™¦0Äqljõ ÃŽo£ÓérúÌQ,ÛÆuL‡Òv»C­ÖÄum\Ï¥ÕlÑj5h6;ÄqHšHjõkLLT(—39¹‚VëçÏŸa#…@ ˆ¢hМr˜ñÃ’ I’üü"ÆÆÆÃÐä=Æq”á8bíÆ ;Ï?±wÿ÷5}lÛûÓT}DÞ5ÜìùÅÒB@+–-!M£¼«—õ²,]ÇqÁ—8ŽadÇqH’Ä4žPÐéÖÐD<ðÀ[©×®sáÂÙœIfPE«Õ1I(qH†´Z]´VÌ]oã8f)ŽãríÚV¯Úˆ´J¬Z5ÅÙs¸r¹Nšš-ɲÅÀƒÙ·0†u!Ìë–%i5[”+|ßC)“òÖë&äÎχ&'øíóç÷·¾/ðŽwü¤£”þ•Ò+…€ññ~švŠV.år…n×$pŽŽèõÂSµM;Yk`´ÛÆŒ ÈBÁG A&$IFœ4±¤b÷îwR«ÍréâÇíçìÑíFÔë¤TDQ†šf£ƒËD‘FÊŒ0j±rÅ}øþãc%^Üó-´–8®…熧iJÇ7Xým¡ï70SRlª##„a„ç™|Èn7©V÷ðá½ôšÀÆõãc÷ÛsµCwÕkË–Íoc~ÉHFcKzaŠcKâ8¥T2Úy»19YÂum’$}™#¨¿ô/´éû›"„QæúSGâ8¥Ý–Û·ÿ ×f®pùòüÀÅ’¦Ô¼Ýéõ"â(!ŽSâ$Îݹ¦!¥çt:ש,%ÆX²dŠFã.\2úG>Ç Ÿ)”eI’Eq¶ˆþÿh·Û¤™&„0Pã(#Ž*Ó[wîxèK‡í¹öšÀøØý°çj‡²;ýÌCþ¤=2býJ–° PtÃŒ°—aY!´v)WªÄqdT*Žc\·Ãvû°?À²,¢(¢ÛíöÛ0 mäL+º!»h »¶ÿ —.ŸcfæAàÇR›Z•’eŠ$Éò‚S•kê½°ÅÊ›Q™dË–U8ðB>üÒô+°mù²ˆaÿœn´J¥AiI¤8®E§¸a¨J'Nîûo¯YÌÕq7àƒãiãIDAT̘Z¾õ-~ ÿ BH ø¾CšwüJ3…ë Úí.ãcK°¤é îùAPÀu\‰zyd®ï2n47øë“$!Ž”Jql›f«‡Àf×®§8þÍælì1íg\·¯p¾Ä4)Q”˜BÚ¦Xœ TgbbÛîpúÔI‚‚O+²¼g€mßxi_žDJ·°%=GbÛ¥4½^Še±qÓ}~þØñ=sßI|[åáw;akjÊ~·Ê´†BÁ!Ž22eÄ¢V&Æ›73{Çuˆ#M£žÐë™ü€R©tCEϰËutttðúÉœ&³x®VG©”Ë—®s}î(ÍÖeÞû¾OP)/§Ñhc&™«8™é2ï7 …1 {F)½xñ0hÅÕ«|ðIFª#(¥p=´êvôàs¼Ì*èÏFA§Ó¦6×ô¨Žúx¾RºàyüìkZ ¼›™7ïÿ‰Ÿ-¦Yúi­E¥)—]£9G¹Ý,%Y¦(ÍF“±±¥Ø®K·“P.Û¹¸, "yÃ?ú"×qÆ 0Ó‰ãØD‘RG4|?¦Œ±uëc=¶F½Ž´|ß´£µl3ÖVë¼=}îì±,›(î01¾† Pbbrœn·Á™3§ Ûîç ˜s3‰+:„ƒÎ§¡e€Äõ||¿Ÿp"è´´Ö7¬ßùŸNœØÛ~Mànhýº?žfÙÇà8V® åÁ…¹0JkÇÆvQ˜11¾”8ÎÈ”©ü‰ã„BÁ€ ïŠ6ŽãØt Ëô}MÜó’D“$1½^—V«‡í„”KËØ´i§N¦Ýiã:Ò’o R ”6ÙÉfa†ã „pY¾|““>¥b•ƒ÷ užòeI3ÅTA¦ÈKÖÅ Ÿñ°HR ÇöPÚè8¾oÅa˜–ª£nýÀ=_y]`×ÎËRŸ |k½éïgSñi4"„¦%<ý!ÒšjÕ§Óix#”J%šM*.ŒEP,þõaôM-­õ ºg^7 'Ç" ™ÇívËî±téF6nÜÆ‰ãûhuºhÕÏÈ<×6]Èèg%…,]²JÙcíº)8M£q°±mËhø›(Ê-ìŒbøR”PkM™þ†–%Ib›RÉD/Ç(„i¦î{ðÁG>wàÀ Ýלp§´t™·ªP°ÓÊhå¾g£y{3TXfÐ@£S*YÌ^¿ˆÇv˜žî‘e­Mi¼äÂí_о“ÈótÛÆ÷}¢(z™èt:7$|ôC­qM ³èõB´Ñ„ÜsÏN–L®àô©CdYJ¦*KZ¦!•6 '’D‘&!,V¬Ø@±(€“'Ž'íA“mKâÈxúLð(Ÿtg(M¾eexžIƒëõJÅ"~`’SÐÐjÅø¾µêíïxâ7¿ùÍç’×%6Ý·óŽ¢l›”Ë–¦”ÛµèvMKx!òmÀ<0{cÞó/IºT«X¶C·£T«>I’àûþ éa}u»]”Rø¾?pƘò,‡0Jp]iô˘xíN$iaɘûî{˜±±e\¸p’$‰‘–ñ#$‰"Ž ã“$L8zÕª{)—=FGKœ=7ÃÌÌ9£/`¦ÅI†ï“VJãú{Yî…„°— Æá¡H‰xÆŸ ÝnJšªI×µìÙó¡×ž}æKÛäWA5‚‘'/à#e0Æ#0ŒÁ4…N3MšÆÆóJHË¡Õ2LéÏ.Š7$bJ)qÃto!lœM‚ë³<ÏÔHË$Îε Ã:®±bÅF&ÆWrýúU’$ÊŶ~©&å8¨,eÙÒUŒŽM06î13rþÂsa¥DHP™©aHSÓÍÔ²i¦ÒÁL2Õ¹n‘7ÂV.Å¢›["¦/"B,yê©ÇÿÃsÏ=§_WX·nÇOiÍA µ ðm E‡FÝ ‹ùR˜¡Mýl!En&Ä8®"Mm|¿@«•à¸&qDkS:Ö—RÊ?ŒFnÛöÀKèº6ZéAÿ@)Y^^^¯w©×g‰¢ë e&'W“)EuRJ+£ZR‚€ (²bj-ããÝŽàÜùStÚu<ß!o…ëÚƒYÆ*ѹØ7¥ÃÒŒ³Íd&„¡&<<ßÂu,z½”8Ê–Šöo¿ðÂó×_7xh÷‡¥K'?­‰W*¥°-ÓW¯P4+YkÆû%…¤Pt |›L™þ>h‘OÉÐ$t;M²Lã{:m3=¤Xz©l»¿êMñH4¸à®k Jz½^žgèÐíÆXŽDef€ÌÍ·(Jh6;4uª£.¥âåò8Qæñ{3×X)…e›pðŠXº¬ˆÓÓuΟ;A©ìÚË»®E’¨<‹I‘e:— ¦Ó¹év®ñ}ì… –eº¦?‚ ÝNlÛ–3û÷¿ø•× ¶Þÿ–7mÚ²ö_diš{ó,J%£œÅ±"ÍŒ‰å:6kÖŽ35U¥2âS.»f0´‚81#cãHåf_( ±mŸ(2>øbÑüN§;Èèv{´š1ŽcaY’ ðó­!#I!SšN'Âól#}´QÚTJgtÚ=”Ê7%ê¥Ò$BÚÄQÛrŒûXJ’$bùòuŒV˸ž¤Û‘œ:}¥SlÛ˜tI>ë¨ßcز¤™d ã+@š¶v±ixe×óÌx]GÒí&Dq¶ú‰Çýì‹{ž^X¿îáÛ¹sÝãJÙ~»Ý$I6"פMÄ=k&+˜²l<Ï¥Tò©V|ßFe:Ÿ÷kößRQ1W«¡µ Mm¢ÈtqÉÜÜ\žâ¥i5c¦§[¡ISA±è3w½…ãØ¤©­L(V†€ÀõŒ4‰“„z½Gš(–, Òª‚ B’&˜~ׂ,K™œ\ÁøøŽah1;{…«W¯ ¥…ç»>Ž®k&žš fŠc µ·5zOàY„aŠmyÛ6Ñ;tÌ/XGöí{qÿk×@ô]Ä#•MGÖoXvʲü÷i­étš8®…ï;ı"NãcE¦¦ª¹ýËP!¦ã¸”ʪUŽ(Έc´$##צgó0°EJJå€BÁ¦Õ2¹Å’G«•ÐëD(ÒhĤYF½Ö@é,/Û±òÆ…+MzI’R«õè´Ãü»-Ò,Ãs‹Ha†\$qL©XaÍÚõTGê×c2•qæÌQ²LeÎ’y“iiïØZ@å PjçÚ9àMσ `ƒ„°—ÒëfËÖ­ÝñNžÚ—½&0¸ru_üÄ?<.…ý¬ëxôÂB˜´—(ÌÐJ³|ªJ©ä¸á‚Ðá¸u´@±è…)­fŒíX¹Ë4¤Õj†1aÏÆ±ƒ\94×§\ñ¹~=DkÓá[ ßwèv;XVîoÈ'“ö‡RXRä­çlÒ$¥ÝŽi6zxžMu¤€ë ÀFZ&£'MÆÆ–°~ýRjµÛö9sö(IçsœÁä4Õ¸žÌKẒ0T=úÊ`J–šVú¾oã{6½nJ’¨UBÈÿ~âäÞ ¯ +àM?¹Úu‚g,ÛHÓ„6Ε ¦¦ª¸®7füÌ‚”Aà16V$˳׻ …‚CeÄ¡6W§ÕjÇ­‹¹‡1Ãu%¥¢‡eKêõ.å’‹ãúxžOš&DQŒçšñôBbt i¦‘¹"ìå’£Þ%Iª£Å’‹ëJ,éÑét8~ü W¯^¦Û‹(—Æèv[LO_D+3ìʶ$Ž-IRëZyE‘ÂqMDǑı±l[E™RHéâ86Å¢C³£•"ͨ:µïO^¸÷ÞÇÇGª•Ù¶--i\¿®«L7a19YÎ ìÓ;¿e«eYŒ—LJx#¤ÛM)—*#Ff³ž×á—ˆ"‹(Jñ<# Šf#6N"Ï¥P(aÛ‚^æÊ£EklGây–ñúņQ£¶Z]j53èjl¬HeÄòÒTpáÂΞ=ÁÅ‹'ÑZÑí¶Ñygsi <¿¯ù‹¼*Hãæ +}¿€çÛFèÏBJ4BØJNžò–!+7oÚýÇŽï^ó)ß§îY½ü×sK¶å¤K–TMâ’¥ËÊ7TÞ§€/Ô·Ï„år`ÀãIjs!•Škæ GŠv»I§ÓÀqlY¦Ó…N;Æu“E¤eQ«‡ùð)×qФD‘eë8’,ƒn7% ³ÜO‘'¡HÓŒz½E½ÖÁ¶l&– °-KzyvRË4“T „(½&jaŽ“o;¹¦Æg µñ‰¸ž$ŠZÓµZõŒG2ÎF\Ï~îÈ‘=G_ó8wþ…ÎOüÈžçßgYV"ÍX15I±8Âú K)•ÊA€çy¸®;H§š¿%ô~$Ͳ%Õj׳™¾ÚƲ$®k2k:íˆV»ŽR ÅâB´ÛíV2Ð ‚Àcé²"…b€ey—òžÉÍ‹2:ybÚÄð¤)‘Ë8Ž™›kÐl†‹K—–ñ};OwÒT0i•‘¤Fšxž=ˆ]ô£ÆÑ×E™2)ŽÌg,Ù¯—´Z1å’sðÀ¿úºˆ¬\ùàÔŠKßÖ8®K§Q,ØŒŽ• ]—B¡@¹\¦R©066Æèèèà¨T*‹E …¾ïòMnF¡àcÙ6FøÒ³Yªév»tÚ \Ï£P(#¥K‰<•’$šBÑcb¢Ää’q&&«¸ž…íÊe pŒ-nË~1'*¯E”Ò˜¥½^™kuzaB¹0>^¤PtÂB Çñs¦¦¨Ìä:hŒ¥Ñ|e@-ÒAç¹½nŠ2…ãáy6ÍfŒ”¢~èðÞÏ¿.ð®wýÈ•‰‰ecåY–…ëxDqÊè¨G±h:„öK¶Çžç™þ€……Bb±˜7[Û„mÛ¹»Õ¢Z5–B§›L[߈óv;¢Ñ˜C©ßp=×õAÛtº ss]êõz#¤ÛÑ =„´ñ\‰¸xžÇÈHj5 P4 °¤ N:Sy„_Ñjv™™iÄ)…Àcl¼€ï™ð±myfЩ”(­‰Â¥e`Y ¥‘Ž®kLRKš Y·›€Î3Œ´E±ä§P”¹+Vlûõ³g÷'¯y|õkVø¡'î/•ƶ)•å›}‚ÀÅÌÜÞ~/Ÿù»‡õƒþ­ã8ô=æ½fÕ”Ë>Z)ºÝß·0]^4µÚÍV0Vˆëy‚"Žã‘eš¨Ÿgd™EKZ­ˆF½G»“’$`Y…¢G¹äS*ùø‡˜à ˜$•z½ÅÌLƒV+ÂvlF*>AààºRºØ¶‹íØ$IFØKÐJ£4yB)¹À Îîvb¤Ø¶K¹\ T6irI¢F:mýå \|-@Ì;8þêµ'ßòCÏJi‹~1G’8LL¢ç+}óÃù€( ƒÆQ}Ašš´¬bÑÃó$­¦Q”GÇ\ÇD ¯_¿N½6C§]'Ž#\×ÁqŒT0Á!ÓÇǶlÇÃÎOâ(¥×Kèt³…Äy`Ȳp=—RѧT)äÕ>!µZ‡N7Á`Ò‰‘p.ŽäÛƒÌ\)vL™ùˆa˜â¹…RÇõ °mA»• µ’Ý®üÛ ÷ïy-@ÜâµÚ•óB”ÃuëVmóÜRIe¶c>+VŽÝνÕÔŽáœ:“tiS(eÚý-!MM`¡àÒlEt; ££¾1ãXt»1ž—ÑlÖ¨7fh6ëtº]<×gùòÕdYR‹ãžv×ñ¼ OHõŒ°×¥Í4Ó$5õ½nJ/Lˆ“ÌhíŽM¹`ÛÝnD»Ý£Ùè¤)Å¢M©äQ(8ø¾‹c»x~Ç pË2~‘b¡L±XF`ÌÒjÕ3Óš1RZt»õ+.ûƒïúÌ·¸ß¿µyúÔùƒÇO¼ðGÛ·=øT©46¦•"I5ã%ÆÇ+ƒðéBóz:†3ƒûºB?;È4^0™j5@)E§“à8&»Çq$q¢QʶÆF—²nÝf–-Y¿°ç¯~íþà·þÇcÇöüεk÷O_½t¼×ë¶AÛŽã$¿`»®gI)y˜'w M¨·Ÿ<Ò Ó<ë7OÿÒQSoth6ÃÜaÂ㥢ƒm›À“ç™ÿâ:(W&&33ÉúJ I¢Ã Ï~NëDßkv—L|¥ï—·‘óŸGJ×UJG7®ßü÷áß~©XŸŠã©© [XB¿ñB?«w~Öïpã……Ú³ô3€[­ssst:Aóé4M8~v^ {à¸%ÆÇ–²bj åÊÇŽíî÷~ï7?}øÈ·þp ˆ¸ŽãŽxž‹•¥££÷—Ë£kKÅꃞ¬u·d[VA›Š“¤’O6!«1C¯•ꂆ…íXØŽƒëß?qDp]™Ó1aäF#2> ×£V¯}ã¯þêKkªœš[Ìüv0Ÿ±ò&âþVÏI!¤­µª?ðÀƒOýƒ¿ÿ+ÿɶ¼JœÄìܵœ©©ij˜†¦ZwxœËpš÷0óçwîS®]¯×©×ë4›-tü¹|©G¥2†ï21¾”Ri„³çþò—ÿã¯ÿí7þ⯲,‹€ gºÎoU†4¿óC!Dø…jÆ*•ÑûŠÅòÚr©º¹TÙæ¸nÕ¶)¤4Ш~öR^ 3e€‚¤Åõý–”¹©9´òõ4 O=và—?ðÙ!¾ 3_¿ÚC·Ã"¾Xóž[è¾5´õ4ÜýÄ»~áþͧ…°‹¶¥Ùpï+W–‘ÁAW¼ìz¡9?óÛ³ô»võß[«ÕÃ.žçÓi;´Ûž[ X*ÒjÏÖþø?ÿ_þè¾ð»½^§‘3^ 1]-„ù÷3 É(l9ŽSqÝ ¥¥Ry£ï–yžW-Ë÷¸n°Á²²eÙž%„#mÛÓÚÌ<ÔJVy~¤Ä’–´–D A’¤+W.þç'÷ÿoÆÌ•\Ré¡óán$xJž5tkçGŸ¹Ö<0X7Kÿ=͇|ËüÂ/üòÿåØžF÷¬á¾McØ–8I²,4‘nʸú¯õýÅ¢O§“q}VS¯+\×£Ó¹ÞÞào¾öÅ/~î·Ï;s:g¼5Áú ¸Ùû†ï§CÀH†^wlÛ):ŽW²,+0[JéÇöV iùž[qÝB%M»Zé$µ,ßQYš*Fa¯{øúÜì_¶š­ÓZ§Z“p“óºcˆW°ú­!æ;C·Öìy˜ÏøaÉÐ~ó›ÿ‡g?öÑ_úù‘‘ªÓl¶qذ¡Êød)¡Ïà$IÇp›Öáßw ‚"õ:\ºØ# 5qÒì~íkø§úgÿõËçξ0tîzèXˆÁÙ-^¿“ûóoÓy[Jÿ6ç‰#¥tlP©RI YöÒwJ_,­UfÚã©ô&ëU€X`ÕÛ€—‹ g öM¤¼ÉsÒ¸‹7lúÀ>üÎ7?öî§ÒLÈ8©V]V­*31ibð¦€Rç­Úú+?¯D›Z,!ð\—nWpîl—fS#P|íoþà›_øÏüöùó§Ïä¿ßïB¹ÐE[ˆq·’ ú€pÛÖY,„%¥´¥RY"¥-…°¥â¤Ý6ôÝ${¥ wiòYC¯Ï|oÚÄ-ô„þû yä­üÔ‡þáû׬Þ4•fE!žK–ŒùضÀó­Á°'Sü‘’Ä)q8–ÌÍ%ÌÎÎD'Nì;ýå?úÏ_{î¹?ÿF®¸YùŠ• 1Dßô-Vùít“[“=ôZ©ÌÿÕÙTRónçKƒÛnß.üüX7[íó}öqU(ǶnݵáÑG~hÇ®]Om]âÅQL’F 4¾k™.b¹¹E®¢(dïÞ¯_>yjÏÑ¿ùú¿pîÜÉK¹r&s¤C¾8·“w*ôM@²ÐV¢ïFBÌ{.[@ ¤óž×¯&ļ½à X 1~T}æ»ùÑÿŒ75µfå›ßüŽ­ozøm÷­^½qÜ÷ B)òÁ‘&?Ðó\êõÙî±ã{/}å+¿øk_ûÓÃqÖç)dñÐJn€á ̼•t; ¨;·É¯IaLà,YàsÃÌÏn!Ô« yô¥À°Äà& ˜€aô¿ß˲«Öo]5µbíÔêUëFFG'=×u:IöìýÆô‘£{/_¼xöZÎh=d–õ€ž2ºZ«ÞXˆ±¯T?x5ß¹‚ó²ïÉn‚a½à–ÛÀÝ€!Ø9“ü¶gEPÜB Ü Î<cØâðsÓÍwN"@˜3¾ t€Žm–VY#Sñì<³ìf àÌ¿SfÏTö s³mèVRàŽ·ûÐ÷5Ï߃’y{û°™ãÜbÕÏ÷+¤CG_Œ¹C&!¤ Â1«X×@ع‡05®£§ÿg;@Dœ¦a:œgré;8ÔmðJúí<¯ïÖÔ»Ùwù~5$úŒvCö™hiÜâûÿüm /Yìyæ¥8Z+{X´ÐF5Vó”ÜèŒÑïe \¼;a¾ºCåðN¿’ïç6‡¾[é~7–Ù<ÆëyÞ/{ž ØÄÖÅ|ç’3ï9{žRɼU¯nâ`™è¤7q©ÞŠêHnˆÛævJèBæç«*†¿0[@:$CL `xå³€°æ1z¾>q3`-$¢³%Ù-& ]dnÁˆù+òN{' (pw*¥Ô ~Õ0Ÿábè‡û+3»ITðv‡\ ¦0Ì|kÀ“X ú&Úò­öÌ….Ø0I]u‡[Ë­˜Ë]>¾T¸mdP¼Bæ‹Vñ|Ï<1Í-òne\ȼ"ÉmVò*Kwsá¹&Þîþ­^ç.¾o!iÅHÁ·G·b°X൅´Ðço•]$nÂ|qÑ~'ÿYßfkà&Ž•[=ÖwpNú6·wòùÛ}çwwÂÐ[ý–¸Ék·Ê,·ø7‘·û¿â6›;xýNÞûí¼v·çpGI!¯îæ{ï„iâ6@¯à?ˆ»ü¿ú.ߎYâ6Û¾‹óà.~—ï¾Ýßß×o÷Ü+aΫ„!“ô•~ö»Æ˜ï5‰×ØÒ¯ÒgÄ·ËÈ7 ¾ÛÿQ³H‹´H‹´H‹´H‹´H‹´H‹´H‹´H¯;Ú¸þrñ*,^ÈEZ¤E¦ÿ7&'Šf)b‹IEND®B`‚pnmixer-0.7.2/data/pixmaps/pnmixer-high.png000066400000000000000000000437121311427610600207110ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aËsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÛ 4¥‘›iTXtCommentCreated with GIMPd.e IDATxÚì½w¸]Wy'ü{WÙíÔÛtuU-Ë–+ØB1&@ÄôªcJ ɤÍ™I€|)$óMHùfžI†™@€ aú„BwW$Y²dÕ+Ý~OÝm­õÎ{ï£#YÛ2à-?çѵtß{ÏÙë·Þò{Ëίóëüú·»èûõƒýȳ>DÿO¯f¸ö ¯~†çÑ36(E¹” Áßô<¬}ù+ÜßÇë¥/yýµÌü¿ssÌpRBáD’ð~!èOþÏßÿåGÿ­@~?¸Wüø›[ÌöϬsWYËŠˆsz"n(E›\vÉ¥×È<þ¶î:€ï§uÙ¥ÿcøg9 MŸš-µHÃZ†sotŒmYÊzçΫï9xÿùy|¬—¿ìõÿÁX~³1®ID˜œ ÑjúˆjR D5eR`ƒR4ÉŒoÎL?éè±ãßà+Pßo蕯øé‰$I_›þ5clhµ|Ô„ ˜Ü‚ ´[>ÀúZ€žäyøÝ™™ìÇ?¯þ®7ýäÏÏôzÃWü^ç\€êu“„ py¶¥$´'A¤‰€M_tÑã¾¶ÿ¾»ÿ ¾oTþ½¾–$ñÓˆø7­u’ð}…‰ÉJÀ`ayi€……:yÎÐR Ùð4?ÛóôÓÏk€ëòKÞ$–V¾Á¿øó¿©:ëËW †æÃ…D@TÓ˜š àyiša0ȱºƒÈGg½ƒá0G–ãÕ4´'10sËY\vᎫ?{ß;×Ïà1¼L¾ÀÑk_ûª÷Úýyž?D¨Õ4&'CHɰ–‘çÀôäÅØ~Áå –WNÂY‹$ÍaŒƒïiÔj$€$±`æ3OþÁ§Þr÷Ý·™óNàct­u?ë>ûY>ö7¿õÇøqçµP£Þð!Ã9Æ–-Û13s%jXX<†Ý»oƒµB ÄC‡¥%‚öÚ¨Õ=ôû9²ÔÖ…ÄMƘ¿pð¼ð^«+ÿtÙÄDíú½>|_¢ÑÐC,Ëñä§ü ®ºêz´[›p|þ þùŸÿq<`œu°6G¯7ÀòRB&&˜±ÍY÷–½øµóxŒ®ù—ûDÁ{Ž;ÌmÜ|Ë­¸ãޝaqé(¢¨kž| ¥ Æ8hO@!4‰‘¥¾' DžÇ?äyÏà1´þׇ¿vu¿×ûÉ~¿¿õøüaø¾@JH%ñô§?õú&,,œÄîÝ_Çñã „„Rßð}‰,³09ƒ™òÜ¡Ùò!ˆ±¼ÔƒãB+.k4åuçðY‡-47Î5o‚誃wË~ÍVÌ—\º Æô{9î»ï›8p`ˆõz€Z]A ŽsäÆÂ:vž/áûYjçqœÀ‹0PPŠçnvy)yñÛñoé<¾Çëஈã䃾|ÙÉ“'&Ž9Ïóø„v»‰f}I\ý{`÷î¯#M¨Õ"D5…ñZ,œìâî»îÆúú¤Ò H ˆ¡uuâ-œs’`EjD5ï¿S)…#GŽ`0âÚkŸ€ ,èeˆˆ^øº›~fËy<‚õ¼ç|èa9PŸùÔ]—))ÿ=X¶¥¥y8°ÇŽß­ —]v 6mÚŽ4•8¹pÌ bÌ`!E8ç 5Á 0CBxg<âû4â8Æüüsm=¾æ<Áºÿð§ò÷þÉ{?ºÿÄ/å)]š&™^]=£Çö`eeBív›7oÅìì&,--ÂvÌåËZ¤ik-„@éÉ;(Eð<‰üøþ ÿ™Õµ%ÌŸ8¥rLMÕ‘çÖXgÀpÎűc‘$C!æRU3HP¹ÉŒ$10¦ð ˜OëÑæŸyò­µ ",,,à¶ÛnƒÖ>¶nÛ¥FߨÎRócÏ~ÖÞ¿v<æJÂþËŸýS}yið®4‰õÂâI ãu\´s J ‡1œsk|ÏC– Üwß:´BÈÒþ¤"x¾€çÒ´(üdˆJ˜×ZBJ kíÞC¥¢(½÷Þ‹,ϰuË&´šz= &Àû8)… {¬=×¼è-Ü–RÄý›ÿ¾ø¯J„~‡ÉóÇ­®.cáälškÀól©¢Ó,ƒuµZ+Ëk¸å–¯buu¡”¦",â5¤©E–ÙrC­ Ì®øàB¢ •|i­±gÏÜ»wv]r)Zí:\)/¥ØÙnë«Î”¹øÂÿ®RÅï|ç;£Ï}îsÛ:ëëÿëùo?ýÒ—¼æ]YžýœsîWÒÔ<ç~þâ_¸ÿàÂ|ãGž»¶ÚmÞè^LNz¨×=(Ep–Ñëáû ¾'0ŒcìÛw‡ß‹<Ï„5Tš ûÏ f‚J0ÂÆT°R¢¬ý;»_ÊÌBÀZ‹ûî»—\ò|´ÚuÐÑe0lZ[Ë®ð¥Ñæï|…Pªö¨RÅ?ö²7Éoúe÷Ò—\ÁpÛm·Ñg>ó0Lv»Ý©ÅÅÅ]KKK/ ÂàÉ;.Ü^¢Z;Ï“³³Î:<ÿ¥ÿý·ßR øEÃÇ(ìÓš ¤‘xÐÍ=! ”¿ø%¬®®ãÒKw•Ü•‚¶ÿž(xϽÿãQÀ nø m¬™ýÿÿç…œKKKÂZ[·ÖnÖZÿ`·Û}Ýn0Æ\²iÓ†ÍÓÓ­ºlœcCÄ»ŒÉžô¾÷ýQã1mþèÿýX¸wïá놯´&O11"Œ|˜Ü¢Óé`yykkë’àiUðòä£^oâòË®ÁÓŸþlìܹ¾¯ rÇ1²Œ!Ëž@f@ˆÂîÃ¥z'8wzü¶åÃÚwÜùu´Ûؼi#„eYæ.|4ŸEž›™é™©Ÿö}ùN"ú0_a­»úÎÛw×àùÏ>_}õÕ†™cç\G)µ–¦épÏž=ùÂâ‚››ÛȵZ)%1³ÏÀ6"wM%ÿ˜À-·ÞilþÆûp½~ͦÆôtñ^;úý~éÌ1ÒÔ ^óáy>z½zý¶n»ϸî¹xúu?Œ-ÛfE¨´ùÖrRòÜÁUÿ/åTý·B­¡?è`}}€‰É 8Î*3P“ ׿ñͯ~Tœé7¿éÍþêÚÚ»6ÌLÿl³=S ±‰)cì“»ñßáÂ0L³,ë !:BˆÁÑcGÍý÷ßïš­–óÁªè~ÌXk/qúœð„kÞö¨†8,ø$òç?~l{·ÓJ2¦¦kR ×ëc0ÀZß÷‘ç$¤"c Uºdÿ:Ý ³3—ãêÇ?ç¦F²ÈüÙ"žŒ"3˜Ä¦ ‰ˆÎjó+ Œ/"ng÷Þ{ææ6BÊS²ql`áø%Šú?>|Ǿ{÷=n˶mSf­Éà€@J±¹VÓ­Ÿÿ¹·R©\3÷sëDÔéu{ÃcGåý~×]y啈j•Þ* A[êuo¢’DxÂÕ¿*²´ó¨6“Î[»ì›wyáÊÊÚlš0½¡†ZÍC–¥‡°ÖÂó4”*/f‹0ô‘çƒáFSS³0&ƒT¶n½—_þ ÌnÜ€¨&1f0Ö³B U©Âù[:g‚@)‰ÅÅE\pÁÔëµQÉY¾¬Õš¿ä\ŸÅk_ûÚºÖú÷Ýwߎ(Œ¼Z=ÔDV2³fæÝn>[oüÀø{4Ì<$¢eçÜb–e«ÇŽ;zÌ\zÉ.n·k,pÖºÉõõô4ù‡ €a¼Èž×´Öæ3³\Xì<¿Û33}7Àð†ÁÀ\[¶l”Ò1sFD"êcÝÎZ6?ØÍÌL @4œNéž«üw ¯zõËô _øšÖúZüKí‰ü“ìì¯;çžü0D’ ‘ç~àcz:‚s\Ôô•$â4 ”*=òBí¦YŽ ç9ŒÉ!•Ɖ“ÇðWþïètá¢]³˜šáùvíºSS!e±YYf!¥8-p¶ØÿÌUù"NSSSð=îGÔòÜÆ´½â¯˜!ÂÛŒ1Ï߸qnÊó|Ÿ™3&çðÆ7¾‘=ÏsÌœè A"$Æ»qã<ϧ3åªu®ò:¯öž÷ÜWͦ±þ©4Íÿ>Iìo:Ç× !H Š$š& ‚õº†ç…yžŸ¶éã/çNyíÌŒz­~¯‡4B)‰ Ð`¶ÈÍÞƒÕÕE\vù,|ÂÇ…;®B½ÞBzåÆóNý™aßÙ–ïûpÎ!79‚@iÖD¨Àk^óyã7^*„x93=5Ž“ ËR–Â9VDhɳ¯ýÏÖ+ð1³qÎ%¥0SljýVrãà=ùG /yñ3ÏyÝH‚þO–â·áð$fŒfËC³©Ñl„¨EM0MA ¡µ@'#u_9€ã& ²¿DyžDˆju †½*ˆF½‰©ÉIìþænÜ»w?´flÚTCT‹pá…W¡Õš‚ kdYâý­Â¾³™€<ÏáœE«Õ…ÓH‰©o¼1pÎmrÎípQ¿ßqÜ·ÌÌ~àé>3×Ò4¯)sBëœKsý~¿›~;¹j«ü9àE/|Sû¥/yã5ŽÝµæßbÇWY¦6àyaPœrÏWp,DuIxžÄÄ„k-²Ì€§`ܨ4@áÉKøÚÇ ß…’àB®Vo`b¢¥î¾û,//àâ‹7@)†Öu\°ýjDQ~ aFæäÁ‹AìßÖÖÖÐl6Q‹jUu1J‘UJq¥±¸$I2"a[­&&Ú-¬$À£Mn¸á(¥¬"+OqòPäFÑÅ9Ê?b¼î¿ Ÿóì×nêõ”¦éGrƒvL›À€Öa¨¡µ„1ŒN'ƒµJ…PÊÈ¡Ý.&xfiŽ$Î1ºÑ‰ÜU¾¦)jõ&@@Ðç©¢êÇ×ðý"Í›ç9î;p?23Äܦêµ[·î‚ö|(E@I=ØFWæ¿yž‡(Š$)ü@#Šô(5lŒ›VJ9çœ%¢L‘‘I’ÄcØó<0Cìêe{u–Y$± Jë|ª´Ú÷4ºlÌP²èÖ©ìú™ºRÿBÄq<Y6s“切ƒò$eãJ)h­F᜔qœ€yˆ©éµZSSsè÷£“}¦ê¯´Ñ™Ú@(*¨ô••hå¡‚±F„¬’¯ÀËì01Ñfk ˜©Hh øRÂ/²u€ïûüH䯸‰G,ÿmðÓoy&w{’Z›e9˜¾'Q‹¢š†µƒA’8(Ʊ€’E“† Ça! "Xk…tg>äñŸçùhƒÆUñpЃPJ=BSÀ¤PJCÁ`PžX‹µµ5hí')6lØ)ý‹w¶®@8ÎITN`³Ù,+bˆ1¾‚âÇÑiNl¯×C³Ù„§=ÅêPÌð”Èø”zDr8Wùo €_}ëïzBèÇ9+ÿ]žf²²™º‡zÃG’t»’¸hÁ&Œ'V® ƒÐ‡ºð¼EѬIħ9mg:\USFš¦£ªL@°Æ@@”^¦ö ÓPÉÇq k-¬uètŠZÃɉf7lçEåDÓ³}gn¾Özôgõ>‡Ã!Â0QÓÌ`)imb*ôÆ1ÏóÐjµ¦H0ÂPU¡sÑäĬ+É<¹12èË?(n|Í{èø|w‹ ï7Ú霃1ÂHCH,µèuóQJttzA$A Heå­E£Ö¸0 a¨G›u¦ ®œ˜êçã‹“f†­vYž›¯Ä(‘äy^¹9(™;‡$I¶QÃæ¨–ðl´sÊ §¥Úí6â8†çù𴪢IÊ3e‰0\¶ 13UÎk£Ñ ápXœ † b%¤¨=õºkùµ¯}-YkéáÊ•’“üƒàõ«¼eÓæ…ÔÏâ4†(†T¢œ©Ç(ªð‹Ó>ª—'ŒN»ÒDªׄ‰¢)£r¶Æ=ðq5\uéžB6BÄþ`$$¿ÇE°1R*A€ F™Ck-ƒ!–––àù@F˜œšyòãÀßø3¿®L’R ÍfI—ŒbYL ‡¹ÒZsõýJ) 8ç¸Þ¨Sù}TbÏüøËoàv»F£ÁW®Ú§s•Pü‡_û³ËƒÀƒÖìê\J…Aß I-¬c<­P¯R@]qÒ “;8Ôj­òʯ IDATq1»¯x³gzáBdY†$IÆ¢Wöö[°<íA) 0y¼ëWÃók†<σ-K³ò<ƒRò4g.I8ç0Ä0yŠV3ÄÌôL|Öèc\;¿·Ê9€f³QRïÅïÎRëš¶¥*Î9""ššš¦$I0Æ,¤,#6r•k®Üx¹ú¹ÈWc_ùÊ—·[+•”ŠªúÙF-ÄäÄ\tÑ&l˜­C©BdÜYªTR»]h@Œ6:·)„DY[/OKõŽçã«ø¿r1eåeØÎ "Aˆ“J x¾ÄúÚy–ŸV z îŠËŸxyEÍQÜí{PZanS¿j&&&J ô¥[BH„a€©é”.þ>I3ôºI€ÎÑ( ;³º¥ðÚ§Õãõxy©êÎ*K“A™Æ0Μ:2¥æƒÁƒá iàJ¦=@Ý›£qߤò®+ 3`¬XG$Š%™YEQ$Úí¶èv{¤ua&Ë bfsN ^¯ƒ™¶\µÎU^ðQ̾SZkI˜ >¸œç‰¢ØÜv»V;Âôt Jùh·ÛhµZ£ººñØYíyh·ëð=ký^†$é#Ï2Suꪑ—>îlÅqŒ,ËFùÿj#Ó4C–q?;F÷JÔ+ä¹”(ZÊÑãW¥†=Š'Žcqq Z ø~¥äiUÁ–:3e\«Õ`­ÅääÔiÚ€˜žª9¥”R*k­""911AÎÙ"©U(`G0Î XXX@­VÃÕ«Ö¹Ê a ßã3–Ôß|ìO?ersH+¯¼n%@-ò!å©phbbõz}dÇA.œ±z=Ñ½Ì œË Ë)ݧ²~ÕÃ5Æ ŽãQh5¾‘Y–ÃSôöÃB"ŒEËÕ¾ƒAŒ••µ‘ó×ï÷qâÄ<—±²²Šn·ƒá „õœøk=óý@/³€åü!f4ÀFŠB­)Ïót†’Hˆ4M©¼ÀÄÌë̼R6›1F<\¹j«¼• ˜Ùˆͺµ6•ÒPJ£ÝŽÐhÔAekÐn·1== NÛüêåy 퉨ýHÀ÷ Y–À:Fœ¸‚<:£Ø3MÓQòg<Æ®œÇÁ0Fž˜Ü€Åd{¶ààFƒAYža}}'Nœ@§ÓÅ``uµ‹,K!Uá˜fYRjœuóÏl¯FÈŽõæÁØSþÆpèÖ{ý„()¥2ƨ0 e³Ù Ü€$Á,€„q¥ÂK^>¹qp.ò•O})¥(’+ÍVˆöDBHh­G¯v»¹¹9ø¾ÿ>H о*Ô-;t{ëȲΤ<ýô¶ºPßUXW  à\Ž4I‘eƒAT}(¼qFž[¬¯wpìè1,..¢ÛíÀ9ÆÊJýþ'Oœ³ƒöƒi:~º‹aP§% qœ–³z¸LõdYŠ(’ŠYþž§¡¤„19âa k2¬®ö = Ï ÖiÓ4s`ƒ¦rcGÇxÿa•Š®Q½—Á`P4¨:‹¥åEXSÜ^â:ž¯VÊ´HDGµÖYžçRJIÎ1¹bÒ83³«ÎáØÍ7ß\ñ/’ˆ´ÖZ?¹jÝ|óÍT:€H¾âüòh¨Ÿ8qdQ+U„:\}Ž;|ãqsU´Ñjµ099‰f³Y&yZÍaà!I,&&B0gÈ2†µ…×Ç1Ò4‡*½ëêTæ†@pH’IRÔú“ÃX‡,ËåiÙSQʹI±¶Þ‰Â7’†š­ dYŽÁ ‡Á "Uªy3Ò:Ƥi:2Õégfø¾Á`€ƒ@U[Ë¡ïÓ±w¿ûÝîþà:ι{œsßh6›!EQ­LÇ‘0 ¢Â0Dš¦Ò£œsÊ9§šÍ¦üvrcI‘eY蜋‰|uâ+ÂO–„“ïß/ŸþtË€ 4u¨×%‚ @’$å´mqZEm¥šÍ&œ+6Ç©æ6µ°pÒ•µ)z½:볨ՋØ ô{9ju­Å·OHÒ ”W¼ìÀÆ Q›j ð#$Éͦ7ª3tΖ3ªŸEp.C3œð´¨èòqÎŽ(ä³µ‹sÖZ4›-,--a0‚#äÉfÛ…ï}ï{—^ùÊW~”ˆîñ}ÒÚ¼ç®á˜¯‚:RJ½^¯ÊÇHçœ6Æ("¾ï“µy1ÜŠ™¥ WrÕZ\\ôœs.rÎm6Æ„äC•gPÂ@ ˆ‡ƒãE§‹õõÌEÍïû¨â§+~:‚²¢F¢ÑG¡! $¢×‹ATDBƒ N<–û/¨f.‰$)D™E,æ§i­=´Z“óÿòÌ‚ÇÊÑ…’8+2™a­}$i†8^-ï *z ’$Qªg{UößZ‹ùùãX]]CªJS—îÝÓ;6þ`?ò‘œ|ûÛßþy¥ÔÇ®»îú÷ÅIüÇŸúô~êãŸøËWÇ1,ϽlœDªN¯ÖZyž'„¢ÓYGœÄ "`ã˜×óÜËÇJ¥æ¬µsq_]«Õ.Þ°aCC!¿<ÆN¿8㥾~û?ß³÷‡o½xçSžÜïH%A$†áèaS¥ãq´çy#MŸEJ9Ž <]`ˆZ'‚çWóúc,ƒjêg¡”ŠûýåmE_G±ÑIç\”š À.êª ᪘!†“CJ3⸠!½’FÎF¬äøg×n• ”Âòò"²ÌŒª¡œc/Šä·ñ×ýþ‘zùûϽÿ0¼ímo£n·KÖZaŒ‘Æç¹jµZ2ÏsZ\\†1̘ˆr©ÿÝÇÿläÄýáþ¡Ì²L[kÌ܇¦§§7=íiO‹Nœ8Á)g&DâòÕɯ:JƵ@4ô×Ü·»VÄ@¯SаJùöoÕÇ_œvï3Àó}äyQàœÁp8D•¾Z—÷ñdÃ8-;I ÇÍÚ2DQÿWTæXCiÚ+¦†e™ÈójTU!Ëå="@š¦°6F– ô{Å¥ÌnTWw&0NÅqŒååe½€zÏû~êg®Yz¸V¿ÿû¿ÏžçåÖÚµ<Ïç­µû„1÷K)W8c3;fî§)©dßóž÷P¯×“yžûƘ¦1¦EDa«Õ¢Í›7óÒÒÝwß2¦¨Ògf“e|ülíáÙˆI9Àô]wß²°¶v²7œ8YäÒ«š»ÊkÏŸ›(Š<σç)4›Ay/Ÿ€T„~Ãa†n·˜ÝÓhxâaŽùùuä9ÃBšH-FÅ$ B’X“œarbˆŠ  ÎrYéSüiŒ+5C)Vs|ßÃââ:Ý„,µeŠ9?­;øt’ÇqQÓ`úý>²Ô”3‚DD/}ñ/&¤Íîw~çwøÿø3cÌ¿ø‹¿øë}èCo Âàg÷ìÙó§ý~r³jP”›Sê):Qɽò•¯„sN&Iæyފ㸭” ¶oß.|ßÇÁƒpâ䘉ˆ ‰¨æk±ò`ÈGÉíS î¼ã–ù;ïüÊ×&Z-ô:µ——-ß²«¦ª¨-B˜œŒlqiâd“[Xë™ÑlÕFZ¤N·ÛG’ä0ÆÁšbü·+9›¤lB­C–ÞŸ+F*OH) µ€çkL´·"Ë ¬BÊ Rj(% ¼âéñXÿ̦‘Š ,H«b,]5jŽ™!¤¸ùWÞö‹ç4nç}ï{ßÈD¼î¦×Ýý¸Ç=îw~ÔY¾ ?gÆ—¢È[­¾çŽ;î áp¨Œ1µ<Ï›I’ÔjµšÞ¹s'-//aÏžû0deâšò<Çá ÐgÕùcJ¾xÜ?ð>óÙí½ëî¯êt2,,&PJ¢È5û£ÜøøC«NNU–T”T+Èr¡°ÉÎ:ÄIy¬­;øžBùð<(ô"¤i¥µZa«EI9ôz}ÄIaªÞ2ÒÔ‚AÐZAÉ‚!TRÁ9 ^ŸD³ÑB½îáØ±#B ¯t*«DTÝœmJØ`0ÀÜÜ<¯àrS\=G‚ÀpÉþþ{Í£=iåÃúàðŸüÀÝþcøÿ›ž©€È²L§iåy^7Æø3334;;Ë·ß~;ïÙ³ŸƒQ„k©-ž I ‚ô þ¾}»ç÷ì½cX]ɱprP´]§›‚qTÚ ð¼ËIŸLˆBBa(!%£ßë”U> Ö0´RHS©“Ÿ ÃÕ«Ò/ÐøÔ§ÿêà7¾ñ/Ò„yi)-êAðý¢øòl ¨<æÊa$"„Qáh-ËîšÖf°F Óqh¶Š<½V¾ï•›(F$EÕJ 9—0šÍvÙŠdyÑ’N‚àù~ ÚP:Àô†œËpèð„¡?š^v<䯸ÉóZkÌÎnÄ`ÐGšæe¾‚ ¤iæ¿Ó“Öþú£ÿƒå—ÝWNYkÙZ›9g»­Vk! ÂùµÕÕ…={ï]ÍRÛ%’]!pŒ@ŸfÆ­¿òË¿ž=˜ˆËW:‚¼‚[YYèÞyçWä&v'O&Ø¿½¼xY! ÃÒœ¾ùUb(‚QÍ@•øÉ3ƒ0Èm‚~¿­5ò\b80ÈrFœXDQ žW¨r¥DY?@PZB*‰41ÈÍÆöQ«· ‹vcä9c8°Eå²(Èv{¦§§01!qüø‘òïËAe()¥±€ã ¨|!ŠIf @*Y^DÅ ÂÞMsõCßí›Ãá™9·Övs‡gggïð»îºûv“Ó=ÖÑ~˜é‹Aü“1îøYç–>,_ƒ3À`ªñãŸxÿýÿðÛ_¯×xЗ¸wÏ’ÄÂ÷5z9©ƒOËïWÉ¢ñâÊ (ZÄš­à½^Å- ÃÐjÕ²”!_qñSI÷–åÜÆºr>@Ž©ÉY„A­¨òÖIlshÕÄäÄß¡Q°¼´ˆN§[Ü&.©¼?€F—NVÔôxE‘sÍfAàa8À7FSÃ[X&ßmlذÁi­ScÌ*ÃðöápðŃÿK›Ï ¢/I)>ODŸqlÔjáàl?§ ùø,¬`õ§*ÿtKË'Ím[wEÌ--uÕ¢È+ʰٕI>m°CUåkm:­¯Çð=ÇŒaœ#"DQ Yf`MŠ™ !@E}€c[xëª vÊœ‘Äïcb¢“ tºäYZÜBDRxhµf°k×5¸hçF ã.>ý™Ï!Ïû£þkaèX½ñS_˜[7B­Í2‹^/ƒ”„,ãt.úÔž½·Œìë ^ðzÒ“žD×]ÿ ºõ–[¾#øâ¿ÈÏyÎsÜ‚œœNNNô:ÎúÊjg9Ix‘'¥¤ýÍfp»É¹û×óçîÁ LJ Œõ Œ€@D Ýí®v“dÀQTkµšÓ¾ç7Åüñ5ä¹E)„¥‹»úªTuù òŸ¾¸½ÓóŠø|}}P¯·AHÒ_ÐÆÃaVtùºSmgÎWÀöE…îÆ¹&œ•Èr M‡p(~¯öŠé£—^r-.½tšM‰Ý»aÏž¯"I†R•§X–£gpÚä°SWÊy–czzaXIŒá pú³”oþä§ÿâcãuß¾}¸ë®»ðÚüj}ùË_æÇ?þñ6399™¬­­÷×V“®µr àeçè„§g>ü¿Þû “0Uiëi gÒ‚™eQ[DtÏ7o;ØëuØäÃ+.»ü‰í;.NœX…1ŒÉ)F³…Í›#¬®v`­Ašæž§F§®âñ…ˆBµµ%xž·!N4––Ø~A ³³“X^ZI.ç 2Ò´¨ü‘HÓƒ~k%uY¿X´²±µØ0»›7oCò\ààÁ½èv;¤K_ÄŽü€j~àÙèí0ІAÉHôz£¶õ^§c¿H¸^2þÅâ{°œs0ÖØþ`hÓÌšÜØÔ÷j†ì¤ûÀ_ýηœ€Yõð˜à3EèŒBîtV³»î¾µbþÀpqq~}fÜŒ‡Î 4ü<k]'!4¤ô µß÷@$àûŒ±è÷ga2[^ A¥§í#B$I†^7F{¢í«+=Xëå»—gIbÀLˆ"A ‘g@šeE¶<ßæ¹ pé%W`Ë– œ8¹„[o½ÃárÙ›ÈeG1ɬdø´FÕây€‰öäX×’EÄ¢’ê½îÿ»ø­Ý»wãöÛoǾðÜzËͼmóÅ,¤tÏîÙßýý_ø¶ ”gôž9GýL@”HØ¿÷è±½Ç>|bþø§iÀIâ…ËËŽ³Ô£•ep iê]ˆ,PÊÃpÂZ‡4Ë‘¦1ˆŠ) U†.ŽËÛ>„ÁúZŒ~/ƒÉÆŸË>&Ú äy¡YÒ,5y\yÅ“qéeÛ¡5pÇ퇰gïWÀ\°€!$²¼ˆFýŒgÔ98h­!´–eÁK “3¤»ê¿ÝwßíCnS··ÎÓS¦òÜË[­­žVÈM‚é©–WÐï­aiù$úý>Œ9„™™Í™Fg°V@ëSÓKK}$q^nP^oˆÜdð<EI<Äöm—`ÓæMh4V–r9ºi:D17¯0)YZ˜Ï«úè´"Ñ‚#pPªè6®îª(`€Ö=öî~8K•_m¸-9€³i7öÊ˺¬ 瘹 €ççpxß¾{v·ZS-§;¶_ÔnOLñ¦¹mîÜyåL£Ùºdzj®699ÑÞ¼é‚`}}É yøÈ~dy†A¿ Ïó‘e Ò´8͵ZøÛ»¶9ŽëüUUwW÷t÷Ìì…»"M‹R$[F‡rA®@~€ü3‚À°ŸüÀ/A`?0ì7[€åÉvŽe„B‚Ø@¬(°$Òb,…!)qIJ¤w—3»;·¾Ô5Õ½izvQË- 1ùì·¾9uÎw¾s´6ØÝÍç²êh0fȲÝ4EÀXKÄ}œ=û8–—;ÂbûÞ= ÷\W‘Ð¥®l]*0d0ûÂSBþgƒÈ\u³Tœ×ªUÈèϯÝèÌ>êh~Óõ+P@WV@HÄQ `µJ%/ÕVe4ŽèËÿñê@N)ý¥1¦üäS¿µ:í˜óçÿð,bòñ?þÔÊÊéNv>½Ü?Õ™ÅcJ([1FGRHLg$®&_ c-˜¥0†Ã)Ò4ARp"‰»8÷è9¤Ýãq­­=üêW7u\Hk¥ âªÇQ=MÔ÷ÿùª–J+ %iÕöÎýYêqt€Ín¾ý u0‚æÆÛ9  +ÈJCX6ˆ£¨ßPÛê>3Æᵫoí°››€aŒý‹Öº|ò‰ßNol\Õ¿ÿš„<öŸ|â7ÿÖóøyÎ9vw»ºšBI‹{÷&®Q£5ØÝãÌ™et»Ãß°¶ž"ŠÞ½9Á­[W(0ϯ”ÅQÇ«*ŠëN[J™ý°Ò€€Â|„õ ⊔¢”Î`éOð_ócàæk£LãV·õ¥*1PBclXY½W7¢ ¯ABqf"ÜÙÝžXkÊ÷ÞÝxïæÍ«wƒ;o}ìÌã¿wÒu¥Š¢„Ö@§ãˆ›¼ÊÉÃZpŸ#ívPä;;ÛX[K»ŒáîÞyçMlmÝA:þ¿––IéœÌ  0U6ĵ¼- ­ ‚€!M{ÙE¡´Åx,,,¤RxöúÛ—7ŽZCÍÆ­i8ºŒú9Q]9%ÔP¦h±*h 7QYRY ©”¼7™ŒD7]z¬×[^-‹R*—Tò)¤P.+g4J¡±¶ÞCà{ &O2ôzë˜ÍfxíõŸÂ‹NÌÁ9ƒçQ…ªr¥¡®bÉIÈ5¢È)›Á¼Ð €aÕüñÓG(D©oݺöʹsŸ¢(~ÚÂ2!$ÊB#Œ<øEQJWsh€õõž+!ËU5ïwˆ½½! IU‡Rêª'1ƒç1ˆÒ@kS5Ã"8yd Qä|†éTBMòµï}ÿ››pÌǰ͘<ZÂ˶Ռ@({ýú/_]_?;[îŸú#c UJÂXÀóBÎ „‚Òý~ ß÷Í$²l‚,Ÿî7`ÌñýA@Q ½Ÿö}—^&–Yº”DQ‚•ådÿ½“Q cì»Ë+Ñóo¼qñÆÃ€yÑ´8„óàÀ‚[rÈæÛ¹ßY¿>¿s÷Æ]Î#t»KŸ² £xèZÅÎf9ÖÖ»°(K©”’0Ƶ¸uìŸÃ§ï¹J$Qj‚J°ê¢?  „Á÷¢}¡JžKÌ2ì&iô¥_\z­x˜ÐÆ è9kÐ|ŽñX9hÓ›ÿ¦ZéÛQo3ê?Å~–PBËÜUuây^B‰~/…ç{(r)]ùwüJêdiÆZ¥³AÀ ´…’¾OáQWkÀyŠ4 A)gÊÑÑ 7¼'/lܼ,64MºYp–£ÅgÀÌ¿=Ä2Pí·Ó´·'½?ö˜·daPJÊ(z½“i! Ö×»ÐÊ¢( Ê"ƒ­Ø;—Û§U×WI†ž5GûÁl"P–6^m| IDATI£ßa­ÅÎŽk‡Ï9ûñ?¾ôÂ1X÷s¼]p-Úx»à~ÛÏ}Ÿc¸½}ç=!ŠW×VO?ü”Ò Æžç¸¢PUaŠ»_9¤VUÿ\WÂ'¥RaäCTþ@]K˜çB*úý.â4€VÓ©€ÑvpúLü×/¾¾ù0€qóí\’ɶvn“:ê×éÑhg§ùV¯¿òXÆëR:¡jš„˜ÍJhc±¼”@+‹,+ •Sð„aÝ3‡Ts \Š·N kmD Ñ_JÐéxPÒ`<*myï„¡ÿÜ¥K¯ v @Z¢„¶ûh™{ì (¡Í§`¦Öš FiÈyøÉ S§ÖUH§Á<øR»ÞBJWòî*Ý[õà!ƒZYP„œ!Ë ‚ ƒ^?F2ä™F–IB€ï?÷ü3Ïá˜,zMþ|²¨–™çEœãƒ äZy¬ðþ”t,óÅZ§¸2ï™ÿ¼ré›E‘]PZhJáŠ6¤†“q†€3$qŒ0ŒaÛtÆhÕpÒˆ¦H'5 #Ei°ªç°û•BÁ»¹²^¨[³ŸøG'p@´°è1BÖ#°Öš[·¯¿üÈ#zNò{µÄ‹P)œÚ- ]ó4(s@JÐTJ ºL¡”y®@àf&‰{ïd,@(†„Яö³Ÿžàà-G‚^àØFT±Dóy‰ypˆÛ·¯_ë¦K¤Û]:O¥Ú¨ªO€E¯p\Aže`•Ƥ²ˆB¿š9`Q–ªj?!I#$‰©Lú /|ûY£u¿-ÀaÎ!üAÛóóŽ ™ 9çVë-€m!˵–%iï1ÆXhAQhmÑëEhåèI§þ1NèrN#øÖ00£Û Ç>¦‰<×çìÇŸÿÂ_þìŽx€_ãh0-›¿ˆE<ˆ1ls?˦×8o3JÖƒ |”R/°p5þ<ðpZYäE ¥4ü€"(„påd®OA)€ÀçX^é@*ƒ½½F[Hi¿øÕ¯þÍÝãdŽäþÅŸ=C~ ošþúª¾²ásbíІƒhZˆ§¦b¹îy|úÖ­ëW†Ã­/Eþ¦6Ìó …ÆhoÏs•GqÒs%d™Àlææ…Ü•²ç™nX—T²®>à‡ÆxÇjól6nýè~†ŠmG‚9äØh¾Ž,p ëíì¶ÇãÝ=uêÌoø~ð” R¤ !ÆäY!$<ß•¼O§®™µÇ|¤iKKòL!Ï5¬%/]xéÙ<”¸OGiaýÚŽÓâL.’ªÏ3…ûQBQdÓ›7¯¾ü±Óç:Q§s^[©¬¥ûònW_¨P– ¢P¥»3d?ØÜº<:Àÿÿ2 6vQȈŷÖÖB☈íW:þXˆ2LÒîiBX0™8“?0F!„|w4}÷õK/üÇx=ˆ8H[€#>¾àˆ°šRß³l8¼û*çÑÆd²›wÓ~̨·N1cÄX”³iñš”å—îÜ}»<Î ðgÚï£?çüÕUE^ã~3UÜj6ÓÌšÏ ©”³»Ýîrw6›­<ý»þ'J•ݵµÕO†Ã]Γg^~ùÅ7qÌyÀ?W“îï[4†÷··iQ1 ×pFSêÃca ädP½vTýÇÉÒl6ÝÅC°ØGè³¶ùäˆÇDµ(%„ÀkÕF6Ûãø”0fa‰ÖZÚz|É ȵ(—pSX]Æ,QUÿm­j¿q°Xõyd±fîÜ·‡0†÷Yƒæ)è , ´µ¯™ç Ì‚ _$Q›§¡’¨à²æ€øŸ, Žì!aËsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÛ žÿ»ÜiTXtCommentCreated with GIMPd.e IDATxÚì½y¼¥YYßû]Ã;îñœSsWõ@Ï4„‚EÅEA‚häFi¹ùÄ„LÆÜL&÷†krs?Ñ{ã5b$oâ1QŒQ„n¦èê®êª®¹êÌÃÞq­uÿXï»kסºA$¡º©UŸ÷³O³÷9{¿Ïo=ãïy\_××õõõ»Ä õƒ}ë7ýñ›¿ý.ðÀËßõº0 αOkQ)…˜LøB²ùûŸøðñëx¯ïüŽ÷=àœûÿ¬µÃ*EP× óÜ—RüäüÍýK_¯P/ä÷Ž·¿àœùçÆÚûqZ!ó Âõ´7wßy×ËÔ-7¿äÓ'N~ò™Gªëx¬ï~ÛûþZmÜûëÚö…,.& úi'@)IÚÑ  , J²Ok±è_Ø»ç•gÏÿ¬ûz€~¡} w¾ãÏ.äyñ½Uíþj]›Ž0Dt{!R êÊ (ÃA„¶6s@¼2 ùû{÷–oÎ_×ÏÃõƒæÏí¦ßîCÖÚÝnÈÂbŒ”!®ÙÛJ „¡B(rpÄžÛn{ñ'?ýèäëò£ò¿ë}<Ïþ„îoc•sEš…Å­˜LJÖV',/OØÞ.¨*G $ý^D+€@÷†0 ^s]<Ö=wþ \]ÿ¬û‘?÷·õöÖÚý“iý­åEB@Ú XZŠ CEQ”L&ëBDlom3V”eM][ÒN@*¦“çÜÀî~Ñ-/ýØÓ'Ùº€kxÕÕ>»M|ï÷~Ï-ÏœzâoVUõ„ Ó X\LPÊaŒ£ª`ÏâíÜtó=kë—°Æum‰Â€N'@HÈsƒs®ã“Wýñoxè±Ç>]_w¯Ñµ¹ó1û±¹ø—ÿÝßy·u¼ÝZG' èö"¤tXë8|ø&öî½I‡å•s<ñħ1¦FJ‰’ljY]áN7d<®( Ó•Š÷Öuý¯“×}€kxm¬ÿöÝ ??‰"E¯$’²¬xÕ«ÿ8÷ßÿ ÃÁ!Î_8ÉÇ?þïɲ)8p¬±S1MX[#¥`a!FsÜhýáoët®à]ÿå¿<Ý"þGçÎ^¨ë‚^?¡Ó ¨ëŠx€—Ü÷¦îòÈ#Ÿäþà?3o'1:€#Ni ¥ecc‡<«HM’jpNçEõVS›Åë¸FW–‰¿}òäñW-/_”ý~ŸN' ®K¾…ƒîeg+äóŸÿ>ò)67/1ôÐZFšn7$IÀÑéllN@@¿!„À^d ßÿÖoÿÁà:®±õ«¿òÄ{VW.~ç¹³§zà "œ­ xàWãÜO=ô0Ÿÿü'YY=Kšv0Æ’8Rè@P×– ”H)‘ Š<£,j¢PÇ!Paè¾1 I®àZÿö>ùÒñhôgÆãñ‘óNE’8Q(­xÍk^M·{ˆååK<ñÄg8þR*´D¡$Šei¨+‡sT•¥?ˆÂ±¶:Â:¯„àî^_½ö:®‘uúÔrÿÀÁþ›â8½ÿäÉ'Ôx¼AÐùš;ﺃ^ï0ãQÅÓO'Ž"„ Ûét5RB–UTµÁX‹³–0RD‘¤,jªª&ËrêÚÄ­Ue÷¯­æoýÀü{q_ãuòĎ̲üu“±zÛ¥KΜ9AFÄ‘`8ìÓïî'Ï:<õä žxâ3Å„N'%íhªÊRUëJAI0™ŒÇYV‘vÂvFAèàœ{ý“§þÃ7ýØ@\À×p=uìÄ}ÇžÚ~ÏÆÆè­­_`}c•^/"Š5½Þ#7ÞÇêê=þË˧‰ãp乡®-ˆ"…Ö’¢0…¡*-¢ù—e†º®ØÙÑé IÓÈ› án—Ò~ûü¸ëø­ý‹ÿlïÅ Ûß1Vïñc£¤¡ßOpÎðÒ—½‚²€'Ÿ|œ£O~¥C1)J ŠÜçcq¬BI¤„…….ÎùŠá ˆ={—°¶ÄY0†oýŽïüþßò–÷‹ëø¬»ï½û¾8N~4 VVγ¹µÌ`ØÅQsçwÐïíãÂ…U>÷ùߥ®ËÖC+”P×–²ò¶?ЂNGc­C)EÚ‰éõb¢HÓï'aÍþ}¾á^Í`ÐÅÔcì]¶¶êWõ§Üuüw^þןè'Iïo D×Z ʲ ƒA—={â\Ÿ‡þ¶·7pЄv~³6줔t»R ªÊPU– ÚcZkªª¢Û xðÁ?ÁâÒ€ª.ÚŸ¿ù ßô§_qÿ—uük݃B(trñâºN'¢Ûéqß}¯à“Ÿü=Nœ|Š<Ÿ 8k8¤ôš M}(X×®ñBH”ô|kàPJ“¦)OÆÖÖ2JBÂpA»ã ÖZ¤˜Ú$i'ü¢¿©µæÌ™3L&SxàåĉO/ Bˆ·|ß{èðu|ëÛ¾ùßü¡¨þú£wk¥þ"N @²ºz'žàÜùgÁÝwßÉ¡C7QŠK˧qÎ!àOñaXk A]p)q"wÝÿ¼€,˸pá·Ür#/yÉH)qªÊ¼~s+{Ùu|ë™Ó¿þe?÷'?ôÑôÔ3ÿBUˆ»Š¼ 66.röÜQÖ×—‘ †Ã!7Üp„ýû±ººB]×8kq®¹Œ¡(*Œ1HIãÉ[´„¡¢ª,ÂÄg4±v…aÈt:å3Ÿù qœò²—½c*Œ±!ð¦ïy×§×ð‡ãÿÜ—íAwûòõƒáðU]ö×7.rîÜQç ½^‡øcloÖÖ66PJ7»ØÛþ(R()¨J¡µ@ Áx\b›’°1Þ,¸98ç°Öòä“ObŒáŽ;^ÄÁC‹—ï™so®«ìÀuü7Ze5Úw`ßÁo“B¾lyåçÏŸ ×—t{“É”$Y\"¥f´3&Ï3´š¤ )PJQWÖGJEªIþTÔu”Ž0TW¼‚‚^¯Çùóç9~ü8·Ür wÞq+u]µÚ¢#„ºù:þ­ßùøé—Œ'Õml®ráâ´®XZêRUS×[ã°$IÊö¶áܹ“äù)%8רj‡¢²#ÏkêÚûÎA3áïÞùÆ„,//óéOš ˆ8rã!´ž=qXõw½á›Þ^ÀWyý‹þÛݵÕÉG£`yåÓl‹ƒ‡h-™N3¬µ$IL†”¥äé§rêÔQ¤T8g±ÖS¾ÃH†‚¢¨}õ¯¶MbH’ P(uuJd Š4Myê©§(«’#‡1è§žMÔµy±R2º€¯òJâàÇêªzñÆÆË—Îpè`0”˜FEe‰±†N§ËúÚ&=ôll,7¯>ôñEa(KÓ¨usÖp©ðI¥g_ApôèQžzòwÜyƒaÛ¼^)yëpÜ¿û5·¿èíâ:¾Ò(áäò·öñ˲è?sê)CºÝ­Ö8F;S¢H…ši–qìØyNŸ~Šª*ÑÁemì,Ô•õ>€…0ôI cEéDZK„xvY9çRbŒáé§Ÿfii‰Á°Û8¡çÜ¡ÍÍò+„ë;¤º×5ÀW²~þç>~ø™gÖÞ8—w?ýô“„¡cq©Ckjc! NH·³Èêê:£ñQ”ÐzgÎá=|JK"ßð1 û‚@ •Fy…ý¿êÍ‘­5ÿõ¿þ[Üu×MnA4BÜ4ÿü—¿Bº£Oý+wÈõOÿ·_Nž|òôƒËËÓwž=ûL0¯3D¤…µŽª¬¨Š k,q"„£®ZwP Œ©æÔ¹§ƒk%PJàœw½°ã{”úҽȩSgX[ÝàöÛo'Ž5Þ €0¯øÑ¿ô£€û±¿ð ¿ð¼+]X\Šîºûî÷om­Ý°¼r¥ý~€TŠ¢(ØÙÙa<{'ÐY‚ $Œ.\8Ëp°—~c UU{ÕÃop®‚Ï„¡$ uö™/©’$FÇïýÞC(Ì4Š™»õüùÍ#üàŸ—UÂkƒþ¡·ùäÁÓ§ŽSW ‹ IQW†íímÖÖÖØÜÜòÞ} }^^Dt»}î¹ûe¼æ5oàÖ[EOîXGY:TÓèH)ÐZR×®Qïk¯Œÿ¯¶¬uSñùG>Ãp¸À ‡ å¬ÊØ+Kû¢ëQÀa=ôÐé[kSýÀ3§OØÑxD¿°gïÅØÞÞf<·NEQÓíD„aÄh4a4qäÆÛxÝkßÈk^û-¾q/i"›oŒ’‚ª²Øöÿ»Â¿Ý‰ Ý«ÓIO¶ÙÚš°°¸€uek:Jóà¼ÿ]úë/Ù_ùª†8'N,GBVo<þÜM;ÛÛR+ÇÒžJIF£1“Éc,QQU!-J êº&Ð]‚&û·½S²ï=¼ô%ß̃K$©ò•?ã³zpøÊ`žÕ>It•`óKÉÎöO=õ8@©Ë¯Í2óÇ–Ïßé^ðxùKÿ²,‹í¯j3é…s›wá±3oY_ßÜ_öìëÐé„”eÁt:ÅChí/ç IQU5“é„^oÈÒÒ~êºDé˜#Gîâž{^ÇþûH;ŠÉ´¤6ÆÏp ¤$Nt£ÂÝs:»A µbee…›o¾…n·3+ Yãî .Üù‚À4[qaØ7_­?ìœSË+Ûrggòmëk RÂÐgüòuâ^çÜ_X^>‹Ö’……”^?dgg<þ¼­6Æ %5y^‘¦]¶w6É‚ q”b¥(¦ôûK¼ôeo`<Ý$ÏŸbšÀú’°”•%ŠlÓú¥?’/'K¬µ,/_ÀZC·›²º’5¤S‡1ööëNà—¹^ûÚû’¿þ×ü®Íéÿuþü¹¥ñxLœh–öÄã˜N3êºFkÝ´p{ h­q®a÷ªi–sîì þôï ¤e0ì „¤¬ ÒdÀ‹ïûFn8t#ÃaˆRkñÅ çhbƒ/û=·æ`gg‡ ¸ùæ‘Ò§—PWîÞï~Ûû®àK¬7¿é{’}{ï}wYv?|ìøÉW//¯*pìÛß!4eYQ–%Zk”RžØÙPv¬µ(¥šú½£ß°¹¹Êñ§ãä©G‰cG„¡$Š쿉½{o! ãYÖOJGz²¨ûCê³V ¬®®±°°Ðø$¾îàœ½õÒr?×ëßô§¾W¼ùMZÌææâ8æÆ#}‚ÐF)GßKšô³•’ Èμý/ÇpÎQ–%B<Ôì|×D"èõä%„Þ÷¾ï?xáÂéŸÚ»wÏcB¸ßþwàû'“úž´ øžw½-xË[Þ=ØÚÌþÂp¡ú5gÍß°Ö¾Q’çSªª&Š#öìI±ÖyN_“¤‘R^a´ÖGîÕnQVÄILUUÔu…Ò/ãçáÿf{ç·Ý±Ÿ¥= a”rǰ´t¥¼°ÊÒ ”¼¢pµØ÷j}‘íí–––ˆâ`ÞèT•½b’È;Þñ޽BðWêºþ“\ Ã(rÎiçèÕ•;ð‚4‚w…o|£[(2÷ÝEQ½x‰µ.ö\§‚n§O§H©èvÂÐ9ªªB)5+Ãz®› ¨ÕÎ9º!ãш¢˜¢µ"Žò<§ª§œ8ù8÷Þwwß³ŸÍͳTeÄ‹n¹ŸÍÍe„“ge$wÕ°ïÙH"Qa­¥ª+âX3xŠ1.К.À»ßýn%¥¼½®ëotN|C–å±”Â)‰¬¬ÓJÑÒíßûþÇîÏüÌÿ9~Áh€ïxë{ö~ó7‹÷)þcYðw±¼Ò9;ýAH¿Ðï%tÒ>Îù¦Œ8I–å3uß:€ó&` IU• i§Ëd:j¤½nŸ¥ÅEžøÂ<õäq‚ÀqèP‡´“ò¢ÝÏ`°„S[TCñ~6;5“àœ£ª*¬5 ƒÆøI J±ôž÷¼'¶Ö²ÖÞ Ü6ïÈ,看âPÊ:"ç\§(ªÎ B|û[~p¨”½ÅØü»×ZwÈžˆ!P /Ob­ N»á¿·°aLMYÖÁlç·æ`>5ÛÆíR*¢ b2ÞA«œ]§Ûcaa€ÖšÇ{œ›n:Âí·æÒ¥ÓA—›oz);;«”åˆzfNž=%Ì,itåÚÜܤßïÓI;¬ºÂ9ÐZ­µ›3'6ÏóRiƒ> ÃØÞZVâèfÓº,?oð}?ðçÕùÓëûG£ÉßKù Np»s~[øŽ[‰”g5ÛÛ%Ý®$zh° ‡~‚g‘WäY…CÐï_Þõ-œóþAKß®ëš}{û `<Ù& 5Î ¢( Š|™·ª*ž>ñ ýÁ"õpç2޹ƒ£Oý.Z¡™ææìûÕ°ûga’¦)y^Åi0œƒº¶{´Ö6Ïs#„(›«ÎóÜÖuíÂ0ΡÀ…ÀB]›kB|E&à‡þìtÒÈ|kšÊÿÐIÕ÷i-nx2f·Ä SÛË}ùœ•8«‰#ß¶„ ­y^vBÒ4@k5Sÿmì-„ðí\Rúy¿B5YAÿÏ9Â6\?ÙT Î=ÇöÖ/ºe„!M‡, £u€hÿb·Àç#‘ùÕj¦^¯GU•þW8Â!•&I*¥”°þW[»³³ã¦“1ÎY!¥P ké[Kð¼3ïøî÷EÝ^ÜßÜÿ¯Ua_㜸»½Ga¨‰c³c Æ:œõÙ2_3¤iç$ZC·«É²¼Éç«YŽ~Þëo…3ïZkXXØÇÎh‹ª*QJ£”'pzðx!†aȉ§è¤Cp7ÝxçÎ=ÙÔ|—ñ•»Rðóm„²±±µ–áÂÕ•±Ï)ú^Ói–Mí˜\UUH)Ù³gŸSJ㜓ι@J‘j-£÷ÿàäOýô?°ÏÜ/ÿÔ·½&±ŽÞØœ¾ÜkLíí§: ‘bey„©msSÎ9Ñ:¯½^OL§S¿+R§¥’oxí×®ø¹ŸÿËîð¡Þ#UðF„ +2¢XÇJËf¦žÃ³ðýn÷¼qԛݮ‰Ú‡kR"¤oÊØílíVÃm—îååf!âx²ŽŠ8ê`ï®k‹Rš8މãxV94Æ0™LY]]%Œ MR—öÏ<ùyàÍ ~÷×­IÒZÓï÷Éó¬É(6œXšN+kŸ¯µf2™`­uÝ^W4Ï öê·÷›®]üµ¿úÏï‰ãèûƒ ÀY‹^+¥™ŒkòÂÇúBBhºÝ©$Rœõ;] ¨+_0étÍ h­šÙ}þ&íöÂ¥””eIžç³¬`]Û¦·ßø~¿ DëœÀ9nª{A†!AÌÂǺ®™fSÈn¯Ç7ã™Á\ÕîÏ }Þ$u:™Fi¿¾œ±ä‚µE%üšÝǽ{÷R›ZXK8$é,×Ä„=3ØsµÍïzÛçϯ¿ùŽ;n(¥)]‰”‚$(òв´H!XXê²°Ø!ŠBB6-¸tq‹Ñ¨À9?Ã7føŸ ÙØë@!åå<ŸèikY–ÍÞdYú³§Ó¥µ©Ù³gç µt‚xŸò¤(Š™w8rƒãB`ìeÓ5/äù]ßšž–‰dŒ¡×ëy …!Bªæ¶9€°ÛíºVƒ9!q³gi‰<ŸR%Î!•’B®™T°˜»ØÚú ½÷ÞÛ^ÇÑ@U×,-u‰‚ˆé¤FÉM7ïáÈK,-uˆã­$½^Ìþ=‚P{“ EÃ눢SÂ@Ï2pó¥×yUÜî²–•kL@`Å(Ë u]E¬õ»¼ÇÑlÏç.^¸D^LÑ$NºÔ•'˜Î  »SÂmx·½½Mš¦ž‰\Õ³÷Fj"%”R4¯“I’ˆ ÄÊÊ*Jj¬uΧ!w®¨9- |ðŸ½îwÖ‘g#ünÓTURø–²Étæøµ¥á³gÏrñâyVVV I%h­®`?[hwɸÓé`Œaqqé íÈ=K«µ–J)mŒÑBµ°° ¬5¾¨å¿jkåµ€¤AT×uäXÕÿî—ÿÙ¯×U}*ÐasÜJL'Pêr8´°°@·ÛÙÅyà¼3Öí3Jƒ]õIDATƳt¯s9Ö–HT3¥ûrÁ§½¹­÷߆Vó‚,Ë S×¾·R‘¤=ßòå<Ûw2ÉX_ßœ9ãñ˜‹/°²²Æúú;;ÛL'N@œt¿hÇ?;h÷ûñ@oª€Íü!çèáj%½ZÓaI’(!¤,ŠBxÀ[À çÜ–snýZ S *ç\¢èõ;Ƙ*‹¢cz=TžNÝ–EµÖ¬¬¬ÌÒµó+¥Ã…”Õµ I Ê2ÇØ>YnéöÄT¯v·¶ÅŸù»u'Ó !uUã¬aq¸ßç°ß“ɘ²*íŒX]]egg‡É$§ªJʲ@ieŽR%a]Uø»[ÆÛ²íšL&Ô¦šù8Ó©Ýs¡µÒJ)]×µN’Dõû=qiyBÒ3@îÙµ€¤q‡€\)%•’ $ýAÂp!`<žÎ¦k9ç‡(¥¸xñ⬩c®:FšÆÄ‘Æa±Î²3Ú"í,`˜ÅêóU¹éÔ«ï6¬›/Áú‰ÞE^P––ÉdÑ }ðÞ¸£ª [[Ûœ;{Ž¢(v°Ö×ÇHYqéâ%îºÃ„!eUaó1Nï‹vú<¹õKÚºD·Û¥,K67·>Cº(M꺖ÖÚ@J©óGŽ¡Ûí^QTBÒíÆt»qSª•Å”º®¨kO£ió÷mè—çùL—̓m 7>ã—eU $³÷$›Ö¯ªªØÞ³¾¾ÁúúFSºÝÁ˜­ý®Íò‡‹*lLÅåˆÃGõì몪šÞƒzæ‹L§S‚ àÌ™3ó -óŒ'·¶\Qi!D†¡Š¢H(%…7Î9‡±Æ±ÙµdêÆ,s`F£íÉþ}©0Q¨ét‚YãæüN ‚€^¯‡”r¦r//E§±¾1¦(,Ãx¼Åd< ª¦SH)šxÝÌLÂeí ˜NËÙLÿª*0u‰†}ûo ÐeY{ ˜L2@Ò톬­í°½5ÂQcŒ& ”P()ɳ)u#è6ülç}“ ­¹ ÃcÇŽ‘ežŽfýq4ašˆ•}û¢2˲°UUé TE"ÏsŸy”Æád]c®%Pµ‘@sMƒ 4Ri¡4tzQ“ ®PÛó©Ò^¯7£Xíìì4±t{)A°í3o ¦Ó1“IEQÌïn? êrBIÌ…Ž,+šY=®)õÖ”eAšzËUו$¡u]‘M3L]²±1"¡ªÆ@Y–¥ÅáMUµ™Eóý‡m)ºDû^&“‰O [ÃêÚ ¦ö¼BkÙ#½Þl !ÄÙ ʪª”RJXë„õ“ÆsÎJä†5×N¨Û( Ñ= {ñ♕@kê8Ñ>ã+½Ö$´Îß`0`qq‘~¿ßy$ƒ~B‡ä¹aa!Á¹’étBY:Œñ^–eE…n¼ëvWzs#Xò¼ Ï=ׯ®+jc)Ë’²*š^?f´ª.ØÜ!¤÷ ”$IH°@YVL&#&“1BèFÍ×3­S×5EQÌL@»ûsDQÄd2áä‰H¡gÌbc\EâÜ?øAû?ñÛÖÚÇ­µŸí÷û)¥HÓNSNa€‰¢¸V4€ž«h´ÎàâÉgޫ׼Æ8¢(,Ý®"ŽcòaŒ¡ß°ººÊd2ÅY‰Ž8V—úÃp"|èCZ}ç;ßùKBˆÇ£(Z4¦V•íYçîURô€m¥T}-Uå®âPM'ç}§‹[[‹‹1Zk¢(š |ÞëŸÏ¼µ5yïÔYz½„µÕ_’<Ÿ2et{­%ÖÂdRR›ª™æébàpM")I52þàë+A2,’/ CIÕ4~¶ttߘR¢ƒ˜$I‚ˆ¼(ɲ ”TØÆÍó|V–¾ZJ¸1† ÎEiš0ç¾Yµ°Å“GGçæ_û‘|äÒG>ò‘KøÀxûÛß+~ý7üy ßú-ï½ ÂòZ€k?éÏ|îãç>ù-ß~ë«_5Õ(­B’$ UUÍläî”i›&mAà›>5ÎA–Õ„A €)í”0jçõA]&“vê§WJþ|?+<­Î÷uø¾ƒ6IPUÎSÍ$ØÚy~€ksü~†P’,’$!:pdÙR…M¹œe%ç?˼vký­5kk+”e=cCYëÂ4UÏ9 âñggêå7ÿÓÏžæYmmç CN'ãÍ“'=Ñé¦äŒ¶}VkM†ÏÙǯ”" ÃË™A Œ"ªÊs¬­™N§d™gúAsOY3ͼIÀyÇ͘&ô\놙c¨ë D¡ŸV–TU; ªeæºæœÀ¤Œ)Šc2ÊR2ùC!ó&k^åÏ_í÷³,cmm ß ÌÀ†òØÿðC/[åy¸döÙ9M ‡pÏ£=´¼¹yi4™Ö\¼äké-ç®UÿóõóùŒZš¦ÄqL†„¡¦ß›sù$J Æã ¦Ó’?»§× A²iÅ… [T•£®EY£9#“ yQcê \ÉâÂ>„ð@­q ÓÇ?Öµm4—Cë€AQ²²²Êö· ,LSb®fv~wBHA–ežÓ`,ãñ˜²¨›A!„øÎ·þHþ|@5+n_AüÈçºðÈ#ŸøäÂ`ÀhÛ²½Y®9l1~ήš–Që"X\L‰ããí"˧ԕÁ˜çýaäËÄÚ'uü´°Šº¶˜Úÿ¶MÎ_U’$é¢ïÏúÑÀ^5K…l‡£€…áʪƘ)J•( µD‡þéùX~µŽî夕K׎šsÎ!•üÔ_ú+?¢Ÿ¯h“?5\‘œÐ@øÑý›'}ì§¶·K–Wr´Vøw4«Ïß´vç´t(O©Ö¨fƒÀÛdk,Y¾MUÂæ–% 5i†’4‰@Š"GkA§ãmµl’AÖÂh4&Ë·I’Ä«zã( ƒC­|†P+µÐí.Òï èvCÎ;Cœ(Â@Í*šmpw‰ºõ&“ $ }þ ª›Ž )pØüÿÃÕÏWä Š] @tìØŽ>ùùãI³±^±|iâÛ®â+MÁ<Zmà=ïfÒ§¤IˆT$ ¥ãÑvÃòјÚhMQX” Ã¥üPFÙœðy™w ˜N'\8ÿiÚ¥Óé7šG!‘M¡¢%MûìYº‘<Ï™fÛHiHvó|Rk>!4ÿ™Ú¹…A¾ñÄ6£ç­a?~øk)Äoý¦ŸL´W« Ú¼@ï×ãçO~ö³ÿåD‘;·ºZx^ ‚( ‰¢èª h=æÖaB¤ÞïúÁP%¦–lo[ú_§´"ŠÂFˆr–¤h›C‚ɤbee pôûæ ʪ9H Â( ŠcâxˆböìëamÉ©ÓgH’h61¼lËA˜ÿm= öï?Àd2¦(ª& H%eQÚ•¯%~ó·ßëþ¨ k®bU»¾¾¼óÈ#p¦ª3{éRÎñã[ÍÁËš$ISp¥ðÛÂPÇ3Î@[ø©Êš$•T&g<Þ&ªJ1Ô”•#Ë iÚ! ½*×Z6üJ+м¦ª§ÔfL§;@ùvcªÊ1Ï\–ª©ZbÏž%çÏŸi¾ïy\m‡Rr–œAëHé'™9@iE]·GÌñ䡃ÝSÞívÜd¬xêè&ynˆ¢€^¯ÛLêpWðñÚbÑ<¹2Ž}‹Xƒ«¶ñ§|h¦ :$qHYÀ‡|þà§&ÝÛйkc›ùK‹ûIâŽgùJ‰1~2I6­tŸÅ…ƒÄ‘¥×Y[]a{Û—‰¥Íùbvèd›šžgYké÷»ÄqÈt2ÁÖv.MM¸¼<ÍŸ¯hC>·+¨æuóhW×.IýÜ‘:ŠÕÕÒŽ&MCOÃv¶)ê¸+;´,_c|è´µ•…ëÓ¬"ŽSÒ´CYÖ˜º`トçXg¼·®}b§9Á™<3ÄQÄÂB‡º’lïlS•…?DX„P(2ìåŽ;^Æm·`šíðýOTÕxÖpbŒ#IBÚ>¿ù]ïM‚i€›Òé¤~¢YiJ””¥û-kÓ_?úäCU{Sßüæ7‹W¾ò•âµ¾N<üÐC×<ZZ¸Û•žA¡A;;;y>qiÚ ú{¢0êË ç7©*Cšj’8Dþ¬¾vµ]>“É´é§÷§w†¡Ï·¶& Û"äEA)ÂP3–¾Ë×2câZë€OÖ(Ê ŠbŠÅÿÝ ôÓGïºóîºëú}ÅOœãèÑ? ϧ(¥›]¬šþ~®˜vyB TeÅž={I’6‘ä˜N¼Ó_îS¿ö?ýËó7õرc<úè£\ëÂgn§3§fÝ}s@žÓ$ÔÊê…ÉùóÏäÃa?MÒŽ:xð–`uu‚©C¤’t: ƒA2£~{Õ]3N(Š’ªªØØ7?sÔ•e4ûjâp‘¢¨˜N§ìÝçŽXYÞ@´çkÑ •ô»$ƒAc È-Óflœk&XìÛw˜{ï}9Ð:âá‡?ÉÉ“_@ ÝŒ’÷§@ ÙN½²e¼5ga±´´Dá+ò¬F1Z_7ÿâÂ…¥/Ài÷|5ómaóc´wƒ`æãmoo”>öðøâ…Ó•• [{÷TÙÔI/ª*\t…”J…AD…!‰¢º6ŒG9µ5Ô¥i…§Ç y^2ÚÉ.tBØXaŒ¥¬Zá[ò¼Æ9AšFÄq@UBQ–^øBF!‡ÞÌ]wÞËáà \¼´ÊÃ?ÄtºÖô&º†à¡¨k×#ïæÊÐ-?À׆‹³p1ÏrE+ý¡Ïü‡‹Ïg`>†Ü=G}7 š$MUŹó§Åç>÷ûëŸþôï}ñÂùeW±Ëó0Y[³®,B±¾VƒëP!Î&”¥Dëé¤ÀKQVE†~ h[¡Ë²æ´Y³µ™1•Ô•£®}ªÂ"ˆãˆ…aªrEEQf³&ûî}wÝ}AŸÿÜ)Ž>ù œóY@ı¢¬|Ä Ô÷¸&»š8NšžFÉÎNA]9”’O8ô¿|úéÏMŸ¯h«f®0/ìùÿ»6Q䜭›è¡nºxñŒ¾téìEç~ís‡ݬ»Ýnï ßôÝ·-.í?rû­/>´3Úr{–ö-UUX GÂ@/PÕ9{–¶Y[_f<Úduíãñ˜º>ÅÞ½7 Ë€,+1F K{jVWÇäYÕÈC`4šRÕ%a(fGžM¹éÆ;9tÃ!z}ÉújÅ™³G)Š)a6EYp†m_Âå1ò-I‹Ö¾Û¸={¨MƒëKÉóxéFð­ÀM“¸š&°sWÄÍs à sn¸ N]N;öøƒÁÒÀáŠ[nºm8\Xr‡Þø¢[o½oo¯?¸sÏÒÁÎââÂð†C7Ç[[«F©NŸ9NY•LÆ;„aDYæ…ßÍN‚1–ÍÍ)YV53-ãñ”é4§ßëF!Î º!‡ßÂâbJY:VVWY[[õSEâ)}ÛzUâXa-3â©—ìA&pNQÕŽ(jT›0PÉO;™Nžï˜ßéæY´@ Óh èÎ%Ž `OSJ^hµÊööú`yô¡5 “R>f­-î¸óÞ=;Ûöþû_}8 ;âÈ‘[î\Z:˜ÆqúâÅáÞtÒÙ‘Bª%kMR•ã‰ß‰Ý®ïɯJƒuå$OûîõºÄ±$Šbº>7Ýx½~ÌÎNÎòò/ž"I}ÈK][:ÍŒ£ö4Ñ `×ôP‡©u%ÛY€>umÚJ¡›žzú'ëvƒ`^ðn—0 ª†CXÌ%Ž’—YÆ®ùZYkK >öÔ¶wéÒ/Ÿ¬Rê·Œ1Åm·Þ×;ùÌSæUüuÝ8ê·ÝzÏßÓ:º?Š"67| vÏžuåX]!¥×››;:´H¿±¾¦ ‚}û{$‰âì©§Oj”f±%IuÓQì?lIêÚÎBBp”•E €¸=ƒ¸IJI)'8ùÛ<Ï×îÙ軋 vîÑ\Å´WÝd§@.„TJ…¸\Õ¼ÖÌEz. 9çol®Œœ³Å¹³Ïœ;uê© kkç¿pá[^ÒI{ûkS’çÆ@šúÄMÖÔäqŽ(ˆèõSò̰±±Â¾}]p‹¬onqâÄã,/Ÿ'‰}þ?hª€UåÌ0”ئšˆð]My^cjK*z½A“ì’ÔÆ±³S:U]ó3ÇŸ~ä™®¶æA`çœF3ŒögeseRHÔ›_E«p•p“FsˆFcTu]­ŽFÛe¿·pó`°¸§ÈsªªöE¥@R•µ¯ÊYCQöíšµµ;£)ƒÁ~&“ úãXëH;Q¤ÐZ’çuS›ðo¥( BúŽ%O!7$‰g6i4¦ Ëk²i-¤¿†{ÿáÑ'ÿ ~¡À]ÅG0»¢‡y Q•sfì°å€ÜU¢ ®òØ®°ªªQQäôû {ƒ ¼? à ÏKQ½^Œ0ç8<¤×ëÐí$ä¹aùÒ%‚íu.]:‡Ö’^?B5}²™iX׎²4D‘j¦~;²iE· %#Ñ*¥×ó`:­™L*Çúãƒþèç>ÿ©¯ \Í'Ø­̳Ã~ Pí6?óàˆË²0§OûÄM7Ý&Iç‡SeYQä†8ÑZ’eYa-ìß?ð-dYÝœ÷»ÎÖÖ:aÒíúDTV•if+´V”…ÅÛ Ã 8,$Þg+ÊÒHÿô>ò/?óBóž öYëiû,y®^^m‰ÝééãÇ{hÿþÓÅáÞ?a•u]aè@G⬩e8ìšé¤b:1ÍÆ³!Jù|JŠÒÌÊÀAàËËB^þë¦!”$I—¥Åîìµ£íkÝÙÅ¥äç?ÿùÏœüzÀnÑ^Å!Ü žåQ| á»]³}~vþÂÉ Q”Ðï/Üå¡O+¢ØŠL2‚}ûû8 Ea©ê’º®°Ö¸õÙ?Ï@ûN¤²0ˆfà´Ò>B‰Š@'3¢J–UL¦56»½äo}î³ç_O¸ZnÀìÒó?_¦Yy.¡Ïÿ_šÚœI’Ί’ÁQRÈ"ó@i'$Ë Ê²b8è¡MžÕ~.@U€€N4POK³Î‘¦)ø(jã¨+GH´ô½Qԣ׋‘²iíÓÑ5ÿv}µúè3§)¿Þ0¯Òí³Ør®â3ðe¨÷%4ƒÒ•§{½Á3îà5Z釥¨j¤’  £qFYZöïïcjG^XŠ|Šk²w¾¶/›©#g}ã‰5~`”R‚ LF%E!èv; ‡1Î966ü8ü(R¿öû“Àújïžåz6Á»gùúj¿÷ Çpeåü¹²ÌÚ·çàaí­Mµ µãò¼nSü×EžQ™º™Ûë[øªÊR׆8 ( í%Ì2CYÕ€f8ìÓé…˜Ú1—XãÖêüÏ|æÓ—¾ž ¾Lá»]E&wáv ù¹ÌCû<³½½±Q”Ùò`¸tswöW•'ªöº1“I±ŽÅ….¦vL§9¦ö ž8ngõˆæÜ_âmËÂÆXŸ !b† ]ÒTSW–íÂʼn>ÇÁ‡?ûه׿Þ5€¸J”pµ¯¹ Ä®ï=W”p5ŸBcçì3JÊ8Šâ;Â0îyF°iB:ƒÒŠ( (+CUÕÔµièÝM¹·™9ÅŠ²4˜Ú!Ä‘b:µ„aÊ`Ø!ŽÙÔ0VBÀG>üó?ýa^ K~UþîbQK3ÏšqÆ3[æqÍ•%éy°ìæ(¶<Å¥-ûÄÑÏþË<Ÿ~´6¥‘ß´Qʪb´3%ŒÝN‡8î଺R²8éBá‰)•§šÅI@^XÀg£Èߢ¢¬±Ö]ZÚ´ Ýøò“F/` §¾Ççób€ÕBÕøšY¾ÀÔx]‰Ú, =¯Dm€ÒfNüO5Ä/àªÔÿÚú=˜Ð8OuRIEND®B`‚pnmixer-0.7.2/data/pixmaps/pnmixer-medium.png000066400000000000000000000412171311427610600212500ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aËsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÛ '!/ÚÊiTXtCommentCreated with GIMPd.e IDATxÚì½y¸¥Y]ßûYÃ;îñ 5võDÏ4H¢@Q4¢( Ð"ˆbn¢OžMrã€÷:d¸ 7÷‰^¯àƘ8Å$ÊÐ BwCÕ]ÕUÝ5:óÙÓ;¬áþ±Þ½kסh, »©UÏûìsjïuöÞïú®ßðý .KãÒøêâ™úÅ^ù ïúçoò·?ÿM/‹c±à={µµRˆÑˆÏÄ1›õáß|øžÁã;¾ým·{ïÿ“sî€÷8¥ˆŒ!8]þa)Å/ü—?ýõßþj€z&¹7¼þ]=ïí/Yçn³Ök!„ô>€^ßÑZ\ÜtÃÏSW_õœ9rï%<“ÆM7>çŒñ¯rÖ§B@§›ˆn/¡•GXëq ~¿ó\Q•>ºæšç~úè£÷Ô—ð ßõº·ýScý»Œq]!‹‹½nBÞŠPJ’·4¨*‹’ìÕZ,zÏgö,¿ðñ'ÿÚµ@?Ó¾Ðßð} EQ¾¥6þŸc[B@¯—ÐîÄH)0µEPú½lm€xaó3{öT¯N^’OÃñοó÷÷ ãïÿ^ç\ ˆv;fa1EJßìm¥B¢X!”…ØbùÚkŸýч¹wôÕùŒùßù¶VQL¾^ÿ“Ö:å=$‰fa1EkF£ŠµÕ++#¶·KêÚ)I·“¦ ¿"Ž£—\’Oƒqó ëíðïÿ¤ÞÞZ»m46ÿÊ9ž%ä­ˆ¥¥”8V”eÅhT³±>Aˆ„í­mÆãšª2ãÈ[Q¬ Þûž³Üô¬«Ÿû'¹gëžÂÃÔ{þZñ–·|÷Õ»ÿŸ×uý „ ÕŠX\ÌPÊc­§®ayñ:®¼êf„€µõ38k)ÊcIÑjE EañÞ·¼gô¢¯ýº»î»ïãæ’ø›;âþäO|ú;ÿñ§Þì<¯wÎÓÊ"Ú)=Îyº’={nEÒbåì î¿ÿãXkR"„d2v¬® ¢¸O«3ÖT¥mKÅ[1¿½d<…ÇÆúŸß´°ÐúÃÁ$Qt:Y&©ªš½øk¹í¶;è÷ròÔQ>ô¡ÿÌd2Þƒ³kkƒk«C¤,,¤!ðž+œuïþ¶×¾£u OÑñßÿû#!ÒqâÄñcJ:ÝŒV;˜šÛo¿çÜz;Ö´¹çžò‘ü7ÃMÒ,EGð¤™"Ï#¤tllìPLj²L“å¼×EY¿Ö»x OÑ1™ˆŸÆ½÷|ŒÍÍ3ôz´–ĉ¦ÝŽÉòð´ÚQ›#Ðí&!p–g9ËÛ_ûmïŒ.à)6~ÿ÷î¿sõìéï8ñø±xz½ïjz½n¿ýÅxßçcwÝͧ>õQή>Nž·°ÖG’4QèH`Œ#Š%RJ¤‚²˜P•†$V¤©FTû¿Çd—ðÿß>úÜá`ðw†Ãáå'O'I$i¦PZñ’—¼˜vû ++g¸ÿþOpòä¤Th-HbI’(ªÊbj÷<Ôµ£ÛK³¶:Àù „à¦NW½ôž"ãø±•îþÝW¥i~ÛÑ£÷«ápƒn¯ƒ÷†n¼žNçÃAÍ#|†#G@A»Òjk¤„ɤ¦6ëÞ9âD‘$’ª4Ôµa2)0Æ’¥­uíö­­¯ýÑüÏâ¾Âãè‘9™/ ÕëΜ9½ðØcGˆã„4ôû]ºí}“=x„ûïÿe9¢ÕÊÉ[šºvÔµÅyR$ŒF%ÃaÉdR“·"âv¢8À{ÿòýî7üØOü¨¸€¯àxèð‘[?´}çÆÆàkÖÖO±¾±J§“¤šN§ÏåWÜÊêê÷}ú.VVŽ“¦9à) ‹1$‰BkIYZÊÒRWÑü›L,ÆÔìlhµúäyÔ„ð×Ié¾í=?ñ³þ¾Bã‡ÿá/î9}jûÛÇãú`9|øÓ(iév3¼·<÷y/ *áÁ?Íþ5JÇ4*kR ””…¥(,ÖzÒTÅ’8ŽÈ[ m¼Ã^÷ Ë{–p®Â;°–W~ûw¼ýŽ×¼æ]â¾ã¦[nº5M³Žãˆ³gO²¹µB¯ßÆc¸á†ëévörêÔ*ŸüÔÿÀ˜jjÀ¡•@J0ÆQÕA÷GZÐjiœó(¥È[)NJ’hºÝŒ(6ìÛßåë¾îÅôzm¬qXëntÆ}ëïÿþ/ûKø2ßüõw³¬óãÑv΂ª*‰cA¯×fyùÞw¹ûî¿`{{k6k“ýƒ”’v;B*A][êÚEÑÔåÃZÖšº®i·#î¸ãëY\êQ›rúü«_ñ ßó‚Kø2çù)çüB(tsúôc´[1­VB»ÕáÖ[_ÀG?ú—9úE1B ðÎ!ðH$AžWÐߨ!$J†|ç<àQJ“ç9÷ßÿN›¿øvÒ4Æ9Tþ¦nW^À—süöoßýF©7K)‰¢ˆ'޲±qD0ØnÁí¬œÙá¾{ïckk¥#„!áAx¢hºã-Î9¤Xcɲˆ¼Ö{j­yì±ÇÆÜ~ûóI³@/ Bˆ×|ï[¿ÿÐ%|ã[¾ñýOÊ€úã?¼÷&­Ô?Ä«HVWOqäÈýœ8ù(Q$¸é¦8xðJÊRqfå8Þ{„¼ÇB‚Î9¢H`Œï‘R¦1rׯ‹˜L&œ:uŠ«¯¾‚ç<çz¤”xum_¾¹5yÞ%|ãÑãø¿öÞûÇù±GOÿP]ŠË¢Š66Nóø‰X__A*è÷û\vÙåìÛwÕÕ³cðÎá}sYKYÖXk‘’Æ’wh-ˆcE];DHŸ¥‰MGÇŒÇc>ñ‰O¦9Ï{Þs±¶ÆZ¯úî7½;¿€'ëÇ?ü_°ÝîÊ—÷úýÔ¦ê®oœæÄ‰èõ4BX¼·t:-n¿ýkØÞ¶¬­m0l ”nvqÐýI¢PRPW„Gk‚á°Â5!akƒZðs(ðÞãœãÁÄZËõ×?‹ÏÝ3ï_mêÉþKøªìÝ¿÷À·H!Ÿ·rö'O¡Ó•´;£Ñ˜,Y\ì#¥f°3¤(&h5¤ )PJaj<%HÕ?5Ƥôı:oÁ§@BÐét8yò$?ü0W_}57\ ÆÔSiÑB]u _¢ñ:þœá¨þþÍUN~ ­k––ÚԵŃu#Ër¶·-'N¥(ÆH)ÁûFT{„Í"{ŠÂ`L° ¼‡8Šf‹¿{ç[kB°²²ÂÇ?þq¢(áò+¢õì…ýª4ßùŠo¸3¾€‹<þÝ/ýy{muôÃÁ Z9{†ñd‹{h-'8çȲ”$Ž©*É#<À±c ¥Â{‡s!å;N$q,(K¢Æ5Ä$Š$Q¤PêÂ)‘SPäyÎC=DUW\~è ½n²‰c쳕’É%\䑥љº~öÆÆ+gãàq,±ˆ.« ë,­V›õµMîºë#ll¬4³Epƒ¿FYZªÊ6b¢Hའ_\*©ôÄ#Š"xàzð0×ßp#½~×ÌWJ^ÓïG·ížsݳ^/.à‹õŽ®¼²ÓK¿¹ªÊî£Çbq1¦ÝŽÑZà¬g°3&I4I¬O&>|’ãÇ¢®+ttN{¦vÁpDzÖSV ÒZ"į•÷)%ÖZyä–––èõÛêñÞÜܬn?oñ¯yƒÔQû¢Þ“ï|Ý;ÕúÏŸÏxüÖo|èУ®}ópXÝôÈ#Ǟťiª1Ö!$xBZZ­˜vk‘ÕÕuÃ’$cjyO°ð(-IBÁÇÌí‹"T!äyúÿ‚7GJ´ÖüÏÿù—lllqã×7Ü‚h$„¸rþõÏô<ôÿ\´XÁ«_õ=‘±fßÿûkÿ:Fàßþ¿“=øàñ;VVÆo|üñG£áp^/!o)œóÔUM]Ö8ëHÓ!<¦öhÝB)°¶žç!\+Rïƒ$€ÃÚP+ ÔçÿêS€;ök«\wÝu¤©&XÇâ?ü~¸ðc?öcâøÀE[üo{Í÷ð¼ó_'p{žÑX\Jn¼é¦wmm­]¶röq”öt»R)ʲdgg‡áhŒ@˜8É8uêqú½=t»‹Xk©kD7gƒ ÀûˆcIëÆí³ŸW dYŠž¿üË»P*šI”0Í_sòäæåïyÏ{.Êâ{ïÄ?ðÁŽÖò&kÝßÿMBˆ½ÿüÇÿ…|Æ ×=øš²ÝqüØÃ˜ºda1#ËLmÙÞÞfmmÍÍ­`ÝG:ðò"¡ÝîróMÏã%/y×\sˆ$‰¹ãA¿¿Àe÷#å,ÊØ©*÷¬‹y/êÚìYÞ³ô}I¢~\ñJ¼¿ÅZ÷Ü{>yë €»î:~±õ;=~Ä †ºÝˆååð]···‡S£‹²4´[ qœ0Œ \~ŵ¼ì¥ßÌK^úMºby#om˜§¤ ®núû.÷o7´{´Z9ÃÑ6[[#p¾šª–ÒÜñŽw½é¢TX½ëïJ667bïžåèvò—+)zX2Æ^mj§¿âxþó~ä¢Z£Gެ$BÖß|òä‰+w¶·¥Vž¥åJIƒ!£ÑkI’P×!J Œ1DºMÔ°Û;ûöÜÌsŸóì?°D–«ù³ÕC€'D‹‰ $Ñ<€y Ì!$;Û[<ôЧ9p`?J›;™Ø¯Y9yÃEÿ'O¼úðC‡Ÿ}èŠ+–:ÝV×ã[@ª”¼¬ÕŠzÿïý°øŠàùÏýDz*·/j1é©›7}æ¾Ç^³¾¾¹¯,G,ïmÑjÅTUÉx<ÆZKGh /ï-Y–P׆ÑxD§ÓgiiÆT(rùå7róÍ/cßþ½ä-Åh\a¬ ½<()I3݈pÿ9¿Ý ÐZqöìY®ºêjÚíÖ,€ä¬¿©×;uÃßô^¼å-oiGQôŽGyäê<ËãV;‹„°Ê{yï÷ïìÔûÚ¯ùÊI€ñä¬ã®½Xoì½W+g·ÿöÎÎè[Ö×NÓëe,.äÄq`üŠ¢@1»´ÖĉF*…”1J&H%R¢¤Ä˜Šv»ÏÕWÞÂe®§×ëEkUip.ÐÀaçvðB °öÜ×MÓ”ÍÍ-œó ¡4µ%¸¬6æe“{qçwfBˆWGQtë]wÝíVW7¸öÚg‰8Ö„¥Xø™Ÿ}ÓEOGû‚õÊýÚE}ó»>väïý­¬<ŽÖ’……œN7fgg8[üy]m­EJjŠ¢&ÏÛlïl2‰F¤I޳޲Óí.ñÜ罂áx“¢xˆñÄ.„„½ ªIâšÐÏÿ•B8YâœceåÎYÚíœÕ³“&éÔc­»î‹¹ï~÷»Åh4ÊsW‚_”R×Ö6ªÕ³ëöÊ+¯ôZ Y–NƒˆãX^õŒ0_úÒ[³öÏ~âÆÍñÿuò䉥ápHši––S¬õŒÇŒ1h­›î­5Þ7Ù½*f<)8ñøîþø_ ¤£×o!„¤ªKò¬Ç³oý[\vð úý¥Î‚AÞÓø_ðgžªƒ¢(⪫®@Ê@/ ÀÔþ–ïzÝ»žì½èt:BJ)Å0Ž£¡”L>ò‘[)•b!¼GyO"„?ð÷~à‡â§5^ýªïÎöî¹åÍUÕþÍÃ}ñÊʪÏÞ}-¢HSU5UU¡µF);›”çJ©&~ïé¶{ln®òð#÷qôؽ¤©'M"âX’$û÷]Éž=W“ÄéŒõ“Ò“Ä!YÔ?Iy6•««k,,,46Iˆ;xï®9³R¤Ÿkþ«¾õ-âÕ¯úžóŒ¸……X!Dá½Zëu]>ú°éõú~ßžeÀ+ ¶Öõ¶·«ü+¦þ&ãu¯{kê}uÕövñÓá}Q§söàòÒAªrL§‘·’Ш©,g‹>]ø©ž‚@k NŽV«ËÉ“Çøè‡ÿ+K {¹üÐÕ´;1ÑÁٌ۞}[Û§Žã½hè`O›&règ6Æ2¬µœ-TÀw¿éuÑk^óæÞÖæä‡ú õxgÿWçÜ‹AdE1¦® Iš°¼œãœ9} I#¥Lyl‘·ržõ¬Ûèõ–ÂaC5)ÞO¤ç/¤¼÷Ôus–^¯×¨€ð”” KwÞygêœ;蜻¸v8Ü‘“ÉÐzï}’ÆPΓxï[eY·‚Dªœ”Ò:çJç܇;åç›÷”À·½æýïøöw<Ïy÷›QäÊ;›õ¢ïEHÄÈÒ°ËãDã¼$ÍÛ¡ˆcÅÂB‚µ–ª2Áy˜·¦ XòŠ$J wÐ*æµÚzh­¹ï¾O³¶¶Âu×íEkOµ¹êÊç’çm’4ÂÌÔ‰B}ÿDÏmnnÒíviå­iv‘ð´Vkí§ pEQTBHÛëuYè÷X% ÆÓžŒMàU¯zZk+¥¬)P|!ó¾âøÞwüõ¯xËÁÁ`ôo˲ü`mø&çÅARNÑ…ZÓñd2vs`òŸÏòò^¯”Æ{/½÷‘”"c™¼ë?*/ r¾ày_F"è6ù­ßò’ÌyÞ½±9~-ø—Xn˜Z­˜(D‰âìÊkB2¦hRtãHR×€P(­±¶Fkð^Î}ºãç-­õ,*xÎ @ÐJS–­v‚1çBä°ª‚K ‚ííe5â²ËX__£×Û‡s’(:·ûçwúnîaw¼À9G¿ßoÀ2ý¬!ÆàŸOÛò ït:èH )…¯… ®*Ä[ßúVñÅÌû²I€¿ðï$/ýú¯ý¦nºæ’$ùI!ÄK¼xIªƒønEA×oXøÑi+ÖPzÄs·ÛÇKžOo\HÏž¿éó ÷a1çÙºÿk막‚~DZ‡¯¢”j‚I$1Ç?޵#’T±oït;1¦þ,þšJ’ÝöÈT8pkmí)'„è:çcï½ðÙDQäµÖÞX+¼7h­m­ÏC3ï{ßû|QâÉÎû²àá‡ÏÆw¼üÖ7//µ_Ç2÷΂$ÑtÚ í¦¼ºª,ÅIJÑÎçR«“8B…°®Rhªu¦z}÷žŠ)%“ÉdÎ €ªã}©j&ãQ³CÚ¸Öš(Ò3wN)ÅdRàý˜¥åŒV«ÃÒÒ†ÃÑlgïýSi´[H)Éó@ů¯¯éx—ÑȦTÓùSðzïXXè{k Þ‹Д$J‘hP$‰ÿbæ}Yð}ï~¹HÓø“EimUÕxïIbE+×ä­k£‘¡(B†v,*iH!qÞ’e9Yšc­%M™¹t»oòü¯ëz¶@ó¢x< u„Ö¡f@ªÐL)‰ÖRJF£Q³c-›››D‘cR”ìÝ{¥’‹w¡…ž‚pž“˜Ýn·Éš çø ïé„?'Î3bƒÝn—8Š Éêh–*N}Qó¾´øÇ?ü3±”ѳUÿK]Vjª3;í˜v'¡( ;;Å$”` æ+׸„i– U,oŠ5…ðçm» ®iQFY–³…šª€4K±Æ %ÈÆÊŒâ ¦ó'“ ÖZ¬ulo‡\ÃÅ…ûö"Žó¦#ÈùѾ݋EÑìqú9Çã1N‡,ËfÔ´÷x¥ÄæÂRÏsqÓëõ(Ë !=Y¦§ 9çòÅ…}®!ƒøbæ}Ipç›ÿ…8yjçñ?qsc*²{œ¨‘”DRJÑÌ“Y–‰(ŠÄÙ³«(©q΋<òØ™J€²,Å“w1 æ¤€¸ãŽ_|~–ÅËZ磻¥hsÙe‹,-µIÓ¨©¾¡YTEž§ìÙ“i^ ¤"K5ΞëÞÇ¡:wºãç­|¥UU7«±œs4IÝXš>kȲœ8ޱMjV]Wh­Î3抢À9Çh4ÁÔ%½nÆžå^ø zóÒiþ³MS€n·ÓP÷ὫҺ¬ÙF”KçœBˆ¥¥eQãñ~t÷ì IDATÄK¥O¸©i“¦)N‡';ïb@Í@~øÃu¥µJ+¥Å4¶ÓÊX\ØËµ×dï¾6Z‡)óÆÒT¤õûA*€œ-tmK¤’€lrëÕy¡ÞùxüÔÿŸƘ&óGà¼Ç:CšæH)˜:’ĉbksL]Õç%wР”¢¬ÆH Z'$iJPPçŒÐÝ~ÿî15§‹.›&“‘¶¼½iD’$DQ$ÃAÕ^F‘&Ib”Ò"Ø ÊÐZnMÿ¦µ–';ïb@Ï]p·Üü‚›ó<ïÎüî$FGšû<ç¶«YXXh(ÐÏNÝ’R‘e)KË-tþ¿(+;#„P Ή™¶;ý:Xí£ÙâO ­ªYXk=Τ†¥© RŠÀD–Œ3繎އTóÑhÌhKÜÏ«£yÛdjO>ÏâY·N†òÞë<Ïe¿ß—;;EAM6ÄÊÖ¾h·ÛxïŸô¼‹ €„ÐûNGQ¤{²cÇ®Õuᤠ‹Ûïwèõs–—[hÐï÷éõz³¼ºyßYJIÇôûm’Xc­g8¨(Š!uUaÌ´RWϬôyck2™PUÕ,þ?]Ȳ¬¨ªà÷{ç)&ƒf×hêÚ ¡¤l4ž~ÓÐðã?ÎéÓ'9{v•(’$I†Ö꼬à' í·Z-¬µ,..'=¹¼ÔrZk©”ÒÖZ-„P Â9‚ZA€;!Á8'VVVhµZ<ÙyY‚Ä“xVõü_üCS›c‘Ž›ãVRZy‚RçÜ¡……ÚíöL/΃Œ±v;ѽÞ8W!QM—îsQ¿éÍ5Æ0™Lf®ÕüBVU5&ÔöcA*²¼J¾|Èö&¬¯oÎŒ¿ápÈéÓ§8{võõ vv¶J¼€4kÖŽ¢‚ÑÝŸ'½‰6ý‡¼§ƒ7J±¦ã8޲,SBHY–¥€w€Þû-ïýzSl"Œ1òÉλ˜È¤Þû„ètÛÖÚz¢u„Öý~N§Ó"MÓ©®¢ßï³¼¼Lš¦ç-þôŠcM!®Ÿ$‰ ª ¬óL È£]ÉžeY΂?ó>öÔx'ÔµÁÔï,‹ý}ÀÍ2„G£!U]±µµÅéÓ§ÙÞÞa4*ØØØ¡ªJ”†iUDá‚‹¿»d|ÚBv:F£Æž³7Æc·5ÐJ)mŒÑY–©n·#jc@(@zÀ…÷L¦* ñÔ“™w±%@v>P(¥d®Hº½ŒþB)QÍ®~¿ÏH’ä³øt!$yž’&:ˆ[ïØlQU5Î ”:÷]Ä÷Ô­› œ«)‹’ªrŒF;ˆ¦éC°Æ=umÙÚÚæÄã'8{ö,;;Û8çY_2Ž8sú Þ;¢8¦ªX¼ÿì>]øéb !.Ñn·©ªŠÍÍ­&Ÿaê’äy† Þz$¥ÔEQ¨$I>´¹q6^i5H3=iªƒhh`õdæ]l КAogg¨Š²<¡tŒRŠÅÅQŸçO-ÿn·Ëå—_N»Ý>BHÚí”v;mBµ’²cL1€w3þ~êúE1[ŒsêÁ5›Àø優.’Ùg’MéW]×loY_ß`}}£ Ýî`m…Öa×NŠ2¸‹*nTÅ9#xfös]×d13[d<E=öØö±)ÿ¢„QEÑ2ïbóIså@hŸ>ýØÙHëàêøô9oðÍûÍÓ¤^¯Çââ"Ýn· òHzÝŒ,) ËÂB†÷ãñˆªòX¬þÉdBYÖèÆºžîÊ nGQ”EÈõ3¦ÆXGUUTuÙTçL)eGmJ6·l¥YÓí-PU5£Ñ€Ñhˆºóf&uŒ1”e9SÓÝï½'IF£GA =Ë,¶ÖgI"N¼ç=ïqÿò_þËmçܧsÝívGRJ‘ç­&œ'¼Â#!D eeY*cŒvÎiçœîv»êóÍ»˜`ÚøÎ7z(>ú°zÉK¬)ÊÒÑn+Ò4¥(Š¦Û¶CHy21ÄÑcZÛ9q2íׯXF£i×Ï ”Âù~)N„ô¸P×ê¦$A]ûj&Áòü”ã=„²l‘,‹Ñ‘g2ÙAª¸¡‘«+9ÿ]æ¥ÛÔÐZ³¶v–ª2³l(ç|œçês6ˆøÿá}3ñò§ÿõ}Ç~äG~Dìììk­4Æ(cLT×µîõzª®kqöìÆxx!D­4õïþÞ/Ù‹mL+Räœ ÈÇ£áæÑ£‡ïoµsŠ ¶ «uˆ·®:þ@Åç˜A Nê:ä8gÇL&!Ó7Ššóx*ÃxR6•$Áp³¶q ù!3ÇbÌ%DqèVUÔõ´Ô4ÃÖ7ç. eJY–X;¡ª$ÃA8Ò{7ËËÛÍÌA“É„µµ5B-`4GËÃ÷ûŸ·údoþÏýÜÏù8Žkkíf]×§¬µ‡¥”G1*¥Ö9Rcœ÷Þyï‡eéûR”‡W3&å`ùÞûîZÙÜ<3 §Ï„Xú4çn*þçãçóŒZžç¤iJÇı¦ÛM›sù$J †Ã ÆãŠÐ»§Ó‰A&ãšS§¶¨k1‚²2¨HÎ’I‚¢4XSƒ¯X\Ø‹¡¨³¾Éô ƸFry´Žèu÷’$1gÏ®²½3À#¨JÛ„˜ëóªƒÏg!“É$ä4XÇp8¤*MÓ#H „ßñÚü¢¬óŸþéŸö?ÿó?_cŽüʯüÊxÿûßÿî4KàøÅá°ø˜”zÒÍEkqúK€zÜ>‚ôžOÝuêž{>üÑ…^Á¶c{³|sØbú9«j¦µ ‚ÅÅœ4±áÐ.&ÅS[¬ñÞÓí‡l£HR't «1ÆaMhÿíÎ_µ)š"Ô6ª±þ\h D³TÈæpˆ8‰Xè_NU¬£T…RZKt‘ž÷õwLÙÀ@Z…¶tÓVsÞ{¤’ûG?òƒ£v;¿ú«¿:SßûÖï½ïÙÏ~öϬœ]ùVgýKAü²÷üežÇ_ LÉÓðÍóöAüÇòþï½ïÃǶ·+VÎh­±êdŸ¿iÓ3Mk )ÕÕ4rì¬cRlSW°¹åHbMž'ı$Ï‚²,ÐZÐj]-2È9 †LŠm², ¢ÞzÊÒâD‘F«Àj¥qÚíEºív̉‘fŠ8R³ˆæ”Ü¢žÚ£ÑˆÇ?¨M8zNHÇÿêçÞk.öâ|àý¿9þý?øû€ÿÝÿ.ïiùR h@Pî’Çï?õÀƒŸz8ËS6ÖkVÎŒBÙUz¾*˜ÁTË»éôéy#d™B)Ïp°Ýdùh¬ñDZS–¥câ8B©Ð”Q6'|žË;PŒÇ#N|ˆa«ßMïæK8þà}'ÏõáëoÞsAà•ßð¾/ºRH »=€æŠ[ uâä£å¡CW/,/]±^´ZÁ_·ÏOßÞ]r5ð…ŠWІúµ½~ïBÊu§Q5R ʪhn¼ª§åaÎz¬D:%Ëzllœe2ACJ)¤ uºÝ}:t/[ÆÚþìÏÿ¸iï25ZÏÙ3ÓdÐù, )n¹åV†ÃÃá„ÉØ„ó‰´¬”V¿t⦅8ó¥Áý÷Š?ý/~Á„°#þ§¿±˜4WÙü>µ àÖ×Wvî¹ç#ÕfâΜ)xøá­æàeM–e*8_ LCišÎr¦Ÿº2d¹¤¶Ãá6QQ׊ñÈPÕžIaÉóqD¹Ö²ÉèH¡´¢, µcìV»‡ åÆÔµg<²!sYr§ß?Èòò Š“'kþ¿iѸ’JÉ 8o Lm)C'3(²›\€hãi:¦7×hÌÔEü½ßߣÿí¿ýÎÃívË†Š‡ؤ(,IÑé´›Nþ¼øþ4X4Ÿ\™¦¡D¬ÛKÁ× Û„S>4ãôz-²4¦*\¾pðSC÷6éÜÆº¦?@ÍÒâ>²´²|¥ÄZ(&†É¸&Ò]&ŽN;emõ,ÛÛ;á4q%šóÄìÐÉ)5=ŸQ䜣Ûm“¦1ãÑgÜMM¼²2.ž®˜º|~¨æuóèV×ÎHÝ+.¿>÷>««;ä-MžÇ! Û»&¨ãÏkì0Íòµ6¸N[[’Xâ¼g<©IÓœùÉ¿ZÿøÇÿâÁÇO¸3ØòËK{—ê:®{½ËãH/P›‚å¥mÖÖW6Y];Ãp8ĘcìÙs²Š˜L*¬•DQÆÒ²auuH1©›  ÆÔ¦"ŽÅÌã(&c®¼â^vNW²¾ZóØãP–cBß½prxUZðÇÓºq^’h¨phª§gM)`ðë¨xÝ,ütÁmÃ\H¸¹«Òæµ%pÀ{ßü©SÇNÇþôý½ÞRÏãË«¯¼¶ß_Xò\ñ¬k®¹uO§Û»ayé@kqq¡ÙÁ«Ò­­U+„TÇ{˜ª® wˆã„ª*(˰›[­ k››c&“ºéèÇŒÇÝN‡8‰ñ^Ðnõ9tèjsªÊsvu•µµÕÐU$2”­×Æ’¦ ç˜%ž qnÈBusmzº`~§Û'SØF Ô@{Ž8*å†=\˜J•ííõÀÞsï]kÀDJyŸs®¼þ†[–w¶7Üm·½øP·Äå—_}ÃÒÒSW6ï| ›Ì›tÛàËQ3àæŸö± @{8Üþ$Iz›¸÷MOxk‹BipÁÑëµ0ždÒbc£ £ yaQä)¨Dï\mŸ—SG ȺÆkÜÀ(!ü€a:–( †8î ß@DÝ8ü0oýþê+ÀÈa®ƒ§†«éà©á¾îs ··?ý§”ù»§Ožy>ÂSÚ8~žç¹4.ÏuÙ˜âî‹<ƒ2ºœ¿ëZø”²ÐÚ jùe<0ë%Ì2©4ý~$€Ñ„ÉDÂÚ9s¶ó“ë×ßß:Î ÀxøT)2Q‹ Ê!/r³×™Ñh8,dö ×_®u6”rÃ$“8ÂtZÀX‰µFÒ4‡ÑŽÁE³™;¬Ü[àJ¼³²°1ÖAŒ±ýµí¶­,öFE-ïoQä_¼qã½Áq·¬&K¨»G"°Ês‹²„º˜B˜ÙMÁy†ÑWƒ J¤2ÐÚ”)ðÂÀ‡TÆÍÒ¦¤w—åÞræ@ Hi`43 ÒÔ"Úèõ;ˆ",5HSÅ𛋯ž¿ˆ%~ˆ&¿Z,ÊñoÆqZ>VÈ3æ±Æã%éye©rg<Åõ½½‡ö¯7oü2ÏÓ+ÚHÃ9\Ó†2Ja¼—"âNQÔYwèBðrà$Á˜#¦(G5‹Z>òÂåÌa÷RÃZÚZ?]™v_Ű [hz RșňÈÞ½wûÚ3Ï<ëµÛñ7fToÆ”TZQà¨dFÃZ.sG4UÊ Œ\¥P)ƒ,Ó`p;ãØ½w¼'Á8Œñ_¼øâ ƒ•,NQãLCl@sYE“UëUå÷îݾÕMÖX·»vŽ1ÎÕåœB¯ßà°‚,M!„C@iB+òË„¢Ðåøù⤅8ö¡´-€_ºtéå X"9l °_pˆ9ü îïÕ@ÐVRΪ¢ÍøŠ`[ªb‡ˆDœôžBDd-ò\ÂB¯×ÀË@O9öuœ@WpÀç + ¼Ýn„NÇÇd¬e&CñÖô½·/¿yy¥ŸÃ5ØšÃoB!†uÁ¢à§éäVF÷gA=˹\øBF²¼€Ö~ÀRº §nNC!Àqb½ ¥->,` A)úñK/ýìþ2Y€ßýöyö9|ÞôÏ®YÐWÌ…y%@œ‡r.@´5ÀS…¶ŽÀ™»woß ü<ϳ5ž% F§ð<×yÔ‰{®…,•˜NÝÞ£(t­ìYjæ,ƒ+*‘ëxÃZo©ÿÀ`ó™*Ö¹»Û˜k gÒîîlïííþùÔ©³_òýàË Ji(m‘Ä!ã°–!KsH©àù®å}2qì=á#IÚX[k!K5²Ì€ˆ]½rõÂëÇRÉ°Ô¯ÎØš`²‰ª^E e yžNîÜùøÚÎ|±Ýj·Ï²PZƒˆ?¢w»þB¢Ð¹†*Üâ)Î9NžJ…“‰„”fâyâßú˃•üç)"kðåM%gìס‡¢t9ãû[›7ûý“A÷ÎYk™« ú®óØóËŠ_à6¢xnÉ…ÛâÑc ;;¢È9Œ‚?~ôÑõÑJ¿v`ñ$ñô xBS@8€±Æ>(òlh¬ÕIÒÿ ÀB¥,ÂP =€ x‡à>ùµÁ`7 ãó×®]þK.숯y¸·:·¨ª ·©a13‚8c8÷á‰(j¼S¾vT~Žìtâµét²‹c âÿè»ÖÅì€n¢Îã KdÉX¥æÅçL1cŒ¢Ùú’•Iiª%, ËËÚ%*û¿ÉRÙûÅdÕ•<%ðˆö±¶â÷iÄpî}dñd‚¯àh)BÝøš*^`¼‰¢V…¡QÔV p„¬]ÿ³àˆöÁêÌÿÒÆÿY6Üä5ÄdÀIEND®B`‚pnmixer-0.7.2/data/pixmaps/pnmixer-muted.png000066400000000000000000000474461311427610600211200ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aËsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÛ ;HYrÀiTXtCommentCreated with GIMPd.e IDATxÚì½wfç]çûy o~;MO–F#4ʲ%ËÂArÀ6Î1¶±Áì]–-/pw÷,¡jw‹¥(¶0µ{º—ÌÖ&øŒ1Nز,ËVÍhrèîéééø†“žpÿ8ç}§G–ÁàÁ–ÍØ»÷ÖǤ¸ €ï€õ½o~÷4Ö¿ß×B09Y£Óލ7”’Ôä¹EI¶h-&½ç‰™éç>3÷ÿ/ú;í ½ým?2‘¦Ù÷ÆÿclCèt"š­)¦° A·!€µÕÏ CþËÌLþV`î²ø6\ïû¡›éõ†ïÿßs1 šÍ‰É)B |u¶•!B…¥`+ˆé«¯¾éþÃGüK€üŽ1ùoyw#M“áÎZ§¼‡(ÒLLÆh-ðÀ`s~iÀââ€õõŒ¢ðJÒnEı„ð/ Ãà…—-À·ÁºþÚ÷ɥ坸ÿ±ŸÓëkço Í/9ÇUB@½05†Š,Ë V–„ˆX_[g8,Èsƒ1Žz# ÃÁ{ßq–ýWí¹õcGŽ>²vÏâeŠ-µøþïÇžã'ütQ/C€ÉÉJy¬õLO^ÃW^p~ù,ÎZÒ¬ÀG4BBšZ¼÷ ïÜùüïzà±Ç4—ƒÀgéZÝø˜ûØÇ|üá?ù…ïsž·:çiÔš­)=Îyv™™‘4Xõg$És¤%Dü‹gΜœ0&£Õ®ÑhSpûí·só·cM“G¹Ÿ/|áôú«ÄµHÀ×õz€”Ž•• Ò¤ VÓÔê¼×iV¼Á;yÏÒ•$âçŽ;|çââ‚l·Û4Æäìܹ‡m[o`c-äᇿȣ|‘ÕÕ³t:-´–„‘¦Ù ©ÕÀÓh¬¬@@»!„ÀY®r–÷¼áõï .àY¶>òÞ¹tnáMgNŸh§Ó‰ð® Ó™àöÛïÂû._|àK<üðýœ[:M½ÞÀZOHâH¡1Ž ”H)‘ ²4!Ï Q¨ˆc¨0ô/ Cj—ð,ZÿûÝk¿×û¡~¿¿knþ$Q$‰k ¥/|á]4›ÛY\<Ë_fnî(R*´D¡$Šyn1…Ç{ŠÂÑîDHá9¿ÔÃùÒ*ÁþV[½è2ž%ëä‰ÅöÖmí×Äqý–cǨ~…v§…÷†k¯ÛG«µ“~¯àÈ‘'8zôI„4›1¦FJH’‚ÂX¬sxç#EIòÌP†$I1ÆR‹5Z ŠÂÍž_JßðïüÏÄe|‹×±£2IÒúêÍgÏ.Lœ:u”0Œˆ#A·Û¦Ýœ%M:x”¾L– h4êÔš¢p…ÅyRE ý~F’Ôa½„ ,ཿçà‰?éÏüì¿—ð-\‡ž:zãS‡Öß¹²Ò{Îùåy–W–hµ"¢XÓjuÙµûF––VxìñX\ àÐJ %ãÈ‹Ò÷ZÐhhœó(¥¨7bZ­˜(Ò´Û5‚Ð0»µÍw}×]t:M¬qXë®sƽú#ù ßäõû¿{_»Vký'h:çAžg„¡ Ói2=½ ïÛ|éKŸf}}UjWÖJýƒ”’f3@*AQXŠÂÁ(åÃZÖš¢(h6î¾ûLNu(L6úúk_öÒ¸ã2¾ÉËy~Á9· „,,œ¢Ùi4"š7Þx÷ßÿ9Ž;Dš¼sí”ß$ óóóìÙ³››oÞ‡”ï¡(ì=«kÉm—ðOXÇO~ôëþÞ_ýïU?q|áß™¸.Kó`eeÓgždyy© Ûí²cÇ.fg·³´tc Þ9¼¯.kɲk-RREò­a¨( ‡(âc™Øh…aÈp8äË_þ2q\ç¶ÛnÅÚk@¼æ÷þhý2þ±yüáßûº#èf[ÞÓévï(LÞ^^YàÌ™'ét4BX¼·´Z n¿ý9¬¯[Ο_¡ß[A)]âÒ÷G‘BIA‘[­RúýW•„­-݂߄ï=Î9<ˆµ–}û®bÛöÉ ÷Ìûך"ÙzÿL+/z[¶nÙö*)äm‹çæ™›;J«-i¶ƒ!µ8dr²‹”šÞFŸ4MÐ:¨HR ”®̔ ŠTEþc񠐢 AA«ÕbnnŽÃ‡³gϮݷcŠ‘µh¡®¼ €¦õéO¼¹?(>°²ºÄüÂ)´.˜šjRk Ö<ŽZ­ÎúºåÌ™c¤é)%x_™j¢ÚdOšŒ)cï! ‚ñæ?ýä[kB°¸¸Èƒ>HDìÚ½­ÇߨÍ3ó–—½ôáe\âõ?~í“ÍóKƒŸí÷zÁâ¹³ “5¶mï µd8LpÎQ«ÅDaHžKŽy’'žDJ…÷çJÉwIÂPe¦¬þWC’ B©g–DŽ@Q¯×9tèy‘³kçv:íz©&Œ±7)%£Ë¸Ä«?cŠâ¦••ó,ž=Åöm-ÂPb+å9ÖY&ËçWyà/°²²X½Z”)`™¯‘e–<·•Y‡ xïÊ7.%©ôµW<ùä“:øû®½ŽN·‰«^¯”ÜÛí·<ý5×\õVqÿÔ,áØâ+Zø•yžµŸ8ÄädH³¢µÀYOocHi¢P3LžzjŽ“'Q9:¸`½S¸2p†% d­'ËK‚Hk‰_{¯¼÷H)±ÖräȦ¦¦èt›UêñÞo_]Ío¿hó÷¾Mê yÙüSÖüÞ§v?~þ•ý~¾ÿÈ‘ƒ„¡grªAkŒu ‡–F#¤Ù˜dii™^ƒ(ª1ŠÎ¼§Œð(-‰Ê†qÚ©4BÈ‹üÿ3Þ)ÑZów÷9VVÖ¸îº}· * !®Øüý‡þo÷ä¡ÿ×_À?rýÊ/¸vðàÉ»‡o?}úxÐï/ÓéDÔ çÐ%//"šÍ6×￾ðeìÝ»“( JrÇyòÜ£ªž@ïAJÖc|eÞÎ]œÿ?ÓrÎcmÁÃ|™nw‚Û·"å¸ÊØÊswÕe|ëNî5¶xïñ“G]¯ß£Ý˜ž.­êúú:ý~t‘e†f#" #z½½~]»¯æÅ/z%/|Ñw³s÷ õzˆ¨|¾µåë”…Ãþþ´ôïéDÐÓW£Q§?XgmmÀÄäÎç#7ÐPš»ßûþ{õ¿<÷¶ÿó’¦8G.FB¯œ›;sÅÆúºÔÊ35Ý@)I¯×g0`­#Š"ŠÂ"¤Ci1†@7 *öo}#gvæzn½ùålÝ6E­®ÊÊŸ-Y=xÊÊ`š˜’$z† `36/!$ëk:ô8Û¶mE© ¯MûœÅ¹kýw<ž{ëOÉ<[¿¤Í¤ógV÷?ñØ©×-/¯ÎfÙ€é- <χXk íËÀË{K­Q†Áp@«Õejjcr”ŽÙµë:®¿þÅÌnÝB½¡ sŒµå,JJâš®L¸ÿ{ƒ¿§ƒ@kŹsç¸òÊ=4›qÉY¿¿Ó™¿ö;Ãäœö½T¿Ø{¯Ï­ÏÆÆàUËçètjLNÔ Ã’ñKÓ!ÄøÒZF©R†(!•@J‰’cršÍ.{®¸ÛöÑé´ 5Ž<38WÒÀåÉÿê à3ÀÚ o7ŽcVW×pÎW„Ò(–`GaÌ‹¿]ðuû®'ýÖ%5s|ñè Þû»¸x­%uZíþxó7ûjk-PR“¦õz“õU’`@ÕqÖ‘eCÚí)n½íeô‡«¤é!†‰\Yö‚¼pD‘«@ÿá·T–“%Î9çqÎÒlÖY:—T¢SµîšÑ÷¿mö®+·f«ÏzwýL¶|M§èߨ]±Å#Ò®B=¾Õ¦÷ÿù–;üË…Ï>ùm€Kµ^ô¢k/~ñ÷^±º2üŸssg¦úý>µšfj:ÆZÏp˜`Œ©ÌþFNk÷I©îU!Ã$åÌé£<5ìóÊW¾…N·A¿Ÿ‘õZ‡›n| Ež°´öœÅÅ%À³e¶IhÒ4#Ïs´Ö•ÇO©s¥TU¿÷´›VW—8uú×\{ ϽívLàñH°uö ffö°Ñ[&M Þ—%`­K±¨ÿGÞn)%EQ°´tž‰‰ À£){N<Å §Ü#MñÒX†Õ†”8Tõw¤Õç=<ýlõå=xyÝ }óÄu?÷áÕƒþŽÀ›ßü®ØûüÊõõô?÷ûöÎVëÜöé©íäÙV+ ÞˆÊAMYVªy«k³ @k NŽF£ÍÜÜ î¿ïo˜šØÂ®{h¶Búƒ³5n¹énÖÖçéžÂ{QÑÁž04UåÐcŒ¯gYk™››#ržÛžzœÙ£Ѷ ™£y2auY ¯>Õ¿:À:pHMzs}õàŸ¼®>û'fžûÇNþåÂ7 ÿ¬#bÞõƒï £`Ãùü§ò¼ø µæ»…­+®ÜGQ”U½v'bfºN’¤äy~‘(c´1BŠ¢ ( ¼÷hÝb×®ýØRmÞreJƒêDŸ6”抗½‰k^þ&f®½‘`bšucXìõàÇAÍ <ƒòµ:ÉÙW°û5´´vhãÛ ‚{ÃW½òÆiü$µ¿dŒ‡s~oyÀqMÐjN091‹Ò!ND·žáp8öûιj†oP–e•”K…StÚ[xü‰/Òë¯R¯GS×¶n`÷îlÝ:ÍÂü¦ç ËËsx,Î:¢(ÓÆOOý¤üêÌ8Xnþ̧¹îìI†@Ø_mØñʤ+`8 ¨0âö׿•[^ôB&:!ÝɳWìaçµ×£»[è'7ÖÈ«—ÕǸú™Â™vl»Žäôm€7¾á3»vñV¥ù³þÍÎú½¯½÷´;!Q$©×Cêµi¢¨‰Ö!݉˜v[3$mºsî"óï} 277(ÝáŠ+®ãþ/þ IÒ' 4µZÙÙ†ƒ>33[عs;EnIRA½ÞfnîƒÁ*ibh6jAð5óÿÍ.Á®gÜõÉ1Ñ[#v7 À#›6ad ˆ^öj®¼õ9( δp4B¨Å³;¶²ýêkQÌÜÂ<©5´7ÅØjùÆ -·Ÿ:=˜øY €×¿î}Ý믿u¿óÅÿø·{ç¯ñˆØùRthE­¦QZ⼤ÝÙJ cjµí;€e0H¢äèG9÷æM0ÆeÙ8 ¬EÓ4]ž|ò+ úÄqH«ÝaÛ¶Â0 ÏsvîÜÆ®Û8sf cEž±²zc J©Êø¿×ìw×6¸ù3Ÿ$NàšêZ>G© €óÀP;žûBº×>‡Õ¡c­ŸÓ “Œ¼ð E–…Š™;hOÍ0?†"K©W` ô©áÙë_¦ã߾ߙìY€|ï¿Q3“WoKÓü¿ á>h=wx/ZxO–š;­%yîÈ2K@4h6§‘R°eK›v; Ï2z½”¢€8ÖcÎ#óŸ¦iUò-˜ž¾Šf³Ëø‹RšN§Åôtï=Íf“ Ù2;ƒsŠ,-Ã'%Ï”Ô3Ϲ–ð‚Oÿ >K‰€­UŠ÷ÙÊTתS®Šö;¯fbßmôWγròKGpæÀÜ|âaÎ>ÄÚùjõ:BEdYFs¢ËÔÌççÐiJPéÙjBÐãýÔzØÍ˜á§ŸUøÀüx# ìKÓ$ÿõ@‹W+-¦|ÕmÓ¨k°ì¿/ ‡1ekv(¤¬399ƒµž©é­–¤·1 5A ÃƘ±?.iõoçÆ,íÖ=ô9ŒIÑ¢^¯31ÑÅ{GÇ8çØºušÛg9uz k‹‹§èõVR}Í,@nÿôDZYF¸yS´þp² ÜVsB`FBD¥8÷Ô£Ìü2+gŽÑ?7G¾¶Dº±ÊúÊ9Neþàh­hNL‘§9:®SŸšbeîAž#*7Á†iÓçmŸ¼åÏ%g—¾åxÛ÷¾;ºóÎçOnôÒ_ÜXËßo¿ET7MŠF#,}¸÷d™ÅW —R ‚ÀÓjÍÇ-¤„;Ú“bE)…Ö !äØlæãG§ßZ‹1†+vßJ’&<òÈ}H A(i·»LNv“““äyÁÔÔ$i"ð>&Mûœ9s(•Á¥ˆTŒA ¥Ä§Žþí_£Ó!ºò÷ÍÊ<Ÿ%RrNòê²B0L†$E†¢ÚHI $-!‰¥Ä I’gœ:~„´7`ÛŽíhéÑQ Ñh2ùRÊqPJI’$ã¬À{Èó!Þ˜¼ *·QÊÆµ.ƒ»m«”"IR¼25]£Ñh15µ~p $„ Xróé Ø"%Û¥$ ¬ Á‚ „à| D³;Èu„ò–I!hIA(J€’U,q¡I!}^H¶)ÉÖ@IũÙ;}š4·ô3K´÷£10›U¯{P¬}ÿ;îyÅ7?ò£÷ˆ8J3kK:Õ…ŠF]SoXë iê²Ç‚¡Ê& )$Î[jµ:µ¸Žµ–8ãâÓ?ú8ú|Dý>½t;ô:@ë²g@ªr ؈æ•R2 *RɲººJ8’4cË–(«B„ó\õÈ—IÔ…dOõU_ùö3BpNæÌ{ê;®" "Lo™I) eÙtª„¨*Õ{¨N}P}-—‚µªieFfƒLÁá'e0 ¬f¶mW±¨K‰– á-Û×üÄ7?õ“ÿ%”2¸ÉYõ¯‹,W#²¦Õ i¶"ÒÔ°±‘“&e ¶`3§.p‚@×"¤ ÊÓ ËfÍQÞ?¢|7ŸþÑçÖZ²,»ÈOK©ˆk1Ö¤Y <‚°t £×'IRŽŽõõRk89Ñ`vËN°^M)×öCGé.ŸÅ ÉÕ@$¶ãjuúç= ­£±íJl½Ioñ]Yþ./…s¬šœ3RsÞ„wØÊÿ{!QB ‰’ÓÞó‚Â&u@º±Á‘#GKWé,zv+.ŠJ^@")°2 –¯|÷«&oxþ7ïü¾_só;¥Ä^çÆäÔêRIòÌÒÛ(»e…àÂéE …B PBVÊ[K«Ñ_º†Z-oÖf¼™ûâ§k¥,ÌÒé¶É‹¼Ü|-Ç$Q†Ôjåd×¢(ûÒ4%Ž-Íf@­Ök ¥”ÈÕ”+ŸxˆBv AGÊjÓÊÓZ–›ß÷ŽæÖ]01Íùùã´¼G+…‚¾³œ"ò[îbï{~Šmoø!Îå-ïhW}™p–í)¦ßùãÈ{^K?OéjÅÚ‹«xkQŒ˜œ*ÙQQƉÀ«ÿßûƒŸò;·ïx§TÁ+‚$KˆbM(-«™zžR…_žöÒ§VzuÚu B£”FI‰eSÆ(àÛœov£.Ý ¦ÿ‚0¤?XFHE5p¾ì6Æ¡”&Žcâ8§ƒÁ¥¥%Âêµ:“S³xï å–¯|THZ(¦…`Q”ÀªœBpÞ9j“³è™­¬.Í$B¥0rçX!Û_/×¼òÕ¼þÍ/çGáWØý¦÷³å(ï©IA]–n`ÝYôÖ+¹ó%/à'~å¿ÑŸÚBÃ;B—³0?O/3à=zf†x)©É*]•õbíU7]ùÚ+ÿÙðÿï]ÇÑ{‚ À;‡¥9WJ3èÒÌb]Io†¦ÙŒ‘J"…À»ò¤ ¦(;vEQ µ@kUÍî+7t³ ÏsÒ4Ý” ¸ª·ß–ý~AˆÖx÷]uúA@†A0N1 “!nD³ÕbëÖ+ÏÕ¢7ÖpBÒ–%û–Vi^.%'„àœwÈv—Ú–í¬­¯cÖ–hFH¬œÏ Z·=Ÿ=7\Ãõûvñ’{îäæê¼óÿú¯L½ü{9›$!¥¤%™ ilÝ Å€ëo¸šýÀ»8[lÓš|}…µAŠÂC­ŽhµÁ{êRÉÒŠ(Ÿ7'’³oºÔ¸ˆ }Ë›&˜›[~mE¥ô¸±¢VpΓç¥išžjrõÞYö];ËÞ«gØ»w†V;?‘KŠ2]ô^QZ±Ê_W­Ù›}þ_nx’$ªqy9Ôa8LAxŒ5t:“xo1Öj ¥4aE%Ý:rýþQXVC]C§9ÍS§°BŽïD*®¢b×€3@ÖhNoch ý•yj£±cR™‚þìNnxñ‹ %¼â»_J”ÕÍç7Ç#¿=RåZkœu8 y>À˜œ(jà\yÊG³€â8BkÖeû׈GX˜?Kš Ñ$®5©Ï­bóŒ ¤ ¬n°!8)=)P[ é÷ÖÐ&'P'$Ò9TÈM¯~vÄóŸÿ\vîÜ…µc,Z8žÿ‚]¼å?}»ï&úYÂÐZô¶½È0¢—Í/Wï¿–—¾ûýOS&”À6XM I^ :-D•q€ªFŸI…rÙwݲçõ­KµÉ €»ïþÐskµð%Öz/EIÚ)ÑAŒÖ!;vL25Õ$Žƒªû†jSõzÌÌL@+ð%µXãì…éaXvçŽNüæ(_)Ežç$I2ŽœsT¢n¬)‡>k¨Õê„aˆ-ÝfÙ&®/X–)äœc0H0EF§]cº5ÁU§Ž" A[%áJÉ@=õ6ªV'µ–dا&/¸«¥¢ uóì¼zSÝ·ß~û¸\íœ#Ï tÜýòxõOýÍ+ÖoÝE½¦‘*ëÞú&ŸÙ†µŽf‘2Ì2¹Ã* µFÉ;‰/x³ukÿøM—jä}÷}þ k•VJ‹‘~¶Õ¨19±…«¯ÞΖÙ&Z—/Ý葊7 CºÝÒ*€ota3¤’€¬´õê«jÿ#g”ÿ‚@c Æ(]Ö¬3Äq)Iš¢I)ÖV‡yq‘¤LËp–‘ÒÇB&ëlÈ’£¯K‰©Ò¹@Î A„øV$i‚0)JI CSЛÝÅ-/¹‡@yî¼óÚí6yž…¬Þ{ŠÂP¯¹÷¼øÇ–³ALÔšbǶnºñ6Ö¼w\}íU|Ï€“ĺ·¸t@îª{×h€„J¢«lÀ#Ù“Íï»TЛ. ¸®¿ãúz½ÞçÝQˆ4Û¶w¹ù–=LLLT‚Ê‹óö2}SÔj1SÓ tPþ{šåô6QҦΉgTߌ"ÿ²%ÌŽÕAÞ{òjc­õ8k¢ ,MaR”Ld–`œ¹(u,Å$ ƒÁÁp€T‚µûþŠ $N:U„í(;‡lÅó»f¡ &}b!pÕLs*ä¦W~íN+v_ɵ×^wQÉfqI–´jðº÷ý û^õÒ¢`ß¾=ìÞ=ÃÚÚ®2o|ï{q;¯ÂƒH$Æ04–°ÙDhM Á(Vãí— ÑHŒÌÔNœÍÂÂçÎ-1<~ˆäØ—1R!Ô+ÒÇUùúè‡!²ÑÂ#Ȭ…ý#ágQã´nó ,ËÊYš‘çŽÁ`Q }õÝ…emm3§Ïe½ÞÎÁòr) ?yœôÈCH¥ð@\‘+®â,2ïÉâŸ9rSàLQŠU€@I6V—ȼàó÷=Ìu×ícçλȲâœ86 pKeSYë‰ã¨lu¯ªŸý‹?#;ö8Óµ:½"Çz(œ#B¤Ò®ª}—ïW,ëîTÉV|ã Q¡t66ú*Ͳ3J‡(¥˜œláETí(òo·ÛìÚµ‹f³9NëFZ€f3¦ÙŒ«R­$ˆS` àݘ¿¥~iš^$ÏvÕì_W• ½¤YB^dÉøÿ$«à¬( Ö×û,/¯°¼¼ÀòòÖæh + ç‘®ÀRæý])±Õé–B µÈÒצiRÝR"•b»ô žx€áò+«=~ë·ÿ<ðà˜Íü‡\÷pöì*ssçY˜ïGÛFqÌFoÀgþà7Ùj‚ ÀÙ¼y/ã¯Ô˜BG”ïy>Ü\*Ш”OõJž^ëõÖR†Q¨iTRêÍŠõÚjµØ¾};Ýn÷i=E£a¬'ËK¿¿Æ ŸSŽÁ µnLüŒHÍÑ?†Us§sž,K±&G Ë–Ù: ÏMÕ^æû++½ò!Ñç7X_ëá}5èyµ‡ô+$ª­Ü—¨E AªºQÃ{u–,KЪ4¹^Bp¥äO=L¶ºÀÂâ*¿ù›ÈÃ?4Ö!|­@Ð{Wº/“amB¿¿N¯—Ž­ËßþéŸ1|ê µz 8'ðÎâ)°J£*¡É˜4ò’q‚F¡•J h­P`´É£, Õj155E·Û†Bš­:A 1(ÃaŸÁ  ËÊ›2"N²,ÛD(]pÖ:’$£ß/ÕFe©×çY%,)gù#Zƒ1É0a}­ÏÊò:J»rC-¨¹ãBá… !ËtÊm"¢r­!ˆÈ]YܲΡ¥DD+BÐCö…yä1Ìê9Î,¬ñë¿þg8ç%k–$ I’eZ©êù>fS…P p¤iFš–Z?c Œ-Ó«¼Èª›;¢”…ÉX]ë!d(%¨Åµµ%ŒÔµZò5¢†!( ´Fê)Ÿðc„$” ¸*R'R¬,0¿¸Áÿü¿ŸS§NÇÑ×RšŠ±Ô˜¢œlh;çÝɪ±YÖ×…T8kËyÇA€P d©+ðÕ}¯¹,ºTµªE•E˜Oñ”ô¯¤DT ` R •B‡!®Rôøª è¤Ä!)DfP?u·ºÄS‡OñÛ¿õG$Iö5Q;f¦·2LR<Œ±å´±~¿ÏM·^ÇóÞôVæ ±Rh%ñÖâ ¬ ªÑï/Ÿuä¥fŸ›Ûr)0’p¨MV ûå‡>5÷äÁû¾ä¬£ß3(­M­Vàk]anf”ï!I a0ÀõÒ?;W¦EÆXƒQJUV!Êçû•f[È‘^„ðUßAIEÙ $Õ¤P ¾êYÐ1V'½f /ˆ6Ë2+¸êô#Bit!«^%R”£’b ­5ûkšÚÉ'Å#ÇÎrúô2BðU. ( [f;ìÜqÛwÌ2=Ý¡(,i’àð¼ýï&™œÁ9G]+<žÜ8†®ä*JUP™± $¡ð—$ pÕµÙ Ô‡ƒþê±cOh4ë¤ ôÖKVë²Þþô“¿93(O{xÂ(¢(JM€s†ápH’”Jß ¨žÇ“†IVⱠܬ­R@Jý_)µ“ ƒˆ ,§†å¹ÅE1EÅÂy-0º‹ÀHIVI¾Fª]S5n(­ªXD"ƒ¡JöÍ‹’.vUMÀŽZ×*wØlÄLÏî`jr† Ð_3°Ö°{÷6öîÝE­V’aÆZú=ö]w5w¼ñ-,Ay&P +Kk„ÑÁ­Þ¥@Î… &#DÀô£=°¸ºz¶7Ζµô‘æns°#Ôëuâ8& CÂPÓnÇÕsù$J úý†Ãœ 0ÆÓj… ɰ`~~¢ð#Èrƒ äXL‚¤™Áš|ÎäÄ„('€:[Z QÕ0q(­ÂS·eþïª㥤¨ª€HI¿jðP‡!…DaYû#ùz @­ª,H•.C~Ç‚Fƒ]»¶3;Û··=ý²ÖÇÆò¼¸¨jé¼ã•÷¾ƒtr¶ «.« (§£‰R{¡ƒJÇ/Š ›ãø‘‡˜ä‘ûîŸètè­;ÖW3ÀW[Œ/:õO·¥ÿ×@““uâ8Ä–í"I‡˜Âbmˆ÷žv·Tº$uÊiaÆ8¬)Ç»Šó@aR‚@R«5QU—I™^•— Y="Œ:AT™Q1N5©¬ÀH½kKDãD ¥C¬TÅ åÆkœTx¥ÐR²®Ú{®¢È7Ýtq\JÞž BÀü\Ÿ§­Òë Ç(ë)»¯º†Î•ûVO/Gã 1î¹@H¼~FôO^ d \”Xj ü«ýáÁG»ïÄúzÎâ¹’¸‚2i6×ó/¼Q1•*£ë8”>ÙYG’®Sä°ºæˆBM½†’z-!Ȳ­FXž¾êÎA¯×'IשÕjå ´U?"‚ ÐhUb¥q¨O–mh”éb¤ R’¨š ª´B(‰Ò¡Ã Lª:…Õ×”ÂIî=Ew’Zw’n§ÍŽS$IöŒ›_Î'V|å¡S<øàœ'ϳ±à5 #–Ï!™?B#ªá…$R•Þ±¢¬ý8‰òÔ¥@Z {$=õÔù'>|¸VYY.X<;(Û®â‹]ÁfŒ¬A­V[¼ ^ ‘ j5…Rž~o½Rùh¬ñZ—)§ åʡŒ²zÂçÝb80?wˆz½I£Ñ®,B"«:ÈŽz½MgjÛøI"bœþ‰*¿”"resI= Æà‘AŒV=*té:Pè@³áí«ö’f‚Ûn»–v»F¯×Æ‚P½^# <òNžzG>ÀêJ9Wªò=>ö…ûPë«ÄQ9-=2-W=íTA Õ\CËÀ+^ú;âÀ°ÁèYƒÑð‹ÖGÿòŽ}å+Ÿ9š¥Þ/-e¥.QZ‰ž£´q0 !¨ÕËx ÊÀ0I2¬Í±F²¾îhwj¥…ÑŠ( «M”ã©~£æP`0(8wî<ài·»U+äEõ| )£€(މã.>îT™„û;?*3VAiLÙ—ÄK¨œ+ó_š~9R@)A²QoÒܶ ­n¹åª±’iTÖÞ<ó( ë~ò4G¾ðqÒAÊüÙÓÌ/¬à¼EIE’å|æ/þšvR]þ”¨ÜžG(U’@Š#?è€øø'ßå¿Q °y®aº).0€[^^Üxä‘/œ*LâΞM9|x­zðr™–®àâÍ#òh3…\ä†Z]RØ”~ ( Åp`È O’ZêõaXšr­e¥(ÛЕVd©¡0CŒíÓhvÊüÝ{ŠÂ3ØR¹,UUµÜNcb _¥QÆy2Ðݹ¸ÛçpR–£ÝŠœf½â0¤B1NTæ“PJ–"Ï­Û¤’›®¿’‰‰6ÆØñT³$IÆ„T³Y§7ðüÝGþµ:‡Yï3xü±ÃhÑ™èðÄCO°tðVƒI„DJ¢«VT$‚5Ùò;Ç?ñ‰n6~ÐWzr•4µDQ@«Õ$ õE#WF¦¯Œ.tÅqÙ"ÖîÄà z½uʧ|h†ètÔâ<+ƒž¢=ø©¢{Ë–9ŒuEŽRS“³ÔâJ–Í'ÖBš’aA ÛLNl£Ù «â‰ÃkM°m7Ùm´vî$h4°#§9µ8¤SBÇuŒTºŒþ¥Ò¨@#µ&c³»RqãM{Ù\±™£¡×q½ÎWxœ…G?Ǿ©6rccGg}½ PŸûëÏÒ¥ C,’n-,_5Æf^–V@j¶†öÀ¥@¶iÓÕ5D²)HÜøøßüñ±~ô÷óÿÉ/±ððçÙÒn‘{M'ÐDË´š-–WR>ñÑ/ Vi5ê ¬@jE- Jª08 §tNêsÇmûË—jDŒðSÃc™xy B[šÌÍO»Ýv½Vo¨mÛöKK¬ ‘JÒhÔètjcéwiº Ãá€,Ë)Š‚••~õ5)½^¿¬&v'ɲ‚ápÈÌ–r€ä¹ÅÄè9Àº|Ì‹1®|0’N§…µ¥Žá°$ƼûÿÛ;³É®ó¾ÿÎ9w­[·–^§gz8C‰"eSÖZ z™/Äq4ÍfLÔª¤`0˜²¾¾F«µÄ“ßyŠ÷^x†í˜Ð¿Ãê9` !ñ‡ÁåAFaÇ›>^%¦•ä†PIö¦Ú@¨Ä÷þðgÏ<ñ šCjS>Ý çGmþÁ#¯xY‚ km °7o^¹l?ÿÖ;ÍærÓbÓ‡O=Òjµ—íñ‡¾ôå/m5n4[YÞˆ––Ú­ÇOýþžBª­«ÈòŒÉxˆçùdYBš–Ÿæ( ÑÚÐëM™ÍòªRf§L§ 8Æó=¬Ô£››³´T#Ë,»{{t:{è¢ ¨»\9œvÆJvgš Qn¾”ež@·×ˆr“%,=t’á{ï#Õ‰× 39'!i¯CïZ©:®äU}ô‘2ö]Œ…¢¼xö]^øîw9Ñ®…e“§PÜ.XˆÛž¸ewœ0Îa£Ю—Ò;yf ]#,™-ö£¿õ "œ¹ >À¢É·sÐUn ¯H¤é\*y¥*%·«ûõ`°?ô›?{¹̤”?7Ƥ>öøÊpÐ5gÎüåMß‹ÄÉ“?¶¼¼Q ‚Ú¯,µVk“h(…TËÆè0ÏrÆ“2¥[¯GS:€ÆZ”•¥Z÷þ˜8®ß¨G N=tЏ0&ììô¹uë aÍÅq${¾eD²›B3·,ùVJ V Üõ jù4iµ[t‡ûD­U¦ÓJqªq¡¿ÇÞc%¾·ÅæÉ –—WYY]!Šë¼vöûDù€µÕf©Khïxض€ö§9ÛC¸,Å+¾ ®õ4’†kßnºö{A0¿ñvÁè yÅ!Lçòa‚ŠYÊ \eŒÉ€àü¹·û€ÝÞþŸW£”ú¡Ö:}äË_‹/]>§í×ÿF=ð#÷‘/ÿò¿rÿŒïûôºcÒ4ge%¦È-{{#¤,­@¯7äøñ% ŸýŽƒëz¬­Ç„¡âÚ•[[ïÊqËX]j¶´Ã£®¢@rsƒr ‚RÐõJ9ä:`-)NŸ&;wž ÃDÕ&šÏ£«{;ô®hΚÞ0åÌ×}Nœ<ÍٽƕŸþ„‡šuâÀý­À‚ÝQƵn†ï*N-NÉ@Z$hà /es¡ÿè?÷Lö °È[â0ݹêCŽ‚ƒG1—7H„J)Ï›€Í«ŸÕsÑ„3Ç;ð­µ º½Ý‘µ&½~íòõ+WÎÝìtn¼}âøÃ_jñz¡3’$Ek¨ÕJ†YZ”Õ]kñ]Ÿ¸Q#™iºÝ]ÖÖê`—Øïõ¹xñ-vvnþmÙZA–(¡Ï¸€BJüÀ%¨*‘Ž’ˆ F½ÖBfÓÅp€­5™Lg´cŸZàÒ =’áˆá`ÈhR0ž9\|÷ o=û}Žù†•¸FÍwn³yo3ªÅö ãZ/CÁÃë5š¡KaKÿ$r5%éL z³!dïíû›çwÏ >Np(‘íÎõ †r°¡fîj*Ÿ fRH “bU8$ܤ²¢²yQä{£Ñ kÄíÓÍæÒJš$äyQ•\IžmJ¦Y[oâ¹ΈáhJ³¹Îd2á•W„1–Zäãû¥ˆu’Œ­¡åÕ ‚Ü ê5ÏU„¾Ga%­å3£h·bÜZHÑïRhH„ƒµ†Zàâ{.KQ@Ã'›’ ÷Io^âtÃ! ))lYbV“Í·eIDAT·O*ÅõnÊö Çu$§×j´#SU2=U¶­å®ô ¡0¿÷ÄËOþ÷-w?°‡øóW³`! ·V-&›ÐbH¹„Å<ª—çù(M“7öªëzg<Ïs“$išÇBÀxœ`)™ qQB’D³³½@0î³½}Ç‘Ä Uõ”…%èŒsj7Ayhá°ºÒÀ ¢F+üÀ#Õ°¾¾Ät–#†=2ë0LÊ1¶5ßA*‡zÍ£y´}ÉjÝ'ð=´­(hBAè9(%¹ºŸr«°ùKumËuW‰Š*¸5LÙŸ„Ž,Z"ûÍ\~÷ÓÀa>Á¢ÐGÃÜT‹ÇÏ<8‚,KõÖÖùOúІÑ7,VeYNšh‚ÐÁudBæëëͲ…lVTó~÷é÷÷ñ|z½LDÙj–AžkŒÌÏ`s©E®ËŒ8 ‚òe9ÇeåØ*“^ФŒ2˜ä–¸îxÈ’(ã:N©R¢ž«|Ïuð‰§W: 7ÍšÇéõˆFeö•,)ç¾(åewÇ97ú®”Xcþð_þð»ÿ‘aݯZ¸3ÿ‹Žáa–Àbæû¤UÇ‹éé ~þòúúæd©µúW5²(rŒÇU¾"Ë mhµb\×a:É™NGLgãÛlb¥ÊÌó$i¦«Z…ĸ9Y"Xoµ™¦%Ë\j¡OVÚ€ij¨5"‚¸NÒÙ#\3Ã0µ´bŸ0pËs^–$ÑR Ib¬`’’Ôpu?¥?Ѭ¶|^ˆmË„µ•”«HrÃŽYI"}þ¿qm÷íO‹¢9Ä!\G\Å=6ß.ü΃ûg7n^ºéû!Fû«á•éc…8U¯á `m½5¦†¼È(ŠcJ‰Û Pdy‰O×);‘²TÓOÇHã±Òl2I ®çR‹¼R€Â š±Ï$1´WÛ¤ˆÉväÓhºÓRËsÕí–î¼°L3Ëþ(§?Ñ ¦eÃÇ#Çël®F¸ª a¥,éîŽ(µ „\ÞK§£xsOÿö^ÿΟð1­:0b17 ¬Áü÷Ä}+wÛôùK]è«aí*é>æ{þ¦B¦³Ç‘Ô"Ù,%ËrZÍÇuHfy^¶! ª¹  (JZZÙÿ¯«]IgÚ'YN¬­1š„”´[!–’þ†Ik'ÖèO d2e£åÓŸjö†ÃÄ0œúÍþ¸ ?Õd¹-Ã)9},¢ûÆ¢MÕýcKªgÝU¸®bkoÆÞ(ÇQ’À¤¿û;Ï~û_ð1® €y“nŽ8Ë9Ägà>Ì¿½‡e@­ÛÝ}?Ž›—£zó¯9Êi[ i^ •¤Ù gd™a}½.,IjH“)Vß™C²R);‰‚ÀÁh‹‚q1b³Z—ÔCŸYf1Ðßî4Ïl¬–ù[å”*‹BuOxŠ[½ŒË»3œ²/püÊÕéßÿý¿sƒyý¢÷¹ùóŽââ}â#ÃÞãx8¸OÝnšÍvš­åÓa­çyITë“IŠ6–¥v]X¦ÓRS@)A8¥V¢j//I›žWNÑÚ€€¬˜péÆ¿tê4ÚzŒ&9ØÇqÍF@VX”ã°±¹ŽŠZÉ„†k9Ö ) $9·›8lÅâ©….JJÒƉ&rÍÈe»—ri{Š«Qð“‹{ÿèÉ—ÿÛS|ë/bÄá•Â}Í!@ ÏÝ-J8̧PÀØZsYIø~ð¨çqÉÖ8Ž"K5ÊQøžKVµa6]·jk7%ÓÈY¦Ñ…E |Åtj®Çöø#h7Óä$™¡,µC’´¤‘×ÛMâõcLf9ÅtÌñv@¸ä9hS*›ÌRK’Yf…a<Éñ”d¹á³?̹´3Å•Qèñü[¯þÓ?{黿Ç'´ôpTØ8¿ùGùGâ°išL÷÷w^=¾qê¤ãºg¤RƒÑ–¼(@³at98:MJþ ï+ mÐÚàz‚<-È3ƒrÀ÷¦³¢cWãØF“©òÓ·Þ`µ½f\Õûƒœ,×ıWjýøBy46Ž!£E’Pw ëK!Ë2Y´Ö h×=ˉÕcí›Ý”­)®ã‘Ùà[Ï=ùŸ{û•ÿÌé>ÅýF5Çà’G8ÌŸ*î–4â.ÑÂQÏq—òÀbxÖZ³uõÂÙcÇrjµú_–ÝCB ò,aPöäEN¡s„´­K…’¼ M3”SúµÓiÂxœTŠ&(kãIÆ›çÞÜÛºúÞSk››ÆÄ~§—1L“‚8öBrls…úÆ(‡t4Æ–•v@«áÓ¬{4jYa¸pcÂn?#ôBö‡û»¿ÿÌÿ³ó7¯¼H9œt™rBm“R°#æŽzËmY?î U¿($ãûÅ#Aáع¨â(-Ö%Á‘]½zá|#n‹F£}F)µ)*K³iª™NÆX[6@E9ÕSC–g̦ ãñ´šSl°äùŒ^@§Óc0è½ñ“W_ø_g_yöÝá¸g[vËóâ (\†c˜N5ÃaÂalëLdÌ85Ø,#Í zcÃN?ãF''+ÊLáÏ.½}åžù“'vûû}à1Êù”ëÀj„e`é@̃Á=äXýT,À½œCæò‡}Ñ4 !ç"ÐÄ‘u7ËÓŽµVÕãæi¥T`!IJ©f3,;‡RMž§X E®‘ ¬ÕäYÙ­+EéXFÛ¦“”Y’“ÉàÚxåŠN — ïi1×Õõ‘ùÚ8Ì ‹¼…­«?Ö,¼>¤„dȪªzãDgïÖ+Q­>õ=¯Öj­þ])º´†Ù,!™•óŠëõˆn/©äæÏ?U—RÖâZ,µWÂåöŠS jBHe²¼ÈÃÞ¸×Ûvû½~Zä#`PÑïgÕu¼@Í?à\s$œbá¹bî¾´º~¤6±ûÀßþ›Oˆ>ÿöûúGQÁ™‹¬äÅ !w47¶¶.¼ë:ο‚ú ?¨ýºrò¬`П°ºÞ¤Ýn -ô{J¢Î!êQ© 8de£G£ÎêZÄd’#lB’äO×£ö÷ºÝ=î(©HëE@`Œ ã‘;äåk—çžÍÑçæû0;³õB}Å.”ã‹CRñ‡]a“ÍÇt$ÌSÌÕœY;pbœ¹³l^½|Þì} 8tHYzž©Ôo·WŸ9óWþMÖþŽ­´kõ•å˜ñ$§ß1öAhê±Oà;ŒF)y®ã³´Ü`ãxÌ~gF¿Ÿ¢5ÿöéÿý_ÿùÂß÷ÉÒÉ#Þÿ»ÕOø¨üIûÜ#›Ç!g¼¹KDÀ!¨¶G$‡>%$Ét|åʹ³'6NÕÂZ팶†¼(°VVƒ¬eÕ_X¦EédUÍ\Y |‡ñ8'ËôØurîü·ŽpNdæÔ>èMþ,€#œ¸£’EG…ƒö>¾>ø»40º¹}ùÝVkūכgŒ1¢¬ ºeç±ã"…ÂuÊžAÇ)‡\A@‡!ètfûM?ð~ðöÛ¯ øœ-õ)þn{DÂÈܧq¯’h£ÍNšÌºÚ˜"Ž[€ðóÜàû ßw@(墤‹ãzDQ@«U£»t:3À^®×½?øÖ·ÿÓŸó9\Χ´ñ,„ymèfé9‡p1&Ž(%X™{í•òÆÖ:ÅúÚúßó|¹6¥Ä±O«å‘¦Ö:hch6§ëÓ¶÷ú”Û{dí=ÊÉPR¸ñhÜ»øó¦l´i{ž¿¬‹R¶®Õ ˆ"‡z½„=eŒ†Z=›ñ[úgO\øŸL¤`ï’-<ìè÷H:ÁÁ0S!jƒÁîv’f¯Y›çRªF-ˆŽç¹³$Çq$Z[¦Óœ^7EÁtjÿKw_ýí7_à“_æˆ5Gl:G_­k„A’Œ²nw÷ÅZ­5̲4¨Ç !”7•&<ÊPJ’eùµÁ`ðíWúÇÏò9^ŸEÜ+4ºŸç8"¬–Òu¬Eíïß|Ù÷ÃË£QoÖˆ[‘’κÂ8J cI'ãä•X#Ÿƒš‹ ³l„­ZÛµ”.Ž ¼,uª{Õÿ“EQ½=™Œ{ü°ÔÿC¯õ0Ÿ@Üç1Q-)…¬±ÖXmò|(®JY¬ÐZçö`|ÉøL.{Hñ^Naõ0æU:ÂÖØr÷?ñ´ì¸¿ä‘½‡%0 ç¾½GÆpîçì"uí@Fÿ |†€°èàÖ£`ŽØð£(j‹iè»QÔ¾ÀgȘ»ÄÿâˆÄ‘½Gžá0óÿ¹õþ/œ}‰Æ[g5IEND®B`‚pnmixer-0.7.2/data/pixmaps/pnmixer-off.png000066400000000000000000000365131311427610600205450ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aËbKGDÿÿÿ ½§“ pHYs  šœtIMEß €®ù© IDATxÚì½y¸åYYßûYÃoÚ󪪫ºªz¦¤`€&bÄ@ âÀÞ{róÄ„LFÉœ'¹O¸&7÷‰Þ+QAŒÃUP!Å8 tÓÐtUWuÍ㙇=üƵÖýcý~»v®ên•HuQ«ŸýœÓçœ]çì½¾ë¾ï÷}\_××õõµ»Äµú¾é~^üÖï¾Ó<ðŠw¾> ÅœsìÖZ”J!Æc¾†lüÑg>rä:®áõmßúÞœsÿŸµv¯sX¥ª „à|–¹#RŠŸø¯¿õ³¿ôµ u-¿¸w|çûúΙÿ`¬½ß§…Ò9z!\Wkq#pÏ]w¿\ÝzËK?ôèã×p-­{î~éOT•{³5.º½HôúíV€1k‘àn°Ž›ŠÜ·Ýö²/;þXy×ÀúŽ·¿÷ïWƽ¯ªlOÁü|B¿Ñj(%iµ5( ƒ’ìÖZÌ;Ç—w-¾êô™³_p_+Ð×Ú ú®wüµ¹,Ë¿§¬Üß«*ÓúýˆN7DJAU„…`ÐÀæFˆW…!ÿb×®â;³×-À pýàüõ]Ãáä»Á}ÈZ¢Ó ™›‘R ¤ÀÕg[)‚ Tyfn±xûí/ùì‘§-@^3&ÿÛßÛβô/ á~Ü«œƒ(ÒÌÍÇh-pÀx\°º2fiiÌÖVNY:%éu#âXB¸7†aðÚëà°^|×Ê•µ/¸÷ÿõ×[›«÷'Õ¿±– ­vÀÂBL*ò¼`<.Y_K"bks‹É¤¤(*ªÊÒj¡b2®pÎõ­ážÝú²O=}ô±Í븊WUî¸ÛÅ÷|ÏwßzüÄ“ÿ¨,Ë7"ívÀü|‚Rce ‹ówpó-/FX]»€5†,/©*K´ÛBB–œsmç¿ú/|ýCO<ñùêzx•®íOÙO}ÊÅ¿òËÿä]ÖñÖ:ÚI@§!¥ÃZÇþý7³k×}HÚ,-ŸáÉ'?1RJ„¤ËÊŠ ´;!£QI‘›ŽT¼§ªªŸŽ]®âµ¾ö»÷Ì͵ÿÆh8"ŠÝn@’HŠ¢äÕ¯ù Üÿƒ úû8{îŸþô¯’¦pàXc1¦d8³º2BJÁÜ\Œç¸ÉûÃßò¶ïo_ÀUºþûº+Dü¯Ïœ99WU9Ý^B»PU%<ð/½ïLÕá±Ç>Ëÿñc8Ú Nbt Gœ(Z­)-ëëÛdiI’h’–çt–—o3•™¿€«t¥©øñcÇŽ¼zié¼ìõz´ÛUU°ÿ­ì½á^¶7C}ôs<þØçØØ¸@¿ßEkIi:¤Žv' `}c z½!Öð"kø¾·}Ë×p•­O|üÉw¯,Ÿÿ¶3§OtÁÑïG8[ÒïÏñÀ¯Á¹Ÿ{èa}ô³,¯œ¦ÕjcŒ# $q¤Ð ª,A(‘R"äYJ‘WD¡"Ž5B ÂÐý¥0$¹€«hý—}öe£áðF£Ñ³çNE’8Q(­xík_C§³¥¥ <ùä#œ={)Z ¢PEŠ¢0T¥Ã9ÊÒÒëGHáX]b· BpO·§^wWÉ:yb©wÃÞÞ›ã¸uÿ±cOªÑh^¿‹swÝ}'Ýî~FÃ’§Ÿþ2GDA§Óîh¤„4-)+ƒ±g-a¤ˆ"I‘W”eEšfT•!‰5Z ÊÒîY]ÉÞö÷ÿª¸€¯ò:vt[¦iöúñH½ýÂ…ós§N% #âH0ôèuö¥mž:t”'Ÿ|„<Ón·hµ5ei)Kƒu¥ Š$sF£œ4-iµÂ¶‡)Aèàœ{á¿ö ?úc×ðU\O>zßá§¶Þ½¾>üºÕµs¬­¯ÐíFD±¦Ûpà¦ûXYYç‰/=ÄÒÒIâ¸8²ÌPUD‘BkIžòÜPQÿ—¦†ª*ÙÞÒnhµ"ï&„»CJû-ü±é®à«´~äoýû]çÏm}ëdR~þJz½ç /{ù+)r8tèK<ô”©]<ÆX¤()È3C–Œqı"%aÐj'ÌÍupÎW û½},îZÀÚgÁ¾é[¿íû|ë[ß'®à«°î¹÷žûâ8ù‘0 X^>ËÆæýAGÅ]wÝI¯»›sçVøâ£¿OUM‡V)¡ª,Eé} í¶ÆZ‡RŠV;¦Û‰"M¯—„{nèñõ_ÿúý¦²cï¶•ý+ŸøÄOºëøs^ùÙÏô’¤û¢c­E‘†‚~¿Ãââ^œëñðÿÇÖÖ:êÔÎÖZýƒ”’N'@*AYÊÒA“òaŒCkMY–t:>ø™_èSVyóý·¼ñþê+¯àÏyYÇ?±Ö=(„B!çÏŸ¢Ói·#:í.÷Ý÷J>ûÙ?ä豧Ȳ1³CJo Z-Ÿ V•«ã%½ÀZ8”Ò´Z-ž|ò Ýn‡×¼æâ8ÄZ‡Tîž^O^ÀŸçú¥_zø»t Þ%¥$Μ9Æúú>`{à•°ta›'‚ÍÍ%”„„á‚æÄ¬µH%0•!IZíð¿SkÍ©S§'<ðÀ+ˆO/ Bˆ·~ï{~hÿuü)Ö7ãÏÿ‰¨OþÆã÷h¥þNõA²²rŽ£GŸäÌÙãàž{îbß¾›ÉsÅ…¥“8çp‡„ø4¬µ ª 8‡”‚8‘;ÞÿsišrîÜ9n½õ&^úÒ;‘R┥yÃÆfúòëøS¬ã'ãyÿìO|è“­ÇÏÿÍ2wçY¬¯Ÿçô™ƒ¬­-! n¼ñ{öìcee™ªªpÖâ\ý0†}ò¥£qùCë+œ; ­K:”¥ÁTÆV8,IÒbkËpæÌ1²l‚”œ«MµCHQo²#Ë*ªÊÇÎAÓÍßyò1!XZZâóŸÿȉ‘RáœÅZ/ù#I ò¼òÕ¿ÊÖÄ$$A Pêò’È­V‹§žzŠ¢,8°ý^Ë«‰€ª2/QJF×ð^IühU–/Y__eéÂ)öíí†S›è¼(0ÖÐnwX[Ýࡇþ˜õõ¥úÙ§€>_#Ï Eaj³A pÎú.žTºò ‚€ƒòÔ¡ÃÜy×Ýôlý|¥ämƒApÿÎçÜñ¢ï×ð§ÍŽ-}S·¿©(òÞñO1?Òé„h-°Æ1ÜžEš(ÔLҔÇÏròäS”e.Zcg¡*­,„¡'Œqä…'ˆ´–qå½rÎ!¥ÄÃÓO?ÍÂÂýA§Bι}Å—lþmï:è\·šõÑŸûôþãÇWß4÷<ýô!ÂÐ1¿Ð&Ž5•± ‹†v;¤Óžgeeáh›(Jh¢3çð¾¥%‘oø˜¦}A J#„¼Äÿ_öÍ‘­5ðÈúú&wß}gÍ-ˆÚBˆ›gþ¯”îàS?í®àO¸þÝÿñ+É¡C'\Zš|×éÓǃÑh~?¢ÕVXë(‹’2/±ÆÇ!B8ªÒ¡u¥À˜rÆœ{9¸V¥ÎùÐ[‹1¾W@©ç~é @Nœ8ÅêÊ:wÜqq¬ñQ„¡xåüíiüèþ¨øØÇ>ö‚+]˜_ˆçî¾çž÷mn®Þ¸´|¥½^€TŠ<ÏÙÞÞf4ù ÐY‚ $ŒÎ;Í ¿‹^oc eYyÓÃïp®‚çÂP†ºNûÌsZ$‰Âñ‡øJS‹âŸæn;{vãÀ?øÁd•ðª@¿·ï­y6~ðä‰#TeÎÜ|BÒŠ¨JÃÖÖ«««lllúè>О—Nßór^ûÚ7rÛmû‰¢À“;ÖQU÷:R ´–T•«Í»ÀÚKóÿË-kÆ”<úØ# sܸ卵V»Ea_t= ø3¬‡:y[eÊï?~ò¨ކôz‹‹¾ckk‹ÑhÔ]äyE§†Ãá˜áhÈ›nçõ¯{¯}Ý_fÿM»hµBDíóñÏSRP–ÛüÿŽôo'´sµÛ-Fã-67ÇÌÍÏa]Ѹ¶Ò<øýï{§þšÀ+^þw¿¢)ÎÑ£K‘å›Îž=sóöÖ–Ôʱ°ØF)Ép8b<cŒ%Š"ÊÒ ¤EiAUUºCP³[Û{v½˜—½ô¹aïIKùÊŸñ¬¾2˜¥•'‰.“Ìav !ÙÞÚä©§¾ÄÞ½7 ÔÅ禩ùº¥³w¹k¯xÙß‘E¾õm&=wfãž/?qê­kk{ò|Ìâî6ívHQäL&Œ1„a€Ö>ðrÎ$eY1žŒév,,졪 ”Ž9pàn^üâ׳ç†Ý´ÚŠñ¤ 2ÆÏp ¤$NtmÂݳ;A µbyy™[n¹•N§=- Yãîé÷ÏÝuÍ`’.»0왯Ô/vΩ¥å­ÿi{{üÍk«çé÷æçZ„¡gü²,C1}h­ #T )C”ŒJ ¥DIIUt:n½ù^nÜ{'ý~ ИÊRäÖzØŸügV/c.¾Ü8ŽÙØØÄZWJM,ÁeU½þ… €çí»>õᯨ™{èsGïuÎýÍ¥¥Óh-™›kÑí…lo¦›?ë«1@IM–•´Z¶¶7Hƒ1qÔÂKžOèõxÙËßÈh²A–=Å$5€õ%a'(JKÙºô¹_’/'K¬µ,-ÃZC§Óbe9­E§cì׃Àç¹^÷ºû’ð~ìîõÉÿ}öì™…ÑhDœhcŒqL&)UU¡µ®[¸=´Ö8W«{UÈ$Í8sú(þ÷ÒÒ´BR”9­¤ÏKîûKܸï&ƒ¥Öâ‹AÎQçÏûonÜÁöö6ApË-7!¥§—P•îÞïxûûæ®à9Ö[ÞüÝÉî]÷¾«(:9|äØk––V8vïiš¢()Š­5J)/ì¬%;ÖZ”RuýÞÑëôÙØXáÈÓOpìÄãı#ŽÂPE7ì¹™]»n% ã)ë'¥# ½XÔý íYcVVV™››«c_wpÎÞva)‹Ÿíùoþ+ßÃ[ÞüW_¸.àϲÞþö÷Äηlmeÿ|42¯îv—÷-.ì£È't»­vä5åùtÓ›oLp­5X XÚígϞ೟ùmævs`ÿ­tº!£q…5 ÷¿äA6·Î1Æ9QÓÁŽ0¬êÊ¡›ÆÏgc8{ö,qä­JU5r3úí¶¾là÷ÿ³üÎï|ŠÏ~öK:á[ÞúzýˆŸû¹Ÿ¼ö-À{¾÷ûÂW=ðÎÞæfú÷¶·óÿטêÛpìë÷çX__ö5ýV@»¦ùt³Ó/„˜~Þ¬,ËèöDQ‹áp“nwÀ‰ÇùøÇ?ÂÆÆ9â8æ¦=‚ÐF-ì¿—VÒE¯þUJÖJ ;öŸO,àœ£( „ìÝ»¯>ù®ÎDÐíÊgBï}ï÷qîÜIvíZDˆ‹¿c<®®mðÝï|{ðÖ·¾«¿¹‘þÍÁ\ùëΚh­} ¢$!Ë&”eEG,.¶°ÖyM_MÒH)/qZë:"÷f7/Jâ$¦,KªªDé€óÎðÑý?lmŸáö;÷°°˜F-î¼ón@)¿EaPJ^R ¸\î¿s5±ÈÖÖ6 Dq0G´ËÒ^2IäïxB@UUÜpÃ^Â0ª -¨JwmºÁ;Ã7½ÉÍå©ûŽzœ^ž½ûº¸3)ÜÉÁ§~­GPOs3þýrØù½0 iµZdYN´Z“‰ñ~½²‹Zk»“Á̲Œªªð)!ø•jøCíýíVd¾©Õ’¿Ön©ïÕZÜ!ðbÌN' ‰¦²ûò8+qVGþB…ÖŽ,ËiµCZ­­ÕÔü7¹··sIéçý U³‚þ?ç [kýdm^sΜ>ÃÖæ*/ºu„¡Õ07ØÖ¢i¬ã‹>›‰Ì®Æ2u»]ʲðÿ„!R‰A’´¤”——ÛÛÛLÆ£)‰ž”zŽ˜óê´ïøŽ÷FnÜÛØý³2·¯uNÜÓ¼Ga¨‰c³c Æ:œõl™¯ÆZ­ÎI´†NGûI ¤TSŽ~6êo6g6´Ö07·›íá&eY ”F)/àôàñ›†!Gž Ý0?—€ ¸ù¦sæÌ¡º໌/Ø¥?û±ÉPÖ××±Ö2˜°²<òœ¢ï5¤éÄ΂©,K¤”,.îF)=µh6á}?ø~ò§þå ÷Ë¿òͯM¬ã‡×7&o÷ZSyÿé€v;$A¤X^b*[¿)^¢’²„Bi1%Zƒsrºé͉o éÓT/„~S´ÒäyF»QUk}å°(¼ËÁÖÖ¼sã9ÖÖVé÷÷`­$.žþ>Ë=ì¬Xk uìÐü­¾Æà¬ÛõŒ7W{w»]t ¦UÈæ÷Å À¼æU?é@¿á®{nûÀòÒ™W™4mYoÕ‰cÿ¢Zí€tR2I3Œñüh³©BÔAœÔôzLehµe=´ééo³ùãógÙ:¯ÿ‡µµóµ_•´ö¿O)U_E!'Ožfÿþ(VìÙ}½î>†£ÓÓÆÑÙŸýfÓÎæccöîÝ‹1ž¶ömh!DÏZ:çÊæß _Ê®ŒÁ¹ ­Æxu²ýéÕ9²>ø†ûÞµ¸ÐyCÊ–³D‘¦Û‰èÔíÕEaÈRÈÚ;_”VGa€ ðe]¥ÐÊwë4~}öä7$PcÒ4É (&8WR%éd\ŸD/×ZzšÎ)¥HÓ ç&,,&´Û]ö2/ÙØY¿¸—Z)%­–ï][[#Ðá%A£slAÑ<¿ ^³ÌÍ 0Æóu ¥@kqõà¯ýðD‡_ÌrcŠ¢ô9m¨h·4­v€1–ñ¸"Ë,Búq,Ê7iH!±Î$-’¸…1†8fšÒí|“gßø²,§4kŠ'ã!Rhí{¤òSÀ”’h ¥d<×'Ö°±±AXÒ,g÷îý(M£ñËmtÂYN¢ {½iš"gø çèúN\ćCz½aN§O%P\Ýø;?ò/B)ƒ—X£þ·2/Tã3»N7"Ë*¶· ²Ô·` f +ë $q!Uà#oé›5…ðAUóϾñÍçÆò<¿$ “R'1¦ªd<¡w ÍóÓ4Ń1–­-¯5œŸk³g÷~°UO¹´Ú·só~1ÀL&ºÝ.I’L©içpJ‰¹…$œj†ôû}ò¼@HG’\:¯`~nÏÕ €w¿ë_‹³ç¶÷Kþ#·y\´¤’¹a¸]NK¢ÓÓ‹@ …@ „¬•·†n»λ†$ ¦›µÓ7ÁSsŠgëñþ¤’ÄÐô(ÊÂo¾–ÓBR†õæP3w–,ˈcãSÔ¤7Õît=Íæ7­õÔ 4 ¤iJF„n²IQ¦Ud²šu-MðÚív™L&SÖÒ§’¯ÝW/~î£Çíßw㻥 Þ„¤yJkâ8@iYÏÔsx¾?í ºLO»$BhŸ®I‰¾)cg°µÓ 7]ºO”›¦ˆ£ñB*â¨u¾ ¸ª,Jiâ8&Žã)gŒa<ž°²²BA+i1¿°gÉÏovãw~Þ¸$­5½^,KkF±ÖÀÂdRêÆZ4ëx<ÆZK§Ûi~®–©Ãw~Ç›¯^üý¿÷^ÇÑ÷A€³)¼9WJ3Ud¹Ïõ…„0Ðt:1RI¤8ëOº@P•¾`Òn÷ë7PÔѰ¾I;£p)%EQeÙ”¬*[÷ößï„h€8'Ðuu/Â0$‚é ¬ªŠI:¡?ˆèt»ÜpÃ-u:Æeýþì¦Ïº¤v»=µ(ÍçKÎY›—;õ»ví¢2ÖRλGw•A—Èd¿ýí?œ=»ö–;ï¼¥¯”¦pR ’VDž•…E ÁÜB‡¹ù6Q¤ÒIÎ…ó› ‡9Îùiñþû¢f‚@!åÅ7x–èijiz1E* _8™L2”vT¦bqqç •´ƒx O y ’çùÔ ŒF۸ѧq¡N0ö¢ëšÝäÙS߸žF‰dŒ¡Ûíz …!Bªúmsa§ÓqÛÛÛS &„ ŽcȲ y^Ô®¯ÂÕA‹™››´÷Þ{û«â8š(«Š……Q1W!¹ù–EÜ´ÀÂB›8ÐJÒíÆì¹¡Kj廊uýQa*Cè)7[z=9Í)kT¹ÆTÖX¬¢SUQÔÆZÊ›Y@qMOñ,pþܲ|‚$qÒ¡*½ÀtvógÁ°“nÒ»­­-Z­–W"—Õôo#5–’`ößJ’„ X^^AI= <»zô’‹GMAðàƒÿþIþ%cœ““6BJt£uÈ7γ°Ð!Žƒºû†zS­VÌ®]-­À ”T$±Æš‹Ó;ÃÐwç6'~6ÊWJQ…O³ê“d­¥uc*?ô¹2IÒ" CL-Í*Ë­Õ%Á\–eXkSª2§ßKص¸ wÙìcÖüÏþmMp Ðëu;{ŠÜؤ˜ÈXXX$Ë2&Ÿ66à¿Z0Ð@Í@~æ3t³1J+¥Ecàºí„ù¹ÝÜ~û>vïé µÊl°Ô¤>ƒ· §]š©d]vºäš­Ç7ùVUU+Ö9Œ­ˆãR Ò,C’0RlnL(‹òϧƒJ)òb‚” uDÇ\MY1í=˜ Lw®&dÈ©é@ ‹[•ˆ¢ˆ ¦ÜEh¢(D)]Ç M,¯虇ì½/~å‹[­VošwG!:ÐìÝ7à¥÷ßÊÜÜ\-¨|¦tKJE’Ä,,¶Ñÿz– ·Ç¡@¬Ó4lv5‘¿o 3—höŠzcqXS!…,«²BJá™È<¥²Õ%©£s^j>OOÆõÈ [3…BŠg˜ûYw4›4Q}ôKÊÇŽ5c…˜U3µZ-ƒÛÛCÏ)4¾ß¹Jdaˆð³ïtJ°+9qòØjYf¶ Ôƒ.ýA‹ÅÅ6ZG úýþTW7›;K) ÂÁ CjŒqŒ†Y6¢,ŠšÿÓŠßN>MSŠ¢˜V›Ìó‚¢(êÚ‘¥CüiÓ”e…Rø–²ñdø5¥áÓ§OsþüY–—WI%h­.Q_©´³dÜn·1Æ0?¿p‰õäâBÛ6V¤ymþ°_Ôªc!¡ºJêÁHjDUUEŽýË¿òï£*«ëëVbÚ­¥.¦Cssst:©_œÎcN<¥{˰¶@¢ê)Ý >Í›ÛDÿMj5»‘EQbªÊ÷öc@*’V×·|Õ‘õxœ²¶¶1 þF£çÏŸcyy•µµu¶··˜Œsœ€8é<ãÄ_I´óïñ@¯«€õü!çèâ*ÕXµ†B’çy x;U"]- Z5)]úJ–È»½¶1¦L£¨ ƒ˜nW •—S7eQ­5ËËËSºvVb¥”`º¦ÁXÌIDAT0×beu BE‚¢È0¶GšY:]q‰Ô«9­Mñg6Çn‚Çñ$EHEUV8k˜ìñ¼¶Ž`<Q”Ãí!+++loo3g”eAQä(íÓ¢ÈPª £ËnþΖñf„l³Æã1•)§1Îdb7‡£L4¢–ªªH’„^¯Ë…¥1UŸ·‹õ€«I™RJ*%AHzý„Á\Àh4™N×rÎ1 PJqþüùiSÇLuŒV+&Ž4‹u–íá&­öÖˆi®>KN&Þ|7iÝl ÖOô.ɳœ¢°ŒÇÛˆZXá£qGY67·8sú yž3nc-¬­²äÂù Ü}§%CвÄf#Úíî3Nú¬¹‰KšºD§Ó¡( 666k=C“º¨ÕJ¨ªjª3ȲŒ(ŠÀù17ÖX7iUš¹:\@ h×@hýíí‘ÊòüŒÒ!J)æçÛAxINÜDþ½^Ðét.)ª!étb:¸.ÕJò|BU•T•—Ñ4ü}“úeY6ÝŒ‹îÁÖù³gü²<¥(s„dú7ɺõ«,K¶¶F¬­­³¶¶^—n·1¦@kjÓ,÷é¢ kWq1ãðÙF5ý¼,˺÷ šÆ"“É„ 8uêÔ,H‹,åÐæ¦S³¼F†DQã:/ kša–W ¨ê@0¯Ý·Æ{v §Â@D¡¦Ý¦›³'%ºÝ.Rʩɽ¸ívÄÚúˆ<· £Ñ&ãQŸ²L˜L|f ¥¨óu3u ­ƒ`2)¦3ýË2ÇTRv﹑@EåA€`•>ò KÊê¢HÓŸJAYU ¨{ ”¯¢9KUMhwºÄQ‹,3µ´Œ©rxDƬ-ÈR‡5’0P |—µ†²,¦©ã,ÿ°34ÆÐëõYYYa<žøª§€$Qzƒpš"|èCšÖ ¢(˜Ò©ªSÆÆj^-˜¥„ ât2>«µvRFlnæ8ç5w>¨QÏÐÑͦRMMÞ+jÝn‚RÊפ$Ë& ‡)BH´öš¾ñ¸`k+©ý{ªÙÕD’’Í€g?78ÏK‚ ¤ßŸççÿ•…ÁÍÈÑ}cJ]ÉL‚ "Ë Òt½¾+È6Y–Q–å%=ûhü¿1†sçβ¾¾A«uQ”ç6?tpxföý…_ø>ð µæu¯{4Kùßü9>þ‰Ÿ%Me^5.ÀÕ˜}èG¾øé³ýå‡ï¸í5¯ +”Vá+\Í›µS;?+…j@àý Æ9HÓŠ0h0¡½Õ"Œšy}¾[fÀ׿óÓt1ËŒrY+ý¡£Çíü 9˜Í!wÎQß ˆú ’¦,óüÌÙ“â‹_ü£µÏþ÷>sèìÉ“'ÏŸ;»äò¿°çÀ·½dßöpÓ-.ì^(˰ì÷„ž£¬2¶X][b4Ü`eõ£Ñˆª:Á®]7"‹€4-0F ‹++#²´¬7ÈC`8œPVa(¦G–N¸ù¦»Øwã>º=ÉÚJÉ©ÓÉóI=¯Ïß^ä„aÓ—p±e«Q# aÑÚw7w50¸®±WÁ˜?#ì̆›š¸œ%°3²Ö uº¸×97ܹs'Î'þÒ“ýþBßáò[o¾}0˜[pûöÞô¢Ûn»oW·×¿kqao{~~npã¾[âÍÍ#„T'O¡( Æ£mÂ0¢(2òÜŸæv;ÁËÆÆ„4-ë–ÑhÂd’Ñëv £çö€ýûoe~¾EQ8–WVX]]ñSEâ)}ÛzYâXÕsû\-G»¸ÁÓVn§(+G5 ªu¨äçk_è˜=éæ V €©­@ tfˆ£X¬KÉsUÙÚZÛÌc?´ ¤RÊ'¬µùwÝ»¸½µnï¿ÿ5û£°-¸õ®……½­8n½d~°«5noK!Õ‚µ&)‹’ÑØŸÄNÇ÷ä—…Á:‡r‹—}w»âXE1v›oº™n/f{;cii“óçO´|ÈKUYÚõŒ£æ6Ñ `ÇôP‡©U)›Y€žº6M¥ÐMN<ýÕµ€ ˜Ýx·Ã˜%^QœÏGI ‚Fb–×Ï e­-€øðS_ÞÜ… ¿r °J©ß1Æä·ßv_÷Øñ§Ì«ÿÂë;qÔn¿íÅÿ\ëèþ(ŠØX÷ìâb—ªt¬¬ ‘Ò[mö훧׋X[ÕAÈî=]’DqúÄ“'Jµ²Ø’´tÝQL­÷“T•¦„à(J‹@„qsqMJI)Ç8ù»¼À×NaÚ΢‚ùh.ã šGU³ˆ B*¥Â\®¬Ÿkf² =CBEÎ9ÄëËCçl~æôñ3'Na Y]²=œÐïïa<óðç?µŽV;"ŠZK²¬ªkþOÉsƒ¾cÉ‹U Iâ•MZ'u€)H³ŠtR )Å…á®uðÐW×:Üeb³#{˜µP:gF[ÌÈ]&«à2›–e9Ìóì±^onW„÷‡adY!ò¼¤ÛF£ ‡W‚t»m:í„,3,]¸€@°µ½Æ… gÐZÒíE¨º¯ QW•£( Q¤ê©ßŽtRÒéH ÆH´jÑíz 0™TŒÇ¥‰cýé~_ò‹~îk—‹ vZs`ØçÕN÷3 ޏ(rsòäáÏÜ|óa’´p8U%yfˆM %Y^R%Öž=}ßB–Võ}¿kln®F!Ž'¢š4°,M=“X¡µ¢È-ÆØz–¨Á¡¸á†9’ÄÇ £QIQ âß}ìþÓ#×Z ðl °W /g ìx.“^^n‰ôô‘#O<´gÏþñü`×_´Îʪ*±t ˆ#EQTTÆ2t Íd\2™ ™¤£é¥<߆’¼0Ó2pøò²»©%IÒaa¾3}îp+ÇZwz~!ùè£>rìk;D{™€p'8¸ÂGñ›ïvüÎæçӳ王¢„^oîn‡=}¬ˆb?*vÂ5²äWÐäï,52󴦈Sž©@n”Ç—–¤gÁ²S£Øè¶·7í“¿ðŸ²lòÉÊFJ|ÓFi(Ê’áö„0RtÚm⸳~Ó•’õÀIG /L)½Ô,N²ÜJð#^ü[”Öº ‹ñ']sõÇõày“FÆ5º¾Úà¹N¹{†Ð=Gzè%EÐŽ6ŽÅQï°µ$J2†Ñ‚©üغÁ ¦ÝÖt:~xãhX0Ü.0Æš4å¯ÿê¯ýÔ‘ëø·vÒ»Wb /ç:ÄóÉüÜ@ÑÚÚZ¾åÅ#Ε¥”ª×ŠÛûÊÒ‰4+ë†ÇdR²±ž×÷»¯¯©_¾°ôØÖuüù/{…½RÊÈ•?:Î !ã,ëëËŸiµÛE‘Çno¯*½É ”’Eyzkkëç?ÿ…_ü]®áu5àÙ´<ϯ_ÁE8#e C­­{(Š’ãÃáFÚëÚJê=B«•Ö‘GÙÃeùÿ·w5+ Ã@x&©? \Å·ð¤WÁ7óE|‹}a{]OŠˆæPcf<˜B6›´Þ6ÖzhË@>&_¾ùi±þÙ}M&ìSIæ|òWveν›*5Ý4³A”e}¡µÚåùG®”/æ«åíVäÓéd¶?޽Þp³Ý~~Aà ÷Ë•{ý¹E>$üo¨bF†ÇÀ#D2Ùï^õyoŸ=Ùï\ƒáH©ËÞÀä ùâøä6aMDLÌĆ´v€Ò(%£1Fsùû’IZ,—PE íE‘íÿfbÛû ÕŪ-þI<âšH@Þ¾Ï5Š¡óüÍSˆi!4¾Æ× (²à±5_†®*QkP4 Šó?F„#®ÑB῱\àãÖo>ˆhdIEND®B`‚pnmixer-0.7.2/data/ui/000077500000000000000000000000001311427610600145315ustar00rootroot00000000000000pnmixer-0.7.2/data/ui/CMakeLists.txt000066400000000000000000000005401311427610600172700ustar00rootroot00000000000000if(WITH_GTK3) file(GLOB ui_files *-gtk3.glade) else(WITH_GTK3) file(GLOB ui_files *-gtk2.glade) endif(WITH_GTK3) install(FILES ${ui_files} DESTINATION "${CMAKE_INSTALL_DATADIR}/${PACKAGE}/ui") ## make running 'src/pnmixer' from the build directory work ## since pnmixer looks up ui files from a relative path symlink_to_binary_dir("${ui_files}") pnmixer-0.7.2/data/ui/hotkey-dialog-gtk2.glade000066400000000000000000000154471311427610600211470ustar00rootroot00000000000000 300 200 False 5 Set HotKey True True input-keyboard dialog True False 2 True False True False 10 57 input-keyboard 3 False False 0 True False True False Defining HotKey True True 0 True False 0.10000000149011612 (press <Ctrl>C to reset) True True 1 True True 1 False True 0 True False False True 1 True False 0.89999997615814209 Press new HotKey for xxx True True True 2 True False end gtk-cancel True True True True False False 0 False True end 3 True False 0.10000000149011612 True True 4 button1 pnmixer-0.7.2/data/ui/hotkey-dialog-gtk3.glade000066400000000000000000000203541311427610600211410ustar00rootroot00000000000000 300 200 False 5 Set xxx HotKey True True input-keyboard dialog True False 2 True False end False True True True True False center True False gtk-cancel False True 0 True False 5 Cancel False True 1 False False 0 False True end 3 True False True False 10 10 57 input-keyboard 3 False False 0 True False vertical True False Defining HotKey True True 0 True False (press <Ctrl>C to reset) True True 1 True True 1 False True 0 True False False True 1 True False Press new HotKey for xxx True True True 2 True False True True 4 button1 pnmixer-0.7.2/data/ui/popup-menu-gtk2.glade000066400000000000000000000153221311427610600205040ustar00rootroot00000000000000 True False gtk-execute 1 True False 2 gtk-refresh 1 popup 285 82 False False mouse utility True True False False False True False _Popup True True False _Mute False True False Mute/Unmute Volume True _Volume Control False True False Open Volume Control True mixer_image False gtk-preferences False True False Preferences True True _Reload Sound False True False Reload Sound True reload_image False gtk-about False True False About True True False True False gtk-quit False True False Quit True True pnmixer-0.7.2/data/ui/popup-menu-gtk3.glade000066400000000000000000000340631311427610600205100ustar00rootroot00000000000000 False popup False mouse utility True True False False False True False _Popup True True False False True False Mute/Unmute Volume True False False True True False center True 0 True False 4 8 Mute 1 False True False Open Volume Control True False True False system-run 0 True False 4 8 Volume Control 1 False True False Preferences True False True False preferences-system 1 0 True False 4 8 Preferences 1 False True False Reload Sound True False True False view-refresh 1 0 True False 4 8 Reload Sound 1 False True False About True False True False help-about 1 0 True False 4 8 About 1 False True False False True False Quit True False True False application-exit 1 0 True False 4 8 Quit 1 pnmixer-0.7.2/data/ui/popup-window-horizontal-gtk2.glade000066400000000000000000000107751311427610600232450ustar00rootroot00000000000000 100 1 10 popup False False mouse utility True True False True False 8 8 8 8 True False 5 True True vol_scale_adj 0 200 True True 0 True False Mute False True True False True True True 0 Mixer False True True True False False 1 False False 1 pnmixer-0.7.2/data/ui/popup-window-horizontal-gtk3.glade000066400000000000000000000111301311427610600232300ustar00rootroot00000000000000 100 1 10 False popup False mouse utility True True False True False 8 8 8 8 vertical 12 200 True True vol_scale_adj 0 0 True True 0 True False Mute False True True False True False False 0 True False True True 1 Mixer False True True True False False 2 False False 1 pnmixer-0.7.2/data/ui/popup-window-vertical-gtk2.glade000066400000000000000000000111711311427610600226540ustar00rootroot00000000000000 100 1 10 popup False False mouse utility True True False True False 8 8 8 8 True False 5 True True vertical vol_scale_adj True 0 200 True True 0 True False Mute False True True False True True True 0 Mixer False True True True False False 1 False False 1 pnmixer-0.7.2/data/ui/popup-window-vertical-gtk3.glade000066400000000000000000000105761311427610600226650ustar00rootroot00000000000000 100 1 10 False popup False mouse utility True True False True False 8 8 8 8 vertical 12 200 True True vertical vol_scale_adj True 0 0 True True 0 True False vertical 4 Mute False True True False True False False 0 Mixer False True True True False False 1 False False 1 pnmixer-0.7.2/data/ui/prefs-dialog-gtk2.glade000066400000000000000000002122211311427610600207500ustar00rootroot00000000000000 True False True False Notification support disabled at compile time. center 1000000000 100 10 True False True False 0 none True False 12 True False 3 Enable Notifications True True False True True True 8 0 True False True False Timeout (ms): False True 5 0 True True â— False False True True noti_timeout_adjustment True True 1 True True 1 True False 0 Notify for volume changes from: True True 2 2 True False 10 HotKeys True True False True True True 3 True False 10 Mouse Scroll True True False True True True 4 True False 10 Adjustment in Popups True True False True True True 5 True False 10 External Change True True False True True True 6 True False <b>Notification Options</b> True False False 5 0 100 1 10 100 1 10 100 10 10 False dialog PNMixer Preferences False preferences-system True False 2 True False 10 end gtk-cancel True True True True False False 0 gtk-ok True True True True False False 1 gtk-apply True True True True False False 2 False True 0 True True False 5 True False True False 0 none True False 12 True False 3 2 5 15 True False 0.079999998211860657 Card: GTK_EXPAND True False 0.079999998211860657 Channel: 1 2 GTK_EXPAND True False 0 1 2 GTK_EXPAND True False 0 1 2 1 2 GTK_FILL GTK_EXPAND True True False 0 True 1 2 2 3 True False 0.15999999642372131 Normalize Volume: Change volume on a logarithmic scale, closer to human perception. 2 3 GTK_EXPAND True False <b>Sound Device</b> True False False 5 0 True False Device False True False True False 0 none True False 10 12 True False 3 2 15 True False 0.079999998211860657 Slider Orientation: GTK_EXPAND True False 0 Vertical Horizontal 1 2 GTK_EXPAND Display Text Volume True True False True 2 1 2 GTK_EXPAND True False 0.079999998211860657 Text Volume Position: 2 3 GTK_EXPAND True False 0 Top Bottom Left Right 1 2 2 3 GTK_EXPAND True False <b>Volume Popup</b> True True True 5 0 True False 0 none True False 10 12 True False 3 2 15 Draw Volume Meter on Tray Icon True True False True 2 GTK_EXPAND True False 0.079999998211860657 Volume Meter Offset (%): 1 2 GTK_EXPAND True False 0.079999998211860657 Volume Meter Color: 2 3 GTK_EXPAND True True • True False False True True vol_meter_pos_adjustment 0.050000000000000003 True 1 2 1 2 GTK_EXPAND True True True #000000000000 1 2 2 3 GTK_EXPAND True False <b>Volume Meter</b> True True True 9 1 True False 0 none True False 5 5 12 Use System Theme True True False True True False <b>Icon Theme</b> True True True 2 1 True False View 1 False True False True False 0 none True False 10 12 True True • False False True True True False <b>Volume Control Command</b> True False False 5 0 True False 0 none True False 12 True False 2 2 5 15 True False 0.079999998211860657 Scroll Step: GTK_EXPAND True False 0.079999998211860657 Fine Scroll Step: 1 2 GTK_EXPAND True True 2 True • False False True True scroll_step_adjustment 1 2 GTK_EXPAND True True 2 True • False False True True fine_scroll_step_adjustment 1 2 1 2 GTK_EXPAND True False <b>Volume Scrolling</b> True False False 5 1 True False 0 none True False 12 True False 2 2 5 15 True False 0.079999998211860657 Middle Click Action: GTK_EXPAND True False 0.079999998211860657 Custom Command: 1 2 GTK_EXPAND True False Mute/Unmute Show Preferences Volume Control Custom (set below) 1 2 GTK_EXPAND True True • False False True True 1 2 1 2 GTK_EXPAND True False <b>Mouse</b> True False False 5 2 2 True False Behavior 2 False True False True False 0 none True False 8 12 True False 20 Enable HotKeys True True False True False False 5 0 True False 5 2 5 15 True False 0.079999998211860657 Mute/Unmute: 1 2 True False 0.079999998211860657 Volume Up: 2 3 True False 0.079999998211860657 Volume Down: 3 4 True False Double-click a HotKey to assign a new HotKey 2 4 5 True False Command True False HotKey 1 2 True False True False (None) 1 2 1 2 True False True False (None) 1 2 2 3 True False True False (None) 1 2 3 4 False False 5 1 True False <b>HotKey Settings</b> True False False 5 0 3 True False HotKeys 3 False True True 5 1 ok_button cancel_button apply_button pnmixer-0.7.2/data/ui/prefs-dialog-gtk3.glade000066400000000000000000002052471311427610600207630ustar00rootroot00000000000000 100 1 10 1000000000 100 10 True False start 5 5 5 5 vertical True False 0 none True False 12 6 12 True True False start Timeout (ms): 0 1 True True False False noti_timeout_adjustment 1 1 Enable Notifications False True True False start True 0 0 True False 5 <b>Notification Options</b> True False False 5 0 True False 0 none True False 12 vertical 3 HotKeys False True True False start True True True 0 Mouse Scroll False True True False start True True True 1 Adjustment in Popups False True True False start True True True 2 External Change False True True False start True True True 3 True False 5 <b>Notify for volume changes from:</b> True False False 5 1 True False start 5 5 5 5 vertical True False center Notification support disabled at compile time. False True 0 100 1 10 100 10 10 False PNMixer Preferences False preferences-system dialog True False vertical 2 True False end False True True True True False center True False gtk-cancel False True 0 True False 5 Cancel False True 1 False False 0 False True True True True False center True False gtk-ok False True 0 True False 5 Ok False True 1 True True 1 False True True True True False center True False gtk-apply False True 0 True False 5 Apply False True 1 True True 2 False True 1 True True False True False start 5 5 5 5 vertical True False 0 none True False 12 6 12 True True False start Card: 0 0 True False start Channel: 0 1 True False Change volume on a logarithmic scale, closer to human perception. start Normalize Volume: 0 2 True False 1 0 True False 1 1 True True False True 1 2 True False 5 <b>Sound Device</b> True False False 5 0 True False Device False True False start 5 5 5 5 vertical True False 0 none True False 12 6 12 True True False start Slider Orientation: 0 0 True False start Text Volume Position: 0 2 Display Text Volume False True True False start True 0 1 True False 0 Vertical Horizontal 1 0 True False 0 Top Bottom Left Right 1 2 True False 5 <b>Volume Popup</b> True False False 5 0 True False 0 none True False 12 6 12 True True False start Volume Meter Color: 0 2 True False start Volume Meter Offset (%): 0 1 False True True True rgb(0,0,0) 1 2 True True • False False vol_meter_pos_adjustment 0.050000000000000003 True 1 1 Draw Volume Meter on Tray Icon False True True False start True 0 0 2 True False 5 <b>Volume Meter</b> True False False 5 1 True False 0 none Use System Theme False True True False start 12 True True False 5 <b>Icon Theme</b> True False False 5 2 1 True False View 1 False True False start 5 5 5 5 vertical True False 0 none True True 12 • False False True False 5 <b>Volume Control Command</b> True False False 5 0 True False 0 none True False 12 6 12 True True False start Scroll Step: 0 0 True False start Fine Scroll Step: 0 1 True True • False False scroll_step_adjustment 2 True 1 0 True True • False False fine_scroll_step_adjustment 2 True 1 1 True False 5 <b>Volume Scrolling</b> True False False 5 1 True False 0 none True False 12 6 12 True True False start Custom Command: 0 1 True False start Middle Click Action: 0 0 True False Mute/Unmute Show Preferences Volume Control Custom (set below) 1 0 True True • False False 1 1 True False 5 <b>Mouse</b> True False False 5 2 2 True False Behavior 2 False True False start 5 5 5 5 vertical True False 0 none True False 12 vertical Enable HotKeys False True True False start True False False 5 0 True False 12 12 True True False start Command 0 0 True False start Mute/Unmute: 0 1 True False start Volume Up: 0 2 True False start Volume Down: 0 3 True False HotKey 1 0 True False True False (None) 1 1 True False True False (None) 1 2 True False True False (None) 1 3 True False Double-click a HotKey to assign a new HotKey 0 4 2 False True 1 True False 5 <b>HotKey Settings</b> True False False 5 0 3 True False HotKeys 3 False True True 5 1 cancel_button ok_button apply_button pnmixer-0.7.2/po/000077500000000000000000000000001311427610600136215ustar00rootroot00000000000000pnmixer-0.7.2/po/CMakeLists.txt000066400000000000000000000035741311427610600163720ustar00rootroot00000000000000## languages file(STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/LINGUAS gettext_languages REGEX "^[^#].*") ## 'update_pot' target add_custom_target( update-pot COMMAND ${XGETTEXT_EXECUTABLE} -o ${PACKAGE}.pot -p "${CMAKE_CURRENT_SOURCE_DIR}" --default-domain=pnmixer --directory="${CMAKE_SOURCE_DIR}" --add-comments=TRANSLATORS: --from-code=UTF-8 --keyword=_ --files-from="${CMAKE_SOURCE_DIR}/po/POTFILES.in" --copyright-holder='Copyright (C) 2010-2017 Nick Lanham' --package-name="${PACKAGE}" --package-version="${PACKAGE_VERSION}" --msgid-bugs-address="https://github.com/nicklan/pnmixer/issues" DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${PACKAGE}.pot" ) ## 'update_po' target set(po_targets) foreach(lang ${gettext_languages}) add_custom_target( update_po_${lang} COMMAND ${GETTEXT_MSGMERGE_EXECUTABLE} --lang=${lang} "${CMAKE_CURRENT_SOURCE_DIR}/${lang}.po" "${CMAKE_CURRENT_SOURCE_DIR}/${PACKAGE}.pot" -o "${CMAKE_CURRENT_SOURCE_DIR}/${lang}.new.po" COMMAND mv -f "${CMAKE_CURRENT_SOURCE_DIR}/${lang}.new.po" "${CMAKE_CURRENT_SOURCE_DIR}/${lang}.po" DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${lang}.po" "${CMAKE_CURRENT_SOURCE_DIR}/${PACKAGE}.pot" ) LIST(APPEND po_targets update_po_${lang}) endforeach() add_custom_target(update-po DEPENDS ${po_targets}) ## 'pnmixer-translations' target (part of default target) set(mo_files) foreach(lang ${gettext_languages}) add_custom_command(OUTPUT ${lang}.gmo COMMAND ${GETTEXT_MSGFMT_EXECUTABLE} -c --directory="${CMAKE_SOURCE_DIR}" -o "${lang}.gmo" "${CMAKE_CURRENT_SOURCE_DIR}/${lang}.po" DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${lang}.po") install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${lang}.gmo" DESTINATION "${CMAKE_INSTALL_FULL_LOCALEDIR}/${lang}/LC_MESSAGES" RENAME "${PACKAGE}.mo") LIST(APPEND mo_files ${lang}.gmo) endforeach() add_custom_target(pnmixer-translations ALL DEPENDS ${mo_files}) pnmixer-0.7.2/po/LINGUAS000066400000000000000000000000411311427610600146410ustar00rootroot00000000000000de fr hr it nl ru sr uk vi zh_CN pnmixer-0.7.2/po/POTFILES.in000066400000000000000000000012451311427610600154000ustar00rootroot00000000000000# List of source files containing translatable strings. src/alsa.c src/audio.c src/hotkey.c src/hotkeys.c src/main.c src/notif.c src/prefs.c src/support-ui.c src/ui-about-dialog.c src/ui-hotkey-dialog.c src/ui-popup-menu.c src/ui-popup-window.c src/ui-prefs-dialog.c src/ui-tray-icon.c data/desktop/pnmixer.desktop.in data/ui/hotkey-dialog-gtk3.glade data/ui/popup-menu-gtk3.glade data/ui/popup-window-horizontal-gtk3.glade data/ui/popup-window-vertical-gtk3.glade data/ui/prefs-dialog-gtk3.glade data/ui/hotkey-dialog-gtk2.glade data/ui/popup-menu-gtk2.glade data/ui/popup-window-horizontal-gtk2.glade data/ui/popup-window-vertical-gtk2.glade data/ui/prefs-dialog-gtk2.glade pnmixer-0.7.2/po/de.po000066400000000000000000000362041311427610600145560ustar00rootroot00000000000000# German translation for pnmixer. # Copyright (C) 2016 PNMixer team (msgids) # This file is distributed under the same license as the pnmixer package. # # Mario Blättermann , 2011, 2015-2017. msgid "" msgstr "" "Project-Id-Version: pnmixer 0.7.1-rc3\n" "Report-Msgid-Bugs-To: https://github.com/nicklan/pnmixer/issues\n" "POT-Creation-Date: 2017-03-13 21:25+0700\n" "PO-Revision-Date: 2017-03-13 21:07+0100\n" "Last-Translator: Mario Blättermann \n" "Language-Team: German \n" "Language: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Bugs: Report translation errors to the Language-Team address.\n" "X-Generator: Poedit 1.8.12\n" #: src/hotkeys.c:175 msgid "Could not grab the following HotKeys" msgstr "Folgende Tastenkürzel konnten nicht belegt werden" #: src/hotkeys.c:176 src/ui-prefs-dialog.c:339 #: data/ui/prefs-dialog-gtk3.glade:973 data/ui/prefs-dialog-gtk2.glade:935 msgid "Mute/Unmute" msgstr "Stumm (ein/aus)" #: src/hotkeys.c:178 src/ui-prefs-dialog.c:342 msgid "Volume Up" msgstr "Lauter" #: src/hotkeys.c:180 src/ui-prefs-dialog.c:345 msgid "Volume Down" msgstr "Leiser" #: src/main.c:69 #, c-format msgid "Unable to run command: %s" msgstr "Befehl %s konnte nicht ausgeführt werden" #: src/main.c:89 msgid "No mixer application was found on your system. Please open preferences and set the command you want to run for volume control." msgstr "Es konnte keine Mixer-Anwendung auf Ihrem Computer gefunden werden. Bitte öffnen Sie Einstellungen und wählen Sie den Befehl für die Lautstärkeregelung." #: src/main.c:109 msgid "You have not specified a custom command to run, please specify one in preferences." msgstr "Sie haben keinen benutzerdefinierten Befehl zur Ausführung angegeben, bitte tun Sie dies in den Einstellungen." #: src/main.c:210 src/main.c:248 msgid "PNMixer Error" msgstr "PNMixer-Fehler" #: src/main.c:239 msgid "Warning: Connection to sound system failed." msgstr "Achtung: Verbindung zum Soundsystem konnte nicht hergestellt werden." #: src/main.c:243 msgid "" "Do you want to re-initialize the audio connection ?\n" "\n" "If you do not, you will either need to restart PNMixer or select the 'Reload Audio' option in the right-click menu in order for PNMixer to function." msgstr "" "Möchten Sie die Audio-Verbindung wieder aufbauen?\n" "\n" "Wenn nicht, müssen Sie entweder PNMixer neustarten oder die Option »Audio neuladen« im Kontextmenü auswählen, damit PNMixer funktioniert." #: src/main.c:334 msgid "- A mixer for the system tray." msgstr "- Ein Mixer für das Benachrichtigungsfeld." #: src/main.c:342 #, c-format msgid "%s version: %s\n" msgstr "%s Version: %s\n" #: src/notif.c:77 msgid "Volume muted" msgstr "Stumm geschaltet" #: src/notif.c:82 src/ui-tray-icon.c:355 msgid "Volume" msgstr "Lautstärke" #: src/notif.c:135 msgid "No sound card" msgstr "Keine Soundkarte" #: src/notif.c:136 msgid "No playable soundcard found" msgstr "Keine nutzbare Soundkarte gefunden" #: src/notif.c:141 msgid "Soundcard disconnected" msgstr "Soundkarte entfernt" #: src/notif.c:142 msgid "Soundcard has been disconnected, reloading sound system..." msgstr "Die Soundkarte wurde entfernt, Soundsystem wird neu geladen …" #: src/prefs.c:356 #, c-format msgid "Couldn't load preferences file: %s" msgstr "Einstellungsdatei konnte nicht geladen werden: %s" #: src/prefs.c:365 #, c-format msgid "Couldn't load default preferences: %s" msgstr "Standardeinstellungen konnten nicht geladen werden: %s" #: src/prefs.c:391 #, c-format msgid "Couldn't write preferences file: %s" msgstr "Die Einstellungsdatei konnte nicht geschrieben werden: %s" #: src/prefs.c:411 #, c-format msgid "'%s' exists but is not a directory, won't be able to save preferences." msgstr "»%s« existiert, aber ist kein Ordner. Einstellungen können nicht gespeichert werden." #: src/prefs.c:415 #, c-format msgid "Couldn't make preferences directory: %s" msgstr "Ordner für Einstellungen konnte nicht angelegt werden: %s" #: src/ui-about-dialog.c:114 msgid "A mixer for the system tray" msgstr "Ein Mixer für das Benachrichtigungsfeld" #: src/ui-about-dialog.c:115 msgid "Copyright © 2010-2016 Nick Lanham" msgstr "Copyright © 2010-2016 Nick Lanham" #: src/ui-hotkey-dialog.c:48 #, c-format msgid "Set %s HotKey" msgstr "Tastenkürzel %s festlegen" #: src/ui-hotkey-dialog.c:52 #, c-format msgid "Press new HotKey for %s" msgstr "Neues Tastenkürzel drücken für %s" #: src/ui-hotkey-dialog.c:174 msgid "Could not grab the keyboard." msgstr "Zugriff auf die Tastatur nicht möglich." #: src/ui-popup-menu.c:57 src/ui-popup-menu.c:84 src/ui-popup-window.c:129 msgid "Soundcard has no mute switch" msgstr "Die Soundkarte verfügt nicht über eine Stummschaltung" #: src/ui-prefs-dialog.c:373 msgid "None" msgstr "Keine" #: src/ui-prefs-dialog.c:867 msgid "Notifications" msgstr "Benachrichtigungen" #: src/ui-tray-icon.c:357 msgid "No mute switch" msgstr "Kein Stummschalter" #: src/ui-tray-icon.c:359 msgid "Muted" msgstr "Stumm" #: data/desktop/pnmixer.desktop.in:3 msgid "PNMixer" msgstr "PNMixer" #: data/desktop/pnmixer.desktop.in:4 msgid "System Tray Mixer" msgstr "Benachrichtigungsfeld Mixer" #: data/desktop/pnmixer.desktop.in:5 msgid "An audio mixer for the system tray" msgstr "Ein Audiomixer für das Benachrichtigungsfeld" #. TRANSLATORS: Search terms to find this application. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! #: data/desktop/pnmixer.desktop.in:7 msgid "alsa;audio;mixer;sound;" msgstr "Alsa;Audio;Mixer;Sound;Klang;Ton;" #. TRANSLATORS: Do NOT translate or transliterate this text (this is an icon file name)! #: data/desktop/pnmixer.desktop.in:11 msgid "pnmixer" msgstr "pnmixer" #: data/ui/hotkey-dialog-gtk3.glade:55 data/ui/prefs-dialog-gtk3.glade:279 msgid "Cancel" msgstr "Abbrechen" #: data/ui/hotkey-dialog-gtk3.glade:109 data/ui/hotkey-dialog-gtk2.glade:49 msgid "Defining HotKey" msgstr "Tastenkürzel wird festgelegt" #: data/ui/hotkey-dialog-gtk3.glade:124 data/ui/hotkey-dialog-gtk2.glade:65 msgid "(press C to reset)" msgstr "(Strg+C zum Zurücksetzen)" #: data/ui/popup-menu-gtk3.glade:33 data/ui/popup-menu-gtk2.glade:49 msgid "Mute/Unmute Volume" msgstr "Stumm (ein/aus)" #: data/ui/popup-menu-gtk3.glade:58 #: data/ui/popup-window-horizontal-gtk3.glade:54 #: data/ui/popup-window-vertical-gtk3.glade:58 #: data/ui/popup-window-horizontal-gtk2.glade:56 #: data/ui/popup-window-vertical-gtk2.glade:58 msgid "Mute" msgstr "Stumm" #: data/ui/popup-menu-gtk3.glade:73 data/ui/popup-menu-gtk2.glade:60 msgid "Open Volume Control" msgstr "Lautstärkeregler öffnen" #: data/ui/popup-menu-gtk3.glade:95 data/ui/prefs-dialog-gtk3.glade:975 #: data/ui/prefs-dialog-gtk2.glade:937 msgid "Volume Control" msgstr "Lautstärkeregler" #: data/ui/popup-menu-gtk3.glade:110 data/ui/popup-menu-gtk3.glade:133 #: data/ui/popup-menu-gtk2.glade:73 msgid "Preferences" msgstr "Einstellungen" #: data/ui/popup-menu-gtk3.glade:148 data/ui/popup-menu-gtk3.glade:171 #: data/ui/popup-menu-gtk2.glade:85 msgid "Reload Sound" msgstr "Sound neu laden" #: data/ui/popup-menu-gtk3.glade:186 data/ui/popup-menu-gtk3.glade:209 #: data/ui/popup-menu-gtk2.glade:98 msgid "About" msgstr "Info" #: data/ui/popup-menu-gtk3.glade:231 data/ui/popup-menu-gtk3.glade:254 #: data/ui/popup-menu-gtk2.glade:117 msgid "Quit" msgstr "Beenden" #: data/ui/popup-window-horizontal-gtk3.glade:81 #: data/ui/popup-window-vertical-gtk3.glade:74 #: data/ui/popup-window-horizontal-gtk2.glade:72 #: data/ui/popup-window-vertical-gtk2.glade:74 msgid "Mixer" msgstr "Mixer" #: data/ui/prefs-dialog-gtk3.glade:43 data/ui/prefs-dialog-gtk2.glade:68 msgid "Timeout (ms):" msgstr "Timeout (ms):" #: data/ui/prefs-dialog-gtk3.glade:65 data/ui/prefs-dialog-gtk2.glade:46 msgid "Enable Notifications" msgstr "Benachrichtigungen aktivieren" #: data/ui/prefs-dialog-gtk3.glade:89 data/ui/prefs-dialog-gtk2.glade:210 msgid "Notification Options" msgstr "Benachrichtigungsptionen" #: data/ui/prefs-dialog-gtk3.glade:116 data/ui/prefs-dialog-gtk3.glade:1255 #: data/ui/prefs-dialog-gtk2.glade:125 data/ui/prefs-dialog-gtk2.glade:1225 msgid "HotKeys" msgstr "Tastenkürzel" #: data/ui/prefs-dialog-gtk3.glade:132 data/ui/prefs-dialog-gtk2.glade:146 msgid "Mouse Scroll" msgstr "Mausrad" #: data/ui/prefs-dialog-gtk3.glade:148 data/ui/prefs-dialog-gtk2.glade:167 msgid "Adjustment in Popups" msgstr "Anpassung in Einblendungen" #: data/ui/prefs-dialog-gtk3.glade:164 data/ui/prefs-dialog-gtk2.glade:188 msgid "External Change" msgstr "Externe Änderung" #: data/ui/prefs-dialog-gtk3.glade:185 msgid "Notify for volume changes from:" msgstr "Benachrichtigungen zu Lautstärkeänderungen von:" #: data/ui/prefs-dialog-gtk3.glade:212 data/ui/prefs-dialog-gtk2.glade:12 msgid "Notification support disabled at compile time." msgstr "Unterstützung für Benachrichtigungen wurde nicht einkompiliert." #: data/ui/prefs-dialog-gtk3.glade:236 data/ui/prefs-dialog-gtk2.glade:241 msgid "PNMixer Preferences" msgstr "PNMixer-Einstellungen" #: data/ui/prefs-dialog-gtk3.glade:324 msgid "Ok" msgstr "OK" #: data/ui/prefs-dialog-gtk3.glade:369 msgid "Apply" msgstr "Anwenden" #: data/ui/prefs-dialog-gtk3.glade:427 data/ui/prefs-dialog-gtk2.glade:338 msgid "Card:" msgstr "Karte:" #: data/ui/prefs-dialog-gtk3.glade:439 data/ui/prefs-dialog-gtk2.glade:349 msgid "Channel:" msgstr "Kanal:" #: data/ui/prefs-dialog-gtk3.glade:450 data/ui/prefs-dialog-gtk2.glade:409 msgid "Change volume on a logarithmic scale, closer to human perception." msgstr "Lautstärke logarithmisch ändern, was besser der menschlichen Wahrnehmung entspricht." #: data/ui/prefs-dialog-gtk3.glade:452 data/ui/prefs-dialog-gtk2.glade:408 msgid "Normalize Volume:" msgstr "Lautstärke normalisieren:" #: data/ui/prefs-dialog-gtk3.glade:502 data/ui/prefs-dialog-gtk2.glade:425 msgid "Sound Device" msgstr "Sound-Gerät" #: data/ui/prefs-dialog-gtk3.glade:520 data/ui/prefs-dialog-gtk2.glade:443 msgid "Device" msgstr "Gerät" #: data/ui/prefs-dialog-gtk3.glade:555 data/ui/prefs-dialog-gtk2.glade:477 msgid "Slider Orientation:" msgstr "Schieberegler-Ausrichtung:" #: data/ui/prefs-dialog-gtk3.glade:567 data/ui/prefs-dialog-gtk2.glade:520 msgid "Text Volume Position:" msgstr "Textposition:" #: data/ui/prefs-dialog-gtk3.glade:576 data/ui/prefs-dialog-gtk2.glade:501 msgid "Display Text Volume" msgstr "Lautstärke als Text anzeigen" #: data/ui/prefs-dialog-gtk3.glade:596 data/ui/prefs-dialog-gtk2.glade:489 msgid "Vertical" msgstr "Vertikal" #: data/ui/prefs-dialog-gtk3.glade:597 data/ui/prefs-dialog-gtk2.glade:490 msgid "Horizontal" msgstr "Horizontal" #: data/ui/prefs-dialog-gtk3.glade:611 data/ui/prefs-dialog-gtk2.glade:534 msgid "Top" msgstr "Oben" #: data/ui/prefs-dialog-gtk3.glade:612 data/ui/prefs-dialog-gtk2.glade:535 msgid "Bottom" msgstr "Unten" #: data/ui/prefs-dialog-gtk3.glade:613 data/ui/prefs-dialog-gtk2.glade:536 msgid "Left" msgstr "Links" #: data/ui/prefs-dialog-gtk3.glade:614 data/ui/prefs-dialog-gtk2.glade:537 msgid "Right" msgstr "Rechts" #: data/ui/prefs-dialog-gtk3.glade:632 data/ui/prefs-dialog-gtk2.glade:556 msgid "Volume Popup" msgstr "Lautstärkeeinblendung" #: data/ui/prefs-dialog-gtk3.glade:663 data/ui/prefs-dialog-gtk2.glade:619 msgid "Volume Meter Color:" msgstr "Lautstärkeskala-Farbe:" #: data/ui/prefs-dialog-gtk3.glade:675 data/ui/prefs-dialog-gtk2.glade:606 msgid "Volume Meter Offset (%):" msgstr "Lautstärkeskala-Versatz (%):" #: data/ui/prefs-dialog-gtk3.glade:713 data/ui/prefs-dialog-gtk2.glade:589 msgid "Draw Volume Meter on Tray Icon" msgstr "Lautstärkeskala im Benachrichtigungssymbol zeichnen" #: data/ui/prefs-dialog-gtk3.glade:735 data/ui/prefs-dialog-gtk2.glade:672 msgid "Volume Meter" msgstr "Lautstärkeskala" #: data/ui/prefs-dialog-gtk3.glade:755 data/ui/prefs-dialog-gtk2.glade:699 msgid "Use System Theme" msgstr "Systemthema verwenden" #: data/ui/prefs-dialog-gtk3.glade:770 data/ui/prefs-dialog-gtk2.glade:712 msgid "Icon Theme" msgstr "Symbolthema" #: data/ui/prefs-dialog-gtk3.glade:791 data/ui/prefs-dialog-gtk2.glade:732 msgid "View" msgstr "Ansicht" #: data/ui/prefs-dialog-gtk3.glade:829 data/ui/prefs-dialog-gtk2.glade:772 msgid "Volume Control Command" msgstr "Befehl zur Lautstärkeregelung" #: data/ui/prefs-dialog-gtk3.glade:860 data/ui/prefs-dialog-gtk2.glade:808 msgid "Scroll Step:" msgstr "Schrittweite des Mausrades:" #: data/ui/prefs-dialog-gtk3.glade:872 data/ui/prefs-dialog-gtk2.glade:819 msgid "Fine Scroll Step:" msgstr "Kleine Schrittweite des Mausrades:" #: data/ui/prefs-dialog-gtk3.glade:918 data/ui/prefs-dialog-gtk2.glade:875 msgid "Volume Scrolling" msgstr "Lautstärke mit Scrollrad" #: data/ui/prefs-dialog-gtk3.glade:949 data/ui/prefs-dialog-gtk2.glade:922 msgid "Custom Command:" msgstr "Benutzerdefinierter Befehl:" #: data/ui/prefs-dialog-gtk3.glade:961 data/ui/prefs-dialog-gtk2.glade:911 msgid "Middle Click Action:" msgstr "Aktion bei Mittelklick:" #: data/ui/prefs-dialog-gtk3.glade:974 data/ui/prefs-dialog-gtk2.glade:936 msgid "Show Preferences" msgstr "Einstellungen anzeigen" #: data/ui/prefs-dialog-gtk3.glade:976 data/ui/prefs-dialog-gtk2.glade:938 msgid "Custom (set below)" msgstr "Benutzerdefiniert (siehe unten)" #: data/ui/prefs-dialog-gtk3.glade:1005 data/ui/prefs-dialog-gtk2.glade:974 msgid "Mouse" msgstr "Maus" #: data/ui/prefs-dialog-gtk3.glade:1026 data/ui/prefs-dialog-gtk2.glade:995 msgid "Behavior" msgstr "Verhalten" #: data/ui/prefs-dialog-gtk3.glade:1057 data/ui/prefs-dialog-gtk2.glade:1025 msgid "Enable HotKeys" msgstr "Tastenkürzel aktivieren" #: data/ui/prefs-dialog-gtk3.glade:1085 data/ui/prefs-dialog-gtk2.glade:1099 msgid "Command" msgstr "Befehl" #: data/ui/prefs-dialog-gtk3.glade:1100 data/ui/prefs-dialog-gtk2.glade:1052 msgid "Mute/Unmute:" msgstr "Stumm (ein/aus):" #: data/ui/prefs-dialog-gtk3.glade:1112 data/ui/prefs-dialog-gtk2.glade:1064 msgid "Volume Up:" msgstr "Lauter:" #: data/ui/prefs-dialog-gtk3.glade:1124 data/ui/prefs-dialog-gtk2.glade:1076 msgid "Volume Down:" msgstr "Leiser:" #: data/ui/prefs-dialog-gtk3.glade:1135 data/ui/prefs-dialog-gtk2.glade:1109 msgid "HotKey" msgstr "Tastenkürzel" #: data/ui/prefs-dialog-gtk3.glade:1154 data/ui/prefs-dialog-gtk3.glade:1175 #: data/ui/prefs-dialog-gtk3.glade:1196 data/ui/prefs-dialog-gtk2.glade:1128 #: data/ui/prefs-dialog-gtk2.glade:1151 data/ui/prefs-dialog-gtk2.glade:1174 msgid "(None)" msgstr "(Keine)" #: data/ui/prefs-dialog-gtk3.glade:1212 data/ui/prefs-dialog-gtk2.glade:1087 msgid "Double-click a HotKey to assign a new HotKey" msgstr "Doppelklicken Sie auf ein Tastenkürzel, um ein neues Tastenkürzel festzulegen" #: data/ui/prefs-dialog-gtk3.glade:1234 data/ui/prefs-dialog-gtk2.glade:1204 msgid "HotKey Settings" msgstr "Tastenkürzel-Einstellungen" #: data/ui/popup-menu-gtk2.glade:45 msgid "_Mute" msgstr "_Stumm" #: data/ui/popup-menu-gtk2.glade:56 msgid "_Volume Control" msgstr "_Lautstärkeregler" #: data/ui/popup-menu-gtk2.glade:81 msgid "_Reload Sound" msgstr "Sound _neu laden" #: data/ui/prefs-dialog-gtk2.glade:106 msgid "Notify for volume changes from:" msgstr "Benachrichtigungen zu Lautstärkeänderungen mittels:" pnmixer-0.7.2/po/fr.po000066400000000000000000000365351311427610600146040ustar00rootroot00000000000000# French translation for pnmixer. # Copyright (C) 2016 PNMixer team (msgids) # This file is distributed under the same license as the pnmixer package. # # Matthieu Bresson , 2011. # El Boulangero , 2015. # Stéphane Aulery , 2016, 2017. msgid "" msgstr "" "Project-Id-Version: pnmixer 0.7.1-rc3\n" "Report-Msgid-Bugs-To: https://github.com/nicklan/pnmixer/issues\n" "POT-Creation-Date: 2017-03-13 21:25+0700\n" "PO-Revision-Date: 2017-04-29 19:40+0200\n" "Last-Translator: Stéphane Aulery \n" "Language-Team: French \n" "Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Bugs: Report translation errors to the Language-Team address.\n" #: src/hotkeys.c:175 msgid "Could not grab the following HotKeys" msgstr "Impossible d’assigner les raccourcis clavier suivants" #: src/hotkeys.c:176 src/ui-prefs-dialog.c:339 #: data/ui/prefs-dialog-gtk3.glade:973 data/ui/prefs-dialog-gtk2.glade:935 msgid "Mute/Unmute" msgstr "Muet actif / inactif" #: src/hotkeys.c:178 src/ui-prefs-dialog.c:342 msgid "Volume Up" msgstr "Augmenter le volume" #: src/hotkeys.c:180 src/ui-prefs-dialog.c:345 msgid "Volume Down" msgstr "Diminuer le volume" #: src/main.c:69 #, c-format msgid "Unable to run command: %s" msgstr "Impossible de lancer la commande : %s" #: src/main.c:89 msgid "No mixer application was found on your system. Please open preferences and set the command you want to run for volume control." msgstr "Aucun mixeur audio n’a été trouvé sur votre système. Veuillez configurer dans les préférences la commande de contrôle du volume." #: src/main.c:109 msgid "You have not specified a custom command to run, please specify one in preferences." msgstr "Vous n’avez pas spécifié de commande, veuillez en spécifier une dans les paramètres." #: src/main.c:210 src/main.c:248 msgid "PNMixer Error" msgstr "PNMixer erreur" #: src/main.c:239 msgid "Warning: Connection to sound system failed." msgstr "Attention : la connection au système audio a échoué." #: src/main.c:243 msgid "" "Do you want to re-initialize the audio connection ?\n" "\n" "If you do not, you will either need to restart PNMixer or select the 'Reload Audio' option in the right-click menu in order for PNMixer to function." msgstr "" "Voulez-vous réinitialiser la connexion audio ?\n" "\n" "Si vous ne le faites pas, vous aurez besoin de relancer PNMixer ou sélectionner l’option « Recharger le système audio » dans le menu déroulant pour que PNMixer puisse fonctionner correctement." #: src/main.c:334 msgid "- A mixer for the system tray." msgstr "- Un mixeur audio de zone de notifications." #: src/main.c:342 #, c-format msgid "%s version: %s\n" msgstr "%s version %s\n" #: src/notif.c:77 msgid "Volume muted" msgstr "Son muet" #: src/notif.c:82 src/ui-tray-icon.c:355 msgid "Volume" msgstr "Volume" #: src/notif.c:135 msgid "No sound card" msgstr "Pas de carte son" #: src/notif.c:136 msgid "No playable soundcard found" msgstr "Pas de carte son utilisable" #: src/notif.c:141 msgid "Soundcard disconnected" msgstr "Carte son désactivée" #: src/notif.c:142 msgid "Soundcard has been disconnected, reloading sound system..." msgstr "Carte son déconnectée, chargement du système audio" #: src/prefs.c:356 #, c-format msgid "Couldn't load preferences file: %s" msgstr "Impossible de charger le fichier de configuration : %s" #: src/prefs.c:365 #, c-format msgid "Couldn't load default preferences: %s" msgstr "Impossible de charger la configuration par défaut : %s" #: src/prefs.c:391 #, c-format msgid "Couldn't write preferences file: %s" msgstr "Impossible d'écrire dans le fichier de configuration \"%s\"." #: src/prefs.c:411 #, c-format msgid "'%s' exists but is not a directory, won't be able to save preferences." msgstr "« %s » existe mais n'est pas un répertoire. Impossible de sauvegarder la configuration." #: src/prefs.c:415 #, c-format msgid "Couldn't make preferences directory: %s" msgstr "Impossible de créer le dossier de configuration : %s" #: src/ui-about-dialog.c:114 msgid "A mixer for the system tray" msgstr "Un mixeur audio de la zone de notifications" #: src/ui-about-dialog.c:115 msgid "Copyright © 2010-2016 Nick Lanham" msgstr "Copyright © 2010-2016 Nick Lanham" #: src/ui-hotkey-dialog.c:48 #, c-format msgid "Set %s HotKey" msgstr "Assignation du raccourci clavier %s" #: src/ui-hotkey-dialog.c:52 #, c-format msgid "Press new HotKey for %s" msgstr "Presser la touche à assigner pour : %s" #: src/ui-hotkey-dialog.c:174 msgid "Could not grab the keyboard." msgstr "Impossible d'accéder au clavier." #: src/ui-popup-menu.c:57 src/ui-popup-menu.c:84 src/ui-popup-window.c:129 msgid "Soundcard has no mute switch" msgstr "Carte son sans option de mise en sourdine" #: src/ui-prefs-dialog.c:373 msgid "None" msgstr "Indéfini" #: src/ui-prefs-dialog.c:867 msgid "Notifications" msgstr "Notifications" #: src/ui-tray-icon.c:357 msgid "No mute switch" msgstr "Pas d’option de mise en sourdine" #: src/ui-tray-icon.c:359 msgid "Muted" msgstr "Muet" #: data/desktop/pnmixer.desktop.in:3 msgid "PNMixer" msgstr "PNMixer" #: data/desktop/pnmixer.desktop.in:4 msgid "System Tray Mixer" msgstr "Mixeur audio de la zone de notification" #: data/desktop/pnmixer.desktop.in:5 msgid "An audio mixer for the system tray" msgstr "Un mixeur audio pour la zone de notification" #. TRANSLATORS: Search terms to find this application. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! #: data/desktop/pnmixer.desktop.in:7 msgid "alsa;audio;mixer;sound;" msgstr "alsa;audio;mixer;sound;" #. TRANSLATORS: Do NOT translate or transliterate this text (this is an icon file name)! #: data/desktop/pnmixer.desktop.in:11 msgid "pnmixer" msgstr "pnmixer" #: data/ui/hotkey-dialog-gtk3.glade:55 data/ui/prefs-dialog-gtk3.glade:279 msgid "Cancel" msgstr "Annuler" #: data/ui/hotkey-dialog-gtk3.glade:109 data/ui/hotkey-dialog-gtk2.glade:49 msgid "Defining HotKey" msgstr "Définition du raccourci clavier" #: data/ui/hotkey-dialog-gtk3.glade:124 data/ui/hotkey-dialog-gtk2.glade:65 msgid "(press C to reset)" msgstr "(appuyez sur C pour réinitialiser)" #: data/ui/popup-menu-gtk3.glade:33 data/ui/popup-menu-gtk2.glade:49 msgid "Mute/Unmute Volume" msgstr "Muet actif / inactif" #: data/ui/popup-menu-gtk3.glade:58 #: data/ui/popup-window-horizontal-gtk3.glade:54 #: data/ui/popup-window-vertical-gtk3.glade:58 #: data/ui/popup-window-horizontal-gtk2.glade:56 #: data/ui/popup-window-vertical-gtk2.glade:58 msgid "Mute" msgstr "Muet" #: data/ui/popup-menu-gtk3.glade:73 data/ui/popup-menu-gtk2.glade:60 msgid "Open Volume Control" msgstr "Ouvrir le contrôle du volume" #: data/ui/popup-menu-gtk3.glade:95 data/ui/prefs-dialog-gtk3.glade:975 #: data/ui/prefs-dialog-gtk2.glade:937 msgid "Volume Control" msgstr "Contrôle du volume" #: data/ui/popup-menu-gtk3.glade:110 data/ui/popup-menu-gtk3.glade:133 #: data/ui/popup-menu-gtk2.glade:73 msgid "Preferences" msgstr "Préférences" #: data/ui/popup-menu-gtk3.glade:148 data/ui/popup-menu-gtk3.glade:171 #: data/ui/popup-menu-gtk2.glade:85 msgid "Reload Sound" msgstr "Recharger le système audio" #: data/ui/popup-menu-gtk3.glade:186 data/ui/popup-menu-gtk3.glade:209 #: data/ui/popup-menu-gtk2.glade:98 msgid "About" msgstr "À propos" #: data/ui/popup-menu-gtk3.glade:231 data/ui/popup-menu-gtk3.glade:254 #: data/ui/popup-menu-gtk2.glade:117 msgid "Quit" msgstr "Quitter" #: data/ui/popup-window-horizontal-gtk3.glade:81 #: data/ui/popup-window-vertical-gtk3.glade:74 #: data/ui/popup-window-horizontal-gtk2.glade:72 #: data/ui/popup-window-vertical-gtk2.glade:74 msgid "Mixer" msgstr "Mixeur" #: data/ui/prefs-dialog-gtk3.glade:43 data/ui/prefs-dialog-gtk2.glade:68 msgid "Timeout (ms):" msgstr "Timeout (ms) :" #: data/ui/prefs-dialog-gtk3.glade:65 data/ui/prefs-dialog-gtk2.glade:46 msgid "Enable Notifications" msgstr "Activer les notifications" #: data/ui/prefs-dialog-gtk3.glade:89 data/ui/prefs-dialog-gtk2.glade:210 msgid "Notification Options" msgstr "

Paramètres de notification" #: data/ui/prefs-dialog-gtk3.glade:116 data/ui/prefs-dialog-gtk3.glade:1255 #: data/ui/prefs-dialog-gtk2.glade:125 data/ui/prefs-dialog-gtk2.glade:1225 msgid "HotKeys" msgstr "Raccourcis clavier" #: data/ui/prefs-dialog-gtk3.glade:132 data/ui/prefs-dialog-gtk2.glade:146 msgid "Mouse Scroll" msgstr "Molette de la souris" #: data/ui/prefs-dialog-gtk3.glade:148 data/ui/prefs-dialog-gtk2.glade:167 msgid "Adjustment in Popups" msgstr "Réglage des des popups" #: data/ui/prefs-dialog-gtk3.glade:164 data/ui/prefs-dialog-gtk2.glade:188 msgid "External Change" msgstr "Modifications externes" #: data/ui/prefs-dialog-gtk3.glade:185 msgid "Notify for volume changes from:" msgstr "Notifier les changements de volume pour :" #: data/ui/prefs-dialog-gtk3.glade:212 data/ui/prefs-dialog-gtk2.glade:12 msgid "Notification support disabled at compile time." msgstr "Support des notifications désactivé lors de la compilation." #: data/ui/prefs-dialog-gtk3.glade:236 data/ui/prefs-dialog-gtk2.glade:241 msgid "PNMixer Preferences" msgstr "Configuration de PNMixer" #: data/ui/prefs-dialog-gtk3.glade:324 msgid "Ok" msgstr "Ok" #: data/ui/prefs-dialog-gtk3.glade:369 msgid "Apply" msgstr "Appliquer" #: data/ui/prefs-dialog-gtk3.glade:427 data/ui/prefs-dialog-gtk2.glade:338 msgid "Card:" msgstr "Carte :" #: data/ui/prefs-dialog-gtk3.glade:439 data/ui/prefs-dialog-gtk2.glade:349 msgid "Channel:" msgstr "Canal :" #: data/ui/prefs-dialog-gtk3.glade:450 data/ui/prefs-dialog-gtk2.glade:409 msgid "Change volume on a logarithmic scale, closer to human perception." msgstr "Changer le volume en suivant une échelle logarithmique, proche de la perception humaine." #: data/ui/prefs-dialog-gtk3.glade:452 data/ui/prefs-dialog-gtk2.glade:408 msgid "Normalize Volume:" msgstr "Normaliser le volume :" #: data/ui/prefs-dialog-gtk3.glade:502 data/ui/prefs-dialog-gtk2.glade:425 msgid "Sound Device" msgstr "Matériel audio" #: data/ui/prefs-dialog-gtk3.glade:520 data/ui/prefs-dialog-gtk2.glade:443 msgid "Device" msgstr "Matériel" #: data/ui/prefs-dialog-gtk3.glade:555 data/ui/prefs-dialog-gtk2.glade:477 msgid "Slider Orientation:" msgstr "Orientation des diaporamas :" #: data/ui/prefs-dialog-gtk3.glade:567 data/ui/prefs-dialog-gtk2.glade:520 msgid "Text Volume Position:" msgstr "Position du texte pour le volume sonore :" #: data/ui/prefs-dialog-gtk3.glade:576 data/ui/prefs-dialog-gtk2.glade:501 msgid "Display Text Volume" msgstr "Afficher un texte pour le volume sonore" #: data/ui/prefs-dialog-gtk3.glade:596 data/ui/prefs-dialog-gtk2.glade:489 msgid "Vertical" msgstr "Portrait" #: data/ui/prefs-dialog-gtk3.glade:597 data/ui/prefs-dialog-gtk2.glade:490 msgid "Horizontal" msgstr "Paysage" #: data/ui/prefs-dialog-gtk3.glade:611 data/ui/prefs-dialog-gtk2.glade:534 msgid "Top" msgstr "En haut" #: data/ui/prefs-dialog-gtk3.glade:612 data/ui/prefs-dialog-gtk2.glade:535 msgid "Bottom" msgstr "En bas" #: data/ui/prefs-dialog-gtk3.glade:613 data/ui/prefs-dialog-gtk2.glade:536 msgid "Left" msgstr "À gauche" #: data/ui/prefs-dialog-gtk3.glade:614 data/ui/prefs-dialog-gtk2.glade:537 msgid "Right" msgstr "À droite" #: data/ui/prefs-dialog-gtk3.glade:632 data/ui/prefs-dialog-gtk2.glade:556 msgid "Volume Popup" msgstr "Contrôle du volume" #: data/ui/prefs-dialog-gtk3.glade:663 data/ui/prefs-dialog-gtk2.glade:619 msgid "Volume Meter Color:" msgstr "Couleur de l'échelle de volume :" #: data/ui/prefs-dialog-gtk3.glade:675 data/ui/prefs-dialog-gtk2.glade:606 msgid "Volume Meter Offset (%):" msgstr "Décalage de l'échelle de volume (%) :" #: data/ui/prefs-dialog-gtk3.glade:713 data/ui/prefs-dialog-gtk2.glade:589 msgid "Draw Volume Meter on Tray Icon" msgstr "Affichage graphique du volume dans la zone de notification" #: data/ui/prefs-dialog-gtk3.glade:735 data/ui/prefs-dialog-gtk2.glade:672 msgid "Volume Meter" msgstr "Échelle de volume" #: data/ui/prefs-dialog-gtk3.glade:755 data/ui/prefs-dialog-gtk2.glade:699 msgid "Use System Theme" msgstr "Utiliser le thème système" #: data/ui/prefs-dialog-gtk3.glade:770 data/ui/prefs-dialog-gtk2.glade:712 msgid "Icon Theme" msgstr "Thème d'icônes" #: data/ui/prefs-dialog-gtk3.glade:791 data/ui/prefs-dialog-gtk2.glade:732 msgid "View" msgstr "Affichage" #: data/ui/prefs-dialog-gtk3.glade:829 data/ui/prefs-dialog-gtk2.glade:772 msgid "Volume Control Command" msgstr "Commande de contrôle du volume" #: data/ui/prefs-dialog-gtk3.glade:860 data/ui/prefs-dialog-gtk2.glade:808 msgid "Scroll Step:" msgstr "Pas normal de la molette :" #: data/ui/prefs-dialog-gtk3.glade:872 data/ui/prefs-dialog-gtk2.glade:819 msgid "Fine Scroll Step:" msgstr "Pas fin de la molette :" #: data/ui/prefs-dialog-gtk3.glade:918 data/ui/prefs-dialog-gtk2.glade:875 msgid "Volume Scrolling" msgstr "Changement de l’échelle de volume" #: data/ui/prefs-dialog-gtk3.glade:949 data/ui/prefs-dialog-gtk2.glade:922 msgid "Custom Command:" msgstr "Commande personnalisée :" #: data/ui/prefs-dialog-gtk3.glade:961 data/ui/prefs-dialog-gtk2.glade:911 msgid "Middle Click Action:" msgstr "Action du clic du milieu :" #: data/ui/prefs-dialog-gtk3.glade:974 data/ui/prefs-dialog-gtk2.glade:936 msgid "Show Preferences" msgstr "Afficher les paramètres" #: data/ui/prefs-dialog-gtk3.glade:976 data/ui/prefs-dialog-gtk2.glade:938 msgid "Custom (set below)" msgstr "Autre (renseigner en-dessous)" #: data/ui/prefs-dialog-gtk3.glade:1005 data/ui/prefs-dialog-gtk2.glade:974 msgid "Mouse" msgstr "Souris" #: data/ui/prefs-dialog-gtk3.glade:1026 data/ui/prefs-dialog-gtk2.glade:995 msgid "Behavior" msgstr "Comportement" #: data/ui/prefs-dialog-gtk3.glade:1057 data/ui/prefs-dialog-gtk2.glade:1025 msgid "Enable HotKeys" msgstr "Autoriser les raccourcis clavier" #: data/ui/prefs-dialog-gtk3.glade:1085 data/ui/prefs-dialog-gtk2.glade:1099 msgid "Command" msgstr "Commande" #: data/ui/prefs-dialog-gtk3.glade:1100 data/ui/prefs-dialog-gtk2.glade:1052 msgid "Mute/Unmute:" msgstr "Muet actif / inactif :" #: data/ui/prefs-dialog-gtk3.glade:1112 data/ui/prefs-dialog-gtk2.glade:1064 msgid "Volume Up:" msgstr "Augmenter le volume :" #: data/ui/prefs-dialog-gtk3.glade:1124 data/ui/prefs-dialog-gtk2.glade:1076 msgid "Volume Down:" msgstr "Diminuer le volume :" #: data/ui/prefs-dialog-gtk3.glade:1135 data/ui/prefs-dialog-gtk2.glade:1109 msgid "HotKey" msgstr "Raccourcis clavier" #: data/ui/prefs-dialog-gtk3.glade:1154 data/ui/prefs-dialog-gtk3.glade:1175 #: data/ui/prefs-dialog-gtk3.glade:1196 data/ui/prefs-dialog-gtk2.glade:1128 #: data/ui/prefs-dialog-gtk2.glade:1151 data/ui/prefs-dialog-gtk2.glade:1174 msgid "(None)" msgstr "(Indéfini)" #: data/ui/prefs-dialog-gtk3.glade:1212 data/ui/prefs-dialog-gtk2.glade:1087 msgid "Double-click a HotKey to assign a new HotKey" msgstr "Double cliquer sur un raccourci clavier pour le réassigner" #: data/ui/prefs-dialog-gtk3.glade:1234 data/ui/prefs-dialog-gtk2.glade:1204 msgid "HotKey Settings" msgstr "Paramètres des raccourcis clavier" #: data/ui/popup-menu-gtk2.glade:45 msgid "_Mute" msgstr "_Muet" #: data/ui/popup-menu-gtk2.glade:56 msgid "_Volume Control" msgstr "_Contrôle du volume" #: data/ui/popup-menu-gtk2.glade:81 msgid "_Reload Sound" msgstr "_Recharger le système audio" #: data/ui/prefs-dialog-gtk2.glade:106 msgid "Notify for volume changes from:" msgstr "Notifier les changements de volumes pour :" pnmixer-0.7.2/po/hr.po000066400000000000000000000365601311427610600146040ustar00rootroot00000000000000# Croatian translation of pnmixer # Copyright (C) 2016 # This file is distributed under the same license as the pnmixer package. # # Božidar Putanec , 2017. msgid "" msgstr "" "Project-Id-Version: pnmixer-0.7.1-rc3\n" "Report-Msgid-Bugs-To: https://github.com/nicklan/pnmixer/issues\n" "POT-Creation-Date: 2017-03-13 21:25+0700\n" "PO-Revision-Date: 2017-03-14 18:01-0700\n" "Last-Translator: Božidar Putanec \n" "Language-Team: Croatian \n" "Language: hr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Bugs: Report translation errors to the Language-Team address.\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.8.9\n" #: src/hotkeys.c:175 msgid "Could not grab the following HotKeys" msgstr "Definiranje sljedećih preÄaca nije uspjelo (HotKeys)." # Možda ovako: Mûk/Glȃs ili Mûk/Zvûk #: src/hotkeys.c:176 src/ui-prefs-dialog.c:339 #: data/ui/prefs-dialog-gtk3.glade:973 data/ui/prefs-dialog-gtk2.glade:935 msgid "Mute/Unmute" msgstr "Zvûk (da/ne)" #: src/hotkeys.c:178 src/ui-prefs-dialog.c:342 msgid "Volume Up" msgstr "PojaÄavanje glasnoće" #: src/hotkeys.c:180 src/ui-prefs-dialog.c:345 msgid "Volume Down" msgstr "Smanjivanje glasnoće" #: src/main.c:69 #, c-format msgid "Unable to run command: %s" msgstr "Nije moguće izvrÅ¡iti naredbu: %s" #: src/main.c:89 msgid "No mixer application was found on your system. Please open preferences and set the command you want to run for volume control." msgstr "VaÅ¡ sustav nema aplikaciju za miksanje zvuka. Otvorite postavke i zadajte naredbu s kojom želite regulirati glasnoću." #: src/main.c:109 msgid "You have not specified a custom command to run, please specify one in preferences." msgstr "Niste specificirali prilagoÄ‘enu naredbu, odaberite jednu od njih u postavkama." #: src/main.c:210 src/main.c:248 msgid "PNMixer Error" msgstr "PNMixer greÅ¡ka" #: src/main.c:239 msgid "Warning: Connection to sound system failed." msgstr "Upozorenje: Spajanje na audiosustav nije uspjelo." #: src/main.c:243 msgid "" "Do you want to re-initialize the audio connection ?\n" "\n" "If you do not, you will either need to restart PNMixer or select the 'Reload Audio' option in the right-click menu in order for PNMixer to function." msgstr "" "Želite li ponovno inicirati spajanje na audiosustav?\n" "\n" "Ako ne, trebate iznova pokrenuti PNMixer, ili s desnim klikom u meniju odabrati opciju ‘Reload Audio (Alsa)’ da bi PNMixer proradio." #: src/main.c:334 msgid "- A mixer for the system tray." msgstr "- Mikser za paletu sustava." #: src/main.c:342 #, c-format msgid "%s version: %s\n" msgstr "%s inaÄica: %s\n" #: src/notif.c:77 msgid "Volume muted" msgstr "Zvûk (glasnoća) je priguÅ¡en" #: src/notif.c:82 src/ui-tray-icon.c:355 msgid "Volume" msgstr "Glasnoća" #: src/notif.c:135 msgid "No sound card" msgstr "Nema audiokartice" #: src/notif.c:136 msgid "No playable soundcard found" msgstr "Nije naÄ‘ena adekvatna audiokartica (za reprodukciju)" #: src/notif.c:141 msgid "Soundcard disconnected" msgstr "Audiokartica nije spojena" #: src/notif.c:142 msgid "Soundcard has been disconnected, reloading sound system..." msgstr "Audiokartica nije bila spojena, audiosustav se iznova pokreće..." #: src/prefs.c:356 #, c-format msgid "Couldn't load preferences file: %s" msgstr "Osobne (prilagoÄ‘ene) postavke nije moguće uÄitati: %s" #: src/prefs.c:365 #, c-format msgid "Couldn't load default preferences: %s" msgstr "Zadane (standardne) postavke nije moguće uÄitati: %s" #: src/prefs.c:391 #, c-format msgid "Couldn't write preferences file: %s" msgstr "Osobne postavke nije moguće zapisati u datoteku: %s" #: src/prefs.c:411 #, c-format msgid "'%s' exists but is not a directory, won't be able to save preferences." msgstr "‘%s’ postoji, ali to nije direktorij, osobne postavke se neće moći spremiti." #: src/prefs.c:415 #, c-format msgid "Couldn't make preferences directory: %s" msgstr "Direktorij za osobne postavke nije moguće napraviti: %s" #: src/ui-about-dialog.c:114 msgid "A mixer for the system tray" msgstr "Mikser za paletu sustava (system tray)" #: src/ui-about-dialog.c:115 msgid "Copyright © 2010-2016 Nick Lanham" msgstr "Copyright © 2010-2016 Nick Lanham" #: src/ui-hotkey-dialog.c:48 #, c-format msgid "Set %s HotKey" msgstr "%s postavljen za preÄac (HotKey)" #: src/ui-hotkey-dialog.c:52 #, c-format msgid "Press new HotKey for %s" msgstr "Pritisni novi preÄac (HotKey) za %s" #: src/ui-hotkey-dialog.c:174 msgid "Could not grab the keyboard." msgstr "Pristup tipkovnici nije moguć." #: src/ui-popup-menu.c:57 src/ui-popup-menu.c:84 src/ui-popup-window.c:129 msgid "Soundcard has no mute switch" msgstr "ZvuÄna kartica nema preklopnik za ukljuÄenje/iskljuÄenje zvuka" #: src/ui-prefs-dialog.c:373 msgid "None" msgstr "Nijedan" #: src/ui-prefs-dialog.c:867 msgid "Notifications" msgstr "Priopćenja" #: src/ui-tray-icon.c:357 msgid "No mute switch" msgstr "Nema preklopnika za ukljuÄenje/iskljuÄenje zvuka" # A ovako: Zamuknut, Umuknut? #: src/ui-tray-icon.c:359 msgid "Muted" msgstr "Zvûk je iskljuÄen" #: data/desktop/pnmixer.desktop.in:3 msgid "PNMixer" msgstr "PNMikser" #: data/desktop/pnmixer.desktop.in:4 msgid "System Tray Mixer" msgstr "Mikser za paletu sustava (System Tray Mixer)" #: data/desktop/pnmixer.desktop.in:5 msgid "An audio mixer for the system tray" msgstr "Audiomikser za paletu sustava (system tray)" #. TRANSLATORS: Search terms to find this application. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! #: data/desktop/pnmixer.desktop.in:7 msgid "alsa;audio;mixer;sound;" msgstr "alsa;audio;mixer;sound;" #. TRANSLATORS: Do NOT translate or transliterate this text (this is an icon file name)! #: data/desktop/pnmixer.desktop.in:11 msgid "pnmixer" msgstr "pnmixer" #: data/ui/hotkey-dialog-gtk3.glade:55 data/ui/prefs-dialog-gtk3.glade:279 msgid "Cancel" msgstr "Odustani" #: data/ui/hotkey-dialog-gtk3.glade:109 data/ui/hotkey-dialog-gtk2.glade:49 msgid "Defining HotKey" msgstr "Definicija preÄaca (HotKey)" #: data/ui/hotkey-dialog-gtk3.glade:124 data/ui/hotkey-dialog-gtk2.glade:65 msgid "(press C to reset)" msgstr "(pritisni C za resetiranje)" #: data/ui/popup-menu-gtk3.glade:33 data/ui/popup-menu-gtk2.glade:49 msgid "Mute/Unmute Volume" msgstr "Zvûk (da/ne) glasnoća" # A ovako: umuknut, zamuknut? #: data/ui/popup-menu-gtk3.glade:58 #: data/ui/popup-window-horizontal-gtk3.glade:54 #: data/ui/popup-window-vertical-gtk3.glade:58 #: data/ui/popup-window-horizontal-gtk2.glade:56 #: data/ui/popup-window-vertical-gtk2.glade:58 msgid "Mute" msgstr "IskljuÄi zvuk" #: data/ui/popup-menu-gtk3.glade:73 data/ui/popup-menu-gtk2.glade:60 msgid "Open Volume Control" msgstr "Otvori regulator glasnoće" #: data/ui/popup-menu-gtk3.glade:95 data/ui/prefs-dialog-gtk3.glade:975 #: data/ui/prefs-dialog-gtk2.glade:937 msgid "Volume Control" msgstr "Regulator glasnoće" #: data/ui/popup-menu-gtk3.glade:110 data/ui/popup-menu-gtk3.glade:133 #: data/ui/popup-menu-gtk2.glade:73 msgid "Preferences" msgstr "Osobne postavke" #: data/ui/popup-menu-gtk3.glade:148 data/ui/popup-menu-gtk3.glade:171 #: data/ui/popup-menu-gtk2.glade:85 msgid "Reload Sound" msgstr "Ponovno pokreni Alsa" #: data/ui/popup-menu-gtk3.glade:186 data/ui/popup-menu-gtk3.glade:209 #: data/ui/popup-menu-gtk2.glade:98 msgid "About" msgstr "O programu..." #: data/ui/popup-menu-gtk3.glade:231 data/ui/popup-menu-gtk3.glade:254 #: data/ui/popup-menu-gtk2.glade:117 msgid "Quit" msgstr "Izlaz" #: data/ui/popup-window-horizontal-gtk3.glade:81 #: data/ui/popup-window-vertical-gtk3.glade:74 #: data/ui/popup-window-horizontal-gtk2.glade:72 #: data/ui/popup-window-vertical-gtk2.glade:74 msgid "Mixer" msgstr "Mikser" #: data/ui/prefs-dialog-gtk3.glade:43 data/ui/prefs-dialog-gtk2.glade:68 msgid "Timeout (ms):" msgstr "Tajmout (ms):" #: data/ui/prefs-dialog-gtk3.glade:65 data/ui/prefs-dialog-gtk2.glade:46 msgid "Enable Notifications" msgstr "Omogući priopćenja" #: data/ui/prefs-dialog-gtk3.glade:89 data/ui/prefs-dialog-gtk2.glade:210 msgid "Notification Options" msgstr "Opcije za priopćavanja" #: data/ui/prefs-dialog-gtk3.glade:116 data/ui/prefs-dialog-gtk3.glade:1255 #: data/ui/prefs-dialog-gtk2.glade:125 data/ui/prefs-dialog-gtk2.glade:1225 msgid "HotKeys" msgstr "PreÄaci (HotKeys)" #: data/ui/prefs-dialog-gtk3.glade:132 data/ui/prefs-dialog-gtk2.glade:146 msgid "Mouse Scroll" msgstr "Klizanje miÅ¡evim kotaÄićem" #: data/ui/prefs-dialog-gtk3.glade:148 data/ui/prefs-dialog-gtk2.glade:167 msgid "Adjustment in Popups" msgstr "PodeÅ¡avanje iskoÄnika (Popups)" #: data/ui/prefs-dialog-gtk3.glade:164 data/ui/prefs-dialog-gtk2.glade:188 msgid "External Change" msgstr "Vanjske izmjene" #: data/ui/prefs-dialog-gtk3.glade:185 msgid "Notify for volume changes from:" msgstr "Promjene glasnoće javi iz:" #: data/ui/prefs-dialog-gtk3.glade:212 data/ui/prefs-dialog-gtk2.glade:12 msgid "Notification support disabled at compile time." msgstr "PodrÅ¡ka za obavjeÅ¡tavanje bila je onemogućena prilikom kompiliranja." #: data/ui/prefs-dialog-gtk3.glade:236 data/ui/prefs-dialog-gtk2.glade:241 msgid "PNMixer Preferences" msgstr "Osobne postavke PNMixer-a" #: data/ui/prefs-dialog-gtk3.glade:324 msgid "Ok" msgstr "U redu" #: data/ui/prefs-dialog-gtk3.glade:369 msgid "Apply" msgstr "Primjeni" #: data/ui/prefs-dialog-gtk3.glade:427 data/ui/prefs-dialog-gtk2.glade:338 msgid "Card:" msgstr "Karta:" #: data/ui/prefs-dialog-gtk3.glade:439 data/ui/prefs-dialog-gtk2.glade:349 msgid "Channel:" msgstr "Kanal:" #: data/ui/prefs-dialog-gtk3.glade:450 data/ui/prefs-dialog-gtk2.glade:409 msgid "Change volume on a logarithmic scale, closer to human perception." msgstr "Glasnoću mijenjaj po logaritamskoj skali." # http://www.learndigitalaudio.com/normalize-audio #: data/ui/prefs-dialog-gtk3.glade:452 data/ui/prefs-dialog-gtk2.glade:408 msgid "Normalize Volume:" msgstr "Normalizacija glasnoće:" #: data/ui/prefs-dialog-gtk3.glade:502 data/ui/prefs-dialog-gtk2.glade:425 msgid "Sound Device" msgstr "AudioureÄ‘aj" #: data/ui/prefs-dialog-gtk3.glade:520 data/ui/prefs-dialog-gtk2.glade:443 msgid "Device" msgstr "UreÄ‘aj" #: data/ui/prefs-dialog-gtk3.glade:555 data/ui/prefs-dialog-gtk2.glade:477 msgid "Slider Orientation:" msgstr "Orijentacija klizaÄa:" #: data/ui/prefs-dialog-gtk3.glade:567 data/ui/prefs-dialog-gtk2.glade:520 msgid "Text Volume Position:" msgstr "Pozicija teksta glasnoće:" #: data/ui/prefs-dialog-gtk3.glade:576 data/ui/prefs-dialog-gtk2.glade:501 msgid "Display Text Volume" msgstr "Glasnoću prikaži kao tekst" #: data/ui/prefs-dialog-gtk3.glade:596 data/ui/prefs-dialog-gtk2.glade:489 msgid "Vertical" msgstr "Okomito" #: data/ui/prefs-dialog-gtk3.glade:597 data/ui/prefs-dialog-gtk2.glade:490 msgid "Horizontal" msgstr "Vodoravno" #: data/ui/prefs-dialog-gtk3.glade:611 data/ui/prefs-dialog-gtk2.glade:534 msgid "Top" msgstr "Vrh" #: data/ui/prefs-dialog-gtk3.glade:612 data/ui/prefs-dialog-gtk2.glade:535 msgid "Bottom" msgstr "Dno" #: data/ui/prefs-dialog-gtk3.glade:613 data/ui/prefs-dialog-gtk2.glade:536 msgid "Left" msgstr "Lijevo" #: data/ui/prefs-dialog-gtk3.glade:614 data/ui/prefs-dialog-gtk2.glade:537 msgid "Right" msgstr "Desno" #: data/ui/prefs-dialog-gtk3.glade:632 data/ui/prefs-dialog-gtk2.glade:556 msgid "Volume Popup" msgstr "Glasnoća, iskoÄnik (Popup)" #: data/ui/prefs-dialog-gtk3.glade:663 data/ui/prefs-dialog-gtk2.glade:619 msgid "Volume Meter Color:" msgstr "Boja fonometra:" #: data/ui/prefs-dialog-gtk3.glade:675 data/ui/prefs-dialog-gtk2.glade:606 msgid "Volume Meter Offset (%):" msgstr "Ofset fonometra(%):" #: data/ui/prefs-dialog-gtk3.glade:713 data/ui/prefs-dialog-gtk2.glade:589 msgid "Draw Volume Meter on Tray Icon" msgstr "Fonometar prikazati u paleti (Tray Icon)" #: data/ui/prefs-dialog-gtk3.glade:735 data/ui/prefs-dialog-gtk2.glade:672 msgid "Volume Meter" msgstr "Fonometar" #: data/ui/prefs-dialog-gtk3.glade:755 data/ui/prefs-dialog-gtk2.glade:699 msgid "Use System Theme" msgstr "Koristite temu vaÅ¡eg sustava" #: data/ui/prefs-dialog-gtk3.glade:770 data/ui/prefs-dialog-gtk2.glade:712 msgid "Icon Theme" msgstr "Tema za sliÄice (Icons)" #: data/ui/prefs-dialog-gtk3.glade:791 data/ui/prefs-dialog-gtk2.glade:732 msgid "View" msgstr "Pogled" #: data/ui/prefs-dialog-gtk3.glade:829 data/ui/prefs-dialog-gtk2.glade:772 msgid "Volume Control Command" msgstr "Naredba za reguliranje glasnoće" #: data/ui/prefs-dialog-gtk3.glade:860 data/ui/prefs-dialog-gtk2.glade:808 msgid "Scroll Step:" msgstr "Pomak kotaÄića na miÅ¡u:" #: data/ui/prefs-dialog-gtk3.glade:872 data/ui/prefs-dialog-gtk2.glade:819 msgid "Fine Scroll Step:" msgstr "Precizni pomak kotaÄića na miÅ¡u:" #: data/ui/prefs-dialog-gtk3.glade:918 data/ui/prefs-dialog-gtk2.glade:875 msgid "Volume Scrolling" msgstr "Pomicanje glasnoće " #: data/ui/prefs-dialog-gtk3.glade:949 data/ui/prefs-dialog-gtk2.glade:922 msgid "Custom Command:" msgstr "Naredba definirana korisnikom:" #: data/ui/prefs-dialog-gtk3.glade:961 data/ui/prefs-dialog-gtk2.glade:911 msgid "Middle Click Action:" msgstr "Akcija klika miÅ¡evim kotaÄićem:" #: data/ui/prefs-dialog-gtk3.glade:974 data/ui/prefs-dialog-gtk2.glade:936 msgid "Show Preferences" msgstr "Prikazivanje postavki" #: data/ui/prefs-dialog-gtk3.glade:976 data/ui/prefs-dialog-gtk2.glade:938 msgid "Custom (set below)" msgstr "Prilagodba (postavke su niže navedene)" #: data/ui/prefs-dialog-gtk3.glade:1005 data/ui/prefs-dialog-gtk2.glade:974 msgid "Mouse" msgstr "MiÅ¡" #: data/ui/prefs-dialog-gtk3.glade:1026 data/ui/prefs-dialog-gtk2.glade:995 msgid "Behavior" msgstr "PonaÅ¡anje" #: data/ui/prefs-dialog-gtk3.glade:1057 data/ui/prefs-dialog-gtk2.glade:1025 msgid "Enable HotKeys" msgstr "Omogući preÄace (HotKeys)" #: data/ui/prefs-dialog-gtk3.glade:1085 data/ui/prefs-dialog-gtk2.glade:1099 msgid "Command" msgstr "Naredba" #: data/ui/prefs-dialog-gtk3.glade:1100 data/ui/prefs-dialog-gtk2.glade:1052 msgid "Mute/Unmute:" msgstr "Zvûk (da/ne):" #: data/ui/prefs-dialog-gtk3.glade:1112 data/ui/prefs-dialog-gtk2.glade:1064 msgid "Volume Up:" msgstr "PojaÄavanje glasnoće:" #: data/ui/prefs-dialog-gtk3.glade:1124 data/ui/prefs-dialog-gtk2.glade:1076 msgid "Volume Down:" msgstr "Smanjivanje glasnoće:" #: data/ui/prefs-dialog-gtk3.glade:1135 data/ui/prefs-dialog-gtk2.glade:1109 msgid "HotKey" msgstr "PreÄac (HotKey)" #: data/ui/prefs-dialog-gtk3.glade:1154 data/ui/prefs-dialog-gtk3.glade:1175 #: data/ui/prefs-dialog-gtk3.glade:1196 data/ui/prefs-dialog-gtk2.glade:1128 #: data/ui/prefs-dialog-gtk2.glade:1151 data/ui/prefs-dialog-gtk2.glade:1174 msgid "(None)" msgstr "(Nijedan)" #: data/ui/prefs-dialog-gtk3.glade:1212 data/ui/prefs-dialog-gtk2.glade:1087 msgid "Double-click a HotKey to assign a new HotKey" msgstr "Dvostrukim klikom na preÄac (HotKey) možete definirati novi preÄac" #: data/ui/prefs-dialog-gtk3.glade:1234 data/ui/prefs-dialog-gtk2.glade:1204 msgid "HotKey Settings" msgstr "Postavke preÄaca" #: data/ui/popup-menu-gtk2.glade:45 msgid "_Mute" msgstr "_IskljuÄi zvuk" #: data/ui/popup-menu-gtk2.glade:56 msgid "_Volume Control" msgstr "_Regulator glasnoće" #: data/ui/popup-menu-gtk2.glade:81 msgid "_Reload Sound" msgstr "_Ponovno pokreni Alsa" #: data/ui/prefs-dialog-gtk2.glade:106 msgid "Notify for volume changes from:" msgstr "Promjene glasnoće javi iz:" pnmixer-0.7.2/po/it.po000066400000000000000000000461241311427610600146040ustar00rootroot00000000000000# Italian translation for pnmixer. # Copyright (C) 2011 # This file is distributed under the same license as the pnmixer package. # # Mattia Bertoni , 2011. msgid "" msgstr "" "Project-Id-Version: pnmixer master\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-05-07 13:58+0700\n" "PO-Revision-Date: 2015-08-10 01:52+0200\n" "Last-Translator: Mattia Bertoni \n" "Language-Team: Italiano \n" "Language: it\n" "X-Bugs: Report translation errors to the Language-Team address.\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 1.8.2\n" #: ../src/hotkeys.c:172 #, fuzzy msgid "Could not grab the following HotKeys" msgstr "Impossibile assegnare i seguenti HotKeys:\n" #: ../src/hotkeys.c:173 ../src/ui-prefs-dialog.c:336 #: ../data/ui/prefs-dialog-gtk3.glade.h:43 #: ../data/ui/prefs-dialog-gtk2.glade.h:41 msgid "Mute/Unmute" msgstr "Muto/Non muto" #: ../src/hotkeys.c:175 ../src/ui-prefs-dialog.c:339 msgid "Volume Up" msgstr "Alza Volume" #: ../src/hotkeys.c:177 ../src/ui-prefs-dialog.c:342 msgid "Volume Down" msgstr "Abbassa Volume" #: ../src/main.c:69 #, c-format msgid "Unable to run command: %s" msgstr "Impossibile eseguire il commando: %s" #: ../src/main.c:89 msgid "" "No mixer application was found on your system. Please open preferences and " "set the command you want to run for volume control." msgstr "" "Nessuna applicazione mixer è stata trovata nel tuo sistema. Per favore apri " "le preferenze ed imposta il comando che vuoi venga eseguito per controllare " "il volume." #: ../src/main.c:109 msgid "" "You have not specified a custom command to run, please specify one in " "preferences." msgstr "" "Non è stato specificato nessun commando personalizzato da eseguire, per " "favour specificane uno nelle preferenze." #: ../src/main.c:204 ../src/main.c:242 msgid "PNMixer Error" msgstr "Errore di PNMixer" #: ../src/main.c:233 msgid "Warning: Connection to sound system failed." msgstr "Attenzione: Connessione al sistema audio fallita." #: ../src/main.c:237 #, fuzzy msgid "" "Do you want to re-initialize the audio connection ?\n" "\n" "If you do not, you will either need to restart PNMixer or select the 'Reload " "Audio' option in the right-click menu in order for PNMixer to function." msgstr "" "Vuoi re-inizializzare la connessione ad ALSA?\n" "\n" "Se non vuoi, avrai bisogno di riavviare PNMixer oppure selezionare l'opzione " "\"Ricarica ALSA\" nel menù del click destro perchè PNMixer funzioni." #. Parse options #: ../src/main.c:328 msgid "- A mixer for the system tray." msgstr "- Un mixer per la system tray." #: ../src/main.c:336 #, c-format msgid "%s version: %s\n" msgstr "%s versione: %s\n" #: ../src/notif.c:130 msgid "No sound card" msgstr "" #: ../src/notif.c:131 msgid "No playable soundcard found" msgstr "" #: ../src/notif.c:136 msgid "Soundcard disconnected" msgstr "" #: ../src/notif.c:137 msgid "Soundcard has been disconnected, reloading sound system..." msgstr "" #: ../src/prefs.c:356 #, c-format msgid "Couldn't load preferences file: %s" msgstr "Impossibile caricare il file delle preferenze: %s" #: ../src/prefs.c:365 #, c-format msgid "Couldn't load default preferences: %s" msgstr "Impossibile caricare le preferenze: %s" #: ../src/prefs.c:391 #, c-format msgid "Couldn't write preferences file: %s" msgstr "Impossibile scrivere nel file delle preferenze: %s" #: ../src/prefs.c:411 #, fuzzy, c-format msgid "'%s' exists but is not a directory, won't be able to save preferences." msgstr "" "Errore: %s esiste ma non è una cartella, sarà impossibile salvare le " "preferenze." #: ../src/prefs.c:415 #, fuzzy, c-format msgid "Couldn't make preferences directory: %s" msgstr "Impossibile creare la cartella per le preferenze: %s" #: ../src/ui-about-dialog.c:112 #, fuzzy msgid "A mixer for the system tray" msgstr "Un mixer per la system tray." #: ../src/ui-about-dialog.c:113 msgid "Copyright © 2010-2016 Nick Lanham" msgstr "Copyright © 2010-2016 Nick Lanham" #: ../src/ui-hotkey-dialog.c:48 #, fuzzy, c-format msgid "Set %s HotKey" msgstr "Assegna HotKey" #: ../src/ui-hotkey-dialog.c:52 #, fuzzy, c-format msgid "Press new HotKey for %s" msgstr "Premere il nuovo HotKey per:" #: ../src/ui-hotkey-dialog.c:150 msgid "Could not grab the keyboard." msgstr "Impossibile attivare la tastiera." #: ../src/ui-prefs-dialog.c:370 #, fuzzy msgid "None" msgstr "(Nessuno)" #: ../src/ui-prefs-dialog.c:845 msgid "Notifications" msgstr "Notifiche" #: ../src/ui-tray-icon.c:332 ../src/ui-tray-icon.c:335 #, fuzzy msgid "Volume" msgstr "Alza Volume" #: ../src/ui-tray-icon.c:335 #, fuzzy msgid "Muted" msgstr "Muto" #: ../data/desktop/pnmixer.desktop.in.h:1 msgid "System Tray Mixer" msgstr "" #: ../data/desktop/pnmixer.desktop.in.h:2 msgid "An audio mixer for the system tray" msgstr "Un mixer per la system tray." #: ../data/ui/hotkey-dialog-gtk3.glade.h:1 #: ../data/ui/prefs-dialog-gtk3.glade.h:11 msgid "Cancel" msgstr "" #: ../data/ui/hotkey-dialog-gtk3.glade.h:2 #: ../data/ui/hotkey-dialog-gtk2.glade.h:1 msgid "Defining HotKey" msgstr "Definizione HotKey" #: ../data/ui/hotkey-dialog-gtk3.glade.h:3 #: ../data/ui/hotkey-dialog-gtk2.glade.h:2 msgid "(press C to reset)" msgstr "(premere C per resettare)" #: ../data/ui/popup-menu-gtk3.glade.h:1 ../data/ui/popup-menu-gtk2.glade.h:2 msgid "Mute/Unmute Volume" msgstr "Volume Muto/Non Muto" #: ../data/ui/popup-menu-gtk3.glade.h:2 #: ../data/ui/popup-window-horizontal-gtk3.glade.h:1 #: ../data/ui/popup-window-vertical-gtk3.glade.h:1 #: ../data/ui/popup-window-horizontal-gtk2.glade.h:1 #: ../data/ui/popup-window-vertical-gtk2.glade.h:1 msgid "Mute" msgstr "Muto" #: ../data/ui/popup-menu-gtk3.glade.h:3 ../data/ui/popup-menu-gtk2.glade.h:4 msgid "Open Volume Control" msgstr "Apri Controllo del Volume" #: ../data/ui/popup-menu-gtk3.glade.h:4 ../data/ui/prefs-dialog-gtk3.glade.h:45 #: ../data/ui/prefs-dialog-gtk2.glade.h:43 msgid "Volume Control" msgstr "Controllo del Volume" #: ../data/ui/popup-menu-gtk3.glade.h:5 ../data/ui/popup-menu-gtk2.glade.h:5 msgid "Preferences" msgstr "Preferenze" #: ../data/ui/popup-menu-gtk3.glade.h:6 ../data/ui/popup-menu-gtk2.glade.h:7 #, fuzzy msgid "Reload Sound" msgstr "Ricarica ALSA" #: ../data/ui/popup-menu-gtk3.glade.h:7 ../data/ui/popup-menu-gtk2.glade.h:8 msgid "About" msgstr "Informazioni" #: ../data/ui/popup-menu-gtk3.glade.h:8 ../data/ui/popup-menu-gtk2.glade.h:9 msgid "Quit" msgstr "Esci" #: ../data/ui/popup-window-horizontal-gtk3.glade.h:2 #: ../data/ui/popup-window-vertical-gtk3.glade.h:2 #: ../data/ui/popup-window-horizontal-gtk2.glade.h:2 #: ../data/ui/popup-window-vertical-gtk2.glade.h:2 msgid "Mixer" msgstr "Mixer" #: ../data/ui/prefs-dialog-gtk3.glade.h:1 #: ../data/ui/prefs-dialog-gtk2.glade.h:1 #, fuzzy msgid "Notification support disabled at compile time." msgstr "Support alle notifiche non abilitato al momento della compilazione." #: ../data/ui/prefs-dialog-gtk3.glade.h:2 #: ../data/ui/prefs-dialog-gtk2.glade.h:2 msgid "Enable Notifications" msgstr "Abilita le Notifiche" #: ../data/ui/prefs-dialog-gtk3.glade.h:3 #: ../data/ui/prefs-dialog-gtk2.glade.h:3 #, fuzzy msgid "Timeout (ms):" msgstr "timeout (ms)" #: ../data/ui/prefs-dialog-gtk3.glade.h:4 #: ../data/ui/prefs-dialog-gtk2.glade.h:9 msgid "Notification Options" msgstr "Opzioni Notifiche" #: ../data/ui/prefs-dialog-gtk3.glade.h:5 #: ../data/ui/prefs-dialog-gtk2.glade.h:5 msgid "HotKeys" msgstr "HotKeys" #: ../data/ui/prefs-dialog-gtk3.glade.h:6 #: ../data/ui/prefs-dialog-gtk2.glade.h:6 msgid "Mouse Scroll" msgstr "Passo della Rotellina del Mouse" #: ../data/ui/prefs-dialog-gtk3.glade.h:7 #: ../data/ui/prefs-dialog-gtk2.glade.h:7 #, fuzzy msgid "Adjustment in Popups" msgstr "Aggiustamento nella Finestra di Popup" #: ../data/ui/prefs-dialog-gtk3.glade.h:8 #: ../data/ui/prefs-dialog-gtk2.glade.h:8 msgid "External Change" msgstr "Cambiamento Esterno" #: ../data/ui/prefs-dialog-gtk3.glade.h:9 #, fuzzy msgid "Notify for volume changes from:" msgstr "Notifica per le variazioni di volume da:" #: ../data/ui/prefs-dialog-gtk3.glade.h:10 #: ../data/ui/prefs-dialog-gtk2.glade.h:10 msgid "PNMixer Preferences" msgstr "Preferenze di PNMixer" #: ../data/ui/prefs-dialog-gtk3.glade.h:12 msgid "Ok" msgstr "" #: ../data/ui/prefs-dialog-gtk3.glade.h:13 #: ../data/ui/prefs-dialog-gtk2.glade.h:11 msgid "Slider Orientation:" msgstr "" #: ../data/ui/prefs-dialog-gtk3.glade.h:14 #: ../data/ui/prefs-dialog-gtk2.glade.h:12 msgid "Vertical" msgstr "" #: ../data/ui/prefs-dialog-gtk3.glade.h:15 #: ../data/ui/prefs-dialog-gtk2.glade.h:13 msgid "Horizontal" msgstr "" #: ../data/ui/prefs-dialog-gtk3.glade.h:16 #: ../data/ui/prefs-dialog-gtk2.glade.h:14 msgid "Display Text Volume" msgstr "Mostra un Testo per il Volume" #: ../data/ui/prefs-dialog-gtk3.glade.h:17 #: ../data/ui/prefs-dialog-gtk2.glade.h:15 #, fuzzy msgid "Text Volume Position:" msgstr "Posizione del Testo:" #: ../data/ui/prefs-dialog-gtk3.glade.h:18 #: ../data/ui/prefs-dialog-gtk2.glade.h:16 msgid "Top" msgstr "Alto" #: ../data/ui/prefs-dialog-gtk3.glade.h:19 #: ../data/ui/prefs-dialog-gtk2.glade.h:17 msgid "Bottom" msgstr "Sotto" #: ../data/ui/prefs-dialog-gtk3.glade.h:20 #: ../data/ui/prefs-dialog-gtk2.glade.h:18 msgid "Left" msgstr "Sinistra" #: ../data/ui/prefs-dialog-gtk3.glade.h:21 #: ../data/ui/prefs-dialog-gtk2.glade.h:19 msgid "Right" msgstr "Destra" #: ../data/ui/prefs-dialog-gtk3.glade.h:22 #: ../data/ui/prefs-dialog-gtk2.glade.h:20 #, fuzzy msgid "Volume Popup" msgstr "Scala del Volume" #: ../data/ui/prefs-dialog-gtk3.glade.h:23 #: ../data/ui/prefs-dialog-gtk2.glade.h:21 #, fuzzy msgid "Draw Volume Meter on Tray Icon" msgstr "Colore Scala del Volume:" #: ../data/ui/prefs-dialog-gtk3.glade.h:25 #: ../data/ui/prefs-dialog-gtk2.glade.h:23 #, fuzzy, no-c-format msgid "Volume Meter Offset (%):" msgstr "Offset Scala del Volume:" #: ../data/ui/prefs-dialog-gtk3.glade.h:26 #: ../data/ui/prefs-dialog-gtk2.glade.h:24 msgid "Volume Meter Color:" msgstr "Colore Scala del Volume:" #: ../data/ui/prefs-dialog-gtk3.glade.h:27 #: ../data/ui/prefs-dialog-gtk2.glade.h:25 msgid "Volume Meter" msgstr "Scala del Volume" #: ../data/ui/prefs-dialog-gtk3.glade.h:28 #: ../data/ui/prefs-dialog-gtk2.glade.h:26 msgid "Use System Theme" msgstr "" #: ../data/ui/prefs-dialog-gtk3.glade.h:29 #: ../data/ui/prefs-dialog-gtk2.glade.h:27 msgid "Icon Theme" msgstr "Tema delle Icone" #: ../data/ui/prefs-dialog-gtk3.glade.h:30 #: ../data/ui/prefs-dialog-gtk2.glade.h:28 msgid "View" msgstr "Vista" #: ../data/ui/prefs-dialog-gtk3.glade.h:31 #: ../data/ui/prefs-dialog-gtk2.glade.h:29 msgid "Card:" msgstr "Scheda:" #: ../data/ui/prefs-dialog-gtk3.glade.h:32 #: ../data/ui/prefs-dialog-gtk2.glade.h:30 msgid "Channel:" msgstr "Canale:" #: ../data/ui/prefs-dialog-gtk3.glade.h:33 #: ../data/ui/prefs-dialog-gtk2.glade.h:31 msgid "Normalize Volume:" msgstr "Normalizza Volume:" #: ../data/ui/prefs-dialog-gtk3.glade.h:34 #: ../data/ui/prefs-dialog-gtk2.glade.h:32 msgid "Change volume on a logarithmic scale, closer to human perception." msgstr "" #: ../data/ui/prefs-dialog-gtk3.glade.h:35 #: ../data/ui/prefs-dialog-gtk2.glade.h:33 msgid "Sound Device" msgstr "Dispositivo Audio" #: ../data/ui/prefs-dialog-gtk3.glade.h:36 #: ../data/ui/prefs-dialog-gtk2.glade.h:34 msgid "Device" msgstr "Dispositivo" #: ../data/ui/prefs-dialog-gtk3.glade.h:37 #: ../data/ui/prefs-dialog-gtk2.glade.h:35 msgid "Volume Control Command" msgstr "Comando per il Controllo del Volume" #: ../data/ui/prefs-dialog-gtk3.glade.h:38 #: ../data/ui/prefs-dialog-gtk2.glade.h:36 #, fuzzy msgid "Scroll Step:" msgstr "Passo della Rotellina del Mouse" #: ../data/ui/prefs-dialog-gtk3.glade.h:39 #: ../data/ui/prefs-dialog-gtk2.glade.h:37 #, fuzzy msgid "Fine Scroll Step:" msgstr "Passo della Rotellina del Mouse" #: ../data/ui/prefs-dialog-gtk3.glade.h:40 #: ../data/ui/prefs-dialog-gtk2.glade.h:38 #, fuzzy msgid "Volume Scrolling" msgstr "Scala del Volume" #: ../data/ui/prefs-dialog-gtk3.glade.h:41 #: ../data/ui/prefs-dialog-gtk2.glade.h:39 msgid "Middle Click Action:" msgstr "Azione del Click Centrale:" #: ../data/ui/prefs-dialog-gtk3.glade.h:42 #: ../data/ui/prefs-dialog-gtk2.glade.h:40 msgid "Custom Command:" msgstr "Comando Personalizzato:" #: ../data/ui/prefs-dialog-gtk3.glade.h:44 #: ../data/ui/prefs-dialog-gtk2.glade.h:42 msgid "Show Preferences" msgstr "Mostra le Preferenze" #: ../data/ui/prefs-dialog-gtk3.glade.h:46 #: ../data/ui/prefs-dialog-gtk2.glade.h:44 msgid "Custom (set below)" msgstr "Personalizza (imposta sotto)" #: ../data/ui/prefs-dialog-gtk3.glade.h:47 #: ../data/ui/prefs-dialog-gtk2.glade.h:45 msgid "Mouse" msgstr "Mouse" #: ../data/ui/prefs-dialog-gtk3.glade.h:48 #: ../data/ui/prefs-dialog-gtk2.glade.h:46 msgid "Behavior" msgstr "Comportamento" #: ../data/ui/prefs-dialog-gtk3.glade.h:49 #: ../data/ui/prefs-dialog-gtk2.glade.h:47 msgid "Enable HotKeys" msgstr "Abilita HotKeys" #: ../data/ui/prefs-dialog-gtk3.glade.h:50 #: ../data/ui/prefs-dialog-gtk2.glade.h:52 msgid "Command" msgstr "Comando" #: ../data/ui/prefs-dialog-gtk3.glade.h:51 #: ../data/ui/prefs-dialog-gtk2.glade.h:48 msgid "Mute/Unmute:" msgstr "Muto/Non muto:" #: ../data/ui/prefs-dialog-gtk3.glade.h:52 #: ../data/ui/prefs-dialog-gtk2.glade.h:49 msgid "Volume Up:" msgstr "Alza il Volume:" #: ../data/ui/prefs-dialog-gtk3.glade.h:53 #: ../data/ui/prefs-dialog-gtk2.glade.h:50 msgid "Volume Down:" msgstr "Abbassare il Volume:" #: ../data/ui/prefs-dialog-gtk3.glade.h:54 #: ../data/ui/prefs-dialog-gtk2.glade.h:51 #, fuzzy msgid "Double-click a HotKey to assign a new HotKey" msgstr "Doppio click su un HotKey per assegnare un nuovo HotKey" #: ../data/ui/prefs-dialog-gtk3.glade.h:55 #: ../data/ui/prefs-dialog-gtk2.glade.h:53 msgid "HotKey" msgstr "HotKey" #: ../data/ui/prefs-dialog-gtk3.glade.h:56 #: ../data/ui/prefs-dialog-gtk2.glade.h:54 msgid "(None)" msgstr "(Nessuno)" #: ../data/ui/prefs-dialog-gtk3.glade.h:57 #: ../data/ui/prefs-dialog-gtk2.glade.h:55 msgid "HotKey Settings" msgstr "Impostazioni HotKey" #: ../data/ui/popup-menu-gtk2.glade.h:1 msgid "_Mute" msgstr "_Muto" #: ../data/ui/popup-menu-gtk2.glade.h:3 msgid "_Volume Control" msgstr "_Controllo del Volume" #: ../data/ui/popup-menu-gtk2.glade.h:6 #, fuzzy msgid "_Reload Sound" msgstr "_Ricarica ALSA" #: ../data/ui/prefs-dialog-gtk2.glade.h:4 msgid "Notify for volume changes from:" msgstr "Notifica per le variazioni di volume da:" #, fuzzy #~ msgid "" #~ "%s (%s)\n" #~ "%s: %ld %%" #~ msgstr "" #~ "%s (%s)\n" #~ "Volume: %d %%" #, fuzzy #~ msgid "" #~ "%s (%s)\n" #~ "%s: %ld %%\n" #~ "%s" #~ msgstr "" #~ "%s (%s)\n" #~ "Volume: %d %%" #~ msgid "PNMixer" #~ msgstr "PNMixer" #~ msgid "" #~ "PNMixer is free software; you can redistribute it and/or modify it under " #~ "the terms of the GNU General Public License as published by the Free " #~ "Software Foundation; either version 3 of the License, or (at your option) " #~ "any later version.\n" #~ "\n" #~ "PNMixer 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.\n" #~ "\n" #~ "You should have received a copy of the GNU General Public License along " #~ "with PNMixer; if not, write to the Free Software Foundation, Inc., 51 " #~ "Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA." #~ msgstr "" #~ "PNMixer è un software libero; puoi ridistribuirlo e/o modificarlo sotto i " #~ "termini della GNU General Public License come pubblicato dalla Free " #~ "Software Foundation; sia la versione 3 della Licenza, o (a tua scelta) " #~ "tutte le versioni successive.\n" #~ "\n" #~ "PNMixer è distribuito nella speranza che sia utile, ma SENZA NESSUNA " #~ "GARANZIA; senza neppure la garanzia implicita di COMMERCIABILITÀ o " #~ "IDONEITÀ PER UN PARTICOLARE SCOPO. Vedi la GNU General Public License per " #~ "maggiori dettagli.\n" #~ "\n" #~ "Dovreste aver ricevuto una copia della GNU General Public License con " #~ "PNMixer; se così non fosse, scrivi alla Free Software Foundation, Inc., " #~ "51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA." #~ msgid "" #~ "French: Matthieu Bresson\n" #~ "German: Mario Blättermann\n" #~ "Italian: Mattia Bertoni\n" #~ "Russian: Pavel Serebryakov" #~ msgstr "" #~ "Italiano: Mattia Bertoni\n" #~ "Francese: Matthieu Bresson\n" #~ "Tedesco: Mario Blättermann\n" #~ "Russo: Pavel Serebryakov" #~ msgid "HotKey Volume Step:" #~ msgstr "Passo del Volume attraverso HotKey:" #~ msgid "HotKeys" #~ msgstr "HotKeys" #, fuzzy #~ msgid "Timeout (ms)" #~ msgstr "timeout (ms)" #~ msgid "" #~ "Warning: Connection to sound system failed, you probably need to restart " #~ "pnmixer\n" #~ msgstr "" #~ "Attenzione: Connessione al sistema audio fallita, probabilmente è " #~ "necessario riavviare PNMixer\n" #~ msgid "" #~ "Can't find main user interface file. Please ensure PNMixer is installed " #~ "correctly. Exiting." #~ msgstr "" #~ "Impossibile trovare il file dell'interfaccia utente principale. Per " #~ "favore assicurati che PNMixer sia installato correttamente. Uscita." #~ msgid "" #~ "Can't find about interface file. Please ensure PNMixer is installed " #~ "correctly." #~ msgstr "" #~ "Impossibile trovare il file dell'interfaccia. Per favore assicurati che " #~ "PNMixer sia installato correttamente." #~ msgid "" #~ "%s (%s)\n" #~ "Volume: %d %%\n" #~ "Muted" #~ msgstr "" #~ "%s (%s)\n" #~ "Volume: %d %%\n" #~ "Muto" #~ msgid "Couldn't find pixmap file: %s" #~ msgstr "Impossibile trovare il file pixmap: %s" #~ msgid "Failed to load pixbuf file: %s: %s" #~ msgstr "Fallito il caricamento del file pixbuf: %s: %s" #~ msgid "PNMixer Icons" #~ msgstr "Icone di PNMixer" #~ msgid "Invalid color for volume meter in config file. Reverting to default." #~ msgstr "" #~ "Colore invalido per la scala del volume nel file di configurazione. " #~ "Ritorno ai valori di default." # original string could have errors #~ msgid "Invalid widget passed to acquire_hotkey: %s" #~ msgstr "Widget non valido fornito per acquire_hotkey: %s" #~ msgid "" #~ "Can't find preferences user interface file. Please ensure PNMixer is " #~ "installed correctly." #~ msgstr "" #~ "Impossibile trovare il file delle preferenze dell'interfaccia utente. Per " #~ "favore assicurarsi che PNMixer sia installato correttamente." #~ msgid "Text" #~ msgstr "Testo" #~ msgid "" #~ "Draw Volume Meter on Tray Icon\n" #~ "(Will cause slightly higher CPU usage)" #~ msgstr "" #~ "Disegna la Scala del Volume nella Tray Icon\n" #~ "(Causerà un leggero aumento nell'uso della CPU)" #~ msgid "(Unknown)" #~ msgstr "(Sconosciuto)" #~ msgid "Volume Control..." #~ msgstr "Controllo del Volume..." #~ msgid "Unable to load icon %s: %s\n" #~ msgstr "Impossibile caricare l'icona %s: %s\n" #~ msgid "Hotkeys" #~ msgstr "Hotkeys" #~ msgid "" #~ "An unknown error occurred trying to launch your volume control command" #~ msgstr "" #~ "Un errore sconosciuto è avvenuto provando a lanciare il tuo comando per " #~ "il controllo del volume" #~ msgid "Couldn't execute custom command: \"%s\"\n" #~ msgstr "Impossibile eseguire il comando personalizzato: \"%s\"\n" pnmixer-0.7.2/po/nl.po000066400000000000000000000356341311427610600146050ustar00rootroot00000000000000# Dutch translations for PNMixer. # Copyright (C) 2017 PNMixer team (msgids) # This file is distributed under the same license as the pnmixer package. # # Benno Schulenberg , 2016, 2017. msgid "" msgstr "" "Project-Id-Version: pnmixer-0.7.1-rc3\n" "Report-Msgid-Bugs-To: https://github.com/nicklan/pnmixer/issues\n" "POT-Creation-Date: 2017-03-13 21:25+0700\n" "PO-Revision-Date: 2017-03-20 11:24+0100\n" "Last-Translator: Benno Schulenberg \n" "Language-Team: Dutch \n" "Language: nl\n" "X-Bugs: Report translation errors to the Language-Team address.\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: Lokalize 1.0\n" #: src/hotkeys.c:175 msgid "Could not grab the following HotKeys" msgstr "Kan de volgende sneltoetsen niet pakken" #: src/hotkeys.c:176 src/ui-prefs-dialog.c:339 #: data/ui/prefs-dialog-gtk3.glade:973 data/ui/prefs-dialog-gtk2.glade:935 msgid "Mute/Unmute" msgstr "Dempen/ontdempen" #: src/hotkeys.c:178 src/ui-prefs-dialog.c:342 msgid "Volume Up" msgstr "Harder" #: src/hotkeys.c:180 src/ui-prefs-dialog.c:345 msgid "Volume Down" msgstr "Zachter" #: src/main.c:69 #, c-format msgid "Unable to run command: %s" msgstr "Kan opdracht niet uitvoeren: %s" #: src/main.c:89 msgid "No mixer application was found on your system. Please open preferences and set the command you want to run for volume control." msgstr "Er is op uw systeem geen mixerprogramma gevonden. Open de Voorkeuren en stel de opdracht in die u wilt gebruiken voor volumeregeling." #: src/main.c:109 msgid "You have not specified a custom command to run, please specify one in preferences." msgstr "U hebt geen aangepaste opdracht opgegeven; geef er een op in de Voorkeuren." #: src/main.c:210 src/main.c:248 msgid "PNMixer Error" msgstr "PNMixer-fout" #: src/main.c:239 msgid "Warning: Connection to sound system failed." msgstr "Waarschuwing: verbinding met geluidssysteem is mislukt." #: src/main.c:243 msgid "" "Do you want to re-initialize the audio connection ?\n" "\n" "If you do not, you will either need to restart PNMixer or select the 'Reload Audio' option in the right-click menu in order for PNMixer to function." msgstr "" "Wilt u de audioverbinding herinitialiseren?\n" "\n" "Zo niet, dan zult u ofwel PNMixer moeten herstarten, ofwel 'Geluidsysteem herladen' in het rechtsklikmenu moeten kiezen om PNMixer te laten functioneren." #: src/main.c:334 msgid "- A mixer for the system tray." msgstr "- Een mixer voor het systeemvak" #: src/main.c:342 #, c-format msgid "%s version: %s\n" msgstr "%s-versie: %s\n" #: src/notif.c:77 msgid "Volume muted" msgstr "Volume is gedempt" #: src/notif.c:82 src/ui-tray-icon.c:355 msgid "Volume" msgstr "Volume" #: src/notif.c:135 msgid "No sound card" msgstr "Geen geluidskaart" #: src/notif.c:136 msgid "No playable soundcard found" msgstr "Geen bruikbare geluidskaart gevonden" #: src/notif.c:141 msgid "Soundcard disconnected" msgstr "Geluidskaart is niet verbonden" #: src/notif.c:142 msgid "Soundcard has been disconnected, reloading sound system..." msgstr "Geluidskaart is niet meer verbonden; herladen van geluidssysteem..." #: src/prefs.c:356 #, c-format msgid "Couldn't load preferences file: %s" msgstr "Kan voorkeurenbestand niet laden: %s" #: src/prefs.c:365 #, c-format msgid "Couldn't load default preferences: %s" msgstr "Kan standaardvoorkeuren niet laden: %s" #: src/prefs.c:391 #, c-format msgid "Couldn't write preferences file: %s" msgstr "Kan voorkeurenbestand niet schrijven: %s" #: src/prefs.c:411 #, c-format msgid "'%s' exists but is not a directory, won't be able to save preferences." msgstr "'%s' bestaat al maar is geen map; zal voorkeuren niet op kunnen slaan" #: src/prefs.c:415 #, c-format msgid "Couldn't make preferences directory: %s" msgstr "Kan voorkeurenmap niet aanmaken: %s" #: src/ui-about-dialog.c:114 msgid "A mixer for the system tray" msgstr "Een mixer voor het systeemvak" #: src/ui-about-dialog.c:115 msgid "Copyright © 2010-2016 Nick Lanham" msgstr "Copyright © 2010-2016 Nick Lanham" #: src/ui-hotkey-dialog.c:48 #, c-format msgid "Set %s HotKey" msgstr "Sneltoets voor %s instellen" #: src/ui-hotkey-dialog.c:52 #, c-format msgid "Press new HotKey for %s" msgstr "Druk op nieuwe sneltoets voor %s." #: src/ui-hotkey-dialog.c:174 msgid "Could not grab the keyboard." msgstr "Kan toetsenbord niet pakken." #: src/ui-popup-menu.c:57 src/ui-popup-menu.c:84 src/ui-popup-window.c:129 msgid "Soundcard has no mute switch" msgstr "Geluidskaart heeft geen dempingsschakelaar" #: src/ui-prefs-dialog.c:373 msgid "None" msgstr "geen" #: src/ui-prefs-dialog.c:867 msgid "Notifications" msgstr "Meldingen" #: src/ui-tray-icon.c:357 msgid "No mute switch" msgstr "Geen dempingsschakelaar" #: src/ui-tray-icon.c:359 msgid "Muted" msgstr "Gedempt" #: data/desktop/pnmixer.desktop.in:3 msgid "PNMixer" msgstr "PNMixer" #: data/desktop/pnmixer.desktop.in:4 msgid "System Tray Mixer" msgstr "Mixer voor systeemvak" #: data/desktop/pnmixer.desktop.in:5 msgid "An audio mixer for the system tray" msgstr "Een geluidsmixer voor het systeemvak" #. TRANSLATORS: Search terms to find this application. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! #: data/desktop/pnmixer.desktop.in:7 msgid "alsa;audio;mixer;sound;" msgstr "alsa;audio;geluid;mixer;sound;volume;" #. TRANSLATORS: Do NOT translate or transliterate this text (this is an icon file name)! #: data/desktop/pnmixer.desktop.in:11 msgid "pnmixer" msgstr "pnmixer" #: data/ui/hotkey-dialog-gtk3.glade:55 data/ui/prefs-dialog-gtk3.glade:279 msgid "Cancel" msgstr "Annuleren" #: data/ui/hotkey-dialog-gtk3.glade:109 data/ui/hotkey-dialog-gtk2.glade:49 msgid "Defining HotKey" msgstr "Definiëren van sneltoets" #: data/ui/hotkey-dialog-gtk3.glade:124 data/ui/hotkey-dialog-gtk2.glade:65 msgid "(press C to reset)" msgstr "(druk op C voor reset)" #: data/ui/popup-menu-gtk3.glade:33 data/ui/popup-menu-gtk2.glade:49 msgid "Mute/Unmute Volume" msgstr "Dempen/ontdempen" #: data/ui/popup-menu-gtk3.glade:58 #: data/ui/popup-window-horizontal-gtk3.glade:54 #: data/ui/popup-window-vertical-gtk3.glade:58 #: data/ui/popup-window-horizontal-gtk2.glade:56 #: data/ui/popup-window-vertical-gtk2.glade:58 msgid "Mute" msgstr "Dempen" #: data/ui/popup-menu-gtk3.glade:73 data/ui/popup-menu-gtk2.glade:60 msgid "Open Volume Control" msgstr "Volumeregeling openen" # Misschien is "Eigenschappenbalk" beter? #: data/ui/popup-menu-gtk3.glade:95 data/ui/prefs-dialog-gtk3.glade:975 #: data/ui/prefs-dialog-gtk2.glade:937 msgid "Volume Control" msgstr "Volumeregeling" #: data/ui/popup-menu-gtk3.glade:110 data/ui/popup-menu-gtk3.glade:133 #: data/ui/popup-menu-gtk2.glade:73 msgid "Preferences" msgstr "Voorkeuren" #: data/ui/popup-menu-gtk3.glade:148 data/ui/popup-menu-gtk3.glade:171 #: data/ui/popup-menu-gtk2.glade:85 msgid "Reload Sound" msgstr "Geluidssysteem herladen" #: data/ui/popup-menu-gtk3.glade:186 data/ui/popup-menu-gtk3.glade:209 #: data/ui/popup-menu-gtk2.glade:98 msgid "About" msgstr "Info" # Verleden tijd, "Afgesloten", net als de andere actiesignaalnamen. #: data/ui/popup-menu-gtk3.glade:231 data/ui/popup-menu-gtk3.glade:254 #: data/ui/popup-menu-gtk2.glade:117 msgid "Quit" msgstr "Afsluiten" #: data/ui/popup-window-horizontal-gtk3.glade:81 #: data/ui/popup-window-vertical-gtk3.glade:74 #: data/ui/popup-window-horizontal-gtk2.glade:72 #: data/ui/popup-window-vertical-gtk2.glade:74 msgid "Mixer" msgstr "Mixer" #: data/ui/prefs-dialog-gtk3.glade:43 data/ui/prefs-dialog-gtk2.glade:68 msgid "Timeout (ms):" msgstr "Tijdslimiet (ms):" #: data/ui/prefs-dialog-gtk3.glade:65 data/ui/prefs-dialog-gtk2.glade:46 msgid "Enable Notifications" msgstr "Meldingen inschakelen" #: data/ui/prefs-dialog-gtk3.glade:89 data/ui/prefs-dialog-gtk2.glade:210 msgid "Notification Options" msgstr "Meldingsopties" #: data/ui/prefs-dialog-gtk3.glade:116 data/ui/prefs-dialog-gtk3.glade:1255 #: data/ui/prefs-dialog-gtk2.glade:125 data/ui/prefs-dialog-gtk2.glade:1225 msgid "HotKeys" msgstr "Sneltoetsen" #: data/ui/prefs-dialog-gtk3.glade:132 data/ui/prefs-dialog-gtk2.glade:146 msgid "Mouse Scroll" msgstr "Muiswiel" #: data/ui/prefs-dialog-gtk3.glade:148 data/ui/prefs-dialog-gtk2.glade:167 msgid "Adjustment in Popups" msgstr "Aanpassing in pop-ups" #: data/ui/prefs-dialog-gtk3.glade:164 data/ui/prefs-dialog-gtk2.glade:188 msgid "External Change" msgstr "Externe wijziging" #: data/ui/prefs-dialog-gtk3.glade:185 msgid "Notify for volume changes from:" msgstr "Melding geven van volumewijzigingen van:" #: data/ui/prefs-dialog-gtk3.glade:212 data/ui/prefs-dialog-gtk2.glade:12 msgid "Notification support disabled at compile time." msgstr "Ondersteuning voor meldingen is uitgeschakeld bij het compileren." #: data/ui/prefs-dialog-gtk3.glade:236 data/ui/prefs-dialog-gtk2.glade:241 msgid "PNMixer Preferences" msgstr "PNMixer-voorkeuren" #: data/ui/prefs-dialog-gtk3.glade:324 msgid "Ok" msgstr "OK" #: data/ui/prefs-dialog-gtk3.glade:369 msgid "Apply" msgstr "Toepassen" #: data/ui/prefs-dialog-gtk3.glade:427 data/ui/prefs-dialog-gtk2.glade:338 msgid "Card:" msgstr "Kaart:" #: data/ui/prefs-dialog-gtk3.glade:439 data/ui/prefs-dialog-gtk2.glade:349 msgid "Channel:" msgstr "Kanaal:" #: data/ui/prefs-dialog-gtk3.glade:450 data/ui/prefs-dialog-gtk2.glade:409 msgid "Change volume on a logarithmic scale, closer to human perception." msgstr "Volume volgens logaritmische schaal wijzigen, dichter bij menselijke waarneming." #: data/ui/prefs-dialog-gtk3.glade:452 data/ui/prefs-dialog-gtk2.glade:408 msgid "Normalize Volume:" msgstr "Volume normaliseren:" #: data/ui/prefs-dialog-gtk3.glade:502 data/ui/prefs-dialog-gtk2.glade:425 msgid "Sound Device" msgstr "Geluidsapparaat" #: data/ui/prefs-dialog-gtk3.glade:520 data/ui/prefs-dialog-gtk2.glade:443 msgid "Device" msgstr "Apparaat" #: data/ui/prefs-dialog-gtk3.glade:555 data/ui/prefs-dialog-gtk2.glade:477 msgid "Slider Orientation:" msgstr "Oriëntatie van schuifregelaar:" #: data/ui/prefs-dialog-gtk3.glade:567 data/ui/prefs-dialog-gtk2.glade:520 msgid "Text Volume Position:" msgstr "Positie van volumetekst:" #: data/ui/prefs-dialog-gtk3.glade:576 data/ui/prefs-dialog-gtk2.glade:501 msgid "Display Text Volume" msgstr "Volumetekst tonen" #: data/ui/prefs-dialog-gtk3.glade:596 data/ui/prefs-dialog-gtk2.glade:489 msgid "Vertical" msgstr "verticaal" #: data/ui/prefs-dialog-gtk3.glade:597 data/ui/prefs-dialog-gtk2.glade:490 msgid "Horizontal" msgstr "horizontaal" #: data/ui/prefs-dialog-gtk3.glade:611 data/ui/prefs-dialog-gtk2.glade:534 msgid "Top" msgstr "bovenaan" #: data/ui/prefs-dialog-gtk3.glade:612 data/ui/prefs-dialog-gtk2.glade:535 msgid "Bottom" msgstr "onderaan" #: data/ui/prefs-dialog-gtk3.glade:613 data/ui/prefs-dialog-gtk2.glade:536 msgid "Left" msgstr "links" #: data/ui/prefs-dialog-gtk3.glade:614 data/ui/prefs-dialog-gtk2.glade:537 msgid "Right" msgstr "rechts" #: data/ui/prefs-dialog-gtk3.glade:632 data/ui/prefs-dialog-gtk2.glade:556 msgid "Volume Popup" msgstr "Volume-pop-up" #: data/ui/prefs-dialog-gtk3.glade:663 data/ui/prefs-dialog-gtk2.glade:619 msgid "Volume Meter Color:" msgstr "Volumemeterkleur:" #: data/ui/prefs-dialog-gtk3.glade:675 data/ui/prefs-dialog-gtk2.glade:606 msgid "Volume Meter Offset (%):" msgstr "Volumemeterverspringing (%):" #: data/ui/prefs-dialog-gtk3.glade:713 data/ui/prefs-dialog-gtk2.glade:589 msgid "Draw Volume Meter on Tray Icon" msgstr "Volumemeter tonen in systeemvakpictogram" #: data/ui/prefs-dialog-gtk3.glade:735 data/ui/prefs-dialog-gtk2.glade:672 msgid "Volume Meter" msgstr "Volumemeter" #: data/ui/prefs-dialog-gtk3.glade:755 data/ui/prefs-dialog-gtk2.glade:699 msgid "Use System Theme" msgstr "Systeemthema gebruiken" #: data/ui/prefs-dialog-gtk3.glade:770 data/ui/prefs-dialog-gtk2.glade:712 msgid "Icon Theme" msgstr "Pictogramthema" #: data/ui/prefs-dialog-gtk3.glade:791 data/ui/prefs-dialog-gtk2.glade:732 msgid "View" msgstr "Beeld" #: data/ui/prefs-dialog-gtk3.glade:829 data/ui/prefs-dialog-gtk2.glade:772 msgid "Volume Control Command" msgstr "Volumeregelingsopdracht" #: data/ui/prefs-dialog-gtk3.glade:860 data/ui/prefs-dialog-gtk2.glade:808 msgid "Scroll Step:" msgstr "Scrollstap:" #: data/ui/prefs-dialog-gtk3.glade:872 data/ui/prefs-dialog-gtk2.glade:819 msgid "Fine Scroll Step:" msgstr "Fijne scrollstap:" #: data/ui/prefs-dialog-gtk3.glade:918 data/ui/prefs-dialog-gtk2.glade:875 msgid "Volume Scrolling" msgstr "Volume-scrollen" #: data/ui/prefs-dialog-gtk3.glade:949 data/ui/prefs-dialog-gtk2.glade:922 msgid "Custom Command:" msgstr "Aangepaste opdracht:" #: data/ui/prefs-dialog-gtk3.glade:961 data/ui/prefs-dialog-gtk2.glade:911 msgid "Middle Click Action:" msgstr "Midklik-actie:" #: data/ui/prefs-dialog-gtk3.glade:974 data/ui/prefs-dialog-gtk2.glade:936 msgid "Show Preferences" msgstr "Voorkeuren tonen" #: data/ui/prefs-dialog-gtk3.glade:976 data/ui/prefs-dialog-gtk2.glade:938 msgid "Custom (set below)" msgstr "Aangepast (hieronder instellen)" #: data/ui/prefs-dialog-gtk3.glade:1005 data/ui/prefs-dialog-gtk2.glade:974 msgid "Mouse" msgstr "Muis" #: data/ui/prefs-dialog-gtk3.glade:1026 data/ui/prefs-dialog-gtk2.glade:995 msgid "Behavior" msgstr "Gedrag" #: data/ui/prefs-dialog-gtk3.glade:1057 data/ui/prefs-dialog-gtk2.glade:1025 msgid "Enable HotKeys" msgstr "Sneltoetsen inschakelen" #: data/ui/prefs-dialog-gtk3.glade:1085 data/ui/prefs-dialog-gtk2.glade:1099 msgid "Command" msgstr "Opdracht" #: data/ui/prefs-dialog-gtk3.glade:1100 data/ui/prefs-dialog-gtk2.glade:1052 msgid "Mute/Unmute:" msgstr "Dempen/ontdempen:" #: data/ui/prefs-dialog-gtk3.glade:1112 data/ui/prefs-dialog-gtk2.glade:1064 msgid "Volume Up:" msgstr "Harder:" #: data/ui/prefs-dialog-gtk3.glade:1124 data/ui/prefs-dialog-gtk2.glade:1076 msgid "Volume Down:" msgstr "Zachter:" #: data/ui/prefs-dialog-gtk3.glade:1135 data/ui/prefs-dialog-gtk2.glade:1109 msgid "HotKey" msgstr "Sneltoets" #: data/ui/prefs-dialog-gtk3.glade:1154 data/ui/prefs-dialog-gtk3.glade:1175 #: data/ui/prefs-dialog-gtk3.glade:1196 data/ui/prefs-dialog-gtk2.glade:1128 #: data/ui/prefs-dialog-gtk2.glade:1151 data/ui/prefs-dialog-gtk2.glade:1174 msgid "(None)" msgstr "(geen)" #: data/ui/prefs-dialog-gtk3.glade:1212 data/ui/prefs-dialog-gtk2.glade:1087 msgid "Double-click a HotKey to assign a new HotKey" msgstr "Dubbelklik op een sneltoets om een nieuwe sneltoets toe te wijzen." #: data/ui/prefs-dialog-gtk3.glade:1234 data/ui/prefs-dialog-gtk2.glade:1204 msgid "HotKey Settings" msgstr "Sneltoetsinstellingen" #: data/ui/popup-menu-gtk2.glade:45 msgid "_Mute" msgstr "_Dempen" # Misschien is "Eigenschappenbalk" beter? #: data/ui/popup-menu-gtk2.glade:56 msgid "_Volume Control" msgstr "_Volumeregeling" #: data/ui/popup-menu-gtk2.glade:81 msgid "_Reload Sound" msgstr "_Geluidssysteem herladen" #: data/ui/prefs-dialog-gtk2.glade:106 msgid "Notify for volume changes from:" msgstr "Melding geven van volumewijzigingen van:" pnmixer-0.7.2/po/pnmixer.pot000066400000000000000000000277711311427610600160450ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR Copyright ( C ) 2010-2017 Nick Lanham # This file is distributed under the same license as the pnmixer package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: pnmixer 0.7.1\n" "Report-Msgid-Bugs-To: https://github.com/nicklan/pnmixer/issues\n" "POT-Creation-Date: 2017-05-19 11:23+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: src/hotkeys.c:175 msgid "Could not grab the following HotKeys" msgstr "" #: src/hotkeys.c:176 src/ui-prefs-dialog.c:339 #: data/ui/prefs-dialog-gtk3.glade:973 data/ui/prefs-dialog-gtk2.glade:935 msgid "Mute/Unmute" msgstr "" #: src/hotkeys.c:178 src/ui-prefs-dialog.c:342 msgid "Volume Up" msgstr "" #: src/hotkeys.c:180 src/ui-prefs-dialog.c:345 msgid "Volume Down" msgstr "" #: src/main.c:69 #, c-format msgid "Unable to run command: %s" msgstr "" #: src/main.c:89 msgid "" "No mixer application was found on your system. Please open preferences and " "set the command you want to run for volume control." msgstr "" #: src/main.c:109 msgid "" "You have not specified a custom command to run, please specify one in " "preferences." msgstr "" #: src/main.c:210 src/main.c:248 msgid "PNMixer Error" msgstr "" #: src/main.c:239 msgid "Warning: Connection to sound system failed." msgstr "" #: src/main.c:243 msgid "" "Do you want to re-initialize the audio connection ?\n" "\n" "If you do not, you will either need to restart PNMixer or select the 'Reload " "Audio' option in the right-click menu in order for PNMixer to function." msgstr "" #: src/main.c:334 msgid "- A mixer for the system tray." msgstr "" #: src/main.c:342 #, c-format msgid "%s version: %s\n" msgstr "" #: src/notif.c:77 msgid "Volume muted" msgstr "" #: src/notif.c:82 src/ui-tray-icon.c:355 msgid "Volume" msgstr "" #: src/notif.c:135 msgid "No sound card" msgstr "" #: src/notif.c:136 msgid "No playable soundcard found" msgstr "" #: src/notif.c:141 msgid "Soundcard disconnected" msgstr "" #: src/notif.c:142 msgid "Soundcard has been disconnected, reloading sound system..." msgstr "" #: src/prefs.c:356 #, c-format msgid "Couldn't load preferences file: %s" msgstr "" #: src/prefs.c:365 #, c-format msgid "Couldn't load default preferences: %s" msgstr "" #: src/prefs.c:391 #, c-format msgid "Couldn't write preferences file: %s" msgstr "" #: src/prefs.c:411 #, c-format msgid "'%s' exists but is not a directory, won't be able to save preferences." msgstr "" #: src/prefs.c:415 #, c-format msgid "Couldn't make preferences directory: %s" msgstr "" #: src/ui-about-dialog.c:114 msgid "A mixer for the system tray" msgstr "" #: src/ui-about-dialog.c:115 msgid "Copyright © 2010-2017 Nick Lanham" msgstr "" #: src/ui-hotkey-dialog.c:48 #, c-format msgid "Set %s HotKey" msgstr "" #: src/ui-hotkey-dialog.c:52 #, c-format msgid "Press new HotKey for %s" msgstr "" #: src/ui-hotkey-dialog.c:174 msgid "Could not grab the keyboard." msgstr "" #: src/ui-popup-menu.c:57 src/ui-popup-menu.c:84 src/ui-popup-window.c:129 msgid "Soundcard has no mute switch" msgstr "" #: src/ui-prefs-dialog.c:373 msgid "None" msgstr "" #: src/ui-prefs-dialog.c:867 msgid "Notifications" msgstr "" #: src/ui-tray-icon.c:357 msgid "No mute switch" msgstr "" #: src/ui-tray-icon.c:359 msgid "Muted" msgstr "" #: data/desktop/pnmixer.desktop.in:3 msgid "PNMixer" msgstr "" #: data/desktop/pnmixer.desktop.in:4 msgid "System Tray Mixer" msgstr "" #: data/desktop/pnmixer.desktop.in:5 msgid "An audio mixer for the system tray" msgstr "" #. TRANSLATORS: Search terms to find this application. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! #: data/desktop/pnmixer.desktop.in:7 msgid "alsa;audio;mixer;sound;" msgstr "" #. TRANSLATORS: Do NOT translate or transliterate this text (this is an icon file name)! #: data/desktop/pnmixer.desktop.in:11 msgid "pnmixer" msgstr "" #: data/ui/hotkey-dialog-gtk3.glade:55 data/ui/prefs-dialog-gtk3.glade:279 msgid "Cancel" msgstr "" #: data/ui/hotkey-dialog-gtk3.glade:109 data/ui/hotkey-dialog-gtk2.glade:49 msgid "Defining HotKey" msgstr "" #: data/ui/hotkey-dialog-gtk3.glade:124 data/ui/hotkey-dialog-gtk2.glade:65 msgid "(press C to reset)" msgstr "" #: data/ui/popup-menu-gtk3.glade:33 data/ui/popup-menu-gtk2.glade:49 msgid "Mute/Unmute Volume" msgstr "" #: data/ui/popup-menu-gtk3.glade:58 #: data/ui/popup-window-horizontal-gtk3.glade:54 #: data/ui/popup-window-vertical-gtk3.glade:58 #: data/ui/popup-window-horizontal-gtk2.glade:56 #: data/ui/popup-window-vertical-gtk2.glade:58 msgid "Mute" msgstr "" #: data/ui/popup-menu-gtk3.glade:73 data/ui/popup-menu-gtk2.glade:60 msgid "Open Volume Control" msgstr "" #: data/ui/popup-menu-gtk3.glade:95 data/ui/prefs-dialog-gtk3.glade:975 #: data/ui/prefs-dialog-gtk2.glade:937 msgid "Volume Control" msgstr "" #: data/ui/popup-menu-gtk3.glade:110 data/ui/popup-menu-gtk3.glade:133 #: data/ui/popup-menu-gtk2.glade:73 msgid "Preferences" msgstr "" #: data/ui/popup-menu-gtk3.glade:148 data/ui/popup-menu-gtk3.glade:171 #: data/ui/popup-menu-gtk2.glade:85 msgid "Reload Sound" msgstr "" #: data/ui/popup-menu-gtk3.glade:186 data/ui/popup-menu-gtk3.glade:209 #: data/ui/popup-menu-gtk2.glade:98 msgid "About" msgstr "" #: data/ui/popup-menu-gtk3.glade:231 data/ui/popup-menu-gtk3.glade:254 #: data/ui/popup-menu-gtk2.glade:117 msgid "Quit" msgstr "" #: data/ui/popup-window-horizontal-gtk3.glade:81 #: data/ui/popup-window-vertical-gtk3.glade:74 #: data/ui/popup-window-horizontal-gtk2.glade:72 #: data/ui/popup-window-vertical-gtk2.glade:74 msgid "Mixer" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:43 data/ui/prefs-dialog-gtk2.glade:68 msgid "Timeout (ms):" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:65 data/ui/prefs-dialog-gtk2.glade:46 msgid "Enable Notifications" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:89 data/ui/prefs-dialog-gtk2.glade:210 msgid "Notification Options" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:116 data/ui/prefs-dialog-gtk3.glade:1255 #: data/ui/prefs-dialog-gtk2.glade:125 data/ui/prefs-dialog-gtk2.glade:1225 msgid "HotKeys" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:132 data/ui/prefs-dialog-gtk2.glade:146 msgid "Mouse Scroll" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:148 data/ui/prefs-dialog-gtk2.glade:167 msgid "Adjustment in Popups" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:164 data/ui/prefs-dialog-gtk2.glade:188 msgid "External Change" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:185 msgid "Notify for volume changes from:" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:212 data/ui/prefs-dialog-gtk2.glade:12 msgid "Notification support disabled at compile time." msgstr "" #: data/ui/prefs-dialog-gtk3.glade:236 data/ui/prefs-dialog-gtk2.glade:241 msgid "PNMixer Preferences" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:324 msgid "Ok" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:369 msgid "Apply" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:427 data/ui/prefs-dialog-gtk2.glade:338 msgid "Card:" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:439 data/ui/prefs-dialog-gtk2.glade:349 msgid "Channel:" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:450 data/ui/prefs-dialog-gtk2.glade:409 msgid "Change volume on a logarithmic scale, closer to human perception." msgstr "" #: data/ui/prefs-dialog-gtk3.glade:452 data/ui/prefs-dialog-gtk2.glade:408 msgid "Normalize Volume:" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:502 data/ui/prefs-dialog-gtk2.glade:425 msgid "Sound Device" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:520 data/ui/prefs-dialog-gtk2.glade:443 msgid "Device" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:555 data/ui/prefs-dialog-gtk2.glade:477 msgid "Slider Orientation:" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:567 data/ui/prefs-dialog-gtk2.glade:520 msgid "Text Volume Position:" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:576 data/ui/prefs-dialog-gtk2.glade:501 msgid "Display Text Volume" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:596 data/ui/prefs-dialog-gtk2.glade:489 msgid "Vertical" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:597 data/ui/prefs-dialog-gtk2.glade:490 msgid "Horizontal" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:611 data/ui/prefs-dialog-gtk2.glade:534 msgid "Top" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:612 data/ui/prefs-dialog-gtk2.glade:535 msgid "Bottom" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:613 data/ui/prefs-dialog-gtk2.glade:536 msgid "Left" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:614 data/ui/prefs-dialog-gtk2.glade:537 msgid "Right" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:632 data/ui/prefs-dialog-gtk2.glade:556 msgid "Volume Popup" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:663 data/ui/prefs-dialog-gtk2.glade:619 msgid "Volume Meter Color:" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:675 data/ui/prefs-dialog-gtk2.glade:606 msgid "Volume Meter Offset (%):" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:713 data/ui/prefs-dialog-gtk2.glade:589 msgid "Draw Volume Meter on Tray Icon" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:735 data/ui/prefs-dialog-gtk2.glade:672 msgid "Volume Meter" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:755 data/ui/prefs-dialog-gtk2.glade:699 msgid "Use System Theme" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:770 data/ui/prefs-dialog-gtk2.glade:712 msgid "Icon Theme" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:791 data/ui/prefs-dialog-gtk2.glade:732 msgid "View" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:829 data/ui/prefs-dialog-gtk2.glade:772 msgid "Volume Control Command" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:860 data/ui/prefs-dialog-gtk2.glade:808 msgid "Scroll Step:" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:872 data/ui/prefs-dialog-gtk2.glade:819 msgid "Fine Scroll Step:" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:918 data/ui/prefs-dialog-gtk2.glade:875 msgid "Volume Scrolling" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:949 data/ui/prefs-dialog-gtk2.glade:922 msgid "Custom Command:" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:961 data/ui/prefs-dialog-gtk2.glade:911 msgid "Middle Click Action:" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:974 data/ui/prefs-dialog-gtk2.glade:936 msgid "Show Preferences" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:976 data/ui/prefs-dialog-gtk2.glade:938 msgid "Custom (set below)" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:1005 data/ui/prefs-dialog-gtk2.glade:974 msgid "Mouse" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:1026 data/ui/prefs-dialog-gtk2.glade:995 msgid "Behavior" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:1057 data/ui/prefs-dialog-gtk2.glade:1025 msgid "Enable HotKeys" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:1085 data/ui/prefs-dialog-gtk2.glade:1099 msgid "Command" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:1100 data/ui/prefs-dialog-gtk2.glade:1052 msgid "Mute/Unmute:" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:1112 data/ui/prefs-dialog-gtk2.glade:1064 msgid "Volume Up:" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:1124 data/ui/prefs-dialog-gtk2.glade:1076 msgid "Volume Down:" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:1135 data/ui/prefs-dialog-gtk2.glade:1109 msgid "HotKey" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:1154 data/ui/prefs-dialog-gtk3.glade:1175 #: data/ui/prefs-dialog-gtk3.glade:1196 data/ui/prefs-dialog-gtk2.glade:1128 #: data/ui/prefs-dialog-gtk2.glade:1151 data/ui/prefs-dialog-gtk2.glade:1174 msgid "(None)" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:1212 data/ui/prefs-dialog-gtk2.glade:1087 msgid "Double-click a HotKey to assign a new HotKey" msgstr "" #: data/ui/prefs-dialog-gtk3.glade:1234 data/ui/prefs-dialog-gtk2.glade:1204 msgid "HotKey Settings" msgstr "" #: data/ui/popup-menu-gtk2.glade:45 msgid "_Mute" msgstr "" #: data/ui/popup-menu-gtk2.glade:56 msgid "_Volume Control" msgstr "" #: data/ui/popup-menu-gtk2.glade:81 msgid "_Reload Sound" msgstr "" #: data/ui/prefs-dialog-gtk2.glade:106 msgid "Notify for volume changes from:" msgstr "" pnmixer-0.7.2/po/ru.po000066400000000000000000000562031311427610600146150ustar00rootroot00000000000000# Russian translation for pnmixer. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the pnmixer package. # # Pavel Serebryakov , 2014. msgid "" msgstr "" "Project-Id-Version: pnmixer 0.7\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-09-16 10:05+0700\n" "PO-Revision-Date: 2016-06-23 19:30+0300\n" "Last-Translator: Pavel Roschin \n" "Language-Team: \n" "Language: ru\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Bugs: Report translation errors to the Language-Team address.\n" "X-Generator: Poedit 1.8.3\n" #: ../src/hotkeys.c:172 #, fuzzy msgid "Could not grab the following HotKeys" msgstr "Ðе удалоÑÑŒ запиÑать Ñледующие ÑÐ¾Ñ‡ÐµÑ‚Ð°Ð½Ð¸Ñ ÐºÐ»Ð°Ð²Ð¸Ñˆ:\n" #: ../src/hotkeys.c:173 ../src/ui-prefs-dialog.c:339 #: ../data/ui/prefs-dialog-gtk3.glade.h:44 #: ../data/ui/prefs-dialog-gtk2.glade.h:41 msgid "Mute/Unmute" msgstr "Вкл/выкл звук" #: ../src/hotkeys.c:175 ../src/ui-prefs-dialog.c:342 msgid "Volume Up" msgstr "Увеличить громкоÑть" #: ../src/hotkeys.c:177 ../src/ui-prefs-dialog.c:345 msgid "Volume Down" msgstr "Уменьшить громкоÑть" #: ../src/main.c:69 #, c-format msgid "Unable to run command: %s" msgstr "Ðе удалоÑÑŒ выполнить команду: %s" #: ../src/main.c:89 msgid "" "No mixer application was found on your system. Please open preferences and " "set the command you want to run for volume control." msgstr "" "Ð’ вашей ÑиÑтеме не обнаружено приложений микшированиÑ. ПожалуйÑта, откройте " "наÑтройки и задайте желаемую команду ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð³Ñ€Ð¾Ð¼ÐºÐ¾Ñтью" #: ../src/main.c:109 msgid "" "You have not specified a custom command to run, please specify one in " "preferences." msgstr "" "Ð’Ñ‹ не задали команду Ð´Ð»Ñ Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ, пожалуйÑта, Ñделайте Ñто в наÑтройках." #: ../src/main.c:210 ../src/main.c:248 msgid "PNMixer Error" msgstr "Ошибка PNMixer" #: ../src/main.c:239 msgid "Warning: Connection to sound system failed." msgstr "Внимание: не удалоÑÑŒ подключитьÑÑ Ðº звуковой подÑиÑтеме" #: ../src/main.c:243 msgid "" "Do you want to re-initialize the audio connection ?\n" "\n" "If you do not, you will either need to restart PNMixer or select the 'Reload " "Audio' option in the right-click menu in order for PNMixer to function." msgstr "" "Ð’Ñ‹ хотите переуÑтановить Ñоединение Ñ Ð·Ð²ÑƒÐºÐ¾Ð²Ñ‹Ð¼ Ñервером?\n" "\n" "ЕÑли нет, вам необходимо будет либо перезапуÑтить PNMixer, либо выбрать " "опцию 'Перезагрузить звук' в меню правой кнопки, чтобы PNMixer работал." #. Parse options #: ../src/main.c:334 msgid "- A mixer for the system tray." msgstr "- Звуковой микшер Ð´Ð»Ñ Ð¾Ð±Ð»Ð°Ñти уведомлений." #: ../src/main.c:342 #, c-format msgid "%s version: %s\n" msgstr "%s верÑиÑ: %s\n" #: ../src/notif.c:133 msgid "No sound card" msgstr "Ðет звуковой карты" #: ../src/notif.c:134 msgid "No playable soundcard found" msgstr "Ðе найдена Ð·Ð²ÑƒÐºÐ¾Ð²Ð°Ñ ÐºÐ°Ñ€Ñ‚Ð° Ð´Ð»Ñ Ð²Ð¾ÑпроизведениÑ" #: ../src/notif.c:139 msgid "Soundcard disconnected" msgstr "Ð—Ð²ÑƒÐºÐ¾Ð²Ð°Ñ ÐºÐ°Ñ€Ñ‚Ð° отключена" #: ../src/notif.c:140 msgid "Soundcard has been disconnected, reloading sound system..." msgstr "Ð—Ð²ÑƒÐºÐ¾Ð²Ð°Ñ ÐºÐ°Ñ€Ñ‚Ð° была отключена, перезагружаем звуковую ÑиÑтему..." #: ../src/prefs.c:355 #, c-format msgid "Couldn't load preferences file: %s" msgstr "Ðе удалоÑÑŒ загрузить файл наÑтроек: %s" #: ../src/prefs.c:364 #, c-format msgid "Couldn't load default preferences: %s" msgstr "Ðе удалоÑÑŒ загрузить наÑтройки по умолчанию: %s" #: ../src/prefs.c:390 #, c-format msgid "Couldn't write preferences file: %s" msgstr "Ðе удалоÑÑŒ запиÑать файл наÑтроек: %s" #: ../src/prefs.c:410 #, c-format msgid "'%s' exists but is not a directory, won't be able to save preferences." msgstr "" "Ошибка: %s ÑущеÑтвует, но не ÑвлÑетÑÑ ÐºÐ°Ñ‚Ð°Ð»Ð¾Ð³Ð¾Ð¼, Ñохранить наÑтройки не " "получитÑÑ" #: ../src/prefs.c:414 #, c-format msgid "Couldn't make preferences directory: %s" msgstr "Ðе удалоÑÑŒ Ñоздать каталог наÑтроек: %s" #: ../src/ui-about-dialog.c:116 msgid "A mixer for the system tray" msgstr "Звуковой микшер Ð´Ð»Ñ Ð¿Ð°Ð½ÐµÐ»Ð¸ уведомлений" #: ../src/ui-about-dialog.c:117 msgid "Copyright © 2010-2016 Nick Lanham" msgstr "ÐвторÑкие права © 2010-2016 Nick Lanham" #: ../src/ui-hotkey-dialog.c:48 #, c-format msgid "Set %s HotKey" msgstr "Ðазначить горÑчую клавишу %s" #: ../src/ui-hotkey-dialog.c:52 #, c-format msgid "Press new HotKey for %s" msgstr "Ðажмите новую клавишу Ð´Ð»Ñ %s" #: ../src/ui-hotkey-dialog.c:174 msgid "Could not grab the keyboard." msgstr "Ðе удалоÑÑŒ захватить клавиатуру." #: ../src/ui-prefs-dialog.c:373 msgid "None" msgstr "ПуÑто" #: ../src/ui-prefs-dialog.c:867 msgid "Notifications" msgstr "YведомлениÑ" #: ../src/ui-tray-icon.c:353 ../src/ui-tray-icon.c:356 msgid "Volume" msgstr "ГромкоÑть" #: ../src/ui-tray-icon.c:356 msgid "Muted" msgstr "Выкл. звук" #: ../data/desktop/pnmixer.desktop.in.h:1 msgid "System Tray Mixer" msgstr "Микшер Ð´Ð»Ñ Ð¿Ð°Ð½ÐµÐ»Ð¸ уведомлений" #: ../data/desktop/pnmixer.desktop.in.h:2 msgid "An audio mixer for the system tray" msgstr "Звуковой микшер Ð´Ð»Ñ Ð¿Ð°Ð½ÐµÐ»Ð¸ уведомлений" #. TRANSLATORS: Search terms to find this application. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! #: ../data/desktop/pnmixer.desktop.in.h:4 msgid "alsa;audio;mixer;sound;" msgstr "" #: ../data/ui/hotkey-dialog-gtk3.glade.h:1 #: ../data/ui/prefs-dialog-gtk3.glade.h:11 msgid "Cancel" msgstr "Отмена" #: ../data/ui/hotkey-dialog-gtk3.glade.h:2 #: ../data/ui/hotkey-dialog-gtk2.glade.h:1 msgid "Defining HotKey" msgstr "УÑтанавливаю Ñочетание клавиш" #: ../data/ui/hotkey-dialog-gtk3.glade.h:3 #: ../data/ui/hotkey-dialog-gtk2.glade.h:2 msgid "(press C to reset)" msgstr "(нажмите C Ð´Ð»Ñ ÑброÑа)" #: ../data/ui/popup-menu-gtk3.glade.h:1 ../data/ui/popup-menu-gtk2.glade.h:2 msgid "Mute/Unmute Volume" msgstr "Вкл/выкл звук" #: ../data/ui/popup-menu-gtk3.glade.h:2 #: ../data/ui/popup-window-horizontal-gtk3.glade.h:1 #: ../data/ui/popup-window-vertical-gtk3.glade.h:1 #: ../data/ui/popup-window-horizontal-gtk2.glade.h:1 #: ../data/ui/popup-window-vertical-gtk2.glade.h:1 msgid "Mute" msgstr "Выкл. звук" #: ../data/ui/popup-menu-gtk3.glade.h:3 ../data/ui/popup-menu-gtk2.glade.h:4 msgid "Open Volume Control" msgstr "ÐаÑтройки громкоÑти" #: ../data/ui/popup-menu-gtk3.glade.h:4 ../data/ui/prefs-dialog-gtk3.glade.h:46 #: ../data/ui/prefs-dialog-gtk2.glade.h:43 msgid "Volume Control" msgstr "Управление громкоÑтью" #: ../data/ui/popup-menu-gtk3.glade.h:5 ../data/ui/popup-menu-gtk2.glade.h:5 msgid "Preferences" msgstr "Параметры" #: ../data/ui/popup-menu-gtk3.glade.h:6 ../data/ui/popup-menu-gtk2.glade.h:7 msgid "Reload Sound" msgstr "Перезагрузить звук" #: ../data/ui/popup-menu-gtk3.glade.h:7 ../data/ui/popup-menu-gtk2.glade.h:8 msgid "About" msgstr "О программе" #: ../data/ui/popup-menu-gtk3.glade.h:8 ../data/ui/popup-menu-gtk2.glade.h:9 msgid "Quit" msgstr "Выход" #: ../data/ui/popup-window-horizontal-gtk3.glade.h:2 #: ../data/ui/popup-window-vertical-gtk3.glade.h:2 #: ../data/ui/popup-window-horizontal-gtk2.glade.h:2 #: ../data/ui/popup-window-vertical-gtk2.glade.h:2 msgid "Mixer" msgstr "Микшер" #: ../data/ui/prefs-dialog-gtk3.glade.h:1 #: ../data/ui/prefs-dialog-gtk2.glade.h:2 msgid "Enable Notifications" msgstr "Включить уведомлениÑ" #: ../data/ui/prefs-dialog-gtk3.glade.h:2 #: ../data/ui/prefs-dialog-gtk2.glade.h:3 #, fuzzy msgid "Timeout (ms):" msgstr "задержка (мÑ)" #: ../data/ui/prefs-dialog-gtk3.glade.h:3 #: ../data/ui/prefs-dialog-gtk2.glade.h:9 msgid "Notification Options" msgstr "Опции уведомлений" #: ../data/ui/prefs-dialog-gtk3.glade.h:4 #: ../data/ui/prefs-dialog-gtk2.glade.h:5 msgid "HotKeys" msgstr "ГорÑчие клавиши" #: ../data/ui/prefs-dialog-gtk3.glade.h:5 #: ../data/ui/prefs-dialog-gtk2.glade.h:6 msgid "Mouse Scroll" msgstr "Прокрутка колеÑом мыши" #: ../data/ui/prefs-dialog-gtk3.glade.h:6 #: ../data/ui/prefs-dialog-gtk2.glade.h:7 #, fuzzy msgid "Adjustment in Popups" msgstr "Корректировка во вÑплывающем окне" #: ../data/ui/prefs-dialog-gtk3.glade.h:7 #: ../data/ui/prefs-dialog-gtk2.glade.h:8 msgid "External Change" msgstr "Изменение извне" #: ../data/ui/prefs-dialog-gtk3.glade.h:8 #, fuzzy msgid "Notify for volume changes from:" msgstr "УведомлÑть об изменении громкоÑти в:" #: ../data/ui/prefs-dialog-gtk3.glade.h:9 #: ../data/ui/prefs-dialog-gtk2.glade.h:1 #, fuzzy msgid "Notification support disabled at compile time." msgstr "Поддержка уведомлений не была включена во Ð²Ñ€ÐµÐ¼Ñ ÐºÐ¾Ð¼Ð¿Ð¸Ð»Ñции." #: ../data/ui/prefs-dialog-gtk3.glade.h:10 #: ../data/ui/prefs-dialog-gtk2.glade.h:10 msgid "PNMixer Preferences" msgstr "Параметры PNMixer" #: ../data/ui/prefs-dialog-gtk3.glade.h:12 msgid "Ok" msgstr "" #: ../data/ui/prefs-dialog-gtk3.glade.h:13 msgid "Apply" msgstr "Применить" #: ../data/ui/prefs-dialog-gtk3.glade.h:14 #: ../data/ui/prefs-dialog-gtk2.glade.h:11 msgid "Card:" msgstr "Карта:" #: ../data/ui/prefs-dialog-gtk3.glade.h:15 #: ../data/ui/prefs-dialog-gtk2.glade.h:12 msgid "Channel:" msgstr "Канал:" #: ../data/ui/prefs-dialog-gtk3.glade.h:16 #: ../data/ui/prefs-dialog-gtk2.glade.h:14 msgid "Change volume on a logarithmic scale, closer to human perception." msgstr "" #: ../data/ui/prefs-dialog-gtk3.glade.h:17 #: ../data/ui/prefs-dialog-gtk2.glade.h:13 msgid "Normalize Volume:" msgstr "Ðормализовать громкоÑть:" #: ../data/ui/prefs-dialog-gtk3.glade.h:18 #: ../data/ui/prefs-dialog-gtk2.glade.h:15 msgid "Sound Device" msgstr "Звуковое уÑтройÑтво" #: ../data/ui/prefs-dialog-gtk3.glade.h:19 #: ../data/ui/prefs-dialog-gtk2.glade.h:16 msgid "Device" msgstr "УÑтройÑтво" #: ../data/ui/prefs-dialog-gtk3.glade.h:20 #: ../data/ui/prefs-dialog-gtk2.glade.h:17 msgid "Slider Orientation:" msgstr "" #: ../data/ui/prefs-dialog-gtk3.glade.h:21 #: ../data/ui/prefs-dialog-gtk2.glade.h:18 msgid "Vertical" msgstr "" #: ../data/ui/prefs-dialog-gtk3.glade.h:22 #: ../data/ui/prefs-dialog-gtk2.glade.h:19 msgid "Horizontal" msgstr "" #: ../data/ui/prefs-dialog-gtk3.glade.h:23 #: ../data/ui/prefs-dialog-gtk2.glade.h:20 msgid "Display Text Volume" msgstr "Отображать уровень громкоÑти текÑтом" #: ../data/ui/prefs-dialog-gtk3.glade.h:24 #: ../data/ui/prefs-dialog-gtk2.glade.h:21 #, fuzzy msgid "Text Volume Position:" msgstr "РаÑположение текÑта громкоÑти:" #: ../data/ui/prefs-dialog-gtk3.glade.h:25 #: ../data/ui/prefs-dialog-gtk2.glade.h:22 msgid "Top" msgstr "Сверху" #: ../data/ui/prefs-dialog-gtk3.glade.h:26 #: ../data/ui/prefs-dialog-gtk2.glade.h:23 msgid "Bottom" msgstr "Снизу" #: ../data/ui/prefs-dialog-gtk3.glade.h:27 #: ../data/ui/prefs-dialog-gtk2.glade.h:24 msgid "Left" msgstr "Слева" #: ../data/ui/prefs-dialog-gtk3.glade.h:28 #: ../data/ui/prefs-dialog-gtk2.glade.h:25 msgid "Right" msgstr "Справа" #: ../data/ui/prefs-dialog-gtk3.glade.h:29 #: ../data/ui/prefs-dialog-gtk2.glade.h:26 #, fuzzy msgid "Volume Popup" msgstr "Измеритель громкоÑти" #: ../data/ui/prefs-dialog-gtk3.glade.h:30 #: ../data/ui/prefs-dialog-gtk2.glade.h:27 #, fuzzy msgid "Draw Volume Meter on Tray Icon" msgstr "Цвет Ð¸Ð·Ð¼ÐµÑ€Ð¸Ñ‚ÐµÐ»Ñ Ð³Ñ€Ð¾Ð¼ÐºÐ¾Ñти:" #: ../data/ui/prefs-dialog-gtk3.glade.h:32 #: ../data/ui/prefs-dialog-gtk2.glade.h:29 #, fuzzy, no-c-format msgid "Volume Meter Offset (%):" msgstr "Смещение Ð¸Ð·Ð¼ÐµÑ€Ð¸Ñ‚ÐµÐ»Ñ Ð³Ñ€Ð¾Ð¼ÐºÐ¾Ñти:" #: ../data/ui/prefs-dialog-gtk3.glade.h:33 #: ../data/ui/prefs-dialog-gtk2.glade.h:30 msgid "Volume Meter Color:" msgstr "Цвет Ð¸Ð·Ð¼ÐµÑ€Ð¸Ñ‚ÐµÐ»Ñ Ð³Ñ€Ð¾Ð¼ÐºÐ¾Ñти:" #: ../data/ui/prefs-dialog-gtk3.glade.h:34 #: ../data/ui/prefs-dialog-gtk2.glade.h:31 msgid "Volume Meter" msgstr "Измеритель громкоÑти" #: ../data/ui/prefs-dialog-gtk3.glade.h:35 #: ../data/ui/prefs-dialog-gtk2.glade.h:32 msgid "Use System Theme" msgstr "" #: ../data/ui/prefs-dialog-gtk3.glade.h:36 #: ../data/ui/prefs-dialog-gtk2.glade.h:33 msgid "Icon Theme" msgstr "Тема иконок" #: ../data/ui/prefs-dialog-gtk3.glade.h:37 #: ../data/ui/prefs-dialog-gtk2.glade.h:34 msgid "View" msgstr "Вид" #: ../data/ui/prefs-dialog-gtk3.glade.h:38 #: ../data/ui/prefs-dialog-gtk2.glade.h:35 msgid "Volume Control Command" msgstr "Команда ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð³Ñ€Ð¾Ð¼ÐºÐ¾Ñтью" #: ../data/ui/prefs-dialog-gtk3.glade.h:39 #: ../data/ui/prefs-dialog-gtk2.glade.h:36 #, fuzzy msgid "Scroll Step:" msgstr "Шаг прокрутки колёÑиком:" #: ../data/ui/prefs-dialog-gtk3.glade.h:40 #: ../data/ui/prefs-dialog-gtk2.glade.h:37 #, fuzzy msgid "Fine Scroll Step:" msgstr "Шаг прокрутки колёÑиком:" #: ../data/ui/prefs-dialog-gtk3.glade.h:41 #: ../data/ui/prefs-dialog-gtk2.glade.h:38 #, fuzzy msgid "Volume Scrolling" msgstr "Измеритель громкоÑти" #: ../data/ui/prefs-dialog-gtk3.glade.h:42 #: ../data/ui/prefs-dialog-gtk2.glade.h:39 msgid "Middle Click Action:" msgstr "ДейÑтвие по клику колёÑиком:" #: ../data/ui/prefs-dialog-gtk3.glade.h:43 #: ../data/ui/prefs-dialog-gtk2.glade.h:40 msgid "Custom Command:" msgstr "ПользовательÑÐºÐ°Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð°:" #: ../data/ui/prefs-dialog-gtk3.glade.h:45 #: ../data/ui/prefs-dialog-gtk2.glade.h:42 msgid "Show Preferences" msgstr "Показать параметры" #: ../data/ui/prefs-dialog-gtk3.glade.h:47 #: ../data/ui/prefs-dialog-gtk2.glade.h:44 msgid "Custom (set below)" msgstr "ПользовательÑÐºÐ°Ñ (уÑтанавливаетÑÑ Ð½Ð¸Ð¶Ðµ)" #: ../data/ui/prefs-dialog-gtk3.glade.h:48 #: ../data/ui/prefs-dialog-gtk2.glade.h:45 msgid "Mouse" msgstr "Мышь" #: ../data/ui/prefs-dialog-gtk3.glade.h:49 #: ../data/ui/prefs-dialog-gtk2.glade.h:46 msgid "Behavior" msgstr "Поведение" #: ../data/ui/prefs-dialog-gtk3.glade.h:50 #: ../data/ui/prefs-dialog-gtk2.glade.h:47 msgid "Enable HotKeys" msgstr "Включить горÑчие клавиши" #: ../data/ui/prefs-dialog-gtk3.glade.h:51 #: ../data/ui/prefs-dialog-gtk2.glade.h:52 msgid "Command" msgstr "Команда" #: ../data/ui/prefs-dialog-gtk3.glade.h:52 #: ../data/ui/prefs-dialog-gtk2.glade.h:48 msgid "Mute/Unmute:" msgstr "Вкл/выкл звук" #: ../data/ui/prefs-dialog-gtk3.glade.h:53 #: ../data/ui/prefs-dialog-gtk2.glade.h:49 msgid "Volume Up:" msgstr "Увеличить громкоÑть" #: ../data/ui/prefs-dialog-gtk3.glade.h:54 #: ../data/ui/prefs-dialog-gtk2.glade.h:50 msgid "Volume Down:" msgstr "Уменьшить громкоÑть" #: ../data/ui/prefs-dialog-gtk3.glade.h:55 #: ../data/ui/prefs-dialog-gtk2.glade.h:51 #, fuzzy msgid "Double-click a HotKey to assign a new HotKey" msgstr "Щёлкните дважды на горÑчую клавишу, чтобы назначить новую" #: ../data/ui/prefs-dialog-gtk3.glade.h:56 #: ../data/ui/prefs-dialog-gtk2.glade.h:53 msgid "HotKey" msgstr "ГорÑÑ‡Ð°Ñ ÐºÐ»Ð°Ð²Ð¸ÑˆÐ°" #: ../data/ui/prefs-dialog-gtk3.glade.h:57 #: ../data/ui/prefs-dialog-gtk2.glade.h:54 msgid "(None)" msgstr "(ПуÑто)" #: ../data/ui/prefs-dialog-gtk3.glade.h:58 #: ../data/ui/prefs-dialog-gtk2.glade.h:55 msgid "HotKey Settings" msgstr "ÐаÑтройки горÑчих клавиш" #: ../data/ui/popup-menu-gtk2.glade.h:1 msgid "_Mute" msgstr "Выкл. звук" #: ../data/ui/popup-menu-gtk2.glade.h:3 msgid "_Volume Control" msgstr "_ÐаÑтройки громкоÑти" #: ../data/ui/popup-menu-gtk2.glade.h:6 msgid "_Reload Sound" msgstr "_Перезагрузить звук" #: ../data/ui/prefs-dialog-gtk2.glade.h:4 msgid "Notify for volume changes from:" msgstr "УведомлÑть об изменении громкоÑти в:" #, fuzzy #~ msgid "" #~ "%s (%s)\n" #~ "%s: %ld %%" #~ msgstr "" #~ "%s (%s)\n" #~ "ГромкоÑть: %d %%" #, fuzzy #~ msgid "" #~ "%s (%s)\n" #~ "%s: %ld %%\n" #~ "%s" #~ msgstr "" #~ "%s (%s)\n" #~ "ГромкоÑть: %d %%" #~ msgid "PNMixer" #~ msgstr "PNMixer" #~ msgid "" #~ "PNMixer is free software; you can redistribute it and/or modify it under " #~ "the terms of the GNU General Public License as published by the Free " #~ "Software Foundation; either version 3 of the License, or (at your option) " #~ "any later version.\n" #~ "\n" #~ "PNMixer 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.\n" #~ "\n" #~ "You should have received a copy of the GNU General Public License along " #~ "with PNMixer; if not, write to the Free Software Foundation, Inc., 51 " #~ "Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA." #~ msgstr "" #~ "PNMixer ÑвлÑетÑÑ Ñвободным программным обеÑпечением. Ð’Ñ‹ можете " #~ "раÑпроÑтранÑть и/или модифицировать её ÑоглаÑно уÑловиÑм Стандартной " #~ "ОбщеÑтвенной Лицензии GNU, опубликованной Фондом Свободного Программного " #~ "ОбеÑпечениÑ, верÑии 3 или, по Вашему желанию, любой более поздней " #~ "верÑии.\n" #~ "\n" #~ "PNMixer раÑпроÑтранÑетÑÑ Ð² надежде, что она будет полезной, но БЕЗ ВСЯКИХ " #~ "ГÐРÐÐТИЙ, в том чиÑле подразумеваемых гарантий ТОВÐРÐОГО СОСТОЯÐИЯ ПРИ " #~ "ПРОДÐЖЕ и ГОДÐОСТИ ДЛЯ ОПРЕДЕЛÐÐÐОГО ПРИМЕÐЕÐИЯ. Смотрите Стандартную " #~ "ОбщеÑтвенную Лицензию GNU Ð´Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ð¹ информации.\n" #~ "\n" #~ "Ð’Ñ‹ должны были получить копию Стандартной ОбщеÑтвенной Лицензии GNU " #~ "вмеÑте Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¼Ð¾Ð¹. Ð’ Ñлучае её отÑутÑтвиÑ, напишите в Free Software " #~ "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, " #~ "USA." #~ msgid "" #~ "French: Matthieu Bresson\n" #~ "German: Mario Blättermann\n" #~ "Italian: Mattia Bertoni\n" #~ "Russian: Pavel Serebryakov" #~ msgstr "" #~ "PуÑÑкий: Pavel Serebryakov\n" #~ "ФранцузÑкий: Matthieu Bresson\n" #~ "Ðемецкий: Mario Blättermann\n" #~ "итальÑнÑкий: Mattia Bertoni" #~ msgid "HotKey Volume Step:" #~ msgstr "Шаг громкоÑти Ð´Ð»Ñ Ð³Ð¾Ñ€Ñчей клавиши:" #~ msgid "HotKeys" #~ msgstr "ГорÑчие клавиши" #, fuzzy #~ msgid "Timeout (ms)" #~ msgstr "задержка (мÑ)" #~ msgid "" #~ "Warning: Connection to sound system failed, you probably need to restart " #~ "pnmixer\n" #~ msgstr "" #~ "Внимание: Ðе удалоÑÑŒ подключитьÑÑ Ðº звуковой подÑиÑтеме, возможно вам " #~ "необходимо перезапуÑтить pnmixer\n" #~ msgid "" #~ "Can't find main user interface file. Please ensure PNMixer is installed " #~ "correctly. Exiting." #~ msgstr "" #~ "Главный файл графичеÑкого интерфейÑа программы не найден. ПожалуйÑта, " #~ "убедитеÑÑŒ, что PNMixer уÑтановлен правильно. Завершение" #~ msgid "" #~ "Can't find about interface file. Please ensure PNMixer is installed " #~ "correctly." #~ msgstr "" #~ "Файл графичеÑкого интерфейÑа окна \"О программе\" не найден. ПожалуйÑта, " #~ "убедитеÑÑŒ, что PNMixer уÑтановлен правильно." #~ msgid "" #~ "%s (%s)\n" #~ "Volume: %d %%\n" #~ "Muted" #~ msgstr "" #~ "%s (%s)\n" #~ "ГромкоÑть: %d %%\n" #~ "Звук выкл." #~ msgid "Couldn't find pixmap file: %s" #~ msgstr "Ðе удалоÑÑŒ найти файл изображениÑ: %s" #~ msgid "Failed to load pixbuf file: %s: %s" #~ msgstr "Ðе удалоÑÑŒ загрузить pixbuf-файл: %s: %s" #~ msgid "PNMixer Icons" #~ msgstr "Иконки PNMixer" #~ msgid "Invalid color for volume meter in config file. Reverting to default." #~ msgstr "" #~ "ÐедопуÑтимое значение цвета Ð´Ð»Ñ Ð¸Ð·Ð¼ÐµÑ€Ð¸Ñ‚ÐµÐ»Ñ Ð³Ñ€Ð¾Ð¼ÐºÐ¾Ñти в файле " #~ "конфигурации. ИÑпользую значение по умолчанию." #~ msgid "Invalid widget passed to acquire_hotkey: %s" #~ msgstr "ÐедопуÑтимый виджет передан в acquire_hotkey: %s" #~ msgid "" #~ "Can't find preferences user interface file. Please ensure PNMixer is " #~ "installed correctly." #~ msgstr "" #~ "Файл графичеÑкого интерфейÑа окна наÑтроек не найден. ПожалуйÑта, " #~ "убедитеÑÑŒ, что PNMixer уÑтановлен правильно. " #~ msgid "Text" #~ msgstr "ТекÑÑ‚" #~ msgid "" #~ "Draw Volume Meter on Tray Icon\n" #~ "(Will cause slightly higher CPU usage)" #~ msgstr "" #~ "Показывать измеритель громкоÑти на иконке в трее\n" #~ "(Потребует чуть больше реÑурÑов процеÑÑора)" #~ msgid "(Unknown)" #~ msgstr "(ÐеизвеÑтно)" #~ msgid "Volume Control..." #~ msgstr "ÐаÑтройки громкоÑти…" #~ msgid "Unable to load icon %s: %s\n" #~ msgstr "Ðе удалоÑÑŒ загрузить иконку: %s: %s\n" #~ msgid "Hotkeys" #~ msgstr "ГорÑчие клавиши" #~ msgid "" #~ "An unknown error occurred trying to launch your volume control command" #~ msgstr "" #~ "Произошла неизвеÑÑ‚Ð½Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ° при попытке выполнить вашу команду " #~ "ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð³Ñ€Ð¾Ð¼ÐºÐ¾Ñтью" #~ msgid "Couldn't execute custom command: \"%s\"\n" #~ msgstr "Ðе удалоÑÑŒ выполнить пользовательÑкую команду: \"%s\".\n" pnmixer-0.7.2/po/sr.po000066400000000000000000000414661311427610600146200ustar00rootroot00000000000000# Serbian translation for pnmixer. # Copyright © 2016 PNMixer team (msgids) # This file is distributed under the same license as the pnmixer package. # МироÑлав Ðиколић , 2016—2017. msgid "" msgstr "" "Project-Id-Version: pnmixer-0.7.1-rc3\n" "Report-Msgid-Bugs-To: https://github.com/nicklan/pnmixer/issues\n" "POT-Creation-Date: 2017-03-13 21:25+0700\n" "PO-Revision-Date: 2017-05-07 18:36+0200\n" "Last-Translator: МироÑлав Ðиколић \n" "Language-Team: Serbian <(nothing)>\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-Bugs: Report translation errors to the Language-Team address.\n" #: src/hotkeys.c:175 msgid "Could not grab the following HotKeys" msgstr "Ðе могу да захватим Ñледеће пречице" #: src/hotkeys.c:176 src/ui-prefs-dialog.c:339 #: data/ui/prefs-dialog-gtk3.glade:973 data/ui/prefs-dialog-gtk2.glade:935 msgid "Mute/Unmute" msgstr "Утишај/Појачај" #: src/hotkeys.c:178 src/ui-prefs-dialog.c:342 msgid "Volume Up" msgstr "ГлаÑније" #: src/hotkeys.c:180 src/ui-prefs-dialog.c:345 msgid "Volume Down" msgstr "Тише" #: src/main.c:69 #, c-format msgid "Unable to run command: %s" msgstr "Ðе могу да покренем наредбу: %s" #: src/main.c:89 msgid "No mixer application was found on your system. Please open preferences and set the command you want to run for volume control." msgstr "ÐиÑам нашао програм мешача на вашем ÑиÑтему. Отворите поÑтавке и подеÑите наредбу ако желите да покренете управљање глаÑноћом." #: src/main.c:109 msgid "You have not specified a custom command to run, please specify one in preferences." msgstr "ÐиÑте навели произвољну наредбу за покретање, наведите неку у поÑтавкама." #: src/main.c:210 src/main.c:248 msgid "PNMixer Error" msgstr "Грешка ПÐМешача" #: src/main.c:239 msgid "Warning: Connection to sound system failed." msgstr "Упозорење: Веза до ÑиÑтема звука није уÑпела." #: src/main.c:243 msgid "" "Do you want to re-initialize the audio connection ?\n" "\n" "If you do not, you will either need to restart PNMixer or select the 'Reload Audio' option in the right-click menu in order for PNMixer to function." msgstr "" "Да ли желите поново да покренете везу звука ?\n" "\n" "Ðко не желите, мораћете поново да покренете ПÐМешача или да изаберете опцију „Поново учитај звук“ у изборнику деÑног клика да би ПÐМешач радио." #: src/main.c:334 msgid "- A mixer for the system tray." msgstr "— Мешач за ÑиÑтемÑку фиоку." #: src/main.c:342 #, c-format msgid "%s version: %s\n" msgstr "„%s“ издање: %s\n" #: src/notif.c:77 msgid "Volume muted" msgstr "Звук је утишан" #: src/notif.c:82 src/ui-tray-icon.c:355 msgid "Volume" msgstr "ГлаÑноћа" #: src/notif.c:135 msgid "No sound card" msgstr "Ðема звучне картице" #: src/notif.c:136 msgid "No playable soundcard found" msgstr "ÐиÑам нашао звучну картицу за пуштање" #: src/notif.c:141 msgid "Soundcard disconnected" msgstr "Звучна картица је иÑкључена" #: src/notif.c:142 msgid "Soundcard has been disconnected, reloading sound system..." msgstr "Звучна картица је иÑкључена, поново учитавам ÑиÑтем звука..." #: src/prefs.c:356 #, c-format msgid "Couldn't load preferences file: %s" msgstr "Ðе могу да учитам датотеку подешавања: %s" #: src/prefs.c:365 #, c-format msgid "Couldn't load default preferences: %s" msgstr "Ðе могу да учитам оÑновне поÑтавке: %s" #: src/prefs.c:391 #, c-format msgid "Couldn't write preferences file: %s" msgstr "Ðе могу да запишем датотеку подешавања: %s" #: src/prefs.c:411 #, c-format msgid "'%s' exists but is not a directory, won't be able to save preferences." msgstr "„%s“ поÑтоји али није директоријум, нећу моћи да Ñачувам поÑтавке." #: src/prefs.c:415 #, c-format msgid "Couldn't make preferences directory: %s" msgstr "Ðе могу да направим датотеку подешавања: %s" #: src/ui-about-dialog.c:114 msgid "A mixer for the system tray" msgstr "Мешач за ÑиÑтемÑку фиоку" #: src/ui-about-dialog.c:115 msgid "Copyright © 2010-2016 Nick Lanham" msgstr "ÐуторÑка права © 2010-2016 Ðик Ланам" #: src/ui-hotkey-dialog.c:48 #, c-format msgid "Set %s HotKey" msgstr "ПодеÑите „%s“ пречицу" #: src/ui-hotkey-dialog.c:52 #, c-format msgid "Press new HotKey for %s" msgstr "ПритиÑните нову пречицу за „%s“" #: src/ui-hotkey-dialog.c:174 msgid "Could not grab the keyboard." msgstr "Ðе могу да добавим таÑтатуру." #: src/ui-popup-menu.c:57 src/ui-popup-menu.c:84 src/ui-popup-window.c:129 msgid "Soundcard has no mute switch" msgstr "Звучна картица нема дугме за утишање" #: src/ui-prefs-dialog.c:373 msgid "None" msgstr "Ðишта" #: src/ui-prefs-dialog.c:867 msgid "Notifications" msgstr "Обавештења" #: src/ui-tray-icon.c:357 msgid "No mute switch" msgstr "Ðема дугмета за утишавање" #: src/ui-tray-icon.c:359 msgid "Muted" msgstr "Утишано" #: data/desktop/pnmixer.desktop.in:3 msgid "PNMixer" msgstr "ПÐ_мешач" #: data/desktop/pnmixer.desktop.in:4 msgid "System Tray Mixer" msgstr "Мешач ÑиÑтемÑке фиоке" #: data/desktop/pnmixer.desktop.in:5 msgid "An audio mixer for the system tray" msgstr "Мешач звука за ÑиÑтемÑку фиоку" #. TRANSLATORS: Search terms to find this application. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! #: data/desktop/pnmixer.desktop.in:7 msgid "alsa;audio;mixer;sound;" msgstr "алÑа;звук;мешач;микÑер;аудио;" #. TRANSLATORS: Do NOT translate or transliterate this text (this is an icon file name)! #: data/desktop/pnmixer.desktop.in:11 msgid "pnmixer" msgstr "пнмешач" #: data/ui/hotkey-dialog-gtk3.glade:55 data/ui/prefs-dialog-gtk3.glade:279 msgid "Cancel" msgstr "Откажи" #: data/ui/hotkey-dialog-gtk3.glade:109 data/ui/hotkey-dialog-gtk2.glade:49 msgid "Defining HotKey" msgstr "Одређујем пречицу" #: data/ui/hotkey-dialog-gtk3.glade:124 data/ui/hotkey-dialog-gtk2.glade:65 msgid "(press C to reset)" msgstr "(притиÑните <Ктрл>Ц да поново поÑтавите)" #: data/ui/popup-menu-gtk3.glade:33 data/ui/popup-menu-gtk2.glade:49 msgid "Mute/Unmute Volume" msgstr "Утишајте/Појачајте звук" #: data/ui/popup-menu-gtk3.glade:58 #: data/ui/popup-window-horizontal-gtk3.glade:54 #: data/ui/popup-window-vertical-gtk3.glade:58 #: data/ui/popup-window-horizontal-gtk2.glade:56 #: data/ui/popup-window-vertical-gtk2.glade:58 msgid "Mute" msgstr "Утишај" #: data/ui/popup-menu-gtk3.glade:73 data/ui/popup-menu-gtk2.glade:60 msgid "Open Volume Control" msgstr "Отворите управљање глаÑноћом" #: data/ui/popup-menu-gtk3.glade:95 data/ui/prefs-dialog-gtk3.glade:975 #: data/ui/prefs-dialog-gtk2.glade:937 msgid "Volume Control" msgstr "Управљање глаÑноћом" #: data/ui/popup-menu-gtk3.glade:110 data/ui/popup-menu-gtk3.glade:133 #: data/ui/popup-menu-gtk2.glade:73 msgid "Preferences" msgstr "ПоÑтавке" #: data/ui/popup-menu-gtk3.glade:148 data/ui/popup-menu-gtk3.glade:171 #: data/ui/popup-menu-gtk2.glade:85 msgid "Reload Sound" msgstr "Поново учитај звук" #: data/ui/popup-menu-gtk3.glade:186 data/ui/popup-menu-gtk3.glade:209 #: data/ui/popup-menu-gtk2.glade:98 msgid "About" msgstr "О програму" #: data/ui/popup-menu-gtk3.glade:231 data/ui/popup-menu-gtk3.glade:254 #: data/ui/popup-menu-gtk2.glade:117 msgid "Quit" msgstr "Изађи" #: data/ui/popup-window-horizontal-gtk3.glade:81 #: data/ui/popup-window-vertical-gtk3.glade:74 #: data/ui/popup-window-horizontal-gtk2.glade:72 #: data/ui/popup-window-vertical-gtk2.glade:74 msgid "Mixer" msgstr "Мешач" #: data/ui/prefs-dialog-gtk3.glade:43 data/ui/prefs-dialog-gtk2.glade:68 msgid "Timeout (ms):" msgstr "Време иÑтека (ms):" #: data/ui/prefs-dialog-gtk3.glade:65 data/ui/prefs-dialog-gtk2.glade:46 msgid "Enable Notifications" msgstr "Укључи обавешења" #: data/ui/prefs-dialog-gtk3.glade:89 data/ui/prefs-dialog-gtk2.glade:210 msgid "Notification Options" msgstr "Опције обавештавања" #: data/ui/prefs-dialog-gtk3.glade:116 data/ui/prefs-dialog-gtk3.glade:1255 #: data/ui/prefs-dialog-gtk2.glade:125 data/ui/prefs-dialog-gtk2.glade:1225 msgid "HotKeys" msgstr "Пречице" #: data/ui/prefs-dialog-gtk3.glade:132 data/ui/prefs-dialog-gtk2.glade:146 msgid "Mouse Scroll" msgstr "Премицање миша" #: data/ui/prefs-dialog-gtk3.glade:148 data/ui/prefs-dialog-gtk2.glade:167 msgid "Adjustment in Popups" msgstr "Дотеривање у облачићима" #: data/ui/prefs-dialog-gtk3.glade:164 data/ui/prefs-dialog-gtk2.glade:188 msgid "External Change" msgstr "Спољна промена" #: data/ui/prefs-dialog-gtk3.glade:185 msgid "Notify for volume changes from:" msgstr "ОбавеÑти о променама глаÑноће Ñа:" #: data/ui/prefs-dialog-gtk3.glade:212 data/ui/prefs-dialog-gtk2.glade:12 msgid "Notification support disabled at compile time." msgstr "Подршка обавештавања је иÑкључена за време превођења програма." #: data/ui/prefs-dialog-gtk3.glade:236 data/ui/prefs-dialog-gtk2.glade:241 msgid "PNMixer Preferences" msgstr "ПоÑтавке ПÐМешача" #: data/ui/prefs-dialog-gtk3.glade:324 msgid "Ok" msgstr "У реду" #: data/ui/prefs-dialog-gtk3.glade:369 msgid "Apply" msgstr "Примени" #: data/ui/prefs-dialog-gtk3.glade:427 data/ui/prefs-dialog-gtk2.glade:338 msgid "Card:" msgstr "Картица:" #: data/ui/prefs-dialog-gtk3.glade:439 data/ui/prefs-dialog-gtk2.glade:349 msgid "Channel:" msgstr "Канал:" #: data/ui/prefs-dialog-gtk3.glade:450 data/ui/prefs-dialog-gtk2.glade:409 msgid "Change volume on a logarithmic scale, closer to human perception." msgstr "Промени глаÑноћу на логаритамÑкој Ñкали, ближе људÑкој перцепцији." #: data/ui/prefs-dialog-gtk3.glade:452 data/ui/prefs-dialog-gtk2.glade:408 msgid "Normalize Volume:" msgstr "Ðормализуј глаÑноће:" #: data/ui/prefs-dialog-gtk3.glade:502 data/ui/prefs-dialog-gtk2.glade:425 msgid "Sound Device" msgstr "Звучни уређај" #: data/ui/prefs-dialog-gtk3.glade:520 data/ui/prefs-dialog-gtk2.glade:443 msgid "Device" msgstr "Уређај" #: data/ui/prefs-dialog-gtk3.glade:555 data/ui/prefs-dialog-gtk2.glade:477 msgid "Slider Orientation:" msgstr "УÑмерење клизача:" #: data/ui/prefs-dialog-gtk3.glade:567 data/ui/prefs-dialog-gtk2.glade:520 msgid "Text Volume Position:" msgstr "Положај текÑта глаÑноће:" #: data/ui/prefs-dialog-gtk3.glade:576 data/ui/prefs-dialog-gtk2.glade:501 msgid "Display Text Volume" msgstr "Прикажи текÑÑ‚ глаÑноће" #: data/ui/prefs-dialog-gtk3.glade:596 data/ui/prefs-dialog-gtk2.glade:489 msgid "Vertical" msgstr "УÑправно" #: data/ui/prefs-dialog-gtk3.glade:597 data/ui/prefs-dialog-gtk2.glade:490 msgid "Horizontal" msgstr "Положено" #: data/ui/prefs-dialog-gtk3.glade:611 data/ui/prefs-dialog-gtk2.glade:534 msgid "Top" msgstr "Горе" #: data/ui/prefs-dialog-gtk3.glade:612 data/ui/prefs-dialog-gtk2.glade:535 msgid "Bottom" msgstr "Доле" #: data/ui/prefs-dialog-gtk3.glade:613 data/ui/prefs-dialog-gtk2.glade:536 msgid "Left" msgstr "Лево" #: data/ui/prefs-dialog-gtk3.glade:614 data/ui/prefs-dialog-gtk2.glade:537 msgid "Right" msgstr "ДеÑно" #: data/ui/prefs-dialog-gtk3.glade:632 data/ui/prefs-dialog-gtk2.glade:556 msgid "Volume Popup" msgstr "Облачић глаÑноће" #: data/ui/prefs-dialog-gtk3.glade:663 data/ui/prefs-dialog-gtk2.glade:619 msgid "Volume Meter Color:" msgstr "Боја мерача глаÑноће:" #: data/ui/prefs-dialog-gtk3.glade:675 data/ui/prefs-dialog-gtk2.glade:606 msgid "Volume Meter Offset (%):" msgstr "Померај мерача глаÑноће (%):" #: data/ui/prefs-dialog-gtk3.glade:713 data/ui/prefs-dialog-gtk2.glade:589 msgid "Draw Volume Meter on Tray Icon" msgstr "ИÑцртај мерач глаÑноће на иконици фиоке" #: data/ui/prefs-dialog-gtk3.glade:735 data/ui/prefs-dialog-gtk2.glade:672 msgid "Volume Meter" msgstr "Мерач глаÑноће" #: data/ui/prefs-dialog-gtk3.glade:755 data/ui/prefs-dialog-gtk2.glade:699 msgid "Use System Theme" msgstr "КориÑти ÑиÑтемÑку тему" #: data/ui/prefs-dialog-gtk3.glade:770 data/ui/prefs-dialog-gtk2.glade:712 msgid "Icon Theme" msgstr "Тема иконице" #: data/ui/prefs-dialog-gtk3.glade:791 data/ui/prefs-dialog-gtk2.glade:732 msgid "View" msgstr "Преглед" #: data/ui/prefs-dialog-gtk3.glade:829 data/ui/prefs-dialog-gtk2.glade:772 msgid "Volume Control Command" msgstr "Ðаредба контроле глаÑноће" #: data/ui/prefs-dialog-gtk3.glade:860 data/ui/prefs-dialog-gtk2.glade:808 msgid "Scroll Step:" msgstr "Корак премицања:" #: data/ui/prefs-dialog-gtk3.glade:872 data/ui/prefs-dialog-gtk2.glade:819 msgid "Fine Scroll Step:" msgstr "Фини корак премицања:" #: data/ui/prefs-dialog-gtk3.glade:918 data/ui/prefs-dialog-gtk2.glade:875 msgid "Volume Scrolling" msgstr "Премицање глаÑноће" #: data/ui/prefs-dialog-gtk3.glade:949 data/ui/prefs-dialog-gtk2.glade:922 msgid "Custom Command:" msgstr "Произвољна радња:" #: data/ui/prefs-dialog-gtk3.glade:961 data/ui/prefs-dialog-gtk2.glade:911 msgid "Middle Click Action:" msgstr "Радња Ñредњег клика:" #: data/ui/prefs-dialog-gtk3.glade:974 data/ui/prefs-dialog-gtk2.glade:936 msgid "Show Preferences" msgstr "Прикажи поÑтавке" #: data/ui/prefs-dialog-gtk3.glade:976 data/ui/prefs-dialog-gtk2.glade:938 msgid "Custom (set below)" msgstr "Произвољно (подешено иÑпод)" #: data/ui/prefs-dialog-gtk3.glade:1005 data/ui/prefs-dialog-gtk2.glade:974 msgid "Mouse" msgstr "Миш" #: data/ui/prefs-dialog-gtk3.glade:1026 data/ui/prefs-dialog-gtk2.glade:995 msgid "Behavior" msgstr "Понашање" #: data/ui/prefs-dialog-gtk3.glade:1057 data/ui/prefs-dialog-gtk2.glade:1025 msgid "Enable HotKeys" msgstr "Укључи пречице" #: data/ui/prefs-dialog-gtk3.glade:1085 data/ui/prefs-dialog-gtk2.glade:1099 msgid "Command" msgstr "Ðаредба" #: data/ui/prefs-dialog-gtk3.glade:1100 data/ui/prefs-dialog-gtk2.glade:1052 msgid "Mute/Unmute:" msgstr "Утишај/Појачај:" #: data/ui/prefs-dialog-gtk3.glade:1112 data/ui/prefs-dialog-gtk2.glade:1064 msgid "Volume Up:" msgstr "ГлаÑније:" #: data/ui/prefs-dialog-gtk3.glade:1124 data/ui/prefs-dialog-gtk2.glade:1076 msgid "Volume Down:" msgstr "Тише:" #: data/ui/prefs-dialog-gtk3.glade:1135 data/ui/prefs-dialog-gtk2.glade:1109 msgid "HotKey" msgstr "Пречица" #: data/ui/prefs-dialog-gtk3.glade:1154 data/ui/prefs-dialog-gtk3.glade:1175 #: data/ui/prefs-dialog-gtk3.glade:1196 data/ui/prefs-dialog-gtk2.glade:1128 #: data/ui/prefs-dialog-gtk2.glade:1151 data/ui/prefs-dialog-gtk2.glade:1174 msgid "(None)" msgstr "(Ðишта)" #: data/ui/prefs-dialog-gtk3.glade:1212 data/ui/prefs-dialog-gtk2.glade:1087 msgid "Double-click a HotKey to assign a new HotKey" msgstr "Кликните два пута на пречицу да доделите нову" #: data/ui/prefs-dialog-gtk3.glade:1234 data/ui/prefs-dialog-gtk2.glade:1204 msgid "HotKey Settings" msgstr "Подешавања пречица" #: data/ui/popup-menu-gtk2.glade:45 msgid "_Mute" msgstr "_Утишај" #: data/ui/popup-menu-gtk2.glade:56 msgid "_Volume Control" msgstr "_Управљај глаÑноћом" #: data/ui/popup-menu-gtk2.glade:81 msgid "_Reload Sound" msgstr "_Поново учитај звук" #: data/ui/prefs-dialog-gtk2.glade:106 msgid "Notify for volume changes from:" msgstr "ОбавеÑти о променама глаÑноће Ñа:" pnmixer-0.7.2/po/uk.po000066400000000000000000000432131311427610600146030ustar00rootroot00000000000000# Ukrainian translation for pnmixer. # Copyright (C) 2016 PNMixer team (msgids) # This file is distributed under the same license as the pnmixer package. # # Yuri Chornoivan , 2016, 2017. msgid "" msgstr "" "Project-Id-Version: pnmixer 0.7.1-rc3\n" "Report-Msgid-Bugs-To: https://github.com/nicklan/pnmixer/issues\n" "POT-Creation-Date: 2017-03-13 21:25+0700\n" "PO-Revision-Date: 2017-03-13 20:32+0200\n" "Last-Translator: Yuri Chornoivan \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" "X-Bugs: Report translation errors to the Language-Team address.\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: Lokalize 1.5\n" #: src/hotkeys.c:175 msgid "Could not grab the following HotKeys" msgstr "Ðе вдалоÑÑ Ð¿ÐµÑ€ÐµÑ…Ð¾Ð¿Ð¸Ñ‚Ð¸ вказані нижче комбінації клавіш" #: src/hotkeys.c:176 src/ui-prefs-dialog.c:339 #: data/ui/prefs-dialog-gtk3.glade:973 data/ui/prefs-dialog-gtk2.glade:935 msgid "Mute/Unmute" msgstr "Вимкнути/Увімкнути звук" #: src/hotkeys.c:178 src/ui-prefs-dialog.c:342 msgid "Volume Up" msgstr "Гучніше" #: src/hotkeys.c:180 src/ui-prefs-dialog.c:345 msgid "Volume Down" msgstr "Тихіше" #: src/main.c:69 #, c-format msgid "Unable to run command: %s" msgstr "Ðе вдалоÑÑ Ð²Ð¸ÐºÐ¾Ð½Ð°Ñ‚Ð¸ таку команду: %s" #: src/main.c:89 msgid "No mixer application was found on your system. Please open preferences and set the command you want to run for volume control." msgstr "У вашій ÑиÑтемі не виÑвлено програми Ð´Ð»Ñ Ð¼Ñ–ÐºÑˆÑƒÐ²Ð°Ð½Ð½Ñ. Будь лаÑка, відкрийте вікно налаштувань програми Ñ– вкажіть команду, Ñку Ñлід викориÑтовувати Ð´Ð»Ñ ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð³ÑƒÑ‡Ð½Ñ–Ñтю." #: src/main.c:109 msgid "You have not specified a custom command to run, please specify one in preferences." msgstr "Вами не вказано нетипової команди. Будь лаÑка, вкажіть Ñ—Ñ— у налаштуваннÑÑ… програми." #: src/main.c:210 src/main.c:248 msgid "PNMixer Error" msgstr "Помилка PNMixer" #: src/main.c:239 msgid "Warning: Connection to sound system failed." msgstr "ПопередженнÑ: не вдалоÑÑ Ð²Ñтановити зв’Ñзок із звуковою підÑиÑтемою." #: src/main.c:243 msgid "" "Do you want to re-initialize the audio connection ?\n" "\n" "If you do not, you will either need to restart PNMixer or select the 'Reload Audio' option in the right-click menu in order for PNMixer to function." msgstr "" "Хочете повторно ініціалізувати Ð·â€™Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð·Ñ– звуковою підÑиÑтемою?\n" "\n" "Якщо ви цього не зробите, вам Ñлід або перезавантажити PNMixer або ÑкориÑтатиÑÑ Ð¿ÑƒÐ½ÐºÑ‚Ð¾Ð¼ «Перезавантажити звук» у контекÑтному меню, щоб змуÑити PNMixer працювати." #: src/main.c:334 msgid "- A mixer for the system tray." msgstr "- Мікшер у ÑиÑтемному лотку." #: src/main.c:342 #, c-format msgid "%s version: %s\n" msgstr "ВерÑÑ–Ñ %s: %s\n" #: src/notif.c:77 msgid "Volume muted" msgstr "Звук вимкнено" #: src/notif.c:82 src/ui-tray-icon.c:355 msgid "Volume" msgstr "ГучніÑть" #: src/notif.c:135 msgid "No sound card" msgstr "Ðемає звукової картки" #: src/notif.c:136 msgid "No playable soundcard found" msgstr "Ðе знайдено звукової картки, Ñка могла б відтворювати звук" #: src/notif.c:141 msgid "Soundcard disconnected" msgstr "Звукову картку від’єднано" #: src/notif.c:142 msgid "Soundcard has been disconnected, reloading sound system..." msgstr "Звукову картку від’єднано, перезавантажуємо звукову підÑиÑтему…" #: src/prefs.c:356 #, c-format msgid "Couldn't load preferences file: %s" msgstr "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ файл налаштувань: %s" #: src/prefs.c:365 #, c-format msgid "Couldn't load default preferences: %s" msgstr "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ типові налаштуваннÑ: %s" #: src/prefs.c:391 #, c-format msgid "Couldn't write preferences file: %s" msgstr "Ðе вдалоÑÑ Ð·Ð°Ð¿Ð¸Ñати файл налаштувань: %s" #: src/prefs.c:411 #, c-format msgid "'%s' exists but is not a directory, won't be able to save preferences." msgstr "«%s» Ñ–Ñнує, але не Ñ” каталогом. Зберегти Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ðµ вдаÑтьÑÑ." #: src/prefs.c:415 #, c-format msgid "Couldn't make preferences directory: %s" msgstr "Ðе вдалоÑÑ Ñтворити каталог Ð´Ð»Ñ Ð·Ð±ÐµÑ€Ñ–Ð³Ð°Ð½Ð½Ñ Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½ÑŒ: %s" #: src/ui-about-dialog.c:114 msgid "A mixer for the system tray" msgstr "Мікшер у ÑиÑтемному лотку" #: src/ui-about-dialog.c:115 msgid "Copyright © 2010-2016 Nick Lanham" msgstr "© Nick Lanham, 2010–2016" #: src/ui-hotkey-dialog.c:48 #, c-format msgid "Set %s HotKey" msgstr "Ð’Ñтановити ÑÐºÐ¾Ñ€Ð¾Ñ‡ÐµÐ½Ð½Ñ %s" #: src/ui-hotkey-dialog.c:52 #, c-format msgid "Press new HotKey for %s" msgstr "ÐатиÑніть нову комбінацію клавіш Ð´Ð»Ñ Ð´Ñ–Ñ— %s" #: src/ui-hotkey-dialog.c:174 msgid "Could not grab the keyboard." msgstr "Ðе вдалоÑÑ Ð¿ÐµÑ€ÐµÑ…Ð¾Ð¿Ð¸Ñ‚Ð¸ дані клавіатури." #: src/ui-popup-menu.c:57 src/ui-popup-menu.c:84 src/ui-popup-window.c:129 msgid "Soundcard has no mute switch" msgstr "У звукової картки немає перемикача Ð²Ð¸Ð¼Ð¸ÐºÐ°Ð½Ð½Ñ Ð·Ð²ÑƒÐºÑƒ" #: src/ui-prefs-dialog.c:373 msgid "None" msgstr "Ðемає" #: src/ui-prefs-dialog.c:867 msgid "Notifications" msgstr "СповіщеннÑ" #: src/ui-tray-icon.c:357 msgid "No mute switch" msgstr "Ðемає перемикача вимиканнÑ" #: src/ui-tray-icon.c:359 msgid "Muted" msgstr "Вимкнено" #: data/desktop/pnmixer.desktop.in:3 msgid "PNMixer" msgstr "PNMixer" #: data/desktop/pnmixer.desktop.in:4 msgid "System Tray Mixer" msgstr "Мікшер у ÑиÑтемному лотку" #: data/desktop/pnmixer.desktop.in:5 msgid "An audio mixer for the system tray" msgstr "Звуковий мікшер у ÑиÑтемному лотку" #. TRANSLATORS: Search terms to find this application. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! #: data/desktop/pnmixer.desktop.in:7 msgid "alsa;audio;mixer;sound;" msgstr "alsa;audio;mixer;sound;алÑа;звук;аудіо;мікшер;" #. TRANSLATORS: Do NOT translate or transliterate this text (this is an icon file name)! #: data/desktop/pnmixer.desktop.in:11 msgid "pnmixer" msgstr "pnmixer" #: data/ui/hotkey-dialog-gtk3.glade:55 data/ui/prefs-dialog-gtk3.glade:279 msgid "Cancel" msgstr "СкаÑувати" #: data/ui/hotkey-dialog-gtk3.glade:109 data/ui/hotkey-dialog-gtk2.glade:49 msgid "Defining HotKey" msgstr "Визначаємо ÑкороченнÑ" #: data/ui/hotkey-dialog-gtk3.glade:124 data/ui/hotkey-dialog-gtk2.glade:65 msgid "(press C to reset)" msgstr "(натиÑніть C, щоб Ñкинути)" #: data/ui/popup-menu-gtk3.glade:33 data/ui/popup-menu-gtk2.glade:49 msgid "Mute/Unmute Volume" msgstr "Вимкнути/Увімкнути звук" #: data/ui/popup-menu-gtk3.glade:58 #: data/ui/popup-window-horizontal-gtk3.glade:54 #: data/ui/popup-window-vertical-gtk3.glade:58 #: data/ui/popup-window-horizontal-gtk2.glade:56 #: data/ui/popup-window-vertical-gtk2.glade:58 msgid "Mute" msgstr "Вимкнути звук" #: data/ui/popup-menu-gtk3.glade:73 data/ui/popup-menu-gtk2.glade:60 msgid "Open Volume Control" msgstr "Відкрити вікно ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð³ÑƒÑ‡Ð½Ñ–Ñтю" #: data/ui/popup-menu-gtk3.glade:95 data/ui/prefs-dialog-gtk3.glade:975 #: data/ui/prefs-dialog-gtk2.glade:937 msgid "Volume Control" msgstr "РегулÑтор гучноÑті" #: data/ui/popup-menu-gtk3.glade:110 data/ui/popup-menu-gtk3.glade:133 #: data/ui/popup-menu-gtk2.glade:73 msgid "Preferences" msgstr "ÐалаштуваннÑ" #: data/ui/popup-menu-gtk3.glade:148 data/ui/popup-menu-gtk3.glade:171 #: data/ui/popup-menu-gtk2.glade:85 msgid "Reload Sound" msgstr "Перезавантажити звук" #: data/ui/popup-menu-gtk3.glade:186 data/ui/popup-menu-gtk3.glade:209 #: data/ui/popup-menu-gtk2.glade:98 msgid "About" msgstr "Про програму" #: data/ui/popup-menu-gtk3.glade:231 data/ui/popup-menu-gtk3.glade:254 #: data/ui/popup-menu-gtk2.glade:117 msgid "Quit" msgstr "Вийти" #: data/ui/popup-window-horizontal-gtk3.glade:81 #: data/ui/popup-window-vertical-gtk3.glade:74 #: data/ui/popup-window-horizontal-gtk2.glade:72 #: data/ui/popup-window-vertical-gtk2.glade:74 msgid "Mixer" msgstr "Мікшер" #: data/ui/prefs-dialog-gtk3.glade:43 data/ui/prefs-dialog-gtk2.glade:68 msgid "Timeout (ms):" msgstr "Ð§Ð°Ñ Ð¾Ñ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ (мÑ):" #: data/ui/prefs-dialog-gtk3.glade:65 data/ui/prefs-dialog-gtk2.glade:46 msgid "Enable Notifications" msgstr "Увімкнути ÑповіщеннÑ" #: data/ui/prefs-dialog-gtk3.glade:89 data/ui/prefs-dialog-gtk2.glade:210 msgid "Notification Options" msgstr "Параметри ÑповіщеннÑ" #: data/ui/prefs-dialog-gtk3.glade:116 data/ui/prefs-dialog-gtk3.glade:1255 #: data/ui/prefs-dialog-gtk2.glade:125 data/ui/prefs-dialog-gtk2.glade:1225 msgid "HotKeys" msgstr "Клавіатурні ÑкороченнÑ" #: data/ui/prefs-dialog-gtk3.glade:132 data/ui/prefs-dialog-gtk2.glade:146 msgid "Mouse Scroll" msgstr "ÐŸÑ€Ð¾ÐºÑ€ÑƒÑ‡ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð»Ñ–Ñ‰Ð°Ñ‚ÐºÐ° миші" #: data/ui/prefs-dialog-gtk3.glade:148 data/ui/prefs-dialog-gtk2.glade:167 msgid "Adjustment in Popups" msgstr "ÐšÐ¾Ñ€Ð¸Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ñƒ контекÑтних вікнах" #: data/ui/prefs-dialog-gtk3.glade:164 data/ui/prefs-dialog-gtk2.glade:188 msgid "External Change" msgstr "Ð—Ð¾Ð²Ð½Ñ–ÑˆÐ½Ñ Ð·Ð¼Ñ–Ð½Ð°" #: data/ui/prefs-dialog-gtk3.glade:185 msgid "Notify for volume changes from:" msgstr "Ð¡Ð¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ Ñ‰Ð¾Ð´Ð¾ зміни гучноÑті від:" #: data/ui/prefs-dialog-gtk3.glade:212 data/ui/prefs-dialog-gtk2.glade:12 msgid "Notification support disabled at compile time." msgstr "Підтримку Ñповіщень було вимкнено під Ñ‡Ð°Ñ Ð·Ð±Ð¸Ñ€Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¸." #: data/ui/prefs-dialog-gtk3.glade:236 data/ui/prefs-dialog-gtk2.glade:241 msgid "PNMixer Preferences" msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ PNMixer" #: data/ui/prefs-dialog-gtk3.glade:324 msgid "Ok" msgstr "Гаразд" #: data/ui/prefs-dialog-gtk3.glade:369 msgid "Apply" msgstr "ЗаÑтоÑувати" #: data/ui/prefs-dialog-gtk3.glade:427 data/ui/prefs-dialog-gtk2.glade:338 msgid "Card:" msgstr "Картка:" #: data/ui/prefs-dialog-gtk3.glade:439 data/ui/prefs-dialog-gtk2.glade:349 msgid "Channel:" msgstr "Канал:" #: data/ui/prefs-dialog-gtk3.glade:450 data/ui/prefs-dialog-gtk2.glade:409 msgid "Change volume on a logarithmic scale, closer to human perception." msgstr "Змінювати гучніÑть у логарифмічній шкалі, близько до людÑького ÑприйнÑттÑ." #: data/ui/prefs-dialog-gtk3.glade:452 data/ui/prefs-dialog-gtk2.glade:408 msgid "Normalize Volume:" msgstr "ÐÐ¾Ñ€Ð¼Ð°Ð»Ñ–Ð·Ð°Ñ†Ñ–Ñ Ð³ÑƒÑ‡Ð½Ð¾Ñті:" #: data/ui/prefs-dialog-gtk3.glade:502 data/ui/prefs-dialog-gtk2.glade:425 msgid "Sound Device" msgstr "Звуковий приÑтрій" #: data/ui/prefs-dialog-gtk3.glade:520 data/ui/prefs-dialog-gtk2.glade:443 msgid "Device" msgstr "ПриÑтрій" #: data/ui/prefs-dialog-gtk3.glade:555 data/ui/prefs-dialog-gtk2.glade:477 msgid "Slider Orientation:" msgstr "ÐžÑ€Ñ–Ñ”Ð½Ñ‚Ð°Ñ†Ñ–Ñ Ð¿Ð¾Ð²Ð·ÑƒÐ½ÐºÐ°:" #: data/ui/prefs-dialog-gtk3.glade:567 data/ui/prefs-dialog-gtk2.glade:520 msgid "Text Volume Position:" msgstr "Ð Ð¾Ð·Ñ‚Ð°ÑˆÑƒÐ²Ð°Ð½Ð½Ñ Ñ‚ÐµÐºÑту гучноÑті:" #: data/ui/prefs-dialog-gtk3.glade:576 data/ui/prefs-dialog-gtk2.glade:501 msgid "Display Text Volume" msgstr "Показувати гучніÑть текÑтом" #: data/ui/prefs-dialog-gtk3.glade:596 data/ui/prefs-dialog-gtk2.glade:489 msgid "Vertical" msgstr "Вертикальна" #: data/ui/prefs-dialog-gtk3.glade:597 data/ui/prefs-dialog-gtk2.glade:490 msgid "Horizontal" msgstr "Горизонтальна" #: data/ui/prefs-dialog-gtk3.glade:611 data/ui/prefs-dialog-gtk2.glade:534 msgid "Top" msgstr "Вгорі" #: data/ui/prefs-dialog-gtk3.glade:612 data/ui/prefs-dialog-gtk2.glade:535 msgid "Bottom" msgstr "Внизу" #: data/ui/prefs-dialog-gtk3.glade:613 data/ui/prefs-dialog-gtk2.glade:536 msgid "Left" msgstr "Ліворуч" #: data/ui/prefs-dialog-gtk3.glade:614 data/ui/prefs-dialog-gtk2.glade:537 msgid "Right" msgstr "Праворуч" #: data/ui/prefs-dialog-gtk3.glade:632 data/ui/prefs-dialog-gtk2.glade:556 msgid "Volume Popup" msgstr "КонтекÑтне вікно гучноÑті" #: data/ui/prefs-dialog-gtk3.glade:663 data/ui/prefs-dialog-gtk2.glade:619 msgid "Volume Meter Color:" msgstr "Колір індикатора гучноÑті:" #: data/ui/prefs-dialog-gtk3.glade:675 data/ui/prefs-dialog-gtk2.glade:606 msgid "Volume Meter Offset (%):" msgstr "ЗÑув індикатора гучноÑті (%):" #: data/ui/prefs-dialog-gtk3.glade:713 data/ui/prefs-dialog-gtk2.glade:589 msgid "Draw Volume Meter on Tray Icon" msgstr "Показувати індикатор гучноÑті на піктограмі лотка" #: data/ui/prefs-dialog-gtk3.glade:735 data/ui/prefs-dialog-gtk2.glade:672 msgid "Volume Meter" msgstr "Індикатор гучноÑті" #: data/ui/prefs-dialog-gtk3.glade:755 data/ui/prefs-dialog-gtk2.glade:699 msgid "Use System Theme" msgstr "ВикориÑтовувати загальноÑиÑтемну тему" #: data/ui/prefs-dialog-gtk3.glade:770 data/ui/prefs-dialog-gtk2.glade:712 msgid "Icon Theme" msgstr "Тема піктограм" #: data/ui/prefs-dialog-gtk3.glade:791 data/ui/prefs-dialog-gtk2.glade:732 msgid "View" msgstr "ПереглÑд" #: data/ui/prefs-dialog-gtk3.glade:829 data/ui/prefs-dialog-gtk2.glade:772 msgid "Volume Control Command" msgstr "Команда ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð³ÑƒÑ‡Ð½Ñ–Ñтю" #: data/ui/prefs-dialog-gtk3.glade:860 data/ui/prefs-dialog-gtk2.glade:808 msgid "Scroll Step:" msgstr "Крок гортаннÑ" #: data/ui/prefs-dialog-gtk3.glade:872 data/ui/prefs-dialog-gtk2.glade:819 msgid "Fine Scroll Step:" msgstr "Підкрок гортаннÑ:" #: data/ui/prefs-dialog-gtk3.glade:918 data/ui/prefs-dialog-gtk2.glade:875 msgid "Volume Scrolling" msgstr "Ð ÐµÐ³ÑƒÐ»ÑŽÐ²Ð°Ð½Ð½Ñ Ð³ÑƒÑ‡Ð½Ð¾Ñті гортаннÑм" #: data/ui/prefs-dialog-gtk3.glade:949 data/ui/prefs-dialog-gtk2.glade:922 msgid "Custom Command:" msgstr "Ðетипова команда:" #: data/ui/prefs-dialog-gtk3.glade:961 data/ui/prefs-dialog-gtk2.glade:911 msgid "Middle Click Action:" msgstr "Ð”Ñ–Ñ Ð·Ð° клацаннÑм Ñередньою:" #: data/ui/prefs-dialog-gtk3.glade:974 data/ui/prefs-dialog-gtk2.glade:936 msgid "Show Preferences" msgstr "Показати налаштуваннÑ" #: data/ui/prefs-dialog-gtk3.glade:976 data/ui/prefs-dialog-gtk2.glade:938 msgid "Custom (set below)" msgstr "Ðетипова (вкажіть нижче)" #: data/ui/prefs-dialog-gtk3.glade:1005 data/ui/prefs-dialog-gtk2.glade:974 msgid "Mouse" msgstr "Миша" #: data/ui/prefs-dialog-gtk3.glade:1026 data/ui/prefs-dialog-gtk2.glade:995 msgid "Behavior" msgstr "Поведінка" #: data/ui/prefs-dialog-gtk3.glade:1057 data/ui/prefs-dialog-gtk2.glade:1025 msgid "Enable HotKeys" msgstr "Увімкнути клавіатурні ÑкороченнÑ" #: data/ui/prefs-dialog-gtk3.glade:1085 data/ui/prefs-dialog-gtk2.glade:1099 msgid "Command" msgstr "Команда" #: data/ui/prefs-dialog-gtk3.glade:1100 data/ui/prefs-dialog-gtk2.glade:1052 msgid "Mute/Unmute:" msgstr "Вимкнути/Увімкнути звук:" #: data/ui/prefs-dialog-gtk3.glade:1112 data/ui/prefs-dialog-gtk2.glade:1064 msgid "Volume Up:" msgstr "Гучніше:" #: data/ui/prefs-dialog-gtk3.glade:1124 data/ui/prefs-dialog-gtk2.glade:1076 msgid "Volume Down:" msgstr "Тихіше:" #: data/ui/prefs-dialog-gtk3.glade:1135 data/ui/prefs-dialog-gtk2.glade:1109 msgid "HotKey" msgstr "СкороченнÑ" #: data/ui/prefs-dialog-gtk3.glade:1154 data/ui/prefs-dialog-gtk3.glade:1175 #: data/ui/prefs-dialog-gtk3.glade:1196 data/ui/prefs-dialog-gtk2.glade:1128 #: data/ui/prefs-dialog-gtk2.glade:1151 data/ui/prefs-dialog-gtk2.glade:1174 msgid "(None)" msgstr "(Ðемає)" #: data/ui/prefs-dialog-gtk3.glade:1212 data/ui/prefs-dialog-gtk2.glade:1087 msgid "Double-click a HotKey to assign a new HotKey" msgstr "Двічі клацніть на Ñкороченні, щоб призначити нове" #: data/ui/prefs-dialog-gtk3.glade:1234 data/ui/prefs-dialog-gtk2.glade:1204 msgid "HotKey Settings" msgstr "Параметри Ñкорочень" #: data/ui/popup-menu-gtk2.glade:45 msgid "_Mute" msgstr "Ð’_имкнути звук" #: data/ui/popup-menu-gtk2.glade:56 msgid "_Volume Control" msgstr "ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ _гучніÑтю" #: data/ui/popup-menu-gtk2.glade:81 msgid "_Reload Sound" msgstr "_Перезавантажити звук" #: data/ui/prefs-dialog-gtk2.glade:106 msgid "Notify for volume changes from:" msgstr "Ð¡Ð¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ Ñ‰Ð¾Ð´Ð¾ зміни гучноÑті від:" pnmixer-0.7.2/po/vi.po000066400000000000000000000361051311427610600146040ustar00rootroot00000000000000# Vietnamese translations for pnmixer package # Bản dịch Tiếng Việt dành cho gói pnmixer. # This file is distributed under the same license as the pnmixer package. # Trần Ngá»c Quân , 2016. # msgid "" msgstr "" "Project-Id-Version: pnmixer 0.7-rc1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-05-07 18:36+0700\n" "PO-Revision-Date: 2016-05-09 14:34+0700\n" "Last-Translator: Trần Ngá»c Quân \n" "Language-Team: Vietnamese \n" "Language: vi\n" "X-Bugs: Report translation errors to the Language-Team address.\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: Gtranslator 2.91.7\n" #: ../src/hotkeys.c:172 msgid "Could not grab the following HotKeys" msgstr "Không thể túm phím nóng sau đây" #: ../src/hotkeys.c:173 ../src/ui-prefs-dialog.c:336 #: ../data/ui/prefs-dialog-gtk3.glade.h:43 #: ../data/ui/prefs-dialog-gtk2.glade.h:41 msgid "Mute/Unmute" msgstr "Câm/thôi câm" #: ../src/hotkeys.c:175 ../src/ui-prefs-dialog.c:339 msgid "Volume Up" msgstr "Tăng âm lượng" #: ../src/hotkeys.c:177 ../src/ui-prefs-dialog.c:342 msgid "Volume Down" msgstr "Giảm âm lượng" #: ../src/main.c:69 #, c-format msgid "Unable to run command: %s" msgstr "Không thể chạy lệnh: %s" #: ../src/main.c:89 msgid "No mixer application was found on your system. Please open preferences and set the command you want to run for volume control." msgstr "Không tìm thấy ứng dụng trá»™n nào trên hệ thống cá»§a bạn. Vui lòng mở tùy thích và đặt lệnh mà bạn muốn chạy cho việc diá»u khiển âm lượng." #: ../src/main.c:109 msgid "You have not specified a custom command to run, please specify one in preferences." msgstr "Bạn chưa đưa ra lệnh tá»± chá»n để chạy, vui lòng chỉ định má»™t cái trong tùy thích." #: ../src/main.c:204 ../src/main.c:242 msgid "PNMixer Error" msgstr "Lá»—i PNMixer" #: ../src/main.c:233 msgid "Warning: Connection to sound system failed." msgstr "Cảnh báo: Kết nối đến hệ thống âm thanh gặp lá»—i." #: ../src/main.c:237 msgid "" "Do you want to re-initialize the audio connection ?\n" "\n" "If you do not, you will either need to restart PNMixer or select the 'Reload Audio' option in the right-click menu in order for PNMixer to function." msgstr "" "Bạn có thá»±c sá»± muốn khởi tạo lại kết nối âm thanh?\n" "\n" "Nếu không, bạn sẽ hoặc là cần khởi động lại PNMixer hoặc là chá»n tùy chá»n “Tải lại âm thanh†trong trình đơn chuá»™t phải để PNMixer thá»±c hiện chức năng." #. Parse options #: ../src/main.c:328 msgid "- A mixer for the system tray." msgstr "- Má»™t bá»™ trá»™n cho khay hệ thống." #: ../src/main.c:336 #, c-format msgid "%s version: %s\n" msgstr "%s phiên bản %s\n" #: ../src/notif.c:130 msgid "No sound card" msgstr "Không có card âm thanh nào" #: ../src/notif.c:131 msgid "No playable soundcard found" msgstr "Không tìm thấy card âm thanh nào phát được" #: ../src/notif.c:136 msgid "Soundcard disconnected" msgstr "Card âm thanh đã ngắt kết nối" #: ../src/notif.c:137 msgid "Soundcard has been disconnected, reloading sound system..." msgstr "Card âm thanh đã ngắt kết nối, Ä‘ang tải lại hệ thống âm thanh…" #: ../src/prefs.c:356 #, c-format msgid "Couldn't load preferences file: %s" msgstr "Không thể tải tập tin tùy thích: %s" #: ../src/prefs.c:365 #, c-format msgid "Couldn't load default preferences: %s" msgstr "Không thể tải tùy thích mặc định: %s" #: ../src/prefs.c:391 #, c-format msgid "Couldn't write preferences file: %s" msgstr "Không thể ghi tập tin tùy thích: %s" #: ../src/prefs.c:411 #, c-format msgid "'%s' exists but is not a directory, won't be able to save preferences." msgstr "“%s†có tồn tại nhưng không phải là má»™t thư mục, không thể ghi lại các tùy thích." #: ../src/prefs.c:415 #, c-format msgid "Couldn't make preferences directory: %s" msgstr "Không thể tạo thư mục cho tùy thích: %s" #: ../src/ui-about-dialog.c:112 msgid "A mixer for the system tray" msgstr "Bá»™ trá»™n cho khay hệ thống" #: ../src/ui-about-dialog.c:113 msgid "Copyright © 2010-2016 Nick Lanham" msgstr "Tác quyá»n © 2010-2016 Nick Lanham" #: ../src/ui-hotkey-dialog.c:48 #, c-format msgid "Set %s HotKey" msgstr "Äặt phím nóng %s" #: ../src/ui-hotkey-dialog.c:52 #, c-format msgid "Press new HotKey for %s" msgstr "Bấm phím nóng cho %s" #: ../src/ui-hotkey-dialog.c:150 msgid "Could not grab the keyboard." msgstr "Không thể túm được phím bấm." #: ../src/ui-prefs-dialog.c:370 msgid "None" msgstr "Không" #: ../src/ui-prefs-dialog.c:845 msgid "Notifications" msgstr "Thông báo" #: ../src/ui-tray-icon.c:332 ../src/ui-tray-icon.c:335 msgid "Volume" msgstr "Âm lượng" #: ../src/ui-tray-icon.c:335 msgid "Muted" msgstr "Câm" #: ../data/desktop/pnmixer.desktop.in.h:1 msgid "System Tray Mixer" msgstr "Bá»™ trá»™n trên khay hệ thống" #: ../data/desktop/pnmixer.desktop.in.h:2 msgid "An audio mixer for the system tray" msgstr "Má»™t bá»™ trá»™n âm dành cho khay hệ thống" #: ../data/ui/hotkey-dialog-gtk3.glade.h:1 #: ../data/ui/prefs-dialog-gtk3.glade.h:11 msgid "Cancel" msgstr "Thôi" #: ../data/ui/hotkey-dialog-gtk3.glade.h:2 #: ../data/ui/hotkey-dialog-gtk2.glade.h:1 msgid "Defining HotKey" msgstr "Äịnh nghÄ©a phím nóng" #: ../data/ui/hotkey-dialog-gtk3.glade.h:3 #: ../data/ui/hotkey-dialog-gtk2.glade.h:2 msgid "(press C to reset)" msgstr "(bấm tổ hợp phím CTRL+C để đặt lại)" #: ../data/ui/popup-menu-gtk3.glade.h:1 ../data/ui/popup-menu-gtk2.glade.h:2 msgid "Mute/Unmute Volume" msgstr "Câm/thôi câm tiếng" #: ../data/ui/popup-menu-gtk3.glade.h:2 #: ../data/ui/popup-window-horizontal-gtk3.glade.h:1 #: ../data/ui/popup-window-vertical-gtk3.glade.h:1 #: ../data/ui/popup-window-horizontal-gtk2.glade.h:1 #: ../data/ui/popup-window-vertical-gtk2.glade.h:1 msgid "Mute" msgstr "Câm" #: ../data/ui/popup-menu-gtk3.glade.h:3 ../data/ui/popup-menu-gtk2.glade.h:4 msgid "Open Volume Control" msgstr "Mở Ä‘iá»u khiển âm lượng" #: ../data/ui/popup-menu-gtk3.glade.h:4 #: ../data/ui/prefs-dialog-gtk3.glade.h:45 #: ../data/ui/prefs-dialog-gtk2.glade.h:43 msgid "Volume Control" msgstr "Äiá»u khiển âm lượng" #: ../data/ui/popup-menu-gtk3.glade.h:5 ../data/ui/popup-menu-gtk2.glade.h:5 msgid "Preferences" msgstr "Tùy thích" #: ../data/ui/popup-menu-gtk3.glade.h:6 ../data/ui/popup-menu-gtk2.glade.h:7 msgid "Reload Sound" msgstr "Tải lại âm thanh" #: ../data/ui/popup-menu-gtk3.glade.h:7 ../data/ui/popup-menu-gtk2.glade.h:8 msgid "About" msgstr "Giá»›i thiệu" #: ../data/ui/popup-menu-gtk3.glade.h:8 ../data/ui/popup-menu-gtk2.glade.h:9 msgid "Quit" msgstr "Thoát" #: ../data/ui/popup-window-horizontal-gtk3.glade.h:2 #: ../data/ui/popup-window-vertical-gtk3.glade.h:2 #: ../data/ui/popup-window-horizontal-gtk2.glade.h:2 #: ../data/ui/popup-window-vertical-gtk2.glade.h:2 msgid "Mixer" msgstr "Trá»™n" #: ../data/ui/prefs-dialog-gtk3.glade.h:1 #: ../data/ui/prefs-dialog-gtk2.glade.h:1 msgid "Notification support disabled at compile time." msgstr "Việc há»— trợ thông báo bị tắt lúc biên dịch." #: ../data/ui/prefs-dialog-gtk3.glade.h:2 #: ../data/ui/prefs-dialog-gtk2.glade.h:2 msgid "Enable Notifications" msgstr "Bật thông báo" #: ../data/ui/prefs-dialog-gtk3.glade.h:3 #: ../data/ui/prefs-dialog-gtk2.glade.h:3 msgid "Timeout (ms):" msgstr "Thá»i hạn (ms):" #: ../data/ui/prefs-dialog-gtk3.glade.h:4 #: ../data/ui/prefs-dialog-gtk2.glade.h:9 msgid "Notification Options" msgstr "Các tùy chá»n cảnh báo" #: ../data/ui/prefs-dialog-gtk3.glade.h:5 #: ../data/ui/prefs-dialog-gtk2.glade.h:5 msgid "HotKeys" msgstr "Phím nóng" #: ../data/ui/prefs-dialog-gtk3.glade.h:6 #: ../data/ui/prefs-dialog-gtk2.glade.h:6 msgid "Mouse Scroll" msgstr "Cuá»™n chuá»™t" #: ../data/ui/prefs-dialog-gtk3.glade.h:7 #: ../data/ui/prefs-dialog-gtk2.glade.h:7 msgid "Adjustment in Popups" msgstr "Chỉnh trong trong trình đơn nhảy lên" #: ../data/ui/prefs-dialog-gtk3.glade.h:8 #: ../data/ui/prefs-dialog-gtk2.glade.h:8 msgid "External Change" msgstr "Thay đổi bên ngoài" #: ../data/ui/prefs-dialog-gtk3.glade.h:9 msgid "Notify for volume changes from:" msgstr "Thông báo các thay đổi âm lượng từ:" #: ../data/ui/prefs-dialog-gtk3.glade.h:10 #: ../data/ui/prefs-dialog-gtk2.glade.h:10 msgid "PNMixer Preferences" msgstr "Tùy thích PNMixer" #: ../data/ui/prefs-dialog-gtk3.glade.h:12 msgid "Ok" msgstr "ÄÆ°á»£c" #: ../data/ui/prefs-dialog-gtk3.glade.h:13 #: ../data/ui/prefs-dialog-gtk2.glade.h:11 msgid "Slider Orientation:" msgstr "Hướng con trượt:" #: ../data/ui/prefs-dialog-gtk3.glade.h:14 #: ../data/ui/prefs-dialog-gtk2.glade.h:12 msgid "Vertical" msgstr "Dá»c" #: ../data/ui/prefs-dialog-gtk3.glade.h:15 #: ../data/ui/prefs-dialog-gtk2.glade.h:13 msgid "Horizontal" msgstr "Ngang" #: ../data/ui/prefs-dialog-gtk3.glade.h:16 #: ../data/ui/prefs-dialog-gtk2.glade.h:14 msgid "Display Text Volume" msgstr "Hiển thị chữ âm lượng" #: ../data/ui/prefs-dialog-gtk3.glade.h:17 #: ../data/ui/prefs-dialog-gtk2.glade.h:15 msgid "Text Volume Position:" msgstr "Vị trí chữ âm lượng:" #: ../data/ui/prefs-dialog-gtk3.glade.h:18 #: ../data/ui/prefs-dialog-gtk2.glade.h:16 msgid "Top" msgstr "Trên" #: ../data/ui/prefs-dialog-gtk3.glade.h:19 #: ../data/ui/prefs-dialog-gtk2.glade.h:17 msgid "Bottom" msgstr "Dưới" #: ../data/ui/prefs-dialog-gtk3.glade.h:20 #: ../data/ui/prefs-dialog-gtk2.glade.h:18 msgid "Left" msgstr "Trái" #: ../data/ui/prefs-dialog-gtk3.glade.h:21 #: ../data/ui/prefs-dialog-gtk2.glade.h:19 msgid "Right" msgstr "Phải" #: ../data/ui/prefs-dialog-gtk3.glade.h:22 #: ../data/ui/prefs-dialog-gtk2.glade.h:20 msgid "Volume Popup" msgstr "Trình đơn âm lượng nổi lên" #: ../data/ui/prefs-dialog-gtk3.glade.h:23 #: ../data/ui/prefs-dialog-gtk2.glade.h:21 msgid "Draw Volume Meter on Tray Icon" msgstr "Thước Ä‘o âm lượng trên biểu tượng khay dạng thô" #: ../data/ui/prefs-dialog-gtk3.glade.h:25 #: ../data/ui/prefs-dialog-gtk2.glade.h:23 #, no-c-format msgid "Volume Meter Offset (%):" msgstr "Vị trí bù thước Ä‘o âm lượng (%):" #: ../data/ui/prefs-dialog-gtk3.glade.h:26 #: ../data/ui/prefs-dialog-gtk2.glade.h:24 msgid "Volume Meter Color:" msgstr "Màu thước Ä‘o âm lượng:" #: ../data/ui/prefs-dialog-gtk3.glade.h:27 #: ../data/ui/prefs-dialog-gtk2.glade.h:25 msgid "Volume Meter" msgstr "Thước Ä‘o âm lượng" #: ../data/ui/prefs-dialog-gtk3.glade.h:28 #: ../data/ui/prefs-dialog-gtk2.glade.h:26 msgid "Use System Theme" msgstr "Dùng sắc thái hệ thống" #: ../data/ui/prefs-dialog-gtk3.glade.h:29 #: ../data/ui/prefs-dialog-gtk2.glade.h:27 msgid "Icon Theme" msgstr "Chá»§ đỠbiểu tượng" #: ../data/ui/prefs-dialog-gtk3.glade.h:30 #: ../data/ui/prefs-dialog-gtk2.glade.h:28 msgid "View" msgstr "Trình bày" #: ../data/ui/prefs-dialog-gtk3.glade.h:31 #: ../data/ui/prefs-dialog-gtk2.glade.h:29 msgid "Card:" msgstr "Card:" #: ../data/ui/prefs-dialog-gtk3.glade.h:32 #: ../data/ui/prefs-dialog-gtk2.glade.h:30 msgid "Channel:" msgstr "Kênh:" #: ../data/ui/prefs-dialog-gtk3.glade.h:33 #: ../data/ui/prefs-dialog-gtk2.glade.h:31 msgid "Normalize Volume:" msgstr "Thưá»ng hóa âm lượng:" #: ../data/ui/prefs-dialog-gtk3.glade.h:34 #: ../data/ui/prefs-dialog-gtk2.glade.h:32 msgid "Change volume on a logarithmic scale, closer to human perception." msgstr "Äổi âm lượng theo thang lô-ga-rít, gần vá»›i cảm nhận cá»§a con ngưá»i." #: ../data/ui/prefs-dialog-gtk3.glade.h:35 #: ../data/ui/prefs-dialog-gtk2.glade.h:33 msgid "Sound Device" msgstr "Thiết bị âm thanh" #: ../data/ui/prefs-dialog-gtk3.glade.h:36 #: ../data/ui/prefs-dialog-gtk2.glade.h:34 msgid "Device" msgstr "Thiết bị" #: ../data/ui/prefs-dialog-gtk3.glade.h:37 #: ../data/ui/prefs-dialog-gtk2.glade.h:35 msgid "Volume Control Command" msgstr "Lệnh Ä‘iá»u khiển âm lượng" #: ../data/ui/prefs-dialog-gtk3.glade.h:38 #: ../data/ui/prefs-dialog-gtk2.glade.h:36 msgid "Scroll Step:" msgstr "Bước cuá»™n:" #: ../data/ui/prefs-dialog-gtk3.glade.h:39 #: ../data/ui/prefs-dialog-gtk2.glade.h:37 msgid "Fine Scroll Step:" msgstr "Bước cuá»™n mịn:" #: ../data/ui/prefs-dialog-gtk3.glade.h:40 #: ../data/ui/prefs-dialog-gtk2.glade.h:38 msgid "Volume Scrolling" msgstr "Cuá»™n âm lượng" #: ../data/ui/prefs-dialog-gtk3.glade.h:41 #: ../data/ui/prefs-dialog-gtk2.glade.h:39 msgid "Middle Click Action:" msgstr "Hành vi khi bấm nút giữa:" #: ../data/ui/prefs-dialog-gtk3.glade.h:42 #: ../data/ui/prefs-dialog-gtk2.glade.h:40 msgid "Custom Command:" msgstr "Lệnh tá»± chá»n:" #: ../data/ui/prefs-dialog-gtk3.glade.h:44 #: ../data/ui/prefs-dialog-gtk2.glade.h:42 msgid "Show Preferences" msgstr "Hiển thị tùy thích" #: ../data/ui/prefs-dialog-gtk3.glade.h:46 #: ../data/ui/prefs-dialog-gtk2.glade.h:44 msgid "Custom (set below)" msgstr "Tá»± chá»n (đặt ở dưới)" #: ../data/ui/prefs-dialog-gtk3.glade.h:47 #: ../data/ui/prefs-dialog-gtk2.glade.h:45 msgid "Mouse" msgstr "Con chuá»™t" #: ../data/ui/prefs-dialog-gtk3.glade.h:48 #: ../data/ui/prefs-dialog-gtk2.glade.h:46 msgid "Behavior" msgstr "Cách ứng xá»­" #: ../data/ui/prefs-dialog-gtk3.glade.h:49 #: ../data/ui/prefs-dialog-gtk2.glade.h:47 msgid "Enable HotKeys" msgstr "Bật các phím nóng" #: ../data/ui/prefs-dialog-gtk3.glade.h:50 #: ../data/ui/prefs-dialog-gtk2.glade.h:52 msgid "Command" msgstr "Lệnh" #: ../data/ui/prefs-dialog-gtk3.glade.h:51 #: ../data/ui/prefs-dialog-gtk2.glade.h:48 msgid "Mute/Unmute:" msgstr "Câm/thôi câm:" #: ../data/ui/prefs-dialog-gtk3.glade.h:52 #: ../data/ui/prefs-dialog-gtk2.glade.h:49 msgid "Volume Up:" msgstr "Tăng âm lượng:" #: ../data/ui/prefs-dialog-gtk3.glade.h:53 #: ../data/ui/prefs-dialog-gtk2.glade.h:50 msgid "Volume Down:" msgstr "Giảm âm lượng:" #: ../data/ui/prefs-dialog-gtk3.glade.h:54 #: ../data/ui/prefs-dialog-gtk2.glade.h:51 msgid "Double-click a HotKey to assign a new HotKey" msgstr "Bấm đúp vào phím nóng để gán má»™t phím má»›i" #: ../data/ui/prefs-dialog-gtk3.glade.h:55 #: ../data/ui/prefs-dialog-gtk2.glade.h:53 msgid "HotKey" msgstr "Phím nóng" #: ../data/ui/prefs-dialog-gtk3.glade.h:56 #: ../data/ui/prefs-dialog-gtk2.glade.h:54 msgid "(None)" msgstr "(Không)" #: ../data/ui/prefs-dialog-gtk3.glade.h:57 #: ../data/ui/prefs-dialog-gtk2.glade.h:55 msgid "HotKey Settings" msgstr "Cài đặt phím nóng" #: ../data/ui/popup-menu-gtk2.glade.h:1 msgid "_Mute" msgstr "Câ_m" #: ../data/ui/popup-menu-gtk2.glade.h:3 msgid "_Volume Control" msgstr "Äiá»u khiển â_m lượng" #: ../data/ui/popup-menu-gtk2.glade.h:6 msgid "_Reload Sound" msgstr "Tải _lại âm thanh" #: ../data/ui/prefs-dialog-gtk2.glade.h:4 msgid "Notify for volume changes from:" msgstr "Thông báo các thay đổi âm lượng đến từ:" pnmixer-0.7.2/po/zh_CN.po000066400000000000000000000343631311427610600151730ustar00rootroot00000000000000# Simplified Chinese translation for pnmixer. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the pnmixer package. # # Yuexuan Gu , 2015. msgid "" msgstr "" "Project-Id-Version: pnmixer 0.7\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-09-16 10:05+0700\n" "PO-Revision-Date: \n" "Last-Translator: Shengyu Zhang \n" "Language-Team: none\n" "Language: zh_CN\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Bugs: Report translation errors to the Language-Team address.\n" "X-Generator: Poedit 1.8.3\n" #: ../src/hotkeys.c:172 msgid "Could not grab the following HotKeys" msgstr "无法绑定以下热键" #: ../src/hotkeys.c:173 ../src/ui-prefs-dialog.c:339 #: ../data/ui/prefs-dialog-gtk3.glade.h:44 #: ../data/ui/prefs-dialog-gtk2.glade.h:41 msgid "Mute/Unmute" msgstr "é™éŸ³/å–æ¶ˆé™éŸ³" #: ../src/hotkeys.c:175 ../src/ui-prefs-dialog.c:342 msgid "Volume Up" msgstr "æé«˜éŸ³é‡" #: ../src/hotkeys.c:177 ../src/ui-prefs-dialog.c:345 msgid "Volume Down" msgstr "é™ä½ŽéŸ³é‡" #: ../src/main.c:69 #, c-format msgid "Unable to run command: %s" msgstr "无法è¿è¡Œå‘½ä»¤ï¼š %s" #: ../src/main.c:89 msgid "" "No mixer application was found on your system. Please open preferences and " "set the command you want to run for volume control." msgstr "没有在系统中å‘çŽ°æ··é¢‘å™¨ã€‚è¯·æ‰“å¼€é¦–é€‰é¡¹å¹¶è®¾ç½®ç”¨äºŽéŸ³é‡æŽ§åˆ¶çš„å‘½ä»¤ã€‚" #: ../src/main.c:109 msgid "" "You have not specified a custom command to run, please specify one in " "preferences." msgstr "没有指定一个命令用于è¿è¡Œï¼Œè¯·åœ¨é¦–选项中设置。" #: ../src/main.c:210 ../src/main.c:248 msgid "PNMixer Error" msgstr "PNMixer å‘生错误" #: ../src/main.c:239 msgid "Warning: Connection to sound system failed." msgstr "警告: 无法连接到音频系统。" #: ../src/main.c:243 msgid "" "Do you want to re-initialize the audio connection ?\n" "\n" "If you do not, you will either need to restart PNMixer or select the 'Reload " "Audio' option in the right-click menu in order for PNMixer to function." msgstr "" "是å¦é‡æ–°åˆå§‹åŒ–音频连接?\n" "\n" "è‹¥å¦ï¼Œä½ éœ€è¦é‡æ–°å¯åЍ PNMixer 或者在å³é”®èœå•中选中「é‡è½½éŸ³é¢‘ã€é€‰é¡¹ä»¥ä½¿ " "PNmixer 继续工作。" #. Parse options #: ../src/main.c:334 msgid "- A mixer for the system tray." msgstr "- 一个è¿è¡Œåœ¨ç³»ç»Ÿæ‰˜ç›˜ä¸Šçš„æ··é¢‘器。" #: ../src/main.c:342 #, c-format msgid "%s version: %s\n" msgstr "%s 版本:%s\n" #: ../src/notif.c:133 msgid "No sound card" msgstr "没有声å¡" #: ../src/notif.c:134 msgid "No playable soundcard found" msgstr "没有å¯ç”¨çš„声å¡" #: ../src/notif.c:139 msgid "Soundcard disconnected" msgstr "声塿œªè¿žæŽ¥" #: ../src/notif.c:140 msgid "Soundcard has been disconnected, reloading sound system..." msgstr "已和声å¡å¤±åŽ»è¿žæŽ¥ï¼Œæ­£åœ¨é‡æ–°åŠ è½½éŸ³é¢‘ç³»ç»Ÿ ……" #: ../src/prefs.c:355 #, c-format msgid "Couldn't load preferences file: %s" msgstr "无法载入默认é…置文件:%s" #: ../src/prefs.c:364 #, c-format msgid "Couldn't load default preferences: %s" msgstr "无法载入默认é…置:%s" #: ../src/prefs.c:390 #, c-format msgid "Couldn't write preferences file: %s" msgstr "无法写入é…置文件: %s" #: ../src/prefs.c:410 #, c-format msgid "'%s' exists but is not a directory, won't be able to save preferences." msgstr "错误:%s å·²å­˜åœ¨ä½†ä¸æ˜¯ä¸€ä¸ªç›®å½•,无法ä¿å­˜é…置。" #: ../src/prefs.c:414 #, c-format msgid "Couldn't make preferences directory: %s" msgstr "无法建立é…置目录:%s" #: ../src/ui-about-dialog.c:116 msgid "A mixer for the system tray" msgstr "一个è¿è¡Œåœ¨ç³»ç»Ÿæ‰˜ç›˜ä¸Šçš„æ··é¢‘器。" #: ../src/ui-about-dialog.c:117 msgid "Copyright © 2010-2016 Nick Lanham" msgstr "ç‰ˆæƒæ‰€æœ‰ © 2010-2016 Nick Lanham" #: ../src/ui-hotkey-dialog.c:48 #, c-format msgid "Set %s HotKey" msgstr "设置热键 %s" #: ../src/ui-hotkey-dialog.c:52 #, c-format msgid "Press new HotKey for %s" msgstr "按下热键以设置 %s" #: ../src/ui-hotkey-dialog.c:174 msgid "Could not grab the keyboard." msgstr "Could not grab the keyboard." #: ../src/ui-prefs-dialog.c:373 msgid "None" msgstr "空" #: ../src/ui-prefs-dialog.c:867 msgid "Notifications" msgstr "通知" #: ../src/ui-tray-icon.c:353 ../src/ui-tray-icon.c:356 msgid "Volume" msgstr "音é‡" #: ../src/ui-tray-icon.c:356 msgid "Muted" msgstr "é™éŸ³" #: ../data/desktop/pnmixer.desktop.in.h:1 msgid "System Tray Mixer" msgstr "系统托盘混频器" #: ../data/desktop/pnmixer.desktop.in.h:2 msgid "An audio mixer for the system tray" msgstr "一个è¿è¡Œåœ¨ç³»ç»Ÿæ‰˜ç›˜ä¸Šçš„音频混åˆå™¨" #. TRANSLATORS: Search terms to find this application. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! #: ../data/desktop/pnmixer.desktop.in.h:4 msgid "alsa;audio;mixer;sound;" msgstr "" #: ../data/ui/hotkey-dialog-gtk3.glade.h:1 #: ../data/ui/prefs-dialog-gtk3.glade.h:11 msgid "Cancel" msgstr "å–æ¶ˆ" #: ../data/ui/hotkey-dialog-gtk3.glade.h:2 #: ../data/ui/hotkey-dialog-gtk2.glade.h:1 msgid "Defining HotKey" msgstr "定义热键" #: ../data/ui/hotkey-dialog-gtk3.glade.h:3 #: ../data/ui/hotkey-dialog-gtk2.glade.h:2 msgid "(press C to reset)" msgstr "(按下 C 以é‡è®¾)" #: ../data/ui/popup-menu-gtk3.glade.h:1 ../data/ui/popup-menu-gtk2.glade.h:2 msgid "Mute/Unmute Volume" msgstr "é™éŸ³/å–æ¶ˆé™éŸ³" #: ../data/ui/popup-menu-gtk3.glade.h:2 #: ../data/ui/popup-window-horizontal-gtk3.glade.h:1 #: ../data/ui/popup-window-vertical-gtk3.glade.h:1 #: ../data/ui/popup-window-horizontal-gtk2.glade.h:1 #: ../data/ui/popup-window-vertical-gtk2.glade.h:1 msgid "Mute" msgstr "é™éŸ³" #: ../data/ui/popup-menu-gtk3.glade.h:3 ../data/ui/popup-menu-gtk2.glade.h:4 msgid "Open Volume Control" msgstr "æ‰“å¼€éŸ³é‡æŽ§åˆ¶" #: ../data/ui/popup-menu-gtk3.glade.h:4 ../data/ui/prefs-dialog-gtk3.glade.h:46 #: ../data/ui/prefs-dialog-gtk2.glade.h:43 msgid "Volume Control" msgstr "éŸ³é‡æŽ§åˆ¶" #: ../data/ui/popup-menu-gtk3.glade.h:5 ../data/ui/popup-menu-gtk2.glade.h:5 msgid "Preferences" msgstr "首选项" #: ../data/ui/popup-menu-gtk3.glade.h:6 ../data/ui/popup-menu-gtk2.glade.h:7 msgid "Reload Sound" msgstr "é‡è½½éŸ³é¢‘系统" #: ../data/ui/popup-menu-gtk3.glade.h:7 ../data/ui/popup-menu-gtk2.glade.h:8 msgid "About" msgstr "关于" #: ../data/ui/popup-menu-gtk3.glade.h:8 ../data/ui/popup-menu-gtk2.glade.h:9 msgid "Quit" msgstr "退出" #: ../data/ui/popup-window-horizontal-gtk3.glade.h:2 #: ../data/ui/popup-window-vertical-gtk3.glade.h:2 #: ../data/ui/popup-window-horizontal-gtk2.glade.h:2 #: ../data/ui/popup-window-vertical-gtk2.glade.h:2 msgid "Mixer" msgstr "混频器" #: ../data/ui/prefs-dialog-gtk3.glade.h:1 #: ../data/ui/prefs-dialog-gtk2.glade.h:2 msgid "Enable Notifications" msgstr "å¯ç”¨é€šçŸ¥" #: ../data/ui/prefs-dialog-gtk3.glade.h:2 #: ../data/ui/prefs-dialog-gtk2.glade.h:3 msgid "Timeout (ms):" msgstr "è¶…æ—¶ (ms):" #: ../data/ui/prefs-dialog-gtk3.glade.h:3 #: ../data/ui/prefs-dialog-gtk2.glade.h:9 msgid "Notification Options" msgstr "通知选项" #: ../data/ui/prefs-dialog-gtk3.glade.h:4 #: ../data/ui/prefs-dialog-gtk2.glade.h:5 msgid "HotKeys" msgstr "热键" #: ../data/ui/prefs-dialog-gtk3.glade.h:5 #: ../data/ui/prefs-dialog-gtk2.glade.h:6 msgid "Mouse Scroll" msgstr "鼠标滚轮" #: ../data/ui/prefs-dialog-gtk3.glade.h:6 #: ../data/ui/prefs-dialog-gtk2.glade.h:7 msgid "Adjustment in Popups" msgstr "在弹窗中调整" #: ../data/ui/prefs-dialog-gtk3.glade.h:7 #: ../data/ui/prefs-dialog-gtk2.glade.h:8 msgid "External Change" msgstr "外部å˜åŒ–" #: ../data/ui/prefs-dialog-gtk3.glade.h:8 msgid "Notify for volume changes from:" msgstr "当音é‡å› ä»¥ä¸‹åŽŸå› æ”¹å˜æ—¶å‘出通知:" #: ../data/ui/prefs-dialog-gtk3.glade.h:9 #: ../data/ui/prefs-dialog-gtk2.glade.h:1 msgid "Notification support disabled at compile time." msgstr "桌é¢é€šçŸ¥çš„æ”¯æŒåœ¨ç¼–译时没有å¯ç”¨ã€‚" #: ../data/ui/prefs-dialog-gtk3.glade.h:10 #: ../data/ui/prefs-dialog-gtk2.glade.h:10 msgid "PNMixer Preferences" msgstr "PNMixer 首选项" #: ../data/ui/prefs-dialog-gtk3.glade.h:12 msgid "Ok" msgstr "确定" #: ../data/ui/prefs-dialog-gtk3.glade.h:13 msgid "Apply" msgstr "应用" #: ../data/ui/prefs-dialog-gtk3.glade.h:14 #: ../data/ui/prefs-dialog-gtk2.glade.h:11 msgid "Card:" msgstr "声å¡ï¼š" #: ../data/ui/prefs-dialog-gtk3.glade.h:15 #: ../data/ui/prefs-dialog-gtk2.glade.h:12 msgid "Channel:" msgstr "声é“:" #: ../data/ui/prefs-dialog-gtk3.glade.h:16 #: ../data/ui/prefs-dialog-gtk2.glade.h:14 msgid "Change volume on a logarithmic scale, closer to human perception." msgstr "è°ƒæ•´éŸ³é‡æ—¶ä½¿ç”¨å¯¹æ•°åˆ»åº¦ï¼Œæ›´ç¬¦åˆäººè€³æ„ŸçŸ¥ã€‚" #: ../data/ui/prefs-dialog-gtk3.glade.h:17 #: ../data/ui/prefs-dialog-gtk2.glade.h:13 msgid "Normalize Volume:" msgstr "音é‡å‡è¡¡ï¼š" #: ../data/ui/prefs-dialog-gtk3.glade.h:18 #: ../data/ui/prefs-dialog-gtk2.glade.h:15 msgid "Sound Device" msgstr "音频设备" #: ../data/ui/prefs-dialog-gtk3.glade.h:19 #: ../data/ui/prefs-dialog-gtk2.glade.h:16 msgid "Device" msgstr "设备" #: ../data/ui/prefs-dialog-gtk3.glade.h:20 #: ../data/ui/prefs-dialog-gtk2.glade.h:17 msgid "Slider Orientation:" msgstr "æ»‘åŠ¨æ¡æ»‘动方å‘" #: ../data/ui/prefs-dialog-gtk3.glade.h:21 #: ../data/ui/prefs-dialog-gtk2.glade.h:18 msgid "Vertical" msgstr "垂直" #: ../data/ui/prefs-dialog-gtk3.glade.h:22 #: ../data/ui/prefs-dialog-gtk2.glade.h:19 msgid "Horizontal" msgstr "æ°´å¹³" #: ../data/ui/prefs-dialog-gtk3.glade.h:23 #: ../data/ui/prefs-dialog-gtk2.glade.h:20 msgid "Display Text Volume" msgstr "ä»¥æ–‡æœ¬å½¢å¼æ˜¾ç¤ºéŸ³é‡" #: ../data/ui/prefs-dialog-gtk3.glade.h:24 #: ../data/ui/prefs-dialog-gtk2.glade.h:21 msgid "Text Volume Position:" msgstr "文本ä½ç½®ï¼š" #: ../data/ui/prefs-dialog-gtk3.glade.h:25 #: ../data/ui/prefs-dialog-gtk2.glade.h:22 msgid "Top" msgstr "置顶" #: ../data/ui/prefs-dialog-gtk3.glade.h:26 #: ../data/ui/prefs-dialog-gtk2.glade.h:23 msgid "Bottom" msgstr "置底" #: ../data/ui/prefs-dialog-gtk3.glade.h:27 #: ../data/ui/prefs-dialog-gtk2.glade.h:24 msgid "Left" msgstr "å±…å³" #: ../data/ui/prefs-dialog-gtk3.glade.h:28 #: ../data/ui/prefs-dialog-gtk2.glade.h:25 msgid "Right" msgstr "å±…å³" #: ../data/ui/prefs-dialog-gtk3.glade.h:29 #: ../data/ui/prefs-dialog-gtk2.glade.h:26 msgid "Volume Popup" msgstr "音é‡å¼¹çª—" #: ../data/ui/prefs-dialog-gtk3.glade.h:30 #: ../data/ui/prefs-dialog-gtk2.glade.h:27 msgid "Draw Volume Meter on Tray Icon" msgstr "在托盘图标上绘制音é‡è®¡" #: ../data/ui/prefs-dialog-gtk3.glade.h:32 #: ../data/ui/prefs-dialog-gtk2.glade.h:29 #, no-c-format msgid "Volume Meter Offset (%):" msgstr "音é‡è®¡å移:" #: ../data/ui/prefs-dialog-gtk3.glade.h:33 #: ../data/ui/prefs-dialog-gtk2.glade.h:30 msgid "Volume Meter Color:" msgstr "音é‡è®¡é¢œè‰²ï¼š" #: ../data/ui/prefs-dialog-gtk3.glade.h:34 #: ../data/ui/prefs-dialog-gtk2.glade.h:31 msgid "Volume Meter" msgstr "音é‡è®¡" #: ../data/ui/prefs-dialog-gtk3.glade.h:35 #: ../data/ui/prefs-dialog-gtk2.glade.h:32 msgid "Use System Theme" msgstr "使用系统主题" #: ../data/ui/prefs-dialog-gtk3.glade.h:36 #: ../data/ui/prefs-dialog-gtk2.glade.h:33 msgid "Icon Theme" msgstr "图标" #: ../data/ui/prefs-dialog-gtk3.glade.h:37 #: ../data/ui/prefs-dialog-gtk2.glade.h:34 msgid "View" msgstr "外观" #: ../data/ui/prefs-dialog-gtk3.glade.h:38 #: ../data/ui/prefs-dialog-gtk2.glade.h:35 msgid "Volume Control Command" msgstr "éŸ³é‡æŽ§åˆ¶å‘½ä»¤" #: ../data/ui/prefs-dialog-gtk3.glade.h:39 #: ../data/ui/prefs-dialog-gtk2.glade.h:36 msgid "Scroll Step:" msgstr "滚动步长:" #: ../data/ui/prefs-dialog-gtk3.glade.h:40 #: ../data/ui/prefs-dialog-gtk2.glade.h:37 msgid "Fine Scroll Step:" msgstr "精细滚动步长:" #: ../data/ui/prefs-dialog-gtk3.glade.h:41 #: ../data/ui/prefs-dialog-gtk2.glade.h:38 msgid "Volume Scrolling" msgstr "滚轮调整音é‡" #: ../data/ui/prefs-dialog-gtk3.glade.h:42 #: ../data/ui/prefs-dialog-gtk2.glade.h:39 msgid "Middle Click Action:" msgstr "中键点击动作:" #: ../data/ui/prefs-dialog-gtk3.glade.h:43 #: ../data/ui/prefs-dialog-gtk2.glade.h:40 msgid "Custom Command:" msgstr "自定义命令:" #: ../data/ui/prefs-dialog-gtk3.glade.h:45 #: ../data/ui/prefs-dialog-gtk2.glade.h:42 msgid "Show Preferences" msgstr "显示首选项" #: ../data/ui/prefs-dialog-gtk3.glade.h:47 #: ../data/ui/prefs-dialog-gtk2.glade.h:44 msgid "Custom (set below)" msgstr "自定义(如下)" #: ../data/ui/prefs-dialog-gtk3.glade.h:48 #: ../data/ui/prefs-dialog-gtk2.glade.h:45 msgid "Mouse" msgstr "é¼ æ ‡" #: ../data/ui/prefs-dialog-gtk3.glade.h:49 #: ../data/ui/prefs-dialog-gtk2.glade.h:46 msgid "Behavior" msgstr "行为" #: ../data/ui/prefs-dialog-gtk3.glade.h:50 #: ../data/ui/prefs-dialog-gtk2.glade.h:47 msgid "Enable HotKeys" msgstr "å¯ç”¨çƒ­é”®" #: ../data/ui/prefs-dialog-gtk3.glade.h:51 #: ../data/ui/prefs-dialog-gtk2.glade.h:52 msgid "Command" msgstr "命令" #: ../data/ui/prefs-dialog-gtk3.glade.h:52 #: ../data/ui/prefs-dialog-gtk2.glade.h:48 msgid "Mute/Unmute:" msgstr "é™éŸ³/å–æ¶ˆé™éŸ³" #: ../data/ui/prefs-dialog-gtk3.glade.h:53 #: ../data/ui/prefs-dialog-gtk2.glade.h:49 msgid "Volume Up:" msgstr "æé«˜éŸ³é‡:" #: ../data/ui/prefs-dialog-gtk3.glade.h:54 #: ../data/ui/prefs-dialog-gtk2.glade.h:50 msgid "Volume Down:" msgstr "é™ä½ŽéŸ³é‡ï¼š" #: ../data/ui/prefs-dialog-gtk3.glade.h:55 #: ../data/ui/prefs-dialog-gtk2.glade.h:51 msgid "Double-click a HotKey to assign a new HotKey" msgstr "åŒå‡»ä»¥åˆ†é…新热键" #: ../data/ui/prefs-dialog-gtk3.glade.h:56 #: ../data/ui/prefs-dialog-gtk2.glade.h:53 msgid "HotKey" msgstr "热键" #: ../data/ui/prefs-dialog-gtk3.glade.h:57 #: ../data/ui/prefs-dialog-gtk2.glade.h:54 msgid "(None)" msgstr "(空)" #: ../data/ui/prefs-dialog-gtk3.glade.h:58 #: ../data/ui/prefs-dialog-gtk2.glade.h:55 msgid "HotKey Settings" msgstr "热键设置" #: ../data/ui/popup-menu-gtk2.glade.h:1 msgid "_Mute" msgstr "é™éŸ³ (_M)" #: ../data/ui/popup-menu-gtk2.glade.h:3 msgid "_Volume Control" msgstr "éŸ³é‡æŽ§åˆ¶ (_V)" #: ../data/ui/popup-menu-gtk2.glade.h:6 msgid "_Reload Sound" msgstr "釿–°åŠ è½½éŸ³é¢‘ç³»ç»Ÿ (_R)" #: ../data/ui/prefs-dialog-gtk2.glade.h:4 msgid "Notify for volume changes from:" msgstr "当音é‡å› ä»¥ä¸‹åŽŸå› æ”¹å˜æ—¶å‘出通知:" pnmixer-0.7.2/src/000077500000000000000000000000001311427610600137725ustar00rootroot00000000000000pnmixer-0.7.2/src/CMakeLists.txt000066400000000000000000000032351311427610600165350ustar00rootroot00000000000000## sources CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h) set(PNMixer_sources alsa.c audio.c hotkey.c hotkeys.c main.c notif.c prefs.c support-intl.c support-log.c support-ui.c ui-about-dialog.c ui-hotkey-dialog.c ui-popup-menu.c ui-popup-window.c ui-prefs-dialog.c ui-tray-icon.c ) ## includes include_directories( "${CMAKE_CURRENT_BINARY_DIR}" ) ## libraries set(default_deps alsa glib-2.0 x11 ) if(WITH_GTK3) LIST(APPEND default_deps "gtk+-3.0>=3.12.0") else(WITH_GTK3) LIST(APPEND default_deps "gtk+-2.0>=2.24.0") endif(WITH_GTK3) if(WITH_LIBNOTIFY) LIST(APPEND default_deps "libnotify") endif(WITH_LIBNOTIFY) pkg_check_modules(PNMixer_DEPS REQUIRED ${default_deps} ) ## main pnmixer target add_executable(pnmixer ${PNMixer_sources}) # and its flags target_link_libraries(pnmixer "${PNMixer_DEPS_LDFLAGS}") target_link_libraries(pnmixer m) target_compile_options(pnmixer PUBLIC "${PNMixer_DEPS_CFLAGS}") target_compile_definitions(pnmixer PUBLIC -DHAVE_CONFIG_H) install(TARGETS pnmixer DESTINATION "${CMAKE_INSTALL_BINDIR}") ## doc target if(BUILD_DOCUMENTATION) find_package(Doxygen) if(NOT DOXYGEN_FOUND) message(FATAL_ERROR "Doxygen is needed to build the documentation. Please install it correctly.") endif() CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in" "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile") # always built add_custom_target(doc ALL ${DOXYGEN_EXECUTABLE} "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile" WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}") install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/html" DESTINATION "${CMAKE_INSTALL_DOCDIR}") endif(BUILD_DOCUMENTATION) pnmixer-0.7.2/src/Doxyfile.in000066400000000000000000002315241311427610600161140ustar00rootroot00000000000000# Doxyfile 1.8.3.1 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # # All text after a hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" "). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # http://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or sequence of words) that should # identify the project. Note that if you do not use Doxywizard you need # to put quotes around the project name if it contains spaces. PROJECT_NAME = "pnmixer" # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer # a quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = "Volume mixer for the system tray" # With the PROJECT_LOGO tag one can specify an logo or icon that is # included in the documentation. The maximum height of the logo should not # exceed 55 pixels and the maximum width should not exceed 200 pixels. # Doxygen will copy the logo to the output directory. PROJECT_LOGO = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = "@CMAKE_CURRENT_BINARY_DIR@" # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, # Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English # messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, # Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, # Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = YES # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. Note that you specify absolute paths here, but also # relative paths, which will be relative from the directory where doxygen is # started. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful if your file system # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = NO # If the QT_AUTOBRIEF tag is set to YES then Doxygen will # interpret the first line (until the first dot) of a Qt-style # comment as the brief description. If set to NO, the comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 4 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # This tag can be used to specify a number of word-keyword mappings (TCL only). # A mapping has the form "name=value". For example adding # "class=itcl::class" will allow you to use the command class in the # itcl::class meaning. TCL_SUBST = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for # Java. For instance, namespaces will be presented as packages, qualified # scopes will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources only. Doxygen will then generate output that is more tailored for # Fortran. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for # VHDL. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, # and language is one of the parsers supported by doxygen: IDL, Java, # Javascript, CSharp, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, # C++. For instance to make doxygen treat .inc files as Fortran files (default # is PHP), and .f files as C (default is Fortran), use: inc=Fortran f=C. Note # that for custom extensions you also need to set FILE_PATTERNS otherwise the # files are not read by doxygen. EXTENSION_MAPPING = # If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all # comments according to the Markdown format, which allows for more readable # documentation. See http://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you # can mix doxygen, HTML, and XML commands with Markdown formatting. # Disable only in case of backward compatibilities issues. MARKDOWN_SUPPORT = YES # When enabled doxygen tries to link words that correspond to documented classes, # or namespaces to their corresponding documentation. Such a link can be # prevented in individual cases by by putting a % sign in front of the word or # globally by setting AUTOLINK_SUPPORT to NO. AUTOLINK_SUPPORT = YES # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also makes the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. # Doxygen will parse them like normal C++ but will assume all classes use public # instead of private inheritance when no explicit protection keyword is present. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate # getter and setter methods for a property. Setting this option to YES (the # default) will make doxygen replace the get and set methods by a property in # the documentation. This will only work if the methods are indeed getting or # setting a simple type. If this is not the case, or you want to show the # methods anyway, you should set this option to NO. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and # unions are shown inside the group in which they are included (e.g. using # @ingroup) instead of on a separate page (for HTML and Man pages) or # section (for LaTeX and RTF). INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and # unions with only public data fields will be shown inline in the documentation # of the scope in which they are defined (i.e. file, namespace, or group # documentation), provided this scope is documented. If set to NO (the default), # structs, classes, and unions are shown on a separate page (for HTML and Man # pages) or section (for LaTeX and RTF). INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum # is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically # be useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. TYPEDEF_HIDES_STRUCT = NO # Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be # set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given # their name and scope. Since this can be an expensive process and often the # same symbol appear multiple times in the code, doxygen keeps a cache of # pre-resolved symbols. If the cache is too small doxygen will become slower. # If the cache is too large, memory is wasted. The cache size is given by this # formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols. LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_PACKAGE tag is set to YES all members with package or internal # scope will be included in the documentation. EXTRACT_PACKAGE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base # name of the file that contains the anonymous namespace. By default # anonymous namespaces are hidden. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen # will list include files with double quotes in the documentation # rather than with sharp brackets. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen # will sort the (brief and detailed) documentation of class members so that # constructors and destructors are listed first. If set to NO (the default) # the constructors will appear in the respective orders defined by # SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. # This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO # and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the # hierarchy of group names into alphabetical order. If set to NO (the default) # the group names will appear in their defined order. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to # do proper type resolution of all parameters of a function it will reject a # match between the prototype and the implementation of a member function even # if there is only one candidate or it is obvious which candidate to choose # by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen # will still accept a match between prototype and implementation in such cases. STRICT_PROTO_MATCHING = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if section-label ... \endif # and \cond section-label ... \endcond blocks. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or macro consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and macros in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the # Namespaces page. # This will remove the Namespaces entry from the Quick Index # and from the Folder Tree View (if specified). The default is YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file # that represents doxygen's defaults, run doxygen with the -l option. # You can optionally specify a file name after the option, if omitted # DoxygenLayout.xml will be used as the name of the layout file. LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files # containing the references data. This must be a list of .bib files. The # .bib extension is automatically appended if omitted. Using this command # requires the bibtex tool to be installed. See also # http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style # of the bibliography can be controlled using LATEX_BIB_STYLE. To use this # feature you need bibtex and perl available in the search path. Do not use # file names with spaces, bibtex cannot handle them. CITE_BIB_FILES = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # The WARN_NO_PARAMDOC option can be enabled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = . # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # also the default input encoding. Doxygen uses libiconv (or the iconv built # into libc) for the transcoding. See http://www.gnu.org/software/libiconv for # the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh # *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py # *.f90 *.f *.for *.vhd *.vhdl FILE_PATTERNS = *.c *.h *.dox # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # Note that relative paths are relative to the directory from which doxygen is # run. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. # If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. # Doxygen will compare the file name with each pattern and apply the # filter if there is a match. # The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty or if # non of the patterns match the file name, INPUT_FILTER is applied. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) # and it is also possible to disable source filtering for a specific pattern # using *.ext= (so without naming a filter). This option only has effect when # FILTER_SOURCE_FILES is enabled. FILTER_SOURCE_PATTERNS = # If the USE_MD_FILE_AS_MAINPAGE tag refers to the name of a markdown file that # is part of the input, its contents will be placed on the main page (index.html). # This can be useful if you have a project on for instance GitHub and want reuse # the introduction page also for the doxygen output. USE_MDFILE_AS_MAINPAGE = #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C, C++ and Fortran comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = NO # If the REFERENCES_RELATION tag is set to YES # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = NO # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. # Otherwise they will link to the documentation. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = YES # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. Note that when using a custom header you are responsible # for the proper inclusion of any scripts and style sheets that doxygen # needs, which is dependent on the configuration options used. # It is advised to generate a default header using "doxygen -w html # header.html footer.html stylesheet.css YourConfigFile" and then modify # that header. Note that the header is subject to change so you typically # have to redo this when upgrading to a newer version of doxygen or when # changing the value of configuration settings such as GENERATE_TREEVIEW! HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If left blank doxygen will # generate a default style sheet. Note that it is recommended to use # HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this # tag will in the future become obsolete. HTML_STYLESHEET = # The HTML_EXTRA_STYLESHEET tag can be used to specify an additional # user-defined cascading style sheet that is included after the standard # style sheets created by doxygen. Using this option one can overrule # certain style aspects. This is preferred over using HTML_STYLESHEET # since it does not replace the standard style sheet and is therefor more # robust against future updates. Doxygen will copy the style sheet file to # the output directory. HTML_EXTRA_STYLESHEET = # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that # the files will be copied as-is; there are no commands or markers available. HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. # Doxygen will adjust the colors in the style sheet and background images # according to this color. Hue is specified as an angle on a colorwheel, # see http://en.wikipedia.org/wiki/Hue for more information. # For instance the value 0 represents red, 60 is yellow, 120 is green, # 180 is cyan, 240 is blue, 300 purple, and 360 is red again. # The allowed range is 0 to 359. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of # the colors in the HTML output. For a value of 0 the output will use # grayscales only. A value of 255 will produce the most vivid colors. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to # the luminance component of the colors in the HTML output. Values below # 100 gradually make the output lighter, whereas values above 100 make # the output darker. The value divided by 100 is the actual gamma applied, # so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, # and 100 does not change the gamma. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting # this to NO can help when comparing the output of multiple runs. HTML_TIMESTAMP = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. HTML_DYNAMIC_SECTIONS = NO # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of # entries shown in the various tree structured indices initially; the user # can expand and collapse entries dynamically later on. Doxygen will expand # the tree to such a level that at most the specified number of entries are # visible (unless a fully collapsed tree already exceeds this amount). # So setting the number of entries 1 will produce a full collapsed tree by # default. 0 is a special value representing an infinite number of entries # and will result in a full expanded tree by default. HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 # integrated development environment, introduced with OSX 10.5 (Leopard). # To create a documentation set, doxygen will generate a Makefile in the # HTML output directory. Running make will produce the docset in that # directory and running "make install" will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find # it at startup. # See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. GENERATE_DOCSET = NO # When GENERATE_DOCSET tag is set to YES, this tag determines the name of the # feed. A documentation feed provides an umbrella under which multiple # documentation sets from a single provider (such as a company or product suite) # can be grouped. DOCSET_FEEDNAME = "Doxygen generated docs" # When GENERATE_DOCSET tag is set to YES, this tag specifies a string that # should uniquely identify the documentation set bundle. This should be a # reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen # will append .docset to the name. DOCSET_BUNDLE_ID = org.doxygen.Project # When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely # identify the documentation publisher. This should be a reverse domain-name # style string, e.g. com.mycompany.MyDocSet.documentation. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING # is used to encode HtmlHelp index (hhk), content (hhc) and project file # content. CHM_INDEX_ENCODING = # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated # that can be used as input for Qt's qhelpgenerator to generate a # Qt Compressed Help (.qch) of the generated HTML documentation. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can # be used to specify the file name of the resulting .qch file. # The path specified is relative to the HTML output folder. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#namespace QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#virtual-folders QHP_VIRTUAL_FOLDER = doc # If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to # add. For more information please see # http://doc.trolltech.com/qthelpproject.html#custom-filters QHP_CUST_FILTER_NAME = # The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see # # Qt Help Project / Custom Filters. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's # filter section matches. # # Qt Help Project / Filter Attributes. QHP_SECT_FILTER_ATTRS = # If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can # be used to specify the location of Qt's qhelpgenerator. # If non-empty doxygen will try to run qhelpgenerator on the generated # .qhp file. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files # will be generated, which together with the HTML files, form an Eclipse help # plugin. To install this plugin and make it available under the help contents # menu in Eclipse, the contents of the directory containing the HTML and XML # files needs to be copied into the plugins directory of eclipse. The name of # the directory within the plugins directory should be the same as # the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before # the help appears. GENERATE_ECLIPSEHELP = NO # A unique identifier for the eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have # this name. ECLIPSE_DOC_ID = org.doxygen.Project # The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) # at top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. Since the tabs have the same information as the # navigation tree you can set this option to NO if you already set # GENERATE_TREEVIEW to YES. DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. # If the tag value is set to YES, a side panel will be generated # containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). # Windows users are probably better off using the HTML help feature. # Since the tree basically has the same information as the tab index you # could consider to set DISABLE_INDEX to NO when enabling this option. GENERATE_TREEVIEW = NO # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values # (range [0,1..20]) that doxygen will group on one line in the generated HTML # documentation. Note that a value of 0 will completely suppress the enum # values from appearing in the overview section. ENUM_VALUES_PER_LINE = 4 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 # When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open # links to external symbols imported via tag files in a separate window. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of Latex formulas included # as images in the HTML documentation. The default is 10. Note that # when you change the font size after a successful doxygen run you need # to manually remove any form_*.png images from the HTML output directory # to force them to be regenerated. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are # not supported properly for IE 6.0, but are supported on all modern browsers. # Note that when changing this option you need to delete any form_*.png files # in the HTML output before the changes have effect. FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax # (see http://www.mathjax.org) which uses client side Javascript for the # rendering instead of using prerendered bitmaps. Use this if you do not # have LaTeX installed or if you want to formulas look prettier in the HTML # output. When enabled you may also need to install MathJax separately and # configure the path to it using the MATHJAX_RELPATH option. USE_MATHJAX = NO # When MathJax is enabled you can set the default output format to be used for # thA MathJax output. Supported types are HTML-CSS, NativeMML (i.e. MathML) and # SVG. The default value is HTML-CSS, which is slower, but has the best # compatibility. MATHJAX_FORMAT = HTML-CSS # When MathJax is enabled you need to specify the location relative to the # HTML output directory using the MATHJAX_RELPATH option. The destination # directory should contain the MathJax.js script. For instance, if the mathjax # directory is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to # the MathJax Content Delivery Network so you can quickly see the result without # installing MathJax. # However, it is strongly recommended to install a local # copy of MathJax from http://www.mathjax.org before deployment. MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest # The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension # names that should be enabled during MathJax rendering. MATHJAX_EXTENSIONS = # When the SEARCHENGINE tag is enabled doxygen will generate a search box # for the HTML output. The underlying search engine uses javascript # and DHTML and should work on any modern browser. Note that when using # HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets # (GENERATE_DOCSET) there is already a search function so this one should # typically be disabled. For large projects the javascript based search engine # can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. SEARCHENGINE = YES # When the SERVER_BASED_SEARCH tag is enabled the search engine will be # implemented using a web server instead of a web client using Javascript. # There are two flavours of web server based search depending on the # EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for # searching and an index file used by the script. When EXTERNAL_SEARCH is # enabled the indexing and searching needs to be provided by external tools. # See the manual for details. SERVER_BASED_SEARCH = NO # When EXTERNAL_SEARCH is enabled doxygen will no longer generate the PHP # script for searching. Instead the search results are written to an XML file # which needs to be processed by an external indexer. Doxygen will invoke an # external search engine pointed to by the SEARCHENGINE_URL option to obtain # the search results. Doxygen ships with an example indexer (doxyindexer) and # search engine (doxysearch.cgi) which are based on the open source search engine # library Xapian. See the manual for configuration details. EXTERNAL_SEARCH = NO # The SEARCHENGINE_URL should point to a search engine hosted by a web server # which will returned the search results when EXTERNAL_SEARCH is enabled. # Doxygen ships with an example search engine (doxysearch) which is based on # the open source search engine library Xapian. See the manual for configuration # details. SEARCHENGINE_URL = # When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed # search data is written to a file for indexing by an external tool. With the # SEARCHDATA_FILE tag the name of this file can be specified. SEARCHDATA_FILE = searchdata.xml # When SERVER_BASED_SEARCH AND EXTERNAL_SEARCH are both enabled the # EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is # useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple # projects and redirect the results back to the right project. EXTERNAL_SEARCH_ID = # The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen # projects other than the one defined by this configuration file, but that are # all added to the same external search index. Each project needs to have a # unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id # of to a relative location where the documentation can be found. # The format is: EXTRA_SEARCH_MAPPINGS = id1=loc1 id2=loc2 ... EXTRA_SEARCH_MAPPINGS = #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = YES # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. # Note that when enabling USE_PDFLATEX this option is only used for # generating bitmaps for formulas in the HTML output, but not in the # Makefile that is written to the output directory. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4 # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for # the generated latex document. The footer should contain everything after # the last chapter. If it is left blank doxygen will generate a # standard footer. Notice: only use this tag if you know what you are doing! LATEX_FOOTER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = YES # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = YES # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO # If LATEX_SOURCE_CODE is set to YES then doxygen will include # source code with syntax highlighting in the LaTeX output. # Note that which sources are shown also depends on other settings # such as SOURCE_BROWSER. LATEX_SOURCE_CODE = NO # The LATEX_BIB_STYLE tag can be used to specify the style to use for the # bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See # http://en.wikipedia.org/wiki/BibTeX for more info. LATEX_BIB_STYLE = plain #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load style sheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. # This is useful # if you want to understand what is going on. # On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # pointed to by INCLUDE_PATH will be searched when a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition that # overrules the definition found in the source code. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all references to function-like macros # that are alone on a line, have an all uppercase name, and do not end with a # semicolon, because these will confuse the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. For each # tag file the location of the external documentation should be added. The # format of a tag file without this location is as follows: # # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths # or URLs. Note that each tag file must have a unique name (where the name does # NOT include the path). If a tag file is not located in the directory in which # doxygen is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option also works with HAVE_DOT disabled, but it is recommended to # install and use dot, since it yields more powerful graphs. CLASS_DIAGRAMS = YES # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the # documentation. The MSCGEN_PATH tag allows you to specify the directory where # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = YES # The DOT_NUM_THREADS specifies the number of dot invocations doxygen is # allowed to run in parallel. When set to 0 (the default) doxygen will # base this on the number of processors available in the system. You can set it # explicitly to a value larger than 0 to get control over the balance # between CPU load and processing speed. DOT_NUM_THREADS = 0 # By default doxygen will use the Helvetica font for all dot files that # doxygen generates. When you want a differently looking font you can specify # the font name using DOT_FONTNAME. You need to make sure dot is able to find # the font, which can be done by putting it in a standard location or by setting # the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the # directory containing the font. DOT_FONTNAME = Helvetica # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. DOT_FONTSIZE = 10 # By default doxygen will tell dot to use the Helvetica font. # If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to # set the path where dot can find it. DOT_FONTPATH = # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If the UML_LOOK tag is enabled, the fields and methods are shown inside # the class node. If there are many fields or methods and many nodes the # graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS # threshold limits the number of items for each type to make the size more # manageable. Set this to 0 for no limit. Note that the threshold may be # exceeded by 50% before the limit is enforced. UML_LIMIT_NUM_FIELDS = 10 # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = NO # If the CALL_GRAPH and HAVE_DOT options are set to YES then # doxygen will generate a call dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable call graphs # for selected functions only using the \callgraph command. CALL_GRAPH = NO # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then # doxygen will generate a caller dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable caller # graphs for selected functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will generate a graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are svg, png, jpg, or gif. # If left blank png will be used. If you choose svg you need to set # HTML_FILE_EXTENSION to xhtml in order to make the SVG files # visible in IE 9+ (other browsers do not have this requirement). DOT_IMAGE_FORMAT = png # If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to # enable generation of interactive SVG images that allow zooming and panning. # Note that this requires a modern browser other than Internet Explorer. # Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you # need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files # visible. Older versions of IE do not have SVG support. INTERACTIVE_SVG = NO # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MSCFILE_DIRS tag can be used to specify one or more directories that # contain msc files that are included in the documentation (see the # \mscfile command). MSCFILE_DIRS = # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the # number of direct children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, because dot on Windows does not # seem to support this out of the box. Warning: Depending on the platform used, # enabling this option may lead to badly anti-aliased labels on the edges of # a graph (i.e. they become hard to read). DOT_TRANSPARENT = NO # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = NO # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES pnmixer-0.7.2/src/alsa.c000066400000000000000000000571211311427610600150640ustar00rootroot00000000000000/* alsa.c * PNmixer is written by Nick Lanham, a fork of OBmixer * which was programmed by Lee Ferrett, derived * from the program "AbsVolume" by Paul Sherman * This program is free software; you can redistribute * it and/or modify it under the terms of the GNU General * Public License v3. source code is available at * */ /** * @file alsa.c * Alsa audio subsystem. * All the alsa-related code is enclosed in here, and this is the only * file that uses the alsa library. * This is the lowest-level part of PNMixer, that's why it doesn't include * any other local headers. If you do so, it probably means that you're * starting messing up the code, so think twice. * @brief Alsa audio subsystem. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #define _GNU_SOURCE /* exp10() */ #include #include #include #include "support-log.h" #include "alsa.h" #define ALSA_DEFAULT_CARD "(default)" #define ALSA_DEFAULT_HCTL "default" /* * Alsa log and debug macros. */ static void alsa_log_msg(enum log_level level, const char *card, const char *strerr, const char *format, ...) { va_list args; char buf[1024]; if (!card && !strerr) snprintf(buf, sizeof buf, "%s", format); else if (card && !strerr) snprintf(buf, sizeof buf, "'%s': %s", card, format); else if (!card && strerr) snprintf(buf, sizeof buf, "%s: %s", format, strerr); else // card && strerr snprintf(buf, sizeof buf, "'%s': %s: %s", card, format, strerr); va_start(args, format); log_msg_v(level, __FILE__, buf, args); va_end(args); } #define ALSA_ERR(err, ...) \ alsa_log_msg(LOG_ERROR, NULL, snd_strerror(err), __VA_ARGS__) #define ALSA_CARD_DEBUG(card, ...) \ alsa_log_msg(LOG_DEBUG, card, NULL, __VA_ARGS__) #define ALSA_CARD_WARN(card, ...) \ alsa_log_msg(LOG_WARN, card, NULL, __VA_ARGS__) #define ALSA_CARD_ERR(card, err, ...) \ alsa_log_msg(LOG_ERROR, card, snd_strerror(err), __VA_ARGS__) /* * Alsa mixer elem handling (deals with 'snd_mixer_elem_t'). * Parts of this code were taken and adapted from the original * `alsa-utils` package, `alsamixer` program, `volume_mapping.c` file. * * Copyright (c) 2010 Clemens Ladisch * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. */ #define MAX_LINEAR_DB_SCALE 24 static inline gboolean use_linear_dB_scale(long db_min, long db_max) { return db_max - db_min <= MAX_LINEAR_DB_SCALE * 100; } static long lrint_dir(double x, int dir) { if (dir > 0) return lrint(ceil(x)); else if (dir < 0) return lrint(floor(x)); else return lrint(x); } /* Return the name of a mixer element */ static const char * elem_get_name(snd_mixer_elem_t *elem) { return snd_mixer_selem_get_name(elem); } /* Get volume, return a value between 0 and 1 */ static double elem_get_volume(const char *hctl, snd_mixer_elem_t *elem, double *volume) { snd_mixer_selem_channel_id_t channel = SND_MIXER_SCHN_FRONT_RIGHT; int err; long min, max, value; *volume = 0; err = snd_mixer_selem_get_playback_volume_range(elem, &min, &max); if (err < 0) { ALSA_CARD_ERR(hctl, err, "Can't get playback volume range"); return FALSE; } if (min >= max) { ALSA_CARD_WARN(hctl, "Invalid playback volume range [%ld - %ld]", min, max); return FALSE; } err = snd_mixer_selem_get_playback_volume(elem, channel, &value); if (err < 0) { ALSA_CARD_ERR(hctl, err, "Can't get playback volume"); return FALSE; } *volume = (value - min) / (double) (max - min); return TRUE; } /* Set volume, input value between 0 and 1 */ static gboolean elem_set_volume(const char *hctl, snd_mixer_elem_t *elem, double volume, int dir) { int err; long min, max, value; err = snd_mixer_selem_get_playback_volume_range(elem, &min, &max); if (err < 0) { ALSA_CARD_ERR(hctl, err, "Can't get playback volume range"); return FALSE; } if (min >= max) { ALSA_CARD_WARN(hctl, "Invalid playback volume range [%ld - %ld]", min, max); return FALSE; } value = lrint_dir(volume * (max - min), dir) + min; err = snd_mixer_selem_set_playback_volume_all(elem, value); if (err < 0) { ALSA_CARD_ERR(hctl, err, "Can't set playback volume to %ld", value); return FALSE; } return TRUE; } /* Get normalized volume, return a value between 0 and 1 */ static gboolean elem_get_volume_normalized(const char *hctl, snd_mixer_elem_t *elem, double *volume) { snd_mixer_selem_channel_id_t channel = SND_MIXER_SCHN_FRONT_RIGHT; int err; long min, max, value; double normalized, min_norm; *volume = 0; err = snd_mixer_selem_get_playback_dB_range(elem, &min, &max); if (err < 0) { ALSA_CARD_ERR(hctl, err, "Can't get playback dB range"); return FALSE; } if (min >= max) { ALSA_CARD_WARN(hctl, "Invalid playback dB range [%ld - %ld]", min, max); return FALSE; } err = snd_mixer_selem_get_playback_dB(elem, channel, &value); if (err < 0) { ALSA_CARD_ERR(hctl, err, "Can't get playback dB"); return FALSE; } if (use_linear_dB_scale(min, max)) { normalized = (value - min) / (double) (max - min); } else { normalized = exp10((value - max) / 6000.0); if (min != SND_CTL_TLV_DB_GAIN_MUTE) { min_norm = exp10((min - max) / 6000.0); normalized = (normalized - min_norm) / (1 - min_norm); } } *volume = normalized; // ALSA_CARD_DEBUG(hctl, "Getting normalized volume: %lf", *volume); return TRUE; } /* Set normalized volume, input value between 0 and 1 */ static gboolean elem_set_volume_normalized(const char *hctl, snd_mixer_elem_t *elem, double volume, int dir) { int err; long min, max, value; err = snd_mixer_selem_get_playback_dB_range(elem, &min, &max); if (err < 0) { ALSA_CARD_ERR(hctl, err, "Can't get playback dB range"); return FALSE; } if (min >= max) { ALSA_CARD_WARN(hctl, "Invalid playback dB range [%ld - %ld]", min, max); return FALSE; } if (use_linear_dB_scale(min, max)) { value = lrint_dir(volume * (max - min), dir) + min; } else { if (min != SND_CTL_TLV_DB_GAIN_MUTE) { double min_norm = exp10((min - max) / 6000.0); volume = volume * (1 - min_norm) + min_norm; } value = lrint_dir(6000.0 * log10(volume), dir) + max; } err = snd_mixer_selem_set_playback_dB_all(elem, value, dir); if (err < 0) { ALSA_CARD_ERR(hctl, err, "Can't set playback dB to %ld", value); return FALSE; } // ALSA_CARD_DEBUG(hctl, "Normalized volume set: %lf (%d)", volume, dir); return TRUE; } /* Whether the card can be muted */ static gboolean elem_has_mute(G_GNUC_UNUSED const char *hctl, snd_mixer_elem_t *elem) { return snd_mixer_selem_has_playback_switch(elem) ? TRUE : FALSE; } /* Get the mute state, either TRUE or FALSE */ static gboolean elem_get_mute(const char *hctl, snd_mixer_elem_t *elem, gboolean *muted) { snd_mixer_selem_channel_id_t channel = SND_MIXER_SCHN_FRONT_RIGHT; int err; int value; *muted = FALSE; if (snd_mixer_selem_has_playback_switch(elem)) { err = snd_mixer_selem_get_playback_switch(elem, channel, &value); if (err < 0) { ALSA_CARD_ERR(hctl, err, "Can't get playback switch"); return FALSE; } } else { /* If there's no playback switch, assume not muted */ value = 1; } /* Value returned: 0 = muted, 1 = not muted */ *muted = value == 0 ? TRUE : FALSE; // ALSA_CARD_DEBUG(hctl, "Getting mute: %d", *muted); return TRUE; } /* Set the mute state, TRUE or FALSE */ static gboolean elem_set_mute(const char *hctl, snd_mixer_elem_t *elem, gboolean mute) { int err; int value; /* Value to set: 0 = muted, 1 = not muted */ value = mute ? 0 : 1; if (snd_mixer_selem_has_playback_switch(elem)) { err = snd_mixer_selem_set_playback_switch_all(elem, value); if (err < 0) { ALSA_CARD_ERR(hctl, err, "Can't set playback switch"); return FALSE; } } else { /* If there's no playback switch, do nothing */ } // ALSA_CARD_DEBUG(hctl, "Mute set: %d", mute); return TRUE; } /* * Alsa mixer handling (deals with 'snd_mixer_t'). */ /* Get poll descriptors in a dynamic array (must be freed). * The array is terminated by a fd set to -1. */ static struct pollfd * mixer_get_poll_descriptors(const char *hctl, snd_mixer_t *mixer) { int err, count; struct pollfd *fds; /* Get the number of poll descriptors. Afaik, it's always one. */ count = snd_mixer_poll_descriptors_count(mixer); /* Get the poll descriptors in a dynamic array */ fds = g_new0(struct pollfd, count + 1); err = snd_mixer_poll_descriptors(mixer, fds, count); if (err < 0) { ALSA_CARD_ERR(hctl, err, "Couldn't get poll descriptors"); return NULL; } /* Terminate the array with a fd set to -1 */ fds[count].fd = -1; return fds; } /* Get the list of playable channels */ static GSList * mixer_list_playable(G_GNUC_UNUSED const char *hctl, snd_mixer_t *mixer) { GSList *list = NULL; snd_mixer_elem_t *elem = NULL; elem = snd_mixer_first_elem(mixer); while (elem) { if (snd_mixer_selem_has_playback_volume(elem)) { const char *chan_name = snd_mixer_selem_get_name(elem); list = g_slist_append(list, g_strdup(chan_name)); } elem = snd_mixer_elem_next(elem); } return list; } /* Return TRUE if the mixer has at least one playable channel, FALSE otherwise */ static gboolean mixer_is_playable(const char *hctl, snd_mixer_t *mixer) { GSList *playable_chans; playable_chans = mixer_list_playable(hctl, mixer); if (playable_chans) { g_slist_free_full(playable_chans, g_free); return TRUE; } return FALSE; } /* Get a playable mixer element by name */ static snd_mixer_elem_t * mixer_get_playable_elem(const char *hctl, snd_mixer_t *mixer, const char *channel) { snd_mixer_elem_t *elem; snd_mixer_selem_id_t *sid; if (!channel) return NULL; ALSA_CARD_DEBUG(hctl, "Looking for playable mixer element '%s'", channel); /* Find the mixer element */ snd_mixer_selem_id_alloca(&sid); snd_mixer_selem_id_set_name(sid, channel); elem = snd_mixer_find_selem(mixer, sid); if (elem == NULL) { ALSA_CARD_WARN(hctl, "Can't find mixer element '%s'", channel); return NULL; } /* Check that it's playable */ if (!snd_mixer_selem_has_playback_volume(elem)) { ALSA_CARD_WARN(hctl, "Mixer element '%s' is not playable", channel); return NULL; } return elem; } /* Get the first playable mixer element */ static snd_mixer_elem_t * mixer_get_first_playable_elem(const char *hctl, snd_mixer_t *mixer) { snd_mixer_elem_t *elem; ALSA_CARD_DEBUG(hctl, "Looking for the first playable mixer element..."); /* Iterate on mixer elements, get the first playable */ elem = snd_mixer_first_elem(mixer); while (elem) { if (snd_mixer_selem_has_playback_volume(elem)) break; elem = snd_mixer_elem_next(elem); } if (elem == NULL) { ALSA_CARD_DEBUG(hctl, "No playable mixer element found"); return NULL; } return elem; } /* Close a mixer */ static void mixer_close(const char *hctl, snd_mixer_t *mixer) { int err; ALSA_CARD_DEBUG(hctl, "Closing mixer"); snd_mixer_free(mixer); err = snd_mixer_detach(mixer, hctl); if (err < 0) ALSA_CARD_ERR(hctl, err, "Can't detach mixer"); err = snd_mixer_close(mixer); if (err < 0) ALSA_CARD_ERR(hctl, err, "Can't close mixer"); } /* Open a mixer */ static snd_mixer_t * mixer_open(const char *hctl) { int err; snd_mixer_t *mixer = NULL; ALSA_CARD_DEBUG(hctl, "Opening mixer"); err = snd_mixer_open(&mixer, 0); if (err < 0) { ALSA_CARD_ERR(hctl, err, "Can't open mixer"); return NULL; } err = snd_mixer_attach(mixer, hctl); if (err < 0) { ALSA_CARD_ERR(hctl, err, "Can't attach card to mixer"); goto failure; } err = snd_mixer_selem_register(mixer, NULL, NULL); if (err < 0) { ALSA_CARD_ERR(hctl, err, "Can't register mixer simple element"); goto failure; } err = snd_mixer_load(mixer); if (err < 0) { ALSA_CARD_ERR(hctl, err, "Can't load mixer elements"); goto failure; } return mixer; failure: snd_mixer_close(mixer); return NULL; } /* * Alsa card iterator. * The Alsa API is really awkward when it comes to deal with cards * and to get various informations from it. * This iterator is here to make it less painful. */ struct alsa_card_iter { int number; char *name; char *hctl; }; typedef struct alsa_card_iter AlsaCardIter; /* Free an iterator */ static void alsa_card_iter_free(AlsaCardIter *iter) { if (iter == NULL) return; g_free(iter->name); g_free(iter->hctl); g_free(iter); } /* Create a new iterator */ static AlsaCardIter * alsa_card_iter_new(void) { AlsaCardIter *iter; iter = g_new0(AlsaCardIter, 1); iter->number = -2; return iter; } /* Iterate over alsa cards. Return TRUE as long as there is a card, * and FALSE when there's no more card. * After it returned FALSE, the iterator shouldn't be used anymore and * should be freed. */ static gboolean alsa_card_iter_loop(AlsaCardIter *iter) { int err; /* Free iter data at first */ g_free(iter->name); iter->name = NULL; g_free(iter->hctl); iter->hctl = NULL; /* First elem is the default alsa soundcard. * It's not really reachable as it with the ALSA API, * so we must add it manually here. */ if (iter->number == -2) { iter->number = -1; iter->name = g_strdup(ALSA_DEFAULT_CARD); iter->hctl = g_strdup(ALSA_DEFAULT_HCTL); return TRUE; } /* Get next alsa soundcard */ err = snd_card_next(&iter->number); if (err < 0) { ALSA_ERR(err, "Can't enumerate sound cards"); return FALSE; } /* No more soundcards ? */ if (iter->number < 0) return FALSE; /* Get card name */ err = snd_card_get_name(iter->number, &(iter->name)); if (err < 0) { ALSA_ERR(err, "Can't get card name"); return FALSE; } /* Get HCTL name */ iter->hctl = g_strdup_printf("hw:%d", iter->number); return TRUE; } /* * Alsa poll descriptors handling with GIO. */ /* Start watching the poll descriptors provided in the input array */ static guint * watch_poll_descriptors(const char *hctl, struct pollfd *pollfds, GIOFunc func, gpointer data) { int nfds, i; guint *watch_ids; /* Count the number of poll file descriptors */ nfds = i = 0; while (pollfds[i++].fd != -1) nfds++; /* Allocate a zero-termintated array to hold the watch ids */ watch_ids = g_new0(guint, nfds + 1); /* Watch every poll fd */ for (i = 0; i < nfds; i++) { GIOChannel *gioc; gioc = g_io_channel_unix_new(pollfds[i].fd); watch_ids[i] = g_io_add_watch(gioc, G_IO_IN | G_IO_ERR, func, data); g_io_channel_unref(gioc); } ALSA_CARD_DEBUG(hctl, "%d poll descriptors are now watched", nfds); return watch_ids; } /* Stop watching poll descriptors */ static void unwatch_poll_descriptors(guint *watch_ids) { int i; for (i = 0; watch_ids[i] != 0; i++) { g_source_remove(watch_ids[i]); watch_ids[i] = 0; } } /* * Public functions & signal handling */ struct alsa_card { gboolean normalize; /* Whether we work with normalized volume */ /* Card names */ char *name; /* Real card name like 'HDA Intel PCH' */ char *hctl; /* HTCL device name, like 'hw:0' */ /* Alsa data pointers */ snd_mixer_t *mixer; /* Alsa mixer */ snd_mixer_elem_t *mixer_elem; /* Alsa mixer elem */ /* Gio watch ids */ guint *watch_ids; /* User callback, to notify when something happens */ AlsaCb cb_func; gpointer cb_data; }; /** * Callback function for volume changes. * We forward changes to higher level, through a callback mechanism again. * * @param source the GIOChannel event source. * @param condition the condition which has been satisfied. * @param card data set in g_io_add_watch(). * @return FALSE if the event source should be removed. */ static gboolean poll_watch_cb(GIOChannel *source, GIOCondition condition, AlsaCard *card) { gchar sbuf[256]; gsize sread = 1; AlsaCb callback = card->cb_func; gpointer data = card->cb_data; // DEBUG("Entering %s()", __func__); /* Handle pending mixer events. * Everything is broken if we don't do that ! */ snd_mixer_handle_events(card->mixer); /* Check if the soundcard has been unplugged. In such case, * the file descriptor we're watching disappeared, causing a G_IO_ERR. */ if (condition == G_IO_ERR) { if (callback) callback(ALSA_CARD_DISCONNECTED, data); return FALSE; } /* Now read data from channel */ sread = 1; while (sread) { GIOStatus stat; /* This handles the case where mixer_elem_cb() doesn't read all * the data on source. If we don't clear it out we'll go into an infinite * callback loop since there will be data on the channel forever. */ stat = g_io_channel_read_chars(source, sbuf, 256, &sread, NULL); switch (stat) { case G_IO_STATUS_AGAIN: /* Normal, means alsa_cb cleared out the channel */ continue; case G_IO_STATUS_NORMAL: /* Actually bad, alsa failed to clear channel */ ERROR("Alsa failed to clear the channel"); if (callback) callback(ALSA_CARD_ERROR, data); break; case G_IO_STATUS_ERROR: case G_IO_STATUS_EOF: ERROR("GIO error has occurred"); if (callback) callback(ALSA_CARD_ERROR, data); break; default: WARN("Unknown status from g_io_channel_read_chars()"); } return TRUE; } /* Arriving here, no errors happened. * We can safely notify that values changed. */ if (callback) callback(ALSA_CARD_VALUES_CHANGED, data); return TRUE; } /** * Get the name of the card. * This is an internal string that shouldn't be modified. * * @param card a Card instance. * @return the name of the card. */ const char * alsa_card_get_name(AlsaCard *card) { return card->name; } /** * Get the name of the channel. * This is an internal string that shouldn't be modified. * * @param card a Card instance. * @return the name of the channel. */ const char * alsa_card_get_channel(AlsaCard *card) { return elem_get_name(card->mixer_elem); } /** * Whether the card has mute capabilities. * * @param card a Card instance. * @return TRUE if the card can be muted, FALSE otherwise. */ gboolean alsa_card_has_mute(AlsaCard *card) { return elem_has_mute(card->hctl, card->mixer_elem); } /** * Get the mute state, either TRUE or FALSE. * * @param card a Card instance. * @return TRUE if the card is muted, FALSE otherwise. */ gboolean alsa_card_is_muted(AlsaCard *card) { gboolean muted; elem_get_mute(card->hctl, card->mixer_elem, &muted); return muted; } /** * Toggle the mute state. * * @param card a Card instance. */ void alsa_card_toggle_mute(AlsaCard *card) { gboolean muted; /* Set mute */ muted = alsa_card_is_muted(card); elem_set_mute(card->hctl, card->mixer_elem, !muted); } /** * Get the volume in percent (value between 0 and 100). * * @param card a Card instance. * @return the volume in percent. */ gdouble alsa_card_get_volume(AlsaCard *card) { gdouble volume = 0; gboolean gotten = FALSE; if (card->normalize) gotten = elem_get_volume_normalized(card->hctl, card->mixer_elem, &volume); if (!gotten) elem_get_volume(card->hctl, card->mixer_elem, &volume); return volume * 100; } /** * Set the volume in percent (value between 0 and 100). * * @param card a Card instance. * @param value the volume in percent. * @param dir the direction of the volume change * (-1: lowering, +1: raising, 0: setting). */ void alsa_card_set_volume(AlsaCard *card, gdouble value, int dir) { gdouble volume; gboolean set = FALSE; volume = value / 100.0; /* Set volume */ if (card->normalize) set = elem_set_volume_normalized(card->hctl, card->mixer_elem, volume, dir); if (!set) elem_set_volume(card->hctl, card->mixer_elem, volume, dir); } /** * Set a callback invoked on volume/mute changes. * * @param card a Card instance. * @param callback the callback to be invoked. * @param user_data the user data passed to the callback. */ void alsa_card_install_callback(AlsaCard *card, AlsaCb callback, gpointer user_data) { card->cb_func = callback; card->cb_data = user_data; } /** * Free a card instance, therefore closing mixer and freeing any allocated ressources. * * @param card a Card instance. */ void alsa_card_free(AlsaCard *card) { if (card == NULL) return; if (card->watch_ids) unwatch_poll_descriptors(card->watch_ids); if (card->mixer) mixer_close(card->hctl, card->mixer); g_free(card->hctl); g_free(card->name); g_free(card); } /** * Create a new Card instance. * Look for the selected card among the available cards. * If found, open it, and look for the selected channel. * If found, all is well, the card is ready to be used. * Otherwise, NULL is returned. * * @param card_name the name of the card, or NULL to use the default card. * @param channel the name of the channel, or NULL to use the first playable channel. * @param normalize whether we use normalized volume or not. * @return a newly allocated Card instance, or NULL on failure. */ AlsaCard * alsa_card_new(const char *card_name, const char *channel, gboolean normalize) { AlsaCard *card; AlsaCardIter *iter; card = g_new0(AlsaCard, 1); /* Save normalize parameter */ card->normalize = normalize; /* Save card name */ if (!card_name) card_name = ALSA_DEFAULT_CARD; card->name = g_strdup(card_name); /* Get corresponding HCTL name */ iter = alsa_card_iter_new(); while (alsa_card_iter_loop(iter)) { if (!g_strcmp0(iter->name, card_name)) { card->hctl = g_strdup(iter->hctl); break; } } alsa_card_iter_free(iter); if (card->hctl == NULL) goto failure; /* Open mixer */ card->mixer = mixer_open(card->hctl); if (card->mixer == NULL) goto failure; /* Get mixer element */ card->mixer_elem = mixer_get_playable_elem(card->hctl, card->mixer, channel); if (card->mixer_elem == NULL) card->mixer_elem = mixer_get_first_playable_elem(card->hctl, card->mixer); if (card->mixer_elem == NULL) goto failure; /* Get mixer poll descriptors and watch them using gio. * That's how we get notified from every volume/mute changes, * may it be external or due to PNMixer. */ struct pollfd *pollfds; pollfds = mixer_get_poll_descriptors(card->hctl, card->mixer); if (pollfds == NULL) goto failure; card->watch_ids = watch_poll_descriptors(card->hctl, pollfds, (GIOFunc) poll_watch_cb, card); g_free(pollfds); /* Sum up the situation */ DEBUG("'%s': Card '%s' with channel '%s' initialized !", card->hctl, card->name, elem_get_name(card->mixer_elem)); return card; failure: alsa_card_free(card); return NULL; } /* * Alsa listing functions */ /** * Return the list of playable cards as a GSList. * Must be freed using g_slist_free_full() and g_free(). * * @return a list of playable cards. */ GSList * alsa_list_cards(void) { AlsaCardIter *iter; GSList *list = NULL; iter = alsa_card_iter_new(); while (alsa_card_iter_loop(iter)) { snd_mixer_t *mixer; /* Open mixer */ mixer = mixer_open(iter->hctl); if (mixer == NULL) continue; /* Only keep cards with playable channels */ if (mixer_is_playable(iter->hctl, mixer)) list = g_slist_append(list, g_strdup(iter->name)); /* Close mixer */ mixer_close(iter->hctl, mixer); } alsa_card_iter_free(iter); return list; } /** * For a given card name, return the list of playable channels as a GSList. * Must be freed using g_slist_free_full() and g_free(). * * @param card_name the name of the card for which we list the channels * @return a list of playable channels. */ GSList * alsa_list_channels(const char *card_name) { AlsaCardIter *iter; char *hctl = NULL; snd_mixer_t *mixer = NULL; GSList *list = NULL; /* Iterate over cards to find the one provided in argument */ iter = alsa_card_iter_new(); while (alsa_card_iter_loop(iter)) { if (!g_strcmp0(iter->name, card_name)) { hctl = g_strdup(iter->hctl); break; } } alsa_card_iter_free(iter); if (hctl == NULL) goto exit; /* Open the mixer */ mixer = mixer_open(hctl); if (mixer == NULL) goto exit; /* Get a list of playable channels */ list = mixer_list_playable(hctl, mixer); exit: /* Cleanup */ if (mixer) mixer_close(hctl, mixer); if (hctl) g_free(hctl); return list; } pnmixer-0.7.2/src/alsa.h000066400000000000000000000025011311427610600150610ustar00rootroot00000000000000/* alsa.h * PNmixer is written by Nick Lanham, a fork of OBmixer * which was programmed by Lee Ferrett, derived * from the program "AbsVolume" by Paul Sherman * This program is free software; you can redistribute * it and/or modify it under the terms of the GNU General * Public License v3. source code is available at * */ /** * @file alsa.h * Header for alsa.c. * @brief Header for alsa.c. */ #ifndef _ALSA_H_ #define _ALSA_H_ #include GSList *alsa_list_cards(void); GSList *alsa_list_channels(const char *card_name); typedef struct alsa_card AlsaCard; AlsaCard *alsa_card_new(const char *card, const char *channel, gboolean normalize); void alsa_card_free(AlsaCard *card); enum alsa_event { ALSA_CARD_ERROR, ALSA_CARD_DISCONNECTED, ALSA_CARD_VALUES_CHANGED }; typedef void (*AlsaCb) (enum alsa_event event, gpointer data); void alsa_card_install_callback(AlsaCard *card, AlsaCb callback, gpointer data); const char *alsa_card_get_name(AlsaCard *card); const char *alsa_card_get_channel(AlsaCard *card); gboolean alsa_card_has_mute(AlsaCard *card); gboolean alsa_card_is_muted(AlsaCard *card); void alsa_card_toggle_mute(AlsaCard *card); gdouble alsa_card_get_volume(AlsaCard *card); void alsa_card_set_volume(AlsaCard *card, gdouble value, int dir); #endif // _ALSA_H_ pnmixer-0.7.2/src/audio.c000066400000000000000000000435351311427610600152510ustar00rootroot00000000000000/* audio.c * PNmixer is written by Nick Lanham, a fork of OBmixer * which was programmed by Lee Ferrett, derived * from the program "AbsVolume" by Paul Sherman * This program is free software; you can redistribute * it and/or modify it under the terms of the GNU General * Public License v3. source code is available at * */ /** * @file audio.c * This file holds the audio related code. * It is a middleman between the low-level audio backend (alsa), * and the high-level ui code. * This abstraction layer allows the high-level code to be completely * unaware of the underlying audio implementation, may it be alsa or whatever. * @brief Audio subsystem. */ #include #include "audio.h" #include "alsa.h" #include "prefs.h" #include "support-log.h" /* * Enumeration to string, for friendly debug messages. */ static const gchar * audio_user_to_str(AudioUser user) { switch (user) { case AUDIO_USER_POPUP: return "popup"; case AUDIO_USER_TRAY_ICON: return "tray icon"; case AUDIO_USER_HOTKEYS: return "hotkeys"; default: return "unknown"; } } static const gchar * audio_signal_to_str(AudioSignal signal) { switch (signal) { case AUDIO_NO_CARD: return "no card"; case AUDIO_CARD_INITIALIZED: return "card initialized"; case AUDIO_CARD_CLEANED_UP: return "card cleaned up"; case AUDIO_CARD_DISCONNECTED: return "card disconnected"; case AUDIO_CARD_ERROR: return "card error"; case AUDIO_VALUES_CHANGED: return "values changed"; default: return "unknown"; } } /* * Audio Event. * An audio event is a struct that contains the current audio status. * It's passed in parameters of the user signal handlers, so that * user doesn't have to query the audio system to know about it. * It make things a little more efficient. */ /* Free an audio event */ static void audio_event_free(AudioEvent *event) { if (event == NULL) return; g_free(event); } /* Create a new audio event */ static AudioEvent * audio_event_new(Audio *audio, AudioSignal signal, AudioUser user) { AudioEvent *event; /* At the moment there's no need to duplicate card/channel * name strings, so let's optimize a very little and make * them const pointers. */ event = g_new0(AudioEvent, 1); event->signal = signal; event->user = user; event->card = audio_get_card(audio); event->channel = audio_get_channel(audio); event->has_mute = audio_has_mute(audio); event->muted = audio_is_muted(audio); event->volume = audio_get_volume(audio); return event; } /* * Audio Signal Handlers. * An audio signal handler is made of a callback and a data pointer. * It's the basic type that holds user signal handlers. */ struct audio_handler { AudioCallback callback; gpointer data; }; typedef struct audio_handler AudioHandler; /* Free an audio handler */ static void audio_handler_free(AudioHandler *handler) { g_free(handler); } /* Create a new audio handler */ static AudioHandler * audio_handler_new(AudioCallback callback, gpointer data) { AudioHandler *handler; handler = g_new0(AudioHandler, 1); handler->callback = callback; handler->data = data; return handler; } /* Check if two handlers are the identical. We compare the content * of the structures, not the pointers. */ static gint audio_handler_cmp(AudioHandler *h1, AudioHandler *h2) { if (h1->callback == h2->callback && h1->data == h2->data) return 0; return -1; } /* Add a handler to a handler list */ static GSList * audio_handler_list_append(GSList *list, AudioHandler *handler) { GSList *item; /* Ensure that the handler is not already part of the list. * It's probably an error to have a duplicated handler. */ item = g_slist_find_custom(list, handler, (GCompareFunc) audio_handler_cmp); if (item) { WARN("Audio handler already in the list"); return list; } /* Append the handler to the list */ return g_slist_append(list, handler); } /* Remove a handler from a handler list */ static GSList * audio_handler_list_remove(GSList *list, AudioHandler *handler) { GSList *item; /* Find the handler */ item = g_slist_find_custom(list, handler, (GCompareFunc) audio_handler_cmp); if (item == NULL) { WARN("Audio handler wasn't found in the list"); return list; } /* Remove the handler from the list. * We assume there's only one such handler. */ list = g_slist_remove_link(list, item); g_slist_free_full(item, (GDestroyNotify) audio_handler_free); return list; } /* * Public functions & signals handlers */ struct audio { /* Preferences */ gdouble scroll_step; gboolean normalize; /* Underlying sound card */ AlsaCard *soundcard; /* Cached value (to avoid querying the underlying * sound card each time we need the info). */ gchar *card; gchar *channel; /* Last action performed (volume/mute change) */ gint64 last_action_timestamp; /* User signal handlers. * To be invoked when the audio status changes. */ GSList *handlers; }; /** * Convenient function to invoke the handlers * * @param audio an Audio instance. * @param signal the signal to dispatch. * @param user the user that made the action. */ static void invoke_handlers(Audio *audio, AudioSignal signal, AudioUser user) { AudioEvent *event; GSList *item; /* Nothing to do if there is no handlers */ if (audio->handlers == NULL) return; /* Create a new event */ event = audio_event_new(audio, signal, user); /* Invoke the various handlers around */ DEBUG("** Dispatching signal '%s' from '%s', vol=%lg, has_mute=%s, muted=%s", audio_signal_to_str(signal), audio_user_to_str(user), event->volume, event->has_mute ? "yes" : "no", event->muted ? "yes" : "no"); for (item = audio->handlers; item; item = item->next) { AudioHandler *handler = item->data; handler->callback(audio, event, handler->data); } /* Then free the event */ audio_event_free(event); } /** * Callback invoked when an alsa event happens. * * @param event the event that happened. * @param data associated data. */ static void on_alsa_event(enum alsa_event event, gpointer data) { Audio *audio = (Audio *) data; /* If we are responsible for this event (aka we changed the volume/mute * values beforehand), we know that we left a timestamp to indicate * when the action was performed. */ if (audio->last_action_timestamp != 0) { gint64 last, now, delay; last = audio->last_action_timestamp; now = g_get_monotonic_time(); /* Discard the timestamp */ audio->last_action_timestamp = 0; /* The delay here is the time between the moment the action * was performed and the moment the callback was invoked. */ delay = now - last; /* The delay is supposed to be very quick, a matter of milliseconds. * We set its maximum delay to 1 second, it's probably far too much. * However it doesn't hurt to set it too long. On the other hand, * setting it too short could hurt. */ if (delay < 1000000) return; /* In some situation we can find a timestamp that was never used */ DEBUG("Discarding last timestamp, too old"); } /* Here, we are not at the origin of this change. * We must invoke the handlers. */ switch (event) { case ALSA_CARD_ERROR: invoke_handlers(audio, AUDIO_CARD_ERROR, AUDIO_USER_UNKNOWN); break; case ALSA_CARD_DISCONNECTED: invoke_handlers(audio, AUDIO_CARD_DISCONNECTED, AUDIO_USER_UNKNOWN); break; case ALSA_CARD_VALUES_CHANGED: invoke_handlers(audio, AUDIO_VALUES_CHANGED, AUDIO_USER_UNKNOWN); break; default: WARN("Unhandled alsa event: %d", event); } } /** * Disconnect a signal handler designed by 'callback' and 'data'. * * @param audio an Audio instance. * @param callback the callback to disconnect. * @param data the data to pass to the callback. */ void audio_signals_disconnect(Audio *audio, AudioCallback callback, gpointer data) { AudioHandler *handler; handler = audio_handler_new(callback, data); audio->handlers = audio_handler_list_remove(audio->handlers, handler); audio_handler_free(handler); } /** * Connect a signal handler designed by 'callback' and 'data'. * Remember to always pair 'connect' calls with 'disconnect' calls, * otherwise you'll be in trouble. * * @param audio an Audio instance. * @param callback the callback to connect. * @param data the data to pass to the callback. */ void audio_signals_connect(Audio *audio, AudioCallback callback, gpointer data) { AudioHandler *handler; handler = audio_handler_new(callback, data); audio->handlers = audio_handler_list_append(audio->handlers, handler); } /** * Get the name of the card currently hooked. * This is an internal string that shouldn't be modified. * * @param audio an Audio instance. * @return the name of the card. */ const char * audio_get_card(Audio *audio) { return audio->card; } /** * Get the name of the channel currently in use. * This is an internal string that shouldn't be modified. * * @param audio a Audio instance. * @return the name of the channel. */ const char * audio_get_channel(Audio *audio) { return audio->channel; } /** * Whether the card has mute capabilities. * * @param audio an Audio instance. * @return TRUE if the card can be muted, FALSE otherwise. */ gboolean audio_has_mute(Audio *audio) { AlsaCard *soundcard = audio->soundcard; if (!soundcard) return FALSE; return alsa_card_has_mute(soundcard); } /** * Get the mute state, either TRUE or FALSE. * * @param audio an Audio instance. * @return TRUE if the card is muted, FALSE otherwise. */ gboolean audio_is_muted(Audio *audio) { AlsaCard *soundcard = audio->soundcard; if (!soundcard) return TRUE; return alsa_card_is_muted(soundcard); } /** * Toggle the mute state. * * @param audio an Audio instance. * @param user the user who performs the action. */ void audio_toggle_mute(Audio *audio, AudioUser user) { AlsaCard *soundcard = audio->soundcard; /* Discard if no soundcard available */ if (!soundcard) return; /* Leave a trace */ audio->last_action_timestamp = g_get_real_time(); /* Toggle mute state */ alsa_card_toggle_mute(soundcard); /* Invoke the handlers */ invoke_handlers(audio, AUDIO_VALUES_CHANGED, user); } /** * Get the volume in percent (value between 0 and 100). * * @param audio an Audio instance. * @return the volume in percent. */ gdouble audio_get_volume(Audio *audio) { AlsaCard *soundcard = audio->soundcard; if (!soundcard) return 0; return alsa_card_get_volume(soundcard); } /** * Set the volume. * * @param audio an Audio instance. * @param user the user who performs the action. * @param cur_volume the current volume value, in percent. * @param new_volume the volume value to set, in percent. * @param dir the direction for the volume change * (-1: lowering, +1: raising, 0: setting). */ void _audio_set_volume(Audio *audio, AudioUser user, gdouble cur_volume, gdouble new_volume, gint dir) { AlsaCard *soundcard = audio->soundcard; /* Discard if no soundcard available */ if (!soundcard) return; /* Set the volume */ DEBUG("Setting volume from %lg to %lg (dir: %d)", cur_volume, new_volume, dir); alsa_card_set_volume(soundcard, new_volume, dir); /* Automatically unmute the volume */ if (alsa_card_is_muted(soundcard)) alsa_card_toggle_mute(soundcard); /* Check if the volume really changed. If it doesn't, * there's no need to invoke any handlers. It also means * that no alsa callback will be triggered, so we don't * save the 'last_action_timestamp'. */ new_volume = alsa_card_get_volume(soundcard); if (new_volume == cur_volume) return; /* Leave a trace */ audio->last_action_timestamp = g_get_real_time(); /* Invoke handlers manually. * In theory, we could skip this step, since the Alsa callback * will be triggered anyway after the volume change is effective, * and we could invoke the handlers at this moment. * In practice, relying on the Alsa callback is not so reliable. * It seems that it's kind of broken if PulseAudio is running. * So, invoking the handlers at this point makes PNMixer more robust. */ invoke_handlers(audio, AUDIO_VALUES_CHANGED, user); } void audio_set_volume(Audio *audio, AudioUser user, gdouble new_volume, gint dir) { AlsaCard *soundcard = audio->soundcard; gdouble cur_volume; cur_volume = alsa_card_get_volume(soundcard); _audio_set_volume(audio, user, cur_volume, new_volume, dir); } /** * Lower the volume. * * @param audio an Audio instance. * @param user the user who performs the action. */ void audio_lower_volume(Audio *audio, AudioUser user) { AlsaCard *soundcard = audio->soundcard; gdouble scroll_step = audio->scroll_step; gdouble cur_volume, new_volume; cur_volume = alsa_card_get_volume(soundcard); new_volume = cur_volume - scroll_step; if (new_volume < 0) new_volume = 0; _audio_set_volume(audio, user, cur_volume, new_volume, -1); } /** * Raise the volume. * * @param audio an Audio instance. * @param user the user who performs the action. */ void audio_raise_volume(Audio *audio, AudioUser user) { AlsaCard *soundcard = audio->soundcard; gdouble scroll_step = audio->scroll_step; gdouble cur_volume, new_volume; cur_volume = alsa_card_get_volume(soundcard); new_volume = cur_volume + scroll_step; if (new_volume > 100) new_volume = 100; _audio_set_volume(audio, user, cur_volume, new_volume, +1); } /** * Unhook the currently hooked audio card. * * @param audio an Audio instance. */ static void audio_unhook_soundcard(Audio *audio) { if (audio->soundcard == NULL) return; DEBUG("Unhooking soundcard from the audio system"); /* Free the soundcard */ alsa_card_free(audio->soundcard); audio->soundcard = NULL; /* Invoke user handlers */ invoke_handlers(audio, AUDIO_CARD_CLEANED_UP, AUDIO_USER_UNKNOWN); } /** * Attempt to hook an audio soundcard. * Try everything possible, the goal is to have a working soundcard. * So if the selected soundcard fails, we try any others until at some * point we have a working soundcard. * * @param audio an Audio instance. */ static void audio_hook_soundcard(Audio *audio) { AlsaCard *soundcard; GSList *card_list, *item; g_assert(audio->soundcard == NULL); /* Attempt to create the card */ DEBUG("Hooking soundcard '%s (%s)' to the audio system", audio->card, audio->channel); soundcard = alsa_card_new(audio->card, audio->channel, audio->normalize); if (soundcard) goto end; /* On failure, try to create the card from the list of available cards. * We don't try with the card name that just failed. */ DEBUG("Could not hook soundcard, trying every card available"); card_list = alsa_list_cards(); item = g_slist_find_custom(card_list, audio->card, (GCompareFunc) g_strcmp0); if (item) { DEBUG("Removing '%s' from card list", (char *) item->data); card_list = g_slist_remove(card_list, item); g_slist_free_full(item, g_free); } /* Now iterate on card list and attempt to get a working soundcard */ for (item = card_list; item; item = item->next) { const char *card = item->data; char *channel; channel = prefs_get_channel(card); soundcard = alsa_card_new(card, channel, audio->normalize); g_free(channel); if (soundcard) break; } /* Free card list */ g_slist_free_full(card_list, g_free); end: /* Save soundcard NOW ! * We're going to invoke handlers later on, and these guys * need a valid soundcard pointer. */ audio->soundcard = soundcard; /* Finish making everything ready */ if (soundcard == NULL) { DEBUG("No soundcard could be hooked !"); /* Card and channel names set to emptry string */ g_free(audio->card); audio->card = g_strdup(""); g_free(audio->channel); audio->channel = g_strdup(""); /* Tell the world */ invoke_handlers(audio, AUDIO_NO_CARD, AUDIO_USER_UNKNOWN); } else { DEBUG("Soundcard successfully hooked (scroll step: %lg, normalize: %s)", audio->scroll_step, audio->normalize ? "true" : "false"); /* Card and channel names must match the truth. * Indeed, in case of failure, we may end up using a soundcard * different from the one specified in the preferences. */ g_free(audio->card); audio->card = g_strdup(alsa_card_get_name(soundcard)); g_free(audio->channel); audio->channel = g_strdup(alsa_card_get_channel(soundcard)); /* Install callbacks */ alsa_card_install_callback(soundcard, on_alsa_event, audio); /* Tell the world */ invoke_handlers(audio, AUDIO_CARD_INITIALIZED, AUDIO_USER_UNKNOWN); } } /** * Reload the current preferences, and reload the hooked soundcard. * This has to be called each time the preferences are modified. * * @param audio an Audio instance. */ void audio_reload(Audio *audio) { /* Get preferences */ g_free(audio->card); audio->card = prefs_get_string("AlsaCard", NULL); g_free(audio->channel); audio->channel = prefs_get_channel(audio->card); audio->normalize = prefs_get_boolean("NormalizeVolume", TRUE); audio->scroll_step = prefs_get_double("ScrollStep", 5); /* Rehook soundcard */ audio_unhook_soundcard(audio); audio_hook_soundcard(audio); } /** * Free an audio instance, therefore unhooking the sound card and * freeing any allocated ressources. * * @param audio an Audio instance. */ void audio_free(Audio *audio) { if (audio == NULL) return; audio_unhook_soundcard(audio); g_free(audio->channel); g_free(audio->card); g_free(audio); } /** * Create a new Audio instance. * This does almost nothing actually, all the heavy job is done * in the audio_hook_soundcard() function. * * @return a newly allocated Audio instance. */ Audio * audio_new(void) { Audio *audio; audio = g_new0(Audio, 1); return audio; } /** * Return the list of playable cards as a GSList. * Must be freed using g_slist_free_full() and g_free(). * * @return a list of playable cards. */ GSList * audio_get_card_list(void) { return alsa_list_cards(); } /** * For a given card name, return the list of playable channels as a GSList. * Must be freed using g_slist_free_full() and g_free(). * * @param card_name the name of the card for which we list the channels * @return a list of playable channels. */ GSList * audio_get_channel_list(const char *card_name) { return alsa_list_channels(card_name); } pnmixer-0.7.2/src/audio.h000066400000000000000000000043651311427610600152540ustar00rootroot00000000000000/* audio.h * PNmixer is written by Nick Lanham, a fork of OBmixer * which was programmed by Lee Ferrett, derived * from the program "AbsVolume" by Paul Sherman * This program is free software; you can redistribute * it and/or modify it under the terms of the GNU General * Public License v3. source code is available at * */ /** * @file audio.h * Header for audio.c. * @brief Header for audio.c. */ #ifndef _AUDIO_H_ #define _AUDIO_H_ #include /* High-level audio functions, no need to have a soundcard ready for that */ GSList *audio_get_card_list(void); GSList *audio_get_channel_list(const char *card); /* Soundcard management */ typedef struct audio Audio; Audio *audio_new(void); void audio_free(Audio *audio); void audio_reload(Audio *audio); /* Audio status: card & channel name, mute & volume handling. * Everyone who changes the volume must say who he is. */ enum audio_user { AUDIO_USER_UNKNOWN, AUDIO_USER_POPUP, AUDIO_USER_TRAY_ICON, AUDIO_USER_HOTKEYS, }; typedef enum audio_user AudioUser; const char *audio_get_card(Audio *audio); const char *audio_get_channel(Audio *audio); gboolean audio_has_mute(Audio *audio); gboolean audio_is_muted(Audio *audio); void audio_toggle_mute(Audio *audio, AudioUser user); gdouble audio_get_volume(Audio *audio); void audio_set_volume(Audio *audio, AudioUser user, gdouble volume, gint direction); void audio_lower_volume(Audio *audio, AudioUser user); void audio_raise_volume(Audio *audio, AudioUser user); /* Signal handling. * The audio system sends signals out there when something happens. */ enum audio_signal { AUDIO_NO_CARD, AUDIO_CARD_INITIALIZED, AUDIO_CARD_CLEANED_UP, AUDIO_CARD_DISCONNECTED, AUDIO_CARD_ERROR, AUDIO_VALUES_CHANGED, }; typedef enum audio_signal AudioSignal; struct audio_event { AudioSignal signal; AudioUser user; const gchar *card; const gchar *channel; gboolean has_mute; gboolean muted; gdouble volume; }; typedef struct audio_event AudioEvent; typedef void (*AudioCallback) (Audio *audio, AudioEvent *event, gpointer data); void audio_signals_connect(Audio *audio, AudioCallback callback, gpointer data); void audio_signals_disconnect(Audio *audio, AudioCallback callback, gpointer data); #endif // _AUDIO_H pnmixer-0.7.2/src/config.h.in000066400000000000000000000007501311427610600160170ustar00rootroot00000000000000/* always defined to indicate that i18n is enabled */ #cmakedefine ENABLE_NLS /* Gettext package. */ #define GETTEXT_PACKAGE "@PACKAGE@" /* Name of package */ #define PACKAGE "@PACKAGE@" /* Define to the version of this package. */ #define PACKAGE_VERSION "@PACKAGE_VERSION@" /* Gtk3 mode */ #cmakedefine WITH_GTK3 /* libnotify mode */ #cmakedefine WITH_LIBNOTIFY #define PACKAGE_DATA_DIR "@CMAKE_INSTALL_FULL_DATADIR@" #define PACKAGE_LOCALE_DIR "@CMAKE_INSTALL_FULL_LOCALEDIR@" pnmixer-0.7.2/src/hotkey.c000066400000000000000000000122721311427610600154450ustar00rootroot00000000000000/* hotkey.c * PNmixer is written by Nick Lanham, a fork of OBmixer * which was programmed by Lee Ferrett, derived * from the program "AbsVolume" by Paul Sherman * This program is free software; you can redistribute * it and/or modify it under the terms of the GNU General * Public License v3. source code is available at * */ /** * @file hotkey.c * This file define what's a hotkey. * Deals with the low-level XKBlib and Gtk/Gdk. * @brief Hotkey subsystem. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "support-log.h" #include "hotkey.h" // `xmodmap -pm` /* List of key modifiers which will be ignored whenever * we check whether the defined hotkeys have been pressed. */ static guint keymasks[] = { 0, /* No Modkey */ GDK_MOD2_MASK, /* Numlock */ GDK_LOCK_MASK, /* Capslock */ GDK_MOD2_MASK | GDK_LOCK_MASK /* Both */ }; /* Error that may be set if grabbing hotkey fails. */ static char grab_error; /* Helpers */ /* When an Xlib error occurs when grabbing the hotkey, this function is called. * The error handler should not call any functions (directly or indirectly) * on the display that will generate protocol requests or that will look for * input events. * Return value is ignored. */ static int grab_error_handler(G_GNUC_UNUSED Display *disp, G_GNUC_UNUSED XErrorEvent *ev) { WARN("Error while grabbing hotkey"); grab_error = 1; return 0; } /* Public functions */ /** * Ungrab a key manually. Should be paired with a hotkey_grab() call. * * @param hotkey a Hotkey instance. * @return TRUE on success, FALSE on error. */ void hotkey_ungrab(Hotkey *hotkey) { Display *disp; guint i; g_return_if_fail(hotkey != NULL); DEBUG("Ungrabbing hotkey '%s'", hotkey->str); disp = gdk_x11_get_default_xdisplay(); /* Ungrab the key */ for (i = 0; i < G_N_ELEMENTS(keymasks); i++) XUngrabKey(disp, hotkey->code, hotkey->mods | keymasks[i], GDK_ROOT_WINDOW()); } /** * Grab a key manually. Should be paired with a hotkey_ungrab() call. * * @param hotkey a Hotkey instance. * @return TRUE on success, FALSE on error. */ gboolean hotkey_grab(Hotkey *hotkey) { Display *disp; XErrorHandler old_hdlr; guint i; g_return_val_if_fail(hotkey != NULL, FALSE); DEBUG("Grabbing hotkey '%s'", hotkey->str); disp = gdk_x11_get_default_xdisplay(); /* Init error handling */ grab_error = 0; old_hdlr = XSetErrorHandler(grab_error_handler); /* Grab the key */ for (i = 0; i < G_N_ELEMENTS(keymasks); i++) XGrabKey(disp, hotkey->code, hotkey->mods | keymasks[i], GDK_ROOT_WINDOW(), 1, GrabModeAsync, GrabModeAsync); /* Synchronize X */ XFlush(disp); XSync(disp, False); /* Restore error handler */ (void) XSetErrorHandler(old_hdlr); /* Check for error */ if (grab_error) return FALSE; return TRUE; } /** * Checks if the keycode we got (minus modifiers like * numlock/capslock) matches the hotkey. * Thus numlock + o will match o. * * @param hotkey a Hotkey instance. * @param code the key code to compare against. * @param mods the key modifiers to compare against. * @return TRUE if there is a match, FALSE otherwise. */ gboolean hotkey_matches(Hotkey *hotkey, guint code, GdkModifierType mods) { guint i; g_return_val_if_fail(hotkey != NULL, FALSE); if (code != hotkey->code) return FALSE; for (i = 0; i < G_N_ELEMENTS(keymasks); i++) if ((hotkey->mods | keymasks[i]) == mods) return TRUE; return FALSE; } /** * Ungrab a key and free any resources. * * @param hotkey a Hotkey instance. */ void hotkey_free(Hotkey *hotkey) { if (hotkey == NULL) return; hotkey_ungrab(hotkey); g_free(hotkey->str); g_free(hotkey); } /** * Creates a new hotkey and grab it. * * @param code the key's code. * @param mods the key's modifiers. * @return the newly created Hotkey instance. */ Hotkey * hotkey_new(guint code, GdkModifierType mods) { Hotkey *hotkey; Display *disp; hotkey = g_new0(Hotkey, 1); disp = gdk_x11_get_default_xdisplay(); hotkey->code = code; hotkey->mods = mods; hotkey->sym = XkbKeycodeToKeysym(disp, hotkey->code, 0, 0); hotkey->str = gtk_accelerator_name(hotkey->sym, hotkey->mods); if (hotkey_grab(hotkey) == FALSE) { hotkey_free(hotkey); hotkey = NULL; } return hotkey; } /** * Translate a key into a Gtk Accelerator string. * * @param code the key code to process. * @param mods the key modifiers to process. * @return the accelerator string, must be freed. */ gchar * hotkey_code_to_accel(guint code, GdkModifierType mods) { Display *disp; guint sym; gchar *accel; disp = gdk_x11_get_default_xdisplay(); sym = XkbKeycodeToKeysym(disp, code, 0, 0); accel = gtk_accelerator_name(sym, mods); return accel; } /** * Translate a Gtk Accelerator string to a key code and mods. * * @param accel the accelerator string to parse. * @param code the key code returned after parsing. * @param mods the key modifiers after parsing. */ void hotkey_accel_to_code(const gchar *accel, gint *code, GdkModifierType *mods) { Display *disp; guint sym; disp = gdk_x11_get_default_xdisplay(); gtk_accelerator_parse(accel, &sym, mods); if (sym != 0) *code = XKeysymToKeycode(disp, sym); else *code = -1; } pnmixer-0.7.2/src/hotkey.h000066400000000000000000000023231311427610600154460ustar00rootroot00000000000000/* hotkey.h * PNmixer is written by Nick Lanham, a fork of OBmixer * which was programmed by Lee Ferrett, derived * from the program "AbsVolume" by Paul Sherman * This program is free software; you can redistribute * it and/or modify it under the terms of the GNU General * Public License v3. source code is available at * */ /** * @file hotkey.h * Header for hotkey.c. * @brief Header for hotkey.c. */ #ifndef _HOTKEY_H_ #define _HOTKEY_H_ #include struct hotkey { /* These values should only be accessed for reading, * and shouldn't be modified outside of hotkey.c */ guint code; /* Key code */ GdkModifierType mods; /* Key modifier */ unsigned long int sym; /* X Key Symbol */ gchar *str; /* Gtk Accelerator string */ }; typedef struct hotkey Hotkey; Hotkey *hotkey_new(guint code, GdkModifierType mods); void hotkey_free(Hotkey *key); gboolean hotkey_matches(Hotkey *hotkey, guint code, GdkModifierType mods); void hotkey_ungrab(Hotkey *hotkey); gboolean hotkey_grab(Hotkey *hotkey); gchar *hotkey_code_to_accel(guint code, GdkModifierType mods); void hotkey_accel_to_code(const gchar *accel, gint *code, GdkModifierType *mods); #endif // _HOTKEY_H pnmixer-0.7.2/src/hotkeys.c000066400000000000000000000145671311427610600156410ustar00rootroot00000000000000/* hotkeys.c * PNmixer is written by Nick Lanham, a fork of OBmixer * which was programmed by Lee Ferrett, derived * from the program "AbsVolume" by Paul Sherman * This program is free software; you can redistribute * it and/or modify it under the terms of the GNU General * Public License v3. source code is available at * */ /** * @file hotkeys.c * This file handles the hotkeys subsystem, including * communication with Xlib and intercepting key presses * before they can be interpreted by Gtk/Gdk. * @brief Hotkeys subsystem. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "audio.h" #include "prefs.h" #include "support-intl.h" #include "support-log.h" #include "hotkey.h" #include "hotkeys.h" #include "main.h" /* Helpers */ /* Removes the previously attached key_filter() function from * the root window. */ static void hotkeys_remove_filter(GdkFilterFunc filter, gpointer data) { GdkWindow *window; window = gdk_x11_window_foreign_new_for_display (gdk_display_get_default(), GDK_ROOT_WINDOW()); gdk_window_remove_filter(window, filter, data); } /* Ataches the key_filter() function as a filter * to the root window, so it will intercept window events. */ static void hotkeys_add_filter(GdkFilterFunc filter, gpointer data) { GdkWindow *window; window = gdk_x11_window_foreign_new_for_display (gdk_display_get_default(), GDK_ROOT_WINDOW()); gdk_window_add_filter(window, filter, data); } /* Public functions & callbacks */ struct hotkeys { /* Audio system */ Audio *audio; /* Hotkeys */ Hotkey *mute_hotkey; Hotkey *up_hotkey; Hotkey *down_hotkey; }; /** * This function is called before Gtk/Gdk can respond * to any(!) window event and handles pressed hotkeys. * * @param gdk_xevent the native event to filter * @param event the GDK event to which the X event will be translated * @param data user data set when the filter was installed * @return a GdkFilterReturn value, should be GDK_FILTER_CONTINUE only */ static GdkFilterReturn key_filter(GdkXEvent *gdk_xevent, G_GNUC_UNUSED GdkEvent *event, gpointer data) { XKeyEvent *xevent = (XKeyEvent *) gdk_xevent; Hotkeys *hotkeys = (Hotkeys *) data; Hotkey *mute_hotkey = hotkeys->mute_hotkey; Hotkey *up_hotkey = hotkeys->up_hotkey; Hotkey *down_hotkey = hotkeys->down_hotkey; Audio *audio = hotkeys->audio; gint type; guint key, state; type = xevent->type; if (type != KeyPress) return GDK_FILTER_CONTINUE; key = xevent->keycode; state = xevent->state; if (mute_hotkey && hotkey_matches(mute_hotkey, key, state)) audio_toggle_mute(audio, AUDIO_USER_HOTKEYS); else if (up_hotkey && hotkey_matches(up_hotkey, key, state)) audio_raise_volume(audio, AUDIO_USER_HOTKEYS); else if (down_hotkey && hotkey_matches(down_hotkey, key, state)) audio_lower_volume(audio, AUDIO_USER_HOTKEYS); return GDK_FILTER_CONTINUE; } /** * Reload hotkey preferences. * This has to be called each time the preferences are modified. * * @param hotkeys a Hotkeys instance. */ void hotkeys_reload(Hotkeys *hotkeys) { gboolean enabled; gint key, mods; gboolean mute_err, up_err, down_err; /* Free any hotkey that may be currently assigned */ hotkey_free(hotkeys->mute_hotkey); hotkeys->mute_hotkey = NULL; hotkey_free(hotkeys->up_hotkey); hotkeys->up_hotkey = NULL; hotkey_free(hotkeys->down_hotkey); hotkeys->down_hotkey = NULL; /* Return if hotkeys are disabled */ enabled = prefs_get_boolean("EnableHotKeys", FALSE); if (enabled == FALSE) return; /* Setup mute hotkey */ mute_err = FALSE; key = prefs_get_integer("VolMuteKey", -1); mods = prefs_get_integer("VolMuteMods", 0); if (key != -1) { hotkeys->mute_hotkey = hotkey_new(key, mods); if (hotkeys->mute_hotkey == NULL) mute_err = TRUE; } /* Setup volume up hotkey */ up_err = FALSE; key = prefs_get_integer("VolUpKey", -1); mods = prefs_get_integer("VolUpMods", 0); if (key != -1) { hotkeys->up_hotkey = hotkey_new(key, mods); if (hotkeys->up_hotkey == NULL) up_err = TRUE; } /* Setup volume down hotkey */ down_err = FALSE; key = prefs_get_integer("VolDownKey", -1); mods = prefs_get_integer("VolDownMods", 0); if (key != -1) { hotkeys->down_hotkey = hotkey_new(key, mods); if (hotkeys->down_hotkey == NULL) down_err = TRUE; } /* Display error message if needed */ if (mute_err || up_err || down_err) { run_error_dialog("%s:\n%s%s%s%s%s%s", _("Could not grab the following HotKeys"), mute_err ? _("Mute/Unmute") : "", mute_err ? "\n" : "", up_err ? _("Volume Up") : "", up_err ? "\n" : "", down_err ? _("Volume Down") : "", down_err ? "\n" : "" ); } } /** * Unbind hotkeys manually. Should be paired with a hotkeys_bind() call. * * @param hotkeys a Hotkeys instance. */ void hotkeys_unbind(Hotkeys *hotkeys) { hotkeys_remove_filter(key_filter, hotkeys); if (hotkeys->mute_hotkey) hotkey_ungrab(hotkeys->mute_hotkey); if (hotkeys->up_hotkey) hotkey_ungrab(hotkeys->up_hotkey); if (hotkeys->down_hotkey) hotkey_ungrab(hotkeys->down_hotkey); } /** * Bind hotkeys manually. Should be paired with a hotkeys_unbind() call. * * @param hotkeys a Hotkeys instance. */ void hotkeys_bind(Hotkeys *hotkeys) { if (hotkeys->mute_hotkey) hotkey_grab(hotkeys->mute_hotkey); if (hotkeys->up_hotkey) hotkey_grab(hotkeys->up_hotkey); if (hotkeys->down_hotkey) hotkey_grab(hotkeys->down_hotkey); hotkeys_add_filter(key_filter, hotkeys); } /** * Cleanup the hotkey subsystem. * * @param hotkeys a Hotkeys instance. */ void hotkeys_free(Hotkeys *hotkeys) { if (hotkeys == NULL) return; /* Disable hotkeys */ hotkeys_remove_filter(key_filter, hotkeys); /* Free anything */ hotkey_free(hotkeys->mute_hotkey); hotkey_free(hotkeys->up_hotkey); hotkey_free(hotkeys->down_hotkey); g_free(hotkeys); } /** * Creates the hotkeys subsystem, and bind the hotkeys. * * @param audio the audio system, needed to control the audio. * @return the newly created Hotkeys instance. */ Hotkeys * hotkeys_new(Audio *audio) { Hotkeys *hotkeys; DEBUG("Creating hotkeys control"); hotkeys = g_new0(Hotkeys, 1); /* Save audio pointer */ hotkeys->audio = audio; /* Load preferences */ hotkeys_reload(hotkeys); /* Bind hotkeys */ hotkeys_add_filter(key_filter, hotkeys); return hotkeys; } pnmixer-0.7.2/src/hotkeys.h000066400000000000000000000013741311427610600156360ustar00rootroot00000000000000/* hotkeys.h * PNmixer is written by Nick Lanham, a fork of OBmixer * which was programmed by Lee Ferrett, derived * from the program "AbsVolume" by Paul Sherman * This program is free software; you can redistribute * it and/or modify it under the terms of the GNU General * Public License v3. source code is available at * */ /** * @file hotkeys.h * Header for hotkeys.c. * @brief Header for hotkeys.c. */ #ifndef _HOTKEYS_H_ #define _HOTKEYS_H_ #include "audio.h" typedef struct hotkeys Hotkeys; Hotkeys *hotkeys_new(Audio *audio); void hotkeys_free(Hotkeys *hotkeys); void hotkeys_reload(Hotkeys *hotkeys); void hotkeys_bind(Hotkeys *hotkeys); void hotkeys_unbind(Hotkeys *hotkeys); #endif // _HOTKEYS_H pnmixer-0.7.2/src/main.c000066400000000000000000000225271311427610600150720ustar00rootroot00000000000000/* main.c * PNmixer is written by Nick Lanham, a fork of OBmixer * which was programmed by Lee Ferrett, derived * from the program "AbsVolume" by Paul Sherman * This program is free software; you can redistribute * it and/or modify it under the terms of the GNU General * Public License v3. source code is available at * */ /** * @file main.c * The main program entry point. Also handles creating and opening * the widgets. Declares some high-level public functions needed by * some widgets. * @brief Main program entry point & high-level public functions. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "main.h" #include "audio.h" #include "notif.h" #include "hotkeys.h" #include "prefs.h" #include "support-intl.h" #include "support-log.h" #include "ui-about-dialog.h" #include "ui-prefs-dialog.h" #include "ui-popup-menu.h" #include "ui-popup-window.h" #include "ui-tray-icon.h" /* Life-long instances */ static Audio *audio; static PopupMenu *popup_menu; static PopupWindow *popup_window; static TrayIcon *tray_icon; static Hotkeys *hotkeys; static Notif *notif; /* Main window, used as the parent for every other window that needs one. * This is also a life-long instance. */ static GtkWindow *main_window; /* Temporary instances */ static PrefsDialog *prefs_dialog; static AboutDialog *about_dialog; /** * Runs a given command via g_spawn_command_line_async(). * * @param cmd the command to run */ static void run_command(const gchar *cmd) { GError *error = NULL; g_assert(cmd != NULL); if (g_spawn_command_line_async(cmd, &error) == FALSE) { run_error_dialog(_("Unable to run command: %s"), error->message); g_error_free(error); error = NULL; } } /** * Run the specified mixer application. */ void run_mixer_command(void) { gchar *cmd; cmd = prefs_get_string("VolumeControlCommand", NULL); if (cmd) { run_command(cmd); g_free(cmd); } else { run_error_dialog(_("No mixer application was found on your system. " "Please open preferences and set the command you want " "to run for volume control.")); } } /** * Run a custom command. */ void run_custom_command(void) { gchar *cmd; cmd = prefs_get_string("CustomCommand", NULL); if (cmd) { run_command(cmd); g_free(cmd); } else { run_error_dialog(_("You have not specified a custom command to run, " "please specify one in preferences.")); } } /** * Bring up the preferences window. */ static void prefs_dialog_response_cb(PrefsDialog *this_dialog, gint response_id) { g_assert(this_dialog == prefs_dialog); /* Get values from the prefs dialog */ if (response_id == GTK_RESPONSE_OK || response_id == GTK_RESPONSE_APPLY) prefs_dialog_retrieve(prefs_dialog); if (response_id != GTK_RESPONSE_APPLY) { /* Now we can destroy it */ prefs_dialog_destroy(prefs_dialog); prefs_dialog = NULL; } /* Apply the new preferences. * It's safer to do that after destroying the preferences dialog, * since it listens for some audio signals that will be emitted * while new prefs are applied. */ if (response_id == GTK_RESPONSE_OK || response_id == GTK_RESPONSE_APPLY) { /* Ask every instance to reload its preferences */ popup_window_reload(popup_window); tray_icon_reload(tray_icon); hotkeys_reload(hotkeys); notif_reload(notif); audio_reload(audio); /* Save preferences to file */ prefs_save(); } } void run_prefs_dialog(void) { /* Create the prefs dialog if needed */ if (prefs_dialog == NULL) { prefs_dialog = prefs_dialog_create(main_window, audio, hotkeys, prefs_dialog_response_cb); prefs_dialog_populate(prefs_dialog); } /* Present it to user */ prefs_dialog_present(prefs_dialog); } /** * Run the about dialog. */ void run_about_dialog(void) { /* Ensure there's no dialog already running */ if (about_dialog) return; /* Run the about dialog */ about_dialog = about_dialog_create(main_window); about_dialog_run(about_dialog); about_dialog_destroy(about_dialog); about_dialog = NULL; } /** * Report an error, usually via a dialog window or on stderr. * * @param fmt the error * @param ... more string segments in the format of printf */ void run_error_dialog(const char *fmt, ...) { GtkWidget *dialog; char err_buf[512]; va_list ap; va_start(ap, fmt); vsnprintf(err_buf, sizeof err_buf, fmt, ap); va_end(ap); ERROR("%s", err_buf); if (!main_window) return; dialog = gtk_message_dialog_new(main_window, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, NULL); g_object_set(dialog, "text", err_buf, NULL); gtk_window_set_title(GTK_WINDOW(dialog), _("PNMixer Error")); gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); } /** * Emits a warning if the sound connection is lost, usually * via a dialog window (with option to reinitialize sound) or stderr. * Asks for alsa reload, check the return value to know. * * @return the response from the dialog window */ gint run_audio_error_dialog(void) { GtkWidget *dialog; gint resp; ERROR("Connection with audio failed, " "you probably need to restart pnmixer."); if (!main_window) return GTK_RESPONSE_NO; dialog = gtk_message_dialog_new (main_window, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_YES_NO, _("Warning: Connection to sound system failed.")); gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG(dialog), _("Do you want to re-initialize the audio connection ?\n\n" "If you do not, you will either need to restart PNMixer " "or select the 'Reload Audio' option in the right-click " "menu in order for PNMixer to function.")); gtk_window_set_title(GTK_WINDOW(dialog), _("PNMixer Error")); resp = gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); return resp; } /** * Toggle the popup window */ void do_toggle_popup_window(void) { /* If a modal dialog is opened, we can open the popup window * (the tray icon catches the mouse click), but we can't close it anymore * (the popup window doesn't catch clicks, because the modal dialog does). * A simple way to solve that is just to forbid showing the popup window * when there's a modal dialog opened. */ if (about_dialog) return; popup_window_toggle(popup_window); } /** * Show the popup menu. */ void do_show_popup_menu(GtkMenuPositionFunc func, gpointer data, guint button, guint activate_time) { popup_window_hide(popup_window); popup_menu_show(popup_menu, func, data, button, activate_time); } /** * Handle signals from the audio subsystem. * * @param audio the Audio instance that emitted the signal. * @param event the AudioEvent containing useful information. * @param data user supplied data. */ static void on_audio_changed(Audio *audio, AudioEvent *event, G_GNUC_UNUSED gpointer data) { switch (event->signal) { case AUDIO_CARD_DISCONNECTED: audio_reload(audio); break; case AUDIO_CARD_ERROR: if (run_audio_error_dialog() == GTK_RESPONSE_YES) audio_reload(audio); break; default: break; } } /* * Options for command-line invokation. */ static gboolean version = FALSE; static GOptionEntry option_entries[] = { { "version", 'v', 0, G_OPTION_ARG_NONE, &version, "Show version and exit", NULL }, { "debug", 'd', 0, G_OPTION_ARG_NONE, &want_debug, "Run in debug mode", NULL }, { NULL, 0, 0, 0, NULL, NULL, NULL } }; /** * Program entry point. Initializes gtk+, calls the widget creating * functions and starts the main loop. * * @param argc count of arguments * @param argv string array of arguments * @return 0 for success, otherwise error code */ int main(int argc, char *argv[]) { GOptionContext *context; /* Init internationalization stuff */ intl_init(); /* Parse options */ context = g_option_context_new(_("- A mixer for the system tray.")); g_option_context_add_main_entries(context, option_entries, GETTEXT_PACKAGE); g_option_context_add_group(context, gtk_get_option_group(TRUE)); g_option_context_parse(context, &argc, &argv, NULL); g_option_context_free(context); /* Print version and exit */ if (version) { printf(_("%s version: %s\n"), PACKAGE, PACKAGE_VERSION); exit(EXIT_SUCCESS); } /* Init Gtk+ */ gtk_init(&argc, &argv); /* Load preferences. * This must be done at first, all the following init code rely on it. */ prefs_ensure_save_dir(); prefs_load(); /* Init the low-level (aka the audio system) at first */ audio = audio_new(); /* Init the high-level (aka the ui) */ popup_menu = popup_menu_create(audio); popup_window = popup_window_create(audio); tray_icon = tray_icon_create(audio); /* Save the main window */ main_window = popup_menu_get_window(popup_menu); /* Init what's left */ hotkeys = hotkeys_new(audio); notif = notif_new(audio); /* Get the audio system ready */ audio_signals_connect(audio, on_audio_changed, NULL); audio_reload(audio); /* Run */ DEBUG("---- Running main loop ----"); gtk_main(); DEBUG("---- Exiting main loop ----"); /* Cleanup */ audio_signals_disconnect(audio, on_audio_changed, NULL); notif_free(notif); hotkeys_free(hotkeys); tray_icon_destroy(tray_icon); popup_window_destroy(popup_window); popup_menu_destroy(popup_menu); audio_free(audio); return EXIT_SUCCESS; } pnmixer-0.7.2/src/main.h000066400000000000000000000015151311427610600150710ustar00rootroot00000000000000/* main.h * PNmixer is written by Nick Lanham, a fork of OBmixer * which was programmed by Lee Ferrett, derived * from the program "AbsVolume" by Paul Sherman * This program is free software; you can redistribute * it and/or modify it under the terms of the GNU General * Public License v3. source code is available at * */ /** * @file main.h * Header for main.c * @brief Header for main.c */ #ifndef _MAIN_H_ #define _MAIN_H_ #include void run_mixer_command(void); void run_custom_command(void); void run_about_dialog(void); void run_error_dialog(const char *, ...); void run_prefs_dialog(void); void do_toggle_popup_window(void); void do_show_popup_menu(GtkMenuPositionFunc func, gpointer data, guint button, guint activate_time); #endif // _MAIN_H pnmixer-0.7.2/src/notif.c000066400000000000000000000160441311427610600152620ustar00rootroot00000000000000/* notif.c * PNmixer is written by Nick Lanham, a fork of OBmixer * which was programmed by Lee Ferrett, derived * from the program "AbsVolume" by Paul Sherman * This program is free software; you can redistribute * it and/or modify it under the terms of the GNU General * Public License v3. source code is available at * */ /** * @file notif.c * This file handles the notification subsystem * via libnotify and mostly reacts to volume changes. * @brief Notification subsystem. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #ifdef WITH_LIBNOTIFY #include #endif #include "audio.h" #include "prefs.h" #include "support-intl.h" #include "support-log.h" #include "notif.h" #include "main.h" #ifdef WITH_LIBNOTIFY #if NOTIFY_CHECK_VERSION (0, 7, 0) #define NOTIFICATION_NEW(summary, body, icon) \ notify_notification_new(summary, body, icon) #define NOTIFICATION_SET_HINT_STRING(notification, key, value) \ notify_notification_set_hint(notification, key, g_variant_new_string(value)) #define NOTIFICATION_SET_HINT_INT32(notification, key, value) \ notify_notification_set_hint(notification, key, g_variant_new_int32(value)) #else #define NOTIFICATION_NEW(summary, body, icon) \ notify_notification_new(summary, body, icon, NULL) #define NOTIFICATION_SET_HINT_STRING(notification, key, value) \ notify_notification_set_hint_string(notification, key, value) #define NOTIFICATION_SET_HINT_INT32(notification, key, value) \ notify_notification_set_hint_int32(notification, key, value) #endif /* Helpers */ static void show_volume_notif(NotifyNotification *notification, const gchar *card, const gchar *channel, gboolean muted, gdouble volume) { GError *error = NULL; gchar *icon, *summary; if (muted) icon = "audio-volume-muted"; else if (volume == 0) icon = "audio-volume-off"; else if (volume < 33) icon = "audio-volume-low"; else if (volume < 66) icon = "audio-volume-medium"; else icon = "audio-volume-high"; if (muted) summary = g_strdup(_("Volume muted")); else summary = g_strdup_printf("%s (%s)\n" "%s: %ld%%", card, channel, _("Volume"), lround(volume)); notify_notification_update(notification, summary, NULL, icon); NOTIFICATION_SET_HINT_INT32(notification, "value", lround(volume)); if (!notify_notification_show(notification, &error)) { ERROR("Could not send notification: %s", error->message); g_error_free(error); } g_free(summary); } static void show_text_notif(NotifyNotification *notification, const gchar *summary, const gchar *body) { GError *error = NULL; notify_notification_update(notification, summary, body, NULL); if (!notify_notification_show(notification, &error)) { ERROR("Could not send notification: %s", error->message); g_error_free(error); } } /* Public functions & signal handlers */ struct notif { /* Audio system */ Audio *audio; /* Preferences */ gboolean enabled; gboolean popup; gboolean tray; gboolean hotkey; gboolean external; /* Notifications */ NotifyNotification *volume_notif; NotifyNotification *text_notif; }; /* Handle signals coming from the audio subsystem. */ static void on_audio_changed(G_GNUC_UNUSED Audio *audio, AudioEvent *event, gpointer data) { Notif *notif = (Notif *) data; switch (event->signal) { case AUDIO_NO_CARD: show_text_notif(notif->text_notif, _("No sound card"), _("No playable soundcard found")); break; case AUDIO_CARD_DISCONNECTED: show_text_notif(notif->text_notif, _("Soundcard disconnected"), _("Soundcard has been disconnected, reloading sound system...")); break; case AUDIO_VALUES_CHANGED: if (!notif->enabled) return; switch (event->user) { case AUDIO_USER_UNKNOWN: if (!notif->external) return; break; case AUDIO_USER_POPUP: if (!notif->popup) return; break; case AUDIO_USER_TRAY_ICON: if (!notif->tray) return; break; case AUDIO_USER_HOTKEYS: if (!notif->hotkey) return; break; default: WARN("Unhandled audio user"); return; } show_volume_notif(notif->volume_notif, event->card, event->channel, event->muted, event->volume); break; default: break; } } /** * Reload notif preferences. * This has to be called each time the preferences are modified. * * @param notif a Notif instance. */ void notif_reload(Notif *notif) { guint timeout; NotifyNotification *notification; /* Get preferences */ notif->enabled = prefs_get_boolean("EnableNotifications", FALSE); notif->popup = prefs_get_boolean("PopupNotifications", FALSE); notif->tray = prefs_get_boolean("MouseNotifications", TRUE); notif->hotkey = prefs_get_boolean("HotkeyNotifications", TRUE); notif->external = prefs_get_boolean("ExternalNotifications", FALSE); timeout = prefs_get_integer("NotificationTimeout", 1500); /* Create volume notification */ notification = NOTIFICATION_NEW("", NULL, NULL); notify_notification_set_timeout(notification, timeout); NOTIFICATION_SET_HINT_STRING(notification, "x-canonical-private-synchronous", ""); if (notif->volume_notif) g_object_unref(notif->volume_notif); notif->volume_notif = notification; /* Create text notification */ notification = NOTIFICATION_NEW("", NULL, NULL); notify_notification_set_timeout(notification, timeout * 2); NOTIFICATION_SET_HINT_STRING(notification, "x-canonical-private-synchronous", ""); if (notif->text_notif) g_object_unref(notif->text_notif); notif->text_notif = notification; } /** * Uninitializes libnotify. * This should be called only once at cleanup. * * @param notif a Notif instance. */ void notif_free(Notif *notif) { if (notif == NULL) return; /* Unref any existing notification */ if (notif->volume_notif) g_object_unref(notif->volume_notif); if (notif->text_notif) g_object_unref(notif->text_notif); /* Disconnect audio signal handlers */ audio_signals_disconnect(notif->audio, on_audio_changed, notif); /* Uninit libnotify. This should be done only once */ g_assert(notify_is_initted() == TRUE); notify_uninit(); g_free(notif); } /** * Initializes libnotify. * This should be called only once at startup. * * @param audio An Audio instance. * @return the newly created Notif instance. */ Notif * notif_new(Audio *audio) { Notif *notif; notif = g_new0(Notif, 1); /* Init libnotify. This should be done only once */ g_assert(notify_is_initted() == FALSE); if (!notify_init(PACKAGE)) run_error_dialog("Unable to initialize libnotify. " "Notifications won't be sent."); /* Connect audio signals handlers */ notif->audio = audio; audio_signals_connect(audio, on_audio_changed, notif); /* Load preferences */ notif_reload(notif); return notif; } #else void notif_free(G_GNUC_UNUSED Notif *notif) { } Notif * notif_new(G_GNUC_UNUSED Audio *audio) { return NULL; } void notif_reload(G_GNUC_UNUSED Notif *notif) { } #endif // WITH_LIBNOTIFY pnmixer-0.7.2/src/notif.h000066400000000000000000000012541311427610600152640ustar00rootroot00000000000000/* notif.h * PNmixer is written by Nick Lanham, a fork of OBmixer * which was programmed by Lee Ferrett, derived * from the program "AbsVolume" by Paul Sherman * This program is free software; you can redistribute * it and/or modify it under the terms of the GNU General * Public License v3. source code is available at * */ /** * @file notif.h * Header for notif.c. * @brief Header for notif.c. */ #ifdef HAVE_CONFIG_H #include #endif #ifndef _NOTIF_H_ #define _NOTIF_H_ typedef struct notif Notif; Notif *notif_new(Audio *audio); void notif_free(Notif *notif); void notif_reload(Notif *notif); #endif // _NOTIF_H_ pnmixer-0.7.2/src/prefs.c000066400000000000000000000220211311427610600152520ustar00rootroot00000000000000/* prefs.c * PNmixer is written by Nick Lanham, a fork of OBmixer * which was programmed by Lee Ferrett, derived * from the program "AbsVolume" by Paul Sherman * This program is free software; you can redistribute * it and/or modify it under the terms of the GNU General * Public License v3. source code is available at * */ /** * @file prefs.c * This file holds the preferences subsystem, * managing the user config file. * @brief Preferences subsystem. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include #include #include "prefs.h" #include "support-log.h" #include "support-intl.h" #include "main.h" #define DEFAULT_PREFS "[PNMixer]\n\ SliderOrientation=vertical\n\ DisplayTextVolume=true\n\ TextVolumePosition=0\n\ ScrollStep=5\n\ FineScrollStep=1\n\ MiddleClickAction=0\n\ CustomCommand=\n\ VolMuteKey=-1\n\ VolUpKey=-1\n\ VolDownKey=-1\n\ AlsaCard=(default)\n\ NormalizeVolume=true\n\ SystemTheme=false" static GKeyFile *keyFile; /* * Default volume commands. */ static const gchar *vol_control_commands[] = { "gnome-alsamixer", "xfce4-mixer", "alsamixergui", NULL }; /* * Look for an installed volume command. */ static const gchar * find_vol_control_command(void) { const char **cmd; DEBUG("Looking for a volume control command..."); cmd = vol_control_commands; while (*cmd) { gchar *absolute_path; absolute_path = g_find_program_in_path(*cmd); if (absolute_path) { g_free(absolute_path); return *cmd; } cmd++; } return NULL; } /** * Gets a boolean value from preferences. * On error, returns def as default value. * * @param key the specific settings key * @param def the default value to return on error * @return the preference value or def on error */ gboolean prefs_get_boolean(const gchar *key, gboolean def) { gboolean ret; GError *error = NULL; ret = g_key_file_get_boolean(keyFile, "PNMixer", key, &error); if (error) { g_error_free(error); return def; } return ret; } /** * Gets an int value from a preferences. * On error, returns def as default value. * * @param key the specific settings key * @param def the default value to return on error * @return the preference value or def on error */ gint prefs_get_integer(const gchar *key, gint def) { gint ret; GError *error = NULL; ret = g_key_file_get_integer(keyFile, "PNMixer", key, &error); if (error) { g_error_free(error); return def; } return ret; } /** * Gets a double value from preferences. * On error, returns def as default value. * * @param key the specific settings key * @param def the default value to return on error * @return the preference value or def on error */ gdouble prefs_get_double(const gchar *key, gdouble def) { gdouble ret; GError *error = NULL; ret = g_key_file_get_double(keyFile, "PNMixer", key, &error); if (error) { g_error_free(error); return def; } return ret; } /** * Gets a string value from preferences. * On error, returns def as default value. * * @param key the specific settings key * @param def the default value to return on error * @return the preference value or def on error. Must be freed. */ gchar * prefs_get_string(const gchar *key, const gchar *def) { gchar *ret; GError *error = NULL; ret = g_key_file_get_string(keyFile, "PNMixer", key, &error); /* Return value if found */ if (error == NULL) return ret; else g_error_free(error); /* If the volume control command is not defined, * be clever and try to find a command installed. */ if (!g_strcmp0(key, "VolumeControlCommand")) { const gchar *cmd = find_vol_control_command(); if (cmd) return g_strdup(cmd); } /* At last, return default value */ return g_strdup(def); } /** * Gets a list of doubles from preferences. * On error, returns NULL. * * @param key the specific settings key * @param n integer pointer that will contain the returned array size * @return the preference value or NULL on error */ gdouble * prefs_get_double_list(const gchar *key, gsize *n) { gsize numcols = 0; gdouble *ret = NULL; GError *error = NULL; ret = g_key_file_get_double_list(keyFile, "PNMixer", key, &numcols, &error); if (error) { g_error_free(error); ret = NULL; } /* For the volume meter color, we need a little bit of care. * Ensure the list is valid, and provide default values if needed. */ if (!g_strcmp0(key, "VolMeterColor")) { gsize i; if (ret && numcols != 3) { g_free(ret); ret = NULL; } if (!ret) { ret = g_malloc(3 * sizeof(gdouble)); ret[0] = 0.909803921569; ret[1] = 0.43137254902; ret[2] = 0.43137254902; } for (i = 0; i < 3; i++) { if (ret[i] < 0) ret[i] = 0; if (ret[i] > 1) ret[i] = 1; } } if (n) *n = numcols; return ret; } /** * Gets the currently selected channel of the specified Alsa Card * from the global keyFile and returns the result. * * @param card the Alsa Card to get the currently selected channel of * @return the currently selected channel as newly allocated string, * NULL on failure */ gchar * prefs_get_channel(const gchar *card) { if (!card) return NULL; return g_key_file_get_string(keyFile, card, "Channel", NULL); } /** * Sets a boolean value to preferences. * * @param key the specific settings key * @param value the value to set */ void prefs_set_boolean(const gchar *key, gboolean value) { g_key_file_set_boolean(keyFile, "PNMixer", key, value); } /** * Sets a integer value to preferences. * * @param key the specific settings key * @param value the value to set */ void prefs_set_integer(const gchar *key, gint value) { g_key_file_set_integer(keyFile, "PNMixer", key, value); } /** * Sets a double value to preferences. * * @param key the specific settings key * @param value the value to set */ void prefs_set_double(const gchar *key, gdouble value) { g_key_file_set_double(keyFile, "PNMixer", key, value); } /** * Sets a string value to preferences. * * @param key the specific settings key * @param value the value to set */ void prefs_set_string(const gchar *key, const gchar *value) { g_key_file_set_string(keyFile, "PNMixer", key, value); } /** * Sets a list of doubles to preferences. * * @param key the specific settings key * @param list the array of double values to set * @param n the array length */ void prefs_set_double_list(const gchar *key, gdouble *list, gsize n) { g_key_file_set_double_list(keyFile, "PNMixer", key, list, n); } /** * Sets the channel for a given card in preferences. * * @param card the Alsa Card associated with the channel * @param channel the channel to save in the preferences. */ void prefs_set_channel(const gchar *card, const gchar *channel) { g_key_file_set_string(keyFile, card, "Channel", channel); } /** * Loads the preferences from the config file to the keyFile object (GKeyFile type). * Creates the keyFile object if it doesn't exist. */ void prefs_load(void) { GError *err = NULL; gchar *filename = g_build_filename(g_get_user_config_dir(), "pnmixer", "config", NULL); if (keyFile != NULL) g_key_file_free(keyFile); keyFile = g_key_file_new(); if (g_file_test(filename, G_FILE_TEST_EXISTS)) { if (!g_key_file_load_from_file(keyFile, filename, 0, &err)) { run_error_dialog(_("Couldn't load preferences file: %s"), err->message); g_error_free(err); g_key_file_free(keyFile); keyFile = NULL; } } else { if (!g_key_file_load_from_data (keyFile, DEFAULT_PREFS, strlen(DEFAULT_PREFS), 0, &err)) { run_error_dialog(_("Couldn't load default preferences: %s"), err->message); g_error_free(err); g_key_file_free(keyFile); keyFile = NULL; } } g_free(filename); } /** * Save the preferences from the keyFile object to the config file. */ void prefs_save(void) { gsize len; GError *err = NULL; gchar *filename = g_build_filename(g_get_user_config_dir(), "pnmixer", "config", NULL); gchar *filedata = g_key_file_to_data(keyFile, &len, NULL); g_file_set_contents(filename, filedata, len, &err); if (err != NULL) { run_error_dialog(_("Couldn't write preferences file: %s"), err->message); g_error_free(err); } g_free(filename); g_free(filedata); } /** * Checks if the preferences dir for saving is present and accessible. * Creates it if doesn't exist. Reports errors via run_error_dialog(). */ void prefs_ensure_save_dir(void) { gchar *prefs_dir = g_build_filename(g_get_user_config_dir(), "pnmixer", NULL); if (!g_file_test(prefs_dir, G_FILE_TEST_IS_DIR)) { if (g_file_test(prefs_dir, G_FILE_TEST_EXISTS)) run_error_dialog(_("'%s' exists but is not a directory, " "won't be able to save preferences."), prefs_dir); else if (g_mkdir(prefs_dir, S_IRWXU)) run_error_dialog(_("Couldn't make preferences directory: %s"), strerror(errno)); } g_free(prefs_dir); } pnmixer-0.7.2/src/prefs.h000066400000000000000000000024471311427610600152710ustar00rootroot00000000000000/* prefs.h * PNmixer is written by Nick Lanham, a fork of OBmixer * which was programmed by Lee Ferrett, derived * from the program "AbsVolume" by Paul Sherman * This program is free software; you can redistribute * it and/or modify it under the terms of the GNU General * Public License v3. source code is available at * */ /** * @file prefs.h * Header for prefs.c. * @brief Header for prefs.c. */ #ifndef _PREFS_H_ #define _PREFS_H_ #include void prefs_load(void); void prefs_save(void); void prefs_ensure_save_dir(void); gboolean prefs_get_boolean(const gchar *key, gboolean def); gint prefs_get_integer(const gchar *key, gint def); gdouble prefs_get_double(const gchar *key, gdouble def); gchar *prefs_get_string(const gchar *key, const gchar *def); gdouble *prefs_get_double_list(const gchar *key, gsize *n); gchar *prefs_get_channel(const gchar *card); void prefs_set_boolean(const gchar *key, gboolean value); void prefs_set_integer(const gchar *key, gint value); void prefs_set_double(const gchar *key, gdouble value); void prefs_set_string(const gchar *key, const gchar *value); void prefs_set_double_list(const gchar *key, gdouble *list, gsize n); void prefs_set_channel(const gchar *card, const gchar *channel); #endif // _PREFS_H_ pnmixer-0.7.2/src/support-intl.c000066400000000000000000000014531311427610600166210ustar00rootroot00000000000000/* support-intl.c * PNmixer is written by Nick Lanham, a fork of OBmixer * which was programmed by Lee Ferrett, derived * from the program "AbsVolume" by Paul Sherman * This program is free software; you can redistribute * it and/or modify it under the terms of the GNU General * Public License v3. source code is available at * */ /** * @file support-intl.c * Internationalization support. * @brief Internationalization support. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "support-intl.h" void intl_init(void) { setlocale(LC_ALL, ""); #ifdef ENABLE_NLS bindtextdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR); bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); textdomain(GETTEXT_PACKAGE); #endif } pnmixer-0.7.2/src/support-intl.h000066400000000000000000000024311311427610600166230ustar00rootroot00000000000000/* support-intl.h * PNmixer is written by Nick Lanham, a fork of OBmixer * which was programmed by Lee Ferrett, derived * from the program "AbsVolume" by Paul Sherman * This program is free software; you can redistribute * it and/or modify it under the terms of the GNU General * Public License v3. source code is available at * */ /** * @file support-intl.h * Internationalization support, should be included by every file. * @brief Internationalization support. */ #ifndef _SUPPORT_INTL_H_ #define _SUPPORT_INTL_H_ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef ENABLE_NLS #include /* Standard gettext macros */ #undef _ #define _(String) dgettext (PACKAGE, String) #define Q_(String) g_strip_context ((String), gettext (String)) #ifdef gettext_noop #define N_(String) gettext_noop (String) #else #define N_(String) (String) #endif #else #define textdomain(String) (String) #define gettext(String) (String) #define dgettext(Domain, Message) (Message) #define dcgettext(Domain, Message, Type) (Message) #define bindtextdomain(Domain, Directory) (Domain) #define _(String) (String) #define Q_(String) g_strip_context ((String), (String)) #define N_(String) (String) #endif void intl_init(void); #endif // _SUPPORT_INTL_H_ pnmixer-0.7.2/src/support-log.c000066400000000000000000000040341311427610600164320ustar00rootroot00000000000000/* support-log.c * PNmixer is written by Nick Lanham, a fork of OBmixer * which was programmed by Lee Ferrett, derived * from the program "AbsVolume" by Paul Sherman * This program is free software; you can redistribute * it and/or modify it under the terms of the GNU General * Public License v3. source code is available at * */ /** * @file support-log.c * Logging support. * @brief Logging support. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "support-log.h" #define VT_ESC "\033" #define VT_RESET "[0m" #define VT_RED "[0;31m" #define VT_GREY "[0;37m" #define VT_YELLOW "[1;33m" /** * Global variable to control whether we want debugging. * This variable is initialized in main() and depends on the * '--debug'/'-d' command line argument. */ gboolean want_debug = FALSE; /** * Log a message. * * @param level the log level. * @param file the file name. * @param format the message format. See the printf() documentation. * @param args the parameters to insert into the format string. */ void log_msg_v(enum log_level level, const char *file, const char *format, va_list args) { char buf[1024]; const char *pfx; if (level == LOG_DEBUG && want_debug == FALSE) return; switch (level) { case LOG_ERROR: pfx = VT_ESC VT_RED "error" VT_ESC VT_RESET; break; case LOG_WARN: pfx = VT_ESC VT_YELLOW "warning" VT_ESC VT_RESET; break; case LOG_DEBUG: pfx = VT_ESC VT_GREY "debug" VT_ESC VT_RESET; break; default: pfx = "unknown"; } snprintf(buf, sizeof buf, "%s: %s: %s\n", pfx, file, format); vfprintf(stderr, buf, args); } /** * Log a message. * * @param level the log level. * @param file the file name. * @param format the message format. See the printf() documentation. * @param ... the parameters to insert into the format string. */ void log_msg(enum log_level level, const char *file, const char *format, ...) { va_list args; va_start(args, format); log_msg_v(level, file, format, args); va_end(args); } pnmixer-0.7.2/src/support-log.h000066400000000000000000000022111311427610600164320ustar00rootroot00000000000000/* support-log.h * PNmixer is written by Nick Lanham, a fork of OBmixer * which was programmed by Lee Ferrett, derived * from the program "AbsVolume" by Paul Sherman * This program is free software; you can redistribute * it and/or modify it under the terms of the GNU General * Public License v3. source code is available at * */ /** * @file support-log.h * Logging support. * Provides various macros to print debug, warning & error messages. * Debug messages are enabled with a command-line argument. * This should be included by every file. * @brief Logging support. */ #ifndef _SUPPORT_LOG_H_ #define _SUPPORT_LOG_H_ #include extern gboolean want_debug; enum log_level { LOG_ERROR, LOG_WARN, LOG_DEBUG }; void log_msg_v(enum log_level level, const char *file, const char *format, va_list args); void log_msg(enum log_level level, const char *file, const char *format, ...); #define ERROR(...) log_msg(LOG_ERROR, __FILE__, __VA_ARGS__) #define WARN(...) log_msg(LOG_WARN, __FILE__, __VA_ARGS__) #define DEBUG(...) log_msg(LOG_DEBUG, __FILE__, __VA_ARGS__) #endif // _SUPPORT_LOG_H_ pnmixer-0.7.2/src/support-ui.c000066400000000000000000000046071311427610600162740ustar00rootroot00000000000000/* support-ui.c * PNmixer is written by Nick Lanham, a fork of OBmixer * which was programmed by Lee Ferrett, derived * from the program "AbsVolume" by Paul Sherman * This program is free software; you can redistribute * it and/or modify it under the terms of the GNU General * Public License v3. source code is available at * */ /** * @file support-ui.c * Various ui-related functions. * @brief Various ui-related functions. */ #include #include #include "support-log.h" #include "support-intl.h" #ifndef WITH_GTK3 GtkBuilder * gtk_builder_new_from_file (const gchar *filename) { GError *error = NULL; GtkBuilder *builder; builder = gtk_builder_new(); if (!gtk_builder_add_from_file(builder, filename, &error)) g_error("failed to add UI: %s", error->message); return builder; } void gtk_combo_box_text_remove_all(GtkComboBoxText *combo_box) { GtkListStore *store; g_return_if_fail(GTK_IS_COMBO_BOX_TEXT(combo_box)); store = GTK_LIST_STORE(gtk_combo_box_get_model(GTK_COMBO_BOX(combo_box))); gtk_list_store_clear(store); } #endif /** * Gets the path to an ui file. * Looks first in ./data/ui/[file], and then in * PACKAGE_DATA_DIR/PACKAGE/ui/[file]. * * @param filename the name of the ui file * @return path to the ui file or NULL on failure. Must be freed. */ gchar * get_ui_file(const char *filename) { gchar *path; path = g_build_filename(".", "data", "ui", filename, NULL); if (g_file_test(path, G_FILE_TEST_EXISTS)) return path; g_free(path); path = g_build_filename(PACKAGE_DATA_DIR, PACKAGE, "ui", filename, NULL); if (g_file_test(path, G_FILE_TEST_EXISTS)) return path; g_free(path); WARN("Could not find ui file '%s'", filename); return NULL; } /** * Gets the path to a pixmap file. * Looks first in ./data/ui/[file], and then in * PACKAGE_DATA_DIR/PACKAGE/ui/[file]. * * @param filename the pixmap file to find * @return path to the ui file or NULL on failure. Must be freed. */ gchar * get_pixmap_file(const gchar *filename) { gchar *path; path = g_build_filename(".", "data", "pixmaps", filename, NULL); if (g_file_test(path, G_FILE_TEST_EXISTS)) return path; g_free(path); path = g_build_filename(PACKAGE_DATA_DIR, PACKAGE, "pixmaps", filename, NULL); if (g_file_test(path, G_FILE_TEST_EXISTS)) return path; g_free(path); WARN("Could not find pixmap file '%s'", filename); return NULL; } pnmixer-0.7.2/src/support-ui.h000066400000000000000000000052731311427610600163010ustar00rootroot00000000000000/* support-ui.h * PNmixer is written by Nick Lanham, a fork of OBmixer * which was programmed by Lee Ferrett, derived * from the program "AbsVolume" by Paul Sherman * This program is free software; you can redistribute * it and/or modify it under the terms of the GNU General * Public License v3. source code is available at * */ /** * @file support-ui.h * Header for support-ui.c. * This should be included in ui files only. * @brief Header for support-ui.c. */ #ifndef _SUPPORT_UI_H_ #define _SUPPORT_UI_H_ #include #ifndef WITH_GTK3 /* * Simple functions lacking in Gtk2 */ GtkBuilder *gtk_builder_new_from_file(const gchar *filename); void gtk_combo_box_text_remove_all(GtkComboBoxText *combo_box); #endif #if GTK_CHECK_VERSION(3,22,0) #define GTK_3_22_UNUSED G_GNUC_UNUSED #else #define GTK_3_22_UNUSED #endif /* * Cast a pointer (that may be a function pointer) to a data pointer, * suppressing any warnings from the compilator. * We need that to suppress pedantic warnings when using * g_signal_handlers_block_by_func(). Indeed, we must feed it a * function pointer, but the signature expects a data pointer. * Aparently Glib doesn't respect ISO C here. * For more details, see this discussion: * http://compgroups.net/comp.lang.c/cast-function-pointer-to-void/722812 */ #define DATA_PTR(ptr) (*((void **)(&ptr))) /* * GtkBuilder helpers */ #define gtk_builder_get_widget(builder, name) \ GTK_WIDGET(gtk_builder_get_object(builder, name)) #define gtk_builder_get_adjustment(builder, name) \ GTK_ADJUSTMENT(gtk_builder_get_object(builder, name)) /* * 'assign' functions are used to retrieve a widget from a GtkBuilder * and to assign it into a structure. This is used a lot when we build * a window, and need to keep a pointer toward some widgets for later use. * This macro is more clever that it seems: * - it ensures that the name used in the struct is the same as the name used * in the ui file, therefore enforcing a consistent naming across the code. * - it ensures that the widget was found amidst the GtkBuilder objects, * therefore detecting errors that can happen when reworking the ui files. */ #define assign_gtk_widget(builder, container, name) \ do { \ container->name = gtk_builder_get_widget(builder, #name); \ g_assert(GTK_IS_WIDGET(container->name)); \ } while (0) #define assign_gtk_adjustment(builder, container, name) \ do { \ container->name = gtk_builder_get_adjustment(builder, #name); \ g_assert(GTK_IS_ADJUSTMENT(container->name)); \ } while (0) /* * File helpers */ gchar *get_ui_file(const char *filename); gchar *get_pixmap_file(const gchar *filename); #endif // _SUPPORT_UI_H_ pnmixer-0.7.2/src/ui-about-dialog.c000066400000000000000000000073131311427610600171240ustar00rootroot00000000000000/* ui-about-dialog.c * PNmixer is written by Nick Lanham, a fork of OBmixer * which was programmed by Lee Ferrett, derived * from the program "AbsVolume" by Paul Sherman * This program is free software; you can redistribute * it and/or modify it under the terms of the GNU General * Public License v3. source code is available at * */ /** * @file ui-about-dialog.c * This file holds the ui-related code for the about dialog. * @brief About dialog subsystem. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "support-intl.h" #include "ui-about-dialog.h" #define LICENSE_GPL3 \ "PNMixer is free software; you can redistribute it and/or modify it " \ "under the terms of the GNU General Public License v3 as published " \ "by the Free Software Foundation.\n" \ "\n" \ "PNMixer 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.\n" \ "\n" \ "You should have received a copy of the GNU General Public License " \ "along with PNMixer; if not, write to the Free Software Foundation, " \ "Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA." /* Public functions */ struct about_dialog { GtkWidget *about_dialog; }; /** * Runs the about dialog. * * @param dialog a AboutDialog instance. */ void about_dialog_run(AboutDialog *dialog) { GtkDialog *about_dialog = GTK_DIALOG(dialog->about_dialog); gtk_dialog_run(about_dialog); } /** * Destroys the about dialog, freeing any resources. * * @param dialog a AboutDialog instance. */ void about_dialog_destroy(AboutDialog *dialog) { gtk_widget_destroy(dialog->about_dialog); g_free(dialog); } /** * Creates the about dialog. * * @param parent a GtkWindow to be used as the parent. * @return the newly created AboutDialog instance. */ AboutDialog * about_dialog_create(GtkWindow *parent) { AboutDialog *dialog; const gchar *artists[] = { "Paul Davey", NULL }; const gchar *authors[] = { "Brian Bidulock", "El Boulangero ", "Julian Ospald ", "Nick Lanham", "Steven Honeyman", NULL }; const gchar *translators = "The Translation Project http://translationproject.org\n" \ "Mario Blättermann (de)\n" \ "Stéphane Aulery (fr)\n" \ "Božidar Putanec (hr)\n" \ "Mattia Bertoni (it)\n" \ "Benno Schulenberg (nl)\n" \ "Pavel Roschin (ru)\n" \ "МироÑлав Ðиколић (sr)\n" \ "Yuri Chornoivan (uk)\n" \ "Trần Ngá»c Quân (vi)\n" \ "Shengyu Zhang (zh_CN)"; /* Create about dialog */ dialog = g_new0(AboutDialog, 1); dialog->about_dialog = gtk_about_dialog_new(); /* Fill with the relevant information */ g_object_set(dialog->about_dialog, "artists", artists, "authors", authors, "comments", _("A mixer for the system tray"), "copyright", _("Copyright © 2010-2017 Nick Lanham"), "license", LICENSE_GPL3, "wrap-license", TRUE, "logo-icon-name", "pnmixer", "program-name", "PNMixer", "translator-credits", translators, "version", PACKAGE_VERSION, "website", "http://github.com/nicklan/pnmixer", NULL); /* More config for window */ gtk_window_set_skip_taskbar_hint(GTK_WINDOW(dialog->about_dialog), TRUE); gtk_window_set_transient_for(GTK_WINDOW(dialog->about_dialog), parent); return dialog; } pnmixer-0.7.2/src/ui-about-dialog.h000066400000000000000000000014251311427610600171270ustar00rootroot00000000000000/* ui-about-dialog.h * PNmixer is written by Nick Lanham, a fork of OBmixer * which was programmed by Lee Ferrett, derived * from the program "AbsVolume" by Paul Sherman * This program is free software; you can redistribute * it and/or modify it under the terms of the GNU General * Public License v3. source code is available at * */ /** * @file ui-about-dialog.h * Header for ui-about-dialog.c. * @brief header for ui-about-dialog.c. */ #ifndef _UI_ABOUT_DIALOG_H_ #define _UI_ABOUT_DIALOG_H_ #include typedef struct about_dialog AboutDialog; AboutDialog *about_dialog_create(GtkWindow *parent); void about_dialog_destroy(AboutDialog *dialog); void about_dialog_run(AboutDialog *dialog); #endif // _UI_ABOUT_DIALOG_H_ pnmixer-0.7.2/src/ui-hotkey-dialog.c000066400000000000000000000155361311427610600173230ustar00rootroot00000000000000/* ui-hotkey-dialog.c * PNmixer is written by Nick Lanham, a fork of OBmixer * which was programmed by Lee Ferrett, derived * from the program "AbsVolume" by Paul Sherman * This program is free software; you can redistribute * it and/or modify it under the terms of the GNU General * Public License v3. source code is available at * */ /** * @file ui-hotkey-dialog.c * This file holds the ui-related code for the hotkey dialog, * usually run from the preferences window. * @brief Hotkey dialog subsystem. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "support-log.h" #include "support-intl.h" #include "support-ui.h" #include "ui-hotkey-dialog.h" #include "main.h" #ifdef WITH_GTK3 #define HOTKEY_DIALOG_UI_FILE "hotkey-dialog-gtk3.glade" #else #define HOTKEY_DIALOG_UI_FILE "hotkey-dialog-gtk2.glade" #endif /* Helpers */ /* Configure the appearance of the hotkey dialog window. */ static void configure_hotkey_dialog(GtkWindow *window, GtkLabel *instruction_label, const gchar *hotkey) { gchar *title; gchar *instruction; title = g_strdup_printf(_("Set %s HotKey"), hotkey); gtk_window_set_title(window, title); g_free(title); instruction = g_strdup_printf(_("Press new HotKey for %s"), hotkey); gtk_label_set_markup(instruction_label, instruction); g_free(instruction); } /* Public functions & signal handlers */ struct hotkey_dialog { GtkWidget *hotkey_dialog; GtkWidget *instruction_label; GtkWidget *key_pressed_label; }; /** * Handles the 'key-press-event' signal on the GtkDialog 'hotkey_dialog'. * Update the text displayed in the dialog. * * @param widget the object which received the signal. * @param event the GdkEventKey which triggered the signal. * @param dialog user data set when the signal handler was connected. * @return TRUE to stop other handlers from being invoked for the event. * FALSE to propagate the event further. */ gboolean on_hotkey_dialog_key_press_event(G_GNUC_UNUSED GtkWidget *widget, GdkEventKey *event, HotkeyDialog *dialog) { GdkModifierType state, consumed; GtkLabel *key_pressed_label; gchar *key_text; guint key_val; key_pressed_label = GTK_LABEL(dialog->key_pressed_label); state = event->state; gdk_keymap_translate_keyboard_state(gdk_keymap_get_default(), event->hardware_keycode, state, event->group, &key_val, NULL, NULL, &consumed); state &= ~consumed; state &= gtk_accelerator_get_default_mod_mask(); key_text = gtk_accelerator_name(key_val, state); gtk_label_set_text(key_pressed_label, key_text); g_free(key_text); return FALSE; } /** * Handles the signal 'key-release-event' on the GtkDialog 'hotkey_dialog'. * Closes the dialog. * * @param widget the object which received the signal. * @param event the GdkEventKey which triggered the signal. * @param dialog user data set when the signal handler was connected. * @return TRUE to stop other handlers from being invoked for the event. * FALSE to propagate the event further. */ gboolean on_hotkey_dialog_key_release_event(GtkWidget *widget, G_GNUC_UNUSED GdkEventKey *event, G_GNUC_UNUSED HotkeyDialog *dialog) { gtk_dialog_response(GTK_DIALOG(widget), GTK_RESPONSE_OK); return FALSE; } /** * Runs the hotkey dialog, and returns a string representing the hotkey * that has been pressed. String must be freed. * * @param dialog a HotkeyDialog instance. * @return the hotkey pressed, must be freed. */ gchar * hotkey_dialog_run(HotkeyDialog *dialog) { GtkDialog *hotkey_dialog = GTK_DIALOG(dialog->hotkey_dialog); GtkLabel *key_pressed_label = GTK_LABEL(dialog->key_pressed_label); GdkWindow *window; GdkGrabStatus grab_status; gint resp; /* Show widget at first, otherwise the following calls fail */ gtk_widget_show_now(GTK_WIDGET(hotkey_dialog)); /* Grab keyboard */ #ifdef WITH_GTK3 GdkDevice *device; device = gtk_get_current_event_device(); if (device == NULL) { WARN("Couldn't get current device"); return NULL; } window = gtk_widget_get_window(GTK_WIDGET(hotkey_dialog)); #if GTK_CHECK_VERSION(3,20,0) grab_status = gdk_seat_grab (gdk_device_get_seat(device), window, GDK_SEAT_CAPABILITY_KEYBOARD, TRUE, NULL, NULL, NULL, NULL); #else grab_status = gdk_device_grab (device, window, GDK_OWNERSHIP_APPLICATION, TRUE, GDK_KEY_PRESS_MASK, NULL, GDK_CURRENT_TIME); #endif /* GTK_CHECK_VERSION(3,20,0) */ #else window = gtk_widget_get_window(GTK_WIDGET(hotkey_dialog)); grab_status = gdk_keyboard_grab (window, TRUE, GDK_CURRENT_TIME); #endif /* WITH_GTK3 */ if (grab_status != GDK_GRAB_SUCCESS) { run_error_dialog(_("Could not grab the keyboard.")); return NULL; } /* Run the dialog */ resp = gtk_dialog_run(hotkey_dialog); /* Ungrab keyboard */ #ifdef WITH_GTK3 #if GTK_CHECK_VERSION(3,20,0) gdk_seat_ungrab(gdk_device_get_seat(device)); #else gdk_device_ungrab(device, GDK_CURRENT_TIME); #endif /* GTK_CHECK_VERSION(3,20,0) */ #else gdk_keyboard_ungrab(GDK_CURRENT_TIME); #endif /* WITH_GTK3 */ /* Handle response */ if (resp != GTK_RESPONSE_OK) return NULL; /* Return the key entered */ return g_strdup(gtk_label_get_text(key_pressed_label)); } /** * Destroys a hotkey dialog, freeing any resources. * * @param dialog a HotkeyDialog instance. */ void hotkey_dialog_destroy(HotkeyDialog *dialog) { DEBUG("Destroying"); gtk_widget_destroy(dialog->hotkey_dialog); g_free(dialog); } /** * Creates a new hotkey dialog. * * @param parent a GtkWindow to be used as the parent. * @param hotkey the hotkey concerned. * @return the newly created HotkeyDialog instance. */ HotkeyDialog * hotkey_dialog_create(GtkWindow *parent, const gchar *hotkey) { gchar *uifile; GtkBuilder *builder; HotkeyDialog *dialog; dialog = g_new0(HotkeyDialog, 1); /* Build UI file */ uifile = get_ui_file(HOTKEY_DIALOG_UI_FILE); g_assert(uifile); DEBUG("Building from ui file '%s'", uifile); builder = gtk_builder_new_from_file(uifile); /* Save some widgets for later use */ assign_gtk_widget(builder, dialog, hotkey_dialog); assign_gtk_widget(builder, dialog, instruction_label); assign_gtk_widget(builder, dialog, key_pressed_label); /* Configure some widgets */ configure_hotkey_dialog(GTK_WINDOW(dialog->hotkey_dialog), GTK_LABEL(dialog->instruction_label), hotkey); /* Set transient parent */ gtk_window_set_transient_for(GTK_WINDOW(dialog->hotkey_dialog), parent); /* Connect ui signal handlers */ gtk_builder_connect_signals(builder, dialog); /* Cleanup */ g_object_unref(builder); g_free(uifile); return dialog; } pnmixer-0.7.2/src/ui-hotkey-dialog.h000066400000000000000000000014731311427610600173230ustar00rootroot00000000000000/* ui-hotkey-dialog.h * PNmixer is written by Nick Lanham, a fork of OBmixer * which was programmed by Lee Ferrett, derived * from the program "AbsVolume" by Paul Sherman * This program is free software; you can redistribute * it and/or modify it under the terms of the GNU General * Public License v3. source code is available at * */ /** * @file ui-hotkey-dialog.h * Header for ui-hotkey-dialog.c. * @brief Header for ui-hotkey-dialog.c. */ #ifndef _UI_HOTKEY_DIALOG_H_ #define _UI_HOTKEY_DIALOG_H_ #include typedef struct hotkey_dialog HotkeyDialog; HotkeyDialog *hotkey_dialog_create(GtkWindow *parent, const gchar *hotkey); void hotkey_dialog_destroy(HotkeyDialog *dialog); gchar *hotkey_dialog_run(HotkeyDialog *dialog); #endif // _UI_HOTKEY_DIALOG_H_ pnmixer-0.7.2/src/ui-popup-menu.c000066400000000000000000000232571311427610600166670ustar00rootroot00000000000000/* ui-popup-menu.c * PNmixer is written by Nick Lanham, a fork of OBmixer * which was programmed by Lee Ferrett, derived * from the program "AbsVolume" by Paul Sherman * This program is free software; you can redistribute * it and/or modify it under the terms of the GNU General * Public License v3. source code is available at * */ /** * @file ui-popup-menu.c * This file holds the ui-related code for the popup menu. * @brief Popup menu subsystem. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "audio.h" #include "support-log.h" #include "support-intl.h" #include "support-ui.h" #include "ui-popup-menu.h" #include "ui-about-dialog.h" #include "main.h" #ifdef WITH_GTK3 #define POPUP_MENU_UI_FILE "popup-menu-gtk3.glade" #else #define POPUP_MENU_UI_FILE "popup-menu-gtk2.glade" #endif /* Helpers */ #ifdef WITH_GTK3 /* Updates the mute checkbox according to the current audio state. */ static void update_mute_check(GtkToggleButton *mute_check, gboolean has_mute, gboolean muted) { /* On Gtk3 version, we listen for the signal sent by the GtkMenuItem. * So, when we change the value of the GtkToggleButton, we don't have * to block the signal handlers, since there's nobody listening to the * GtkToggleButton anyway. */ if (has_mute == FALSE) { gtk_toggle_button_set_active(mute_check, TRUE); gtk_widget_set_sensitive(GTK_WIDGET(mute_check), FALSE); gtk_widget_set_tooltip_text(GTK_WIDGET(mute_check), _("Soundcard has no mute switch")); } else { gtk_toggle_button_set_active(mute_check, muted); gtk_widget_set_tooltip_text(GTK_WIDGET(mute_check), NULL); } } #else /* Updates the mute item according to the current audio state. */ static void update_mute_item(GtkCheckMenuItem *mute_item, GCallback handler_func, gpointer handler_data, gboolean has_mute, gboolean muted) { /* On Gtk2 version, we must block the signals sent by the GtkCheckMenuItem * before we update it manually. */ gint n_blocked; n_blocked = g_signal_handlers_block_by_func (G_OBJECT(mute_item), DATA_PTR(handler_func), handler_data); g_assert(n_blocked == 1); if (has_mute == FALSE) { gtk_check_menu_item_set_active(mute_item, TRUE); gtk_widget_set_sensitive(GTK_WIDGET(mute_item), FALSE); gtk_widget_set_tooltip_text(GTK_WIDGET(mute_item), _("Soundcard has no mute switch")); } else { gtk_check_menu_item_set_active(mute_item, muted); gtk_widget_set_tooltip_text(GTK_WIDGET(mute_item), NULL); } g_signal_handlers_unblock_by_func (G_OBJECT(mute_item), DATA_PTR(handler_func), handler_data); } #endif /* Public functions & signal handlers */ struct popup_menu { /* Audio system */ Audio *audio; /* Widgets */ GtkWidget *menu_window; GtkWidget *menu; #ifdef WITH_GTK3 GtkWidget *mute_check; #else GtkWidget *mute_item; #endif }; /** * Handles a click on 'mute_item', toggling the mute audio state. * * @param item the object which received the signal. * @param menu PopupMenu instance set when the signal handler was connected. */ void #ifdef WITH_GTK3 on_mute_item_activate(G_GNUC_UNUSED GtkMenuItem *item, #else on_mute_item_activate(G_GNUC_UNUSED GtkCheckMenuItem *item, #endif PopupMenu *menu) { audio_toggle_mute(menu->audio, AUDIO_USER_POPUP); } /** * Handles a click on 'mixer_item', opening the specified mixer application. * * @param item the object which received the signal. * @param menu PopupMenu instance set when the signal handler was connected. */ void on_mixer_item_activate(G_GNUC_UNUSED GtkMenuItem *item, G_GNUC_UNUSED PopupMenu *menu) { run_mixer_command(); } /** * Handles a click on 'prefs_item', opening the preferences window. * * @param item the object which received the signal. * @param menu PopupMenu instance set when the signal handler was connected. */ void on_prefs_item_activate(G_GNUC_UNUSED GtkMenuItem *item, G_GNUC_UNUSED PopupMenu *menu) { run_prefs_dialog(); } /** * Handles a click on 'reload_item', re-initializing the audio subsystem. * * @param item the object which received the signal. * @param menu PopupMenu instance set when the signal handler was connected. */ void on_reload_item_activate(G_GNUC_UNUSED GtkMenuItem *item, PopupMenu *menu) { audio_reload(menu->audio); } /** * Handles a click on 'about_item', opening the About dialog. * * @param item the object which received the signal. * @param menu PopupMenu instance set when the signal handler was connected. */ void on_about_item_activate(G_GNUC_UNUSED GtkMenuItem *item, G_GNUC_UNUSED PopupMenu *menu) { run_about_dialog(); } /** * Handle signals from the audio subsystem. * * @param audio the Audio instance that emitted the signal. * @param event the AudioEvent containing useful information. * @param data user supplied data. */ static void on_audio_changed(G_GNUC_UNUSED Audio *audio, AudioEvent *event, gpointer data) { PopupMenu *menu = (PopupMenu *) data; #ifdef WITH_GTK3 update_mute_check(GTK_TOGGLE_BUTTON(menu->mute_check), event->has_mute, event->muted); #else update_mute_item(GTK_CHECK_MENU_ITEM(menu->mute_item), G_CALLBACK(on_mute_item_activate), menu, event->has_mute, event->muted); #endif } /** * Return a pointer toward the internal GtkWindow instance. * * @param menu a PopupMenu instance. */ GtkWindow * popup_menu_get_window(PopupMenu *menu) { return GTK_WINDOW(menu->menu_window); } /** * Shows the popup menu. * The weird prototype of this function comes from the underlying * gtk_menu_popup() that is used to display the popup menu. * * @param menu a PopupMenu instance. * @param func a user supplied function used to position the menu, or NULL. * @param data user supplied data to be passed to func. * @param button the mouse button which was pressed to initiate the event. * @param activate_time the time at which the activation event occurred. */ void popup_menu_show(PopupMenu *menu, GTK_3_22_UNUSED GtkMenuPositionFunc func, GTK_3_22_UNUSED gpointer data, GTK_3_22_UNUSED guint button, GTK_3_22_UNUSED guint activate_time) { #if GTK_CHECK_VERSION(3,22,0) gtk_menu_popup_at_pointer(GTK_MENU(menu->menu), NULL); #else gtk_menu_popup(GTK_MENU(menu->menu), NULL, NULL, func, data, button, activate_time); #endif } /** * Destroys the popup menu, freeing any resources. * * @param menu a PopupMenu instance. */ void popup_menu_destroy(PopupMenu *menu) { DEBUG("Destroying"); audio_signals_disconnect(menu->audio, on_audio_changed, menu); gtk_widget_destroy(menu->menu_window); g_free(menu); } /** * Creates the popup menu and connects all the signals. * * @param audio pointer to this audio subsystem. * @return the newly created PopupMenu instance. */ PopupMenu * popup_menu_create(Audio *audio) { gchar *uifile; GtkBuilder *builder; PopupMenu *menu; menu = g_new0(PopupMenu, 1); /* Build UI file */ uifile = get_ui_file(POPUP_MENU_UI_FILE); g_assert(uifile); DEBUG("Building from ui file '%s'", uifile); builder = gtk_builder_new_from_file(uifile); /* Save some widgets for later use */ assign_gtk_widget(builder, menu, menu_window); assign_gtk_widget(builder, menu, menu); #ifdef WITH_GTK3 assign_gtk_widget(builder, menu, mute_check); #else assign_gtk_widget(builder, menu, mute_item); #endif #ifdef WITH_GTK3 /* Gtk3 doesn't seem to scale images automatically like Gtk2 did. * If we have a 'broken' icon set that only provides one size of icon * (let's say 128x128), Gtk2 would scale it appropriately, but not Gtk3. * This will result in huge icons in the menu. * If we follow the Gtk3 logic, then we shouldn't do anything to handle that, * and when users report such problem, we tell them to fix the icon theme. * If we want PNMixer to work in as many cases as possible, then we must * handle the broken icon theme and resize the icons by ourself. * We choose the second option here. */ GtkRequisition label_req; GtkRequisition image_req; GtkWidget *mute_accellabel; GtkWidget *mixer_image; GtkWidget *prefs_image; GtkWidget *reload_image; GtkWidget *about_image; GtkWidget *quit_image; mute_accellabel = gtk_builder_get_widget(builder, "mute_accellabel"); mixer_image = gtk_builder_get_widget(builder, "mixer_image"); prefs_image = gtk_builder_get_widget(builder, "prefs_image"); reload_image = gtk_builder_get_widget(builder, "reload_image"); about_image = gtk_builder_get_widget(builder, "about_image"); quit_image = gtk_builder_get_widget(builder, "quit_image"); gtk_widget_get_preferred_size(mute_accellabel, &label_req, NULL); gtk_widget_get_preferred_size(mixer_image, &image_req, NULL); /* We only care about height. We want the image to stick to the text height. */ if (image_req.height > (label_req.height + 1)) { gint new_height = label_req.height; if (new_height % 2) new_height++; // make it even DEBUG("Gtk3 workaround: resizing images from %dpx to %dpx", image_req.height, new_height); gtk_image_set_pixel_size(GTK_IMAGE(mixer_image), new_height); gtk_image_set_pixel_size(GTK_IMAGE(prefs_image), new_height); gtk_image_set_pixel_size(GTK_IMAGE(reload_image), new_height); gtk_image_set_pixel_size(GTK_IMAGE(about_image), new_height); gtk_image_set_pixel_size(GTK_IMAGE(quit_image), new_height); } #endif /* Connect ui signal handlers */ gtk_builder_connect_signals(builder, menu); /* Connect audio signal handlers */ menu->audio = audio; audio_signals_connect(audio, on_audio_changed, menu); /* Cleanup */ g_object_unref(builder); g_free(uifile); return menu; } pnmixer-0.7.2/src/ui-popup-menu.h000066400000000000000000000016271311427610600166710ustar00rootroot00000000000000/* ui-popup-menu.h * PNmixer is written by Nick Lanham, a fork of OBmixer * which was programmed by Lee Ferrett, derived * from the program "AbsVolume" by Paul Sherman * This program is free software; you can redistribute * it and/or modify it under the terms of the GNU General * Public License v3. source code is available at * */ /** * @file ui-popup-menu.h * Header for ui-popup-menu.c. * @brief Header for ui-popup-menu.c. */ #ifndef _UI_POPUP_MENU_H_ #define _UI_POPUP_MENU_H_ #include "audio.h" typedef struct popup_menu PopupMenu; PopupMenu *popup_menu_create(Audio *audio); void popup_menu_destroy(PopupMenu *menu); void popup_menu_show(PopupMenu *menu, GtkMenuPositionFunc func, gpointer data, guint button, guint activate_time); #include GtkWindow *popup_menu_get_window(PopupMenu *menu); #endif // _UI_POPUP_MENU_H_ pnmixer-0.7.2/src/ui-popup-window.c000066400000000000000000000351331311427610600172260ustar00rootroot00000000000000/* ui-popup-window.c * PNmixer is written by Nick Lanham, a fork of OBmixer * which was programmed by Lee Ferrett, derived * from the program "AbsVolume" by Paul Sherman * This program is free software; you can redistribute * it and/or modify it under the terms of the GNU General * Public License v3. source code is available at * */ /** * @file ui-popup-window.c * This file holds the ui-related code for the popup window. * * There are two ways to handle the slider value. * - It can reflect the value set by the user. * It means that we ignore the volume value reported by the audio system. * - It can reflect the value reported by the audio system. * It means that we prevent Gtk from updating the slider, and we do it * ourselves when the audio system invoke the callback. * * I tried both ways. The second one is a real pain in the ass. A few * unexpected problems arise, it makes things complex, and ends up with * dirty workarounds. So, trust me, don't try it. * * The first way is much simpler, works great. * * So, here's the current behavior for the slider. * When you open it, it queries the audio system, and display the real * volume value. Then, when you change the volume, it displays the volume * as you ask it to be, not as it is. So if volume is 60, and you move it * to 61, then 61 is displayed. But the truth may be that the volume is * still 60, because your hardware doesn't have such fine capabilities, * and the next real step will be 65. * * @brief Popup window subsystem. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #ifndef WITH_GTK3 #include #endif #include "audio.h" #include "prefs.h" #include "support-intl.h" #include "support-log.h" #include "support-ui.h" #include "ui-popup-window.h" #include "main.h" #ifdef WITH_GTK3 #define POPUP_WINDOW_HORIZONTAL_UI_FILE "popup-window-horizontal-gtk3.glade" #define POPUP_WINDOW_VERTICAL_UI_FILE "popup-window-vertical-gtk3.glade" #else #define POPUP_WINDOW_HORIZONTAL_UI_FILE "popup-window-horizontal-gtk2.glade" #define POPUP_WINDOW_VERTICAL_UI_FILE "popup-window-vertical-gtk2.glade" #endif /* Helpers */ /* Configure the appearance of the text that is shown around the volume slider, * according to the current preferences. */ static void configure_vol_text(GtkScale *vol_scale) { gboolean enabled; gint position; GtkPositionType gtk_position; enabled = prefs_get_boolean("DisplayTextVolume", TRUE); position = prefs_get_integer("TextVolumePosition", 0); gtk_position = position == 0 ? GTK_POS_TOP : position == 1 ? GTK_POS_BOTTOM : position == 2 ? GTK_POS_LEFT : GTK_POS_RIGHT; if (enabled) { gtk_scale_set_draw_value(vol_scale, TRUE); gtk_scale_set_value_pos(vol_scale, gtk_position); } else { gtk_scale_set_draw_value(vol_scale, FALSE); } } /* Configure the page and step increment of the volume slider, * according to the current preferences. */ static void configure_vol_increment(GtkAdjustment *vol_scale_adj) { gdouble scroll_step; gdouble fine_scroll_step; scroll_step = prefs_get_double("ScrollStep", 5); fine_scroll_step = prefs_get_double("FineScrollStep", 1); gtk_adjustment_set_page_increment(vol_scale_adj, scroll_step); gtk_adjustment_set_step_increment(vol_scale_adj, fine_scroll_step); } /* Update the mute checkbox according to the current audio state. */ static void update_mute_check(GtkToggleButton *mute_check, GCallback handler_func, gpointer handler_data, gboolean has_mute, gboolean muted) { gint n_blocked; n_blocked = g_signal_handlers_block_by_func (G_OBJECT(mute_check), DATA_PTR(handler_func), handler_data); g_assert(n_blocked == 1); if (has_mute == FALSE) { gtk_toggle_button_set_active(mute_check, TRUE); gtk_widget_set_sensitive(GTK_WIDGET(mute_check), FALSE); gtk_widget_set_tooltip_text(GTK_WIDGET(mute_check), _("Soundcard has no mute switch")); } else { gtk_toggle_button_set_active(mute_check, muted); gtk_widget_set_tooltip_text(GTK_WIDGET(mute_check), NULL); } g_signal_handlers_unblock_by_func (G_OBJECT(mute_check), DATA_PTR(handler_func), handler_data); } /* Update the volume slider according to the current audio state. */ static void update_volume_slider(GtkAdjustment *vol_scale_adj, gdouble volume) { gtk_adjustment_set_value(vol_scale_adj, volume); } /* Grab mouse and keyboard */ #ifdef WITH_GTK3 #if GTK_CHECK_VERSION(3,20,0) static void grab_devices(GtkWidget *window) { GdkGrabStatus status; GdkDevice *device; /* Grab the current event device */ device = gtk_get_current_event_device(); if (device == NULL) { WARN("Couldn't get current device"); return; } /* Grab every seat capabilities */ status = gdk_seat_grab(gdk_device_get_seat(device), gtk_widget_get_window(window), GDK_SEAT_CAPABILITY_ALL, TRUE, NULL, NULL, NULL, NULL); if (status != GDK_GRAB_SUCCESS) WARN("Could not grab %s", gdk_device_get_name(device)); } #else static void grab_devices(GtkWidget *window) { GdkDevice *pointer_dev; GdkDevice *keyboard_dev; GdkGrabStatus status; /* Grab the mouse */ pointer_dev = gtk_get_current_event_device(); if (pointer_dev == NULL) { WARN("Couldn't get current device"); return; } status = gdk_device_grab(pointer_dev, gtk_widget_get_window(window), GDK_OWNERSHIP_NONE, TRUE, GDK_BUTTON_PRESS_MASK, NULL, GDK_CURRENT_TIME); if (status != GDK_GRAB_SUCCESS) WARN("Could not grab %s", gdk_device_get_name(pointer_dev)); /* Grab the keyboard */ keyboard_dev = gdk_device_get_associated_device(pointer_dev); if (keyboard_dev == NULL) { WARN("Couldn't get associated device"); return; } status = gdk_device_grab(keyboard_dev, gtk_widget_get_window(window), GDK_OWNERSHIP_NONE, TRUE, GDK_KEY_PRESS_MASK, NULL, GDK_CURRENT_TIME); if (status != GDK_GRAB_SUCCESS) WARN("Could not grab %s", gdk_device_get_name(keyboard_dev)); } #endif /* GTK_CHECK_VERSION(3,20,0) */ #else static void grab_devices(GtkWidget *window) { gdk_pointer_grab(gtk_widget_get_window(window), TRUE, GDK_BUTTON_PRESS_MASK, NULL, NULL, GDK_CURRENT_TIME); gdk_keyboard_grab(gtk_widget_get_window(window), TRUE, GDK_CURRENT_TIME); } #endif /* WITH_GTK3 */ /* Public functions & signal handlers */ struct popup_window { /* Audio system */ Audio *audio; /* Widgets */ GtkWidget *popup_window; GtkWidget *vol_scale; GtkAdjustment *vol_scale_adj; GtkWidget *mute_check; }; /** * Handles 'button-press-event', 'key-press-event' and 'grab-broken-event' signals, * on the GtkWindow. Used to hide the volume popup window. * * @param widget the object which received the signal. * @param event the GdkEvent which triggered this signal. * @param window user data set when the signal handler was connected. * @return TRUE to stop other handlers from being invoked for the event. * FALSE to propagate the event further. */ gboolean on_popup_window_event(G_GNUC_UNUSED GtkWidget *widget, GdkEvent *event, PopupWindow *window) { switch (event->type) { /* If a click happens outside of the popup, hide it */ case GDK_BUTTON_PRESS: { gint x, y; #ifdef WITH_GTK3 GdkDevice *device = gtk_get_current_event_device(); if (!gdk_device_get_window_at_position(device, &x, &y)) #else if (!gdk_window_at_pointer(&x, &y)) #endif popup_window_hide(window); break; } /* If 'Esc' is pressed, hide popup */ case GDK_KEY_PRESS: if (event->key.keyval == GDK_KEY_Escape) popup_window_hide(window); break; /* Broken grab, hide popup */ case GDK_GRAB_BROKEN: popup_window_hide(window); break; /* Unhandle event, do nothing */ default: break; } return FALSE; } /** * Handles the 'value-changed' signal on the GtkRange 'vol_scale', * changing the voume accordingly. * * There are many ways for the user to change the slider value. * Think about testing them all if you touch this function. * Here's a list of actions you can do to trigger this callback: * - click somewhere on the slider * - click on the slider's knob and drag it * - mouse scroll on the slider * - keyboard (when the slider has focus), here's a list of keys: * Up, Down, Left, Right, Page Up, Page Down, Home, End * * @param range the GtkRange that received the signal. * @param window user data set when the signal handler was connected. */ void on_vol_scale_value_changed(GtkRange *range, PopupWindow *window) { gdouble value; value = gtk_range_get_value(range); audio_set_volume(window->audio, AUDIO_USER_POPUP, value, 0); } /** * Handles the 'toggled' signal on the GtkToggleButton 'mute_check', * changing the mute status accordingly. * * @param button the GtkToggleButton that received the signal. * @param window user data set when the signal handler was connected. */ void on_mute_check_toggled(G_GNUC_UNUSED GtkToggleButton *button, PopupWindow *window) { audio_toggle_mute(window->audio, AUDIO_USER_POPUP); } /** * Handles the 'clicked' signal on the GtkButton 'mixer_button', * therefore opening the mixer application. * * @param button the GtkButton that received the signal. * @param window user data set when the signal handler was connected. */ void on_mixer_button_clicked(G_GNUC_UNUSED GtkButton *button, PopupWindow *window) { popup_window_hide(window); run_mixer_command(); } /** * Handle signals from the audio subsystem. * * @param audio the Audio instance that emitted the signal. * @param event the AudioEvent containing useful information. * @param data user supplied data. */ static void on_audio_changed(G_GNUC_UNUSED Audio *audio, AudioEvent *event, gpointer data) { PopupWindow *window = (PopupWindow *) data; GtkWidget *popup_window = window->popup_window; /* Nothing to do if the window is hidden. * The window will be updated anyway when shown. */ if (!gtk_widget_get_visible(popup_window)) return; /* Update mute checkbox */ update_mute_check(GTK_TOGGLE_BUTTON(window->mute_check), G_CALLBACK(on_mute_check_toggled), window, event->has_mute, event->muted); /* Update volume slider * If the user changes the volume through the popup window, * we MUST NOT update the slider value, it's been done already. * It means that, as long as the popup window is visible, * the slider value reflects the value set by user, * and not the real value reported by the audio system. */ if (event->user != AUDIO_USER_POPUP) update_volume_slider(window->vol_scale_adj, event->volume); } /** * Shows the popup window, and grab the focus. * * @param window a PopupWindow instance. */ void popup_window_show(PopupWindow *window) { GtkWidget *popup_window = window->popup_window; GtkWidget *vol_scale = window->vol_scale; Audio *audio = window->audio; /* Update window elements at first */ update_mute_check(GTK_TOGGLE_BUTTON(window->mute_check), G_CALLBACK(on_mute_check_toggled), window, audio_has_mute(audio), audio_is_muted(audio)); update_volume_slider(window->vol_scale_adj, audio_get_volume(audio)); /* Show the window */ gtk_widget_show_now(popup_window); /* Give focus to volume scale */ gtk_widget_grab_focus(vol_scale); /* Grab mouse and keyboard */ grab_devices(popup_window); } /** * Hides the popup window. * * @param window a PopupWindow instance. */ void popup_window_hide(PopupWindow *window) { gtk_widget_hide(window->popup_window); } /** * Toggle the popup window (aka hide or show). * * @param window a PopupWindow instance. */ void popup_window_toggle(PopupWindow *window) { GtkWidget *popup_window = window->popup_window; if (gtk_widget_get_visible(popup_window)) popup_window_hide(window); else popup_window_show(window); } /* * Cleanup a popup window. */ static void popup_window_cleanup(PopupWindow *window) { DEBUG("Destroying"); /* Disconnect audio signals */ audio_signals_disconnect(window->audio, on_audio_changed, window); /* Destroy the Gtk window, freeing any resources */ gtk_widget_destroy(window->popup_window); /* Set the struct value to zero since it will be re-used */ memset(window, 0, sizeof(PopupWindow)); } /* Initialize a popup window. * The struct is supposed to be empty at this point. */ static void popup_window_init(PopupWindow *window, Audio *audio) { gchar *uifile; GtkBuilder *builder; /* Build UI file depending on slider orientation */ gchar *orientation; orientation = prefs_get_string("SliderOrientation", "vertical"); if (!g_strcmp0(orientation, "horizontal")) uifile = get_ui_file(POPUP_WINDOW_HORIZONTAL_UI_FILE); else uifile = get_ui_file(POPUP_WINDOW_VERTICAL_UI_FILE); g_free(orientation); DEBUG("Building from ui file '%s'", uifile); builder = gtk_builder_new_from_file(uifile); /* Save some widgets for later use */ assign_gtk_widget(builder, window, popup_window); assign_gtk_widget(builder, window, mute_check); assign_gtk_widget(builder, window, vol_scale); assign_gtk_adjustment(builder, window, vol_scale_adj); /* Configure some widgets */ configure_vol_text(GTK_SCALE(window->vol_scale)); configure_vol_increment(GTK_ADJUSTMENT(window->vol_scale_adj)); /* Connect ui signal handlers */ gtk_builder_connect_signals(builder, window); /* Connect audio signal handlers */ window->audio = audio; audio_signals_connect(audio, on_audio_changed, window); /* Cleanup */ g_object_unref(builder); g_free(uifile); } /** * Update the popup window according to the current preferences. * This has to be called each time the preferences are modified. * * @param window a PopupWindow instance. */ void popup_window_reload(PopupWindow *window) { Audio *audio; /* Keep track of this pointer before cleaning up, we need it */ audio = window->audio; popup_window_cleanup(window); popup_window_init(window, audio); } /** * Destroys the popup window, freeing any resources. * * @param window a PopupWindow instance. */ void popup_window_destroy(PopupWindow *window) { popup_window_cleanup(window); g_free(window); } /** * Creates the popup window and connects all the signals. * * @param audio pointer to this audio subsystem. * @return the newly created PopupWindow instance. */ PopupWindow * popup_window_create(Audio *audio) { PopupWindow *window; window = g_new0(PopupWindow, 1); popup_window_init(window, audio); return window; } pnmixer-0.7.2/src/ui-popup-window.h000066400000000000000000000016321311427610600172300ustar00rootroot00000000000000/* ui-popup-window.h * PNmixer is written by Nick Lanham, a fork of OBmixer * which was programmed by Lee Ferrett, derived * from the program "AbsVolume" by Paul Sherman * This program is free software; you can redistribute * it and/or modify it under the terms of the GNU General * Public License v3. source code is available at * */ /** * @file ui-popup-window.h * Header for ui-popup-window.c. * @brief Header for ui-popup-window.c. */ #ifndef _UI_POPUP_WINDOW_H_ #define _UI_POPUP_WINDOW_H_ #include "audio.h" typedef struct popup_window PopupWindow; PopupWindow *popup_window_create(Audio *audio); void popup_window_destroy(PopupWindow *window); void popup_window_reload(PopupWindow *window); void popup_window_show(PopupWindow *window); void popup_window_hide(PopupWindow *window); void popup_window_toggle(PopupWindow *window); #endif // _UI_POPUP_WINDOW_H_ pnmixer-0.7.2/src/ui-prefs-dialog.c000066400000000000000000000713061311427610600171340ustar00rootroot00000000000000/* ui-prefs-dialog.c * PNmixer is written by Nick Lanham, a fork of OBmixer * which was programmed by Lee Ferrett, derived * from the program "AbsVolume" by Paul Sherman * This program is free software; you can redistribute * it and/or modify it under the terms of the GNU General * Public License v3. source code is available at * */ /** * @file ui-prefs-dialog.c * This file holds the ui-related code for the preferences window. * @brief Preferences dialog ui subsystem. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #ifndef WITH_GTK3 #include #endif #include "audio.h" #include "prefs.h" #include "hotkey.h" #include "hotkeys.h" #include "support-log.h" #include "support-intl.h" #include "support-ui.h" #include "ui-prefs-dialog.h" #include "ui-hotkey-dialog.h" #include "main.h" #ifdef WITH_GTK3 #define PREFS_UI_FILE "prefs-dialog-gtk3.glade" #else #define PREFS_UI_FILE "prefs-dialog-gtk2.glade" #endif /* Helpers */ /* Gets one of the hotkey code and mode in the Hotkeys settings * from the specified label (parsed as an accelerator name). */ static void get_keycode_for_label(GtkLabel *label, gint *code, GdkModifierType *mods) { const gchar *key_accel; key_accel = gtk_label_get_text(label); hotkey_accel_to_code(key_accel, code, mods); } /* Sets one of the hotkey labels in the Hotkeys settings * to the specified keycode (converted to a accelerator name). */ static void set_label_for_keycode(GtkLabel *label, gint code, GdkModifierType mods) { gchar *key_accel; if (code < 0) return; key_accel = hotkey_code_to_accel(code, mods); gtk_label_set_text(label, key_accel); g_free(key_accel); } /** * Fills the GtkComboBoxText 'chan_combo' with the currently available channels * for a given card. * The active channel in the combo box is set to the SELECTED channel found in * preferences for this card. * * @param combo the GtkComboBoxText widget for the channels. * @param card_name the card to use to get the channels list. */ static void fill_chan_combo(GtkComboBoxText *combo, const gchar *card_name) { int idx, sidx; gchar *selected_channel; GSList *channel_list, *item; DEBUG("Filling channels ComboBox for card '%s'", card_name); selected_channel = prefs_get_channel(card_name); channel_list = audio_get_channel_list(card_name); /* Empty the combo box */ gtk_combo_box_text_remove_all(combo); /* Fill the combo box with the channels, save the selected channel index */ for (sidx = idx = 0, item = channel_list; item; idx++, item = item->next) { const char *channel_name = item->data; gtk_combo_box_text_append_text(combo, channel_name); if (!g_strcmp0(channel_name, selected_channel)) sidx = idx; } /* Set the combo box active item */ gtk_combo_box_set_active(GTK_COMBO_BOX(combo), sidx); /* Cleanup */ g_slist_free_full(channel_list, g_free); g_free(selected_channel); } /** * Fills the GtkComboBoxText 'card_combo' with the currently available cards. * The active card in the combo box is set to the currently ACTIVE card, * which may be different from the SELECTED card found in preferences. * * @param combo the GtkComboBoxText widget for the cards. * @param audio an Audio instance. */ static void fill_card_combo(GtkComboBoxText *combo, Audio *audio) { int idx, sidx; const gchar *active_card; GSList *card_list, *item; DEBUG("Filling cards ComboBox"); active_card = audio_get_card(audio); card_list = audio_get_card_list(); /* Empty the combo box */ gtk_combo_box_text_remove_all(combo); /* Fill the combo box with the cards, save the active card index */ for (sidx = idx = 0, item = card_list; item; idx++, item = item->next) { const char *card_name = item->data; gtk_combo_box_text_append_text(combo, card_name); if (!g_strcmp0(card_name, active_card)) sidx = idx; } /* Set the combo box active item */ gtk_combo_box_set_active(GTK_COMBO_BOX(combo), sidx); /* Cleanup */ g_slist_free_full(card_list, g_free); } /* Public functions & signals handlers */ struct prefs_dialog { /* Dialog response handling (when OK/Cancel buttons are clicked) */ PrefsDialogResponseCallback response_user_cb; gulong response_handler; /* Audio system * We need it to display card/channel lists, and also to be notified * if something interesting happens (card disappearing, for example). */ Audio *audio; /* Hotkeys system * When assigning hotkeys, we must unbind the hotkeys first. * Otherwise the currently assigned keys are intercepted * and can't be used. */ Hotkeys *hotkeys; HotkeyDialog *hotkey_dialog; /* Top-level widgets */ GtkWidget *prefs_dialog; GtkWidget *notebook; GtkWidget *ok_button; GtkWidget *cancel_button; /* View panel */ GtkWidget *vol_orientation_combo; GtkWidget *vol_text_check; GtkWidget *vol_pos_label; GtkWidget *vol_pos_combo; GtkWidget *vol_meter_draw_check; GtkWidget *vol_meter_pos_label; GtkWidget *vol_meter_pos_spin; GtkAdjustment *vol_meter_pos_adjustment; GtkWidget *vol_meter_color_label; GtkWidget *vol_meter_color_button; GtkWidget *system_theme; /* Device panel */ GtkWidget *card_combo; GtkWidget *chan_combo; GtkWidget *normalize_vol_check; /* Behavior panel */ GtkWidget *vol_control_entry; GtkWidget *scroll_step_spin; GtkWidget *fine_scroll_step_spin; GtkWidget *middle_click_combo; GtkWidget *custom_label; GtkWidget *custom_entry; /* Hotkeys panel */ GtkWidget *hotkeys_enable_check; GtkWidget *hotkeys_grid; GtkWidget *hotkeys_mute_eventbox; GtkWidget *hotkeys_mute_label; GtkWidget *hotkeys_up_eventbox; GtkWidget *hotkeys_up_label; GtkWidget *hotkeys_down_eventbox; GtkWidget *hotkeys_down_label; /* Notifications panel */ #ifdef WITH_LIBNOTIFY GtkWidget *noti_vbox_enabled; GtkWidget *noti_enable_check; GtkWidget *noti_timeout_label; GtkWidget *noti_timeout_spin; GtkWidget *noti_hotkey_check; GtkWidget *noti_mouse_check; GtkWidget *noti_popup_check; GtkWidget *noti_ext_check; #else GtkWidget *noti_vbox_disabled; #endif }; /** * Handles the 'toggled' signal on the GtkCheckButton 'vol_text_check'. * Updates the preferences dialog. * * @param button the button which received the signal. * @param dialog user data set when the signal handler was connected. */ void on_vol_text_check_toggled(GtkToggleButton *button, PrefsDialog *dialog) { gboolean active = gtk_toggle_button_get_active(button); gtk_widget_set_sensitive(dialog->vol_pos_label, active); gtk_widget_set_sensitive(dialog->vol_pos_combo, active); } /** * Handles the 'toggled' signal on the GtkCheckButton 'vol_meter_draw_check'. * Updates the preferences dialog. * * @param button the button which received the signal. * @param dialog user data set when the signal handler was connected. */ void on_vol_meter_draw_check_toggled(GtkToggleButton *button, PrefsDialog *dialog) { gboolean active = gtk_toggle_button_get_active(button); gtk_widget_set_sensitive(dialog->vol_meter_pos_label, active); gtk_widget_set_sensitive(dialog->vol_meter_pos_spin, active); gtk_widget_set_sensitive(dialog->vol_meter_color_label, active); gtk_widget_set_sensitive(dialog->vol_meter_color_button, active); } /** * Handles the 'changed' signal on the GtkComboBoxText 'card_combo'. * This basically refills the channel list if the card changes. * * @param box the box which received the signal. * @param dialog user data set when the signal handler was connected. */ void on_card_combo_changed(GtkComboBoxText *box, PrefsDialog *dialog) { gchar *card_name; card_name = gtk_combo_box_text_get_active_text(box); fill_chan_combo(GTK_COMBO_BOX_TEXT(dialog->chan_combo), card_name); g_free(card_name); } /** * Handles the 'changed' signal on the GtkComboBoxText 'middle_click_combo'. * Updates the preferences dialog. * * @param box the combobox which received the signal. * @param dialog user data set when the signal handler was connected. */ void on_middle_click_combo_changed(GtkComboBoxText *box, PrefsDialog *dialog) { gboolean cust = gtk_combo_box_get_active(GTK_COMBO_BOX(box)) == 3; gtk_widget_set_sensitive(dialog->custom_label, cust); gtk_widget_set_sensitive(dialog->custom_entry, cust); } /** * Handles the 'toggled' signal on the GtkCheckButton 'hotkeys_enable_check'. * Updates the preferences dialog. * * @param button the button which received the signal. * @param dialog user data set when the signal handler was connected. */ void on_hotkeys_enable_check_toggled(GtkToggleButton *button, PrefsDialog *dialog) { gboolean active = gtk_toggle_button_get_active(button); gtk_widget_set_sensitive(dialog->hotkeys_grid, active); } /** * Handles 'button-press-event' signal on one of the GtkEventBoxes used to * define a hotkey: 'hotkeys_mute/up/down_eventbox'. * Runs a dialog dialog where user can define a new hotkey. * User should double-click on the event box to define a new hotkey. * * @param widget the object which received the signal. * @param event the GdkEventButton which triggered this signal. * @param dialog user data set when the signal handler was connected. * @return TRUE to stop other handlers from being invoked for the event. * FALSE to propagate the event further. */ gboolean on_hotkey_event_box_button_press_event(GtkWidget *widget, GdkEventButton *event, PrefsDialog *dialog) { const gchar *hotkey; GtkLabel *hotkey_label; gchar *key_pressed; /* We want a left-click */ if (event->button != 1) return FALSE; /* We want it to be double-click */ if (event->type != GDK_2BUTTON_PRESS) return FALSE; /* Let's check which eventbox was clicked */ hotkey = NULL; if (widget == dialog->hotkeys_mute_eventbox) { hotkey_label = GTK_LABEL(dialog->hotkeys_mute_label); hotkey = _("Mute/Unmute"); } else if (widget == dialog->hotkeys_up_eventbox) { hotkey_label = GTK_LABEL(dialog->hotkeys_up_label); hotkey = _("Volume Up"); } else if (widget == dialog->hotkeys_down_eventbox) { hotkey_label = GTK_LABEL(dialog->hotkeys_down_label); hotkey = _("Volume Down"); } g_assert(hotkey); /* Ensure there's no dialog already running */ if (dialog->hotkey_dialog) return FALSE; /* Unbind hotkeys */ hotkeys_unbind(dialog->hotkeys); /* Run the hotkey dialog */ dialog->hotkey_dialog = hotkey_dialog_create (GTK_WINDOW(dialog->prefs_dialog), hotkey); key_pressed = hotkey_dialog_run(dialog->hotkey_dialog); hotkey_dialog_destroy(dialog->hotkey_dialog); dialog->hotkey_dialog = NULL; /* Bind hotkeys */ hotkeys_bind(dialog->hotkeys); /* Check the response */ if (key_pressed == NULL) return FALSE; /* c is used to disable the hotkey */ if (!g_ascii_strcasecmp(key_pressed, "c")) { g_free(key_pressed); key_pressed = g_strdup_printf("(%s)", _("None")); } /* Set */ gtk_label_set_text(hotkey_label, key_pressed); g_free(key_pressed); return FALSE; } /** * Handles the 'toggled' signal on the GtkCheckButton 'noti_enable_check'. * Updates the preferences dialog. * * @param button the button which received the signal. * @param dialog user data set when the signal handler was connected. */ #ifdef WITH_LIBNOTIFY void on_noti_enable_check_toggled(GtkToggleButton *button, PrefsDialog *dialog) { gboolean active = gtk_toggle_button_get_active(button); gtk_widget_set_sensitive(dialog->noti_timeout_label, active); gtk_widget_set_sensitive(dialog->noti_timeout_spin, active); gtk_widget_set_sensitive(dialog->noti_hotkey_check, active); gtk_widget_set_sensitive(dialog->noti_mouse_check, active); gtk_widget_set_sensitive(dialog->noti_popup_check, active); gtk_widget_set_sensitive(dialog->noti_ext_check, active); } #else void on_noti_enable_check_toggled(G_GNUC_UNUSED GtkToggleButton *button, G_GNUC_UNUSED PrefsDialog *dialog) { } #endif /** * Handles the 'response' signal from the GtkDialog. * Just invoke the user callback. * * @param widget the GtkDialog which emitted the signal * @param response_id the id of the response * @param dialog user data set when the signal handler was connected. */ static void on_prefs_dialog_response(G_GNUC_UNUSED GtkDialog *widget, gint response_id, PrefsDialog *dialog) { dialog->response_user_cb(dialog, response_id); } /** * Handle signals from the audio subsystem. * * @param audio the Audio instance that emitted the signal. * @param event the AudioEvent containing useful information. * @param data user supplied data. */ static void on_audio_changed(Audio *audio, AudioEvent *event, gpointer data) { PrefsDialog *dialog = (PrefsDialog *) data; GtkComboBoxText *card_combo = GTK_COMBO_BOX_TEXT(dialog->card_combo); GtkComboBoxText *chan_combo = GTK_COMBO_BOX_TEXT(dialog->chan_combo); switch (event->signal) { case AUDIO_CARD_INITIALIZED: case AUDIO_CARD_CLEANED_UP: /* A card may have appeared or disappeared */ fill_card_combo(card_combo, audio); fill_chan_combo(chan_combo, audio_get_card(audio)); break; default: break; } } /** * Retrieve the preferences dialog values and assign then to preferences. * @param dialog struct holding the GtkWidgets of the preferences dialog. */ void prefs_dialog_retrieve(PrefsDialog *dialog) { DEBUG("Retrieving prefs dialog values"); // volume slider orientation GtkWidget *soc = dialog->vol_orientation_combo; const gchar *orientation; #ifdef WITH_GTK3 orientation = gtk_combo_box_get_active_id(GTK_COMBO_BOX(soc)); #else /* Gtk2 ComboBoxes don't have item ids */ orientation = "vertical"; if (gtk_combo_box_get_active(GTK_COMBO_BOX(soc)) == 1) orientation = "horizontal"; #endif prefs_set_string("SliderOrientation", orientation); // volume text display GtkWidget *vtc = dialog->vol_text_check; gboolean active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(vtc)); prefs_set_boolean("DisplayTextVolume", active); // volume text position GtkWidget *vpc = dialog->vol_pos_combo; gint idx = gtk_combo_box_get_active(GTK_COMBO_BOX(vpc)); prefs_set_integer("TextVolumePosition", idx); // volume meter display GtkWidget *dvc = dialog->vol_meter_draw_check; active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dvc)); prefs_set_boolean("DrawVolMeter", active); // volume meter position GtkWidget *vmps = dialog->vol_meter_pos_spin; gint vmpos = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(vmps)); prefs_set_integer("VolMeterPos", vmpos); // volume meter colors GtkWidget *vcb = dialog->vol_meter_color_button; gdouble colors[3]; #ifdef WITH_GTK3 GdkRGBA color; gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(vcb), &color); colors[0] = color.red; colors[1] = color.green; colors[2] = color.blue; #else GdkColor color; gtk_color_button_get_color(GTK_COLOR_BUTTON(vcb), &color); colors[0] = (gdouble) color.red / 65536; colors[1] = (gdouble) color.green / 65536; colors[2] = (gdouble) color.blue / 65536; #endif prefs_set_double_list("VolMeterColor", colors, 3); // icon theme GtkWidget *system_theme = dialog->system_theme; active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(system_theme)); prefs_set_boolean("SystemTheme", active); // audio card GtkWidget *acc = dialog->card_combo; gchar *card = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(acc)); prefs_set_string("AlsaCard", card); // audio channel GtkWidget *ccc = dialog->chan_combo; gchar *chan = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(ccc)); prefs_set_channel(card, chan); g_free(card); g_free(chan); // normalize volume GtkWidget *vnorm = dialog->normalize_vol_check; gboolean is_pressed; is_pressed = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(vnorm)); prefs_set_boolean("NormalizeVolume", is_pressed); // volume control command GtkWidget *ve = dialog->vol_control_entry; const gchar *vc = gtk_entry_get_text(GTK_ENTRY(ve)); prefs_set_string("VolumeControlCommand", vc); // volume scroll steps GtkWidget *sss = dialog->scroll_step_spin; gdouble step = gtk_spin_button_get_value(GTK_SPIN_BUTTON(sss)); prefs_set_double("ScrollStep", step); GtkWidget *fsss = dialog->fine_scroll_step_spin; gdouble fine_step = gtk_spin_button_get_value(GTK_SPIN_BUTTON(fsss)); prefs_set_double("FineScrollStep", fine_step); // middle click GtkWidget *mcc = dialog->middle_click_combo; idx = gtk_combo_box_get_active(GTK_COMBO_BOX(mcc)); prefs_set_integer("MiddleClickAction", idx); // custom command GtkWidget *ce = dialog->custom_entry; const gchar *cc = gtk_entry_get_text(GTK_ENTRY(ce)); prefs_set_string("CustomCommand", cc); // hotkeys enabled GtkWidget *hkc = dialog->hotkeys_enable_check; active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(hkc)); prefs_set_boolean("EnableHotKeys", active); // hotkeys GtkWidget *kl; gint keycode; GdkModifierType mods; kl = dialog->hotkeys_mute_label; get_keycode_for_label(GTK_LABEL(kl), &keycode, &mods); prefs_set_integer("VolMuteKey", keycode); prefs_set_integer("VolMuteMods", mods); kl = dialog->hotkeys_up_label; get_keycode_for_label(GTK_LABEL(kl), &keycode, &mods); prefs_set_integer("VolUpKey", keycode); prefs_set_integer("VolUpMods", mods); kl = dialog->hotkeys_down_label; get_keycode_for_label(GTK_LABEL(kl), &keycode, &mods); prefs_set_integer("VolDownKey", keycode); prefs_set_integer("VolDownMods", mods); // notifications #ifdef WITH_LIBNOTIFY GtkWidget *nc = dialog->noti_enable_check; gint noti_spin; active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(nc)); prefs_set_boolean("EnableNotifications", active); nc = dialog->noti_hotkey_check; active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(nc)); prefs_set_boolean("HotkeyNotifications", active); nc = dialog->noti_mouse_check; active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(nc)); prefs_set_boolean("MouseNotifications", active); nc = dialog->noti_popup_check; active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(nc)); prefs_set_boolean("PopupNotifications", active); nc = dialog->noti_ext_check; active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(nc)); prefs_set_boolean("ExternalNotifications", active); nc = dialog->noti_timeout_spin; noti_spin = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(nc)); prefs_set_integer("NotificationTimeout", noti_spin); #endif } /** * Set the preferences dialog values according to current preferences. * @param dialog struct holding the GtkWidgets of the preferences dialog. */ void prefs_dialog_populate(PrefsDialog *dialog) { gdouble *vol_meter_clrs; gchar *slider_orientation, *vol_cmd, *custcmd; DEBUG("Populating prefs dialog values"); // volume slider orientation slider_orientation = prefs_get_string("SliderOrientation", NULL); if (slider_orientation) { GtkComboBox *combo_box = GTK_COMBO_BOX(dialog->vol_orientation_combo); #ifndef WITH_GTK3 /* Gtk2 ComboBoxes don't have item ids */ if (!strcmp(slider_orientation, "horizontal")) gtk_combo_box_set_active(combo_box, 1); else gtk_combo_box_set_active(combo_box, 0); #else gtk_combo_box_set_active_id(combo_box, slider_orientation); #endif g_free(slider_orientation); } // volume text display gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(dialog->vol_text_check), prefs_get_boolean("DisplayTextVolume", FALSE)); on_vol_text_check_toggled (GTK_TOGGLE_BUTTON(dialog->vol_text_check), dialog); // volume text position gtk_combo_box_set_active (GTK_COMBO_BOX(dialog->vol_pos_combo), prefs_get_integer("TextVolumePosition", 0)); // volume meter display gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(dialog->vol_meter_draw_check), prefs_get_boolean("DrawVolMeter", FALSE)); on_vol_meter_draw_check_toggled (GTK_TOGGLE_BUTTON(dialog->vol_meter_draw_check), dialog); // volume meter position gtk_spin_button_set_value (GTK_SPIN_BUTTON(dialog->vol_meter_pos_spin), prefs_get_integer("VolMeterPos", 0)); // volume meter colors vol_meter_clrs = prefs_get_double_list("VolMeterColor", NULL); #ifdef WITH_GTK3 GdkRGBA vol_meter_color_button_color; vol_meter_color_button_color.red = vol_meter_clrs[0]; vol_meter_color_button_color.green = vol_meter_clrs[1]; vol_meter_color_button_color.blue = vol_meter_clrs[2]; vol_meter_color_button_color.alpha = 1.0; gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER(dialog->vol_meter_color_button), &vol_meter_color_button_color); #else GdkColor vol_meter_color_button_color; vol_meter_color_button_color.red = (guint32) (vol_meter_clrs[0] * 65536); vol_meter_color_button_color.green = (guint32) (vol_meter_clrs[1] * 65536); vol_meter_color_button_color.blue = (guint32) (vol_meter_clrs[2] * 65536); gtk_color_button_set_color (GTK_COLOR_BUTTON(dialog->vol_meter_color_button), &vol_meter_color_button_color); #endif g_free(vol_meter_clrs); // icon theme gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(dialog->system_theme), prefs_get_boolean("SystemTheme", FALSE)); // fill in card & channel combo boxes fill_card_combo(GTK_COMBO_BOX_TEXT(dialog->card_combo), dialog->audio); #ifdef GTK3 /* On Gtk3, refilling the card combo doesn't emit a 'changed' signal, * therefore we must refill channel combo explicitely. */ fill_chan_combo(GTK_COMBO_BOX_TEXT(dialog->chan_combo), audio_get_card(dialog->audio)); #endif // normalize volume gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(dialog->normalize_vol_check), prefs_get_boolean("NormalizeVolume", FALSE)); // volume control command vol_cmd = prefs_get_string("VolumeControlCommand", NULL); if (vol_cmd) { gtk_entry_set_text(GTK_ENTRY(dialog->vol_control_entry), vol_cmd); g_free(vol_cmd); } // volume scroll steps gtk_spin_button_set_value (GTK_SPIN_BUTTON(dialog->scroll_step_spin), prefs_get_double("ScrollStep", 5)); gtk_spin_button_set_value (GTK_SPIN_BUTTON(dialog->fine_scroll_step_spin), prefs_get_double("FineScrollStep", 1)); // middle click gtk_combo_box_set_active (GTK_COMBO_BOX(dialog->middle_click_combo), prefs_get_integer("MiddleClickAction", 0)); on_middle_click_combo_changed (GTK_COMBO_BOX_TEXT(dialog->middle_click_combo), dialog); // custom command gtk_entry_set_invisible_char(GTK_ENTRY(dialog->custom_entry), 8226); custcmd = prefs_get_string("CustomCommand", NULL); if (custcmd) { gtk_entry_set_text(GTK_ENTRY(dialog->custom_entry), custcmd); g_free(custcmd); } // hotkeys enabled gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(dialog->hotkeys_enable_check), prefs_get_boolean("EnableHotKeys", FALSE)); // hotkeys set_label_for_keycode(GTK_LABEL(dialog->hotkeys_mute_label), prefs_get_integer("VolMuteKey", -1), prefs_get_integer("VolMuteMods", 0)); set_label_for_keycode(GTK_LABEL(dialog->hotkeys_up_label), prefs_get_integer("VolUpKey", -1), prefs_get_integer("VolUpMods", 0)); set_label_for_keycode(GTK_LABEL(dialog->hotkeys_down_label), prefs_get_integer("VolDownKey", -1), prefs_get_integer("VolDownMods", 0)); on_hotkeys_enable_check_toggled (GTK_TOGGLE_BUTTON(dialog->hotkeys_enable_check), dialog); // notifications #ifdef WITH_LIBNOTIFY gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(dialog->noti_enable_check), prefs_get_boolean("EnableNotifications", FALSE)); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(dialog->noti_hotkey_check), prefs_get_boolean("HotkeyNotifications", TRUE)); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(dialog->noti_mouse_check), prefs_get_boolean("MouseNotifications", TRUE)); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(dialog->noti_popup_check), prefs_get_boolean("PopupNotifications", FALSE)); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(dialog->noti_ext_check), prefs_get_boolean("ExternalNotifications", FALSE)); gtk_spin_button_set_value (GTK_SPIN_BUTTON(dialog->noti_timeout_spin), prefs_get_integer("NotificationTimeout", 1500)); on_noti_enable_check_toggled (GTK_TOGGLE_BUTTON(dialog->noti_enable_check), dialog); #endif } /** * Presents the preferences dialog. * * @param dialog a PrefsDialog instance. */ void prefs_dialog_present(PrefsDialog *dialog) { GtkWindow *prefs_window = GTK_WINDOW(dialog->prefs_dialog); /* Present the window */ gtk_window_present(prefs_window); } /** * Destroys the preferences dialog, freeing any resources. * * @param dialog a PrefsDialog instance. */ void prefs_dialog_destroy(PrefsDialog *dialog) { DEBUG("Destroying"); g_signal_handler_disconnect(GTK_WINDOW(dialog->prefs_dialog), dialog->response_handler); audio_signals_disconnect(dialog->audio, on_audio_changed, dialog); if (dialog->hotkey_dialog) hotkey_dialog_destroy(dialog->hotkey_dialog); gtk_widget_destroy(dialog->prefs_dialog); g_free(dialog); } /** * Creates the preferences dialog. * * @param parent a GtkWindow to be used as the parent. * @param audio pointer to this audio subsystem. * @param hotkeys pointer to this hotkey subsystem. * @param cb user callback to handle responses from the dialog * @return the newly created PrefsDialog instance. */ PrefsDialog * prefs_dialog_create(GtkWindow *parent, Audio *audio, Hotkeys *hotkeys, PrefsDialogResponseCallback cb) { gchar *uifile = NULL; GtkBuilder *builder = NULL; PrefsDialog *dialog; dialog = g_new0(PrefsDialog, 1); /* Build UI file */ uifile = get_ui_file(PREFS_UI_FILE); g_assert(uifile); DEBUG("Building from ui file '%s'", uifile); builder = gtk_builder_new_from_file(uifile); /* Append the notification page. * This has to be done manually here, in the C code, * because notifications support is optional at build time. */ gtk_notebook_append_page (GTK_NOTEBOOK(gtk_builder_get_object(builder, "notebook")), #ifdef WITH_LIBNOTIFY GTK_WIDGET(gtk_builder_get_object(builder, "noti_vbox_enabled")), #else GTK_WIDGET(gtk_builder_get_object(builder, "noti_vbox_disabled")), #endif gtk_label_new(_("Notifications"))); /* Save some widgets for later use */ // Top level widgets assign_gtk_widget(builder, dialog, prefs_dialog); assign_gtk_widget(builder, dialog, notebook); assign_gtk_widget(builder, dialog, ok_button); assign_gtk_widget(builder, dialog, cancel_button); // View panel assign_gtk_widget(builder, dialog, vol_orientation_combo); assign_gtk_widget(builder, dialog, vol_text_check); assign_gtk_widget(builder, dialog, vol_pos_label); assign_gtk_widget(builder, dialog, vol_pos_combo); assign_gtk_widget(builder, dialog, vol_meter_draw_check); assign_gtk_widget(builder, dialog, vol_meter_pos_label); assign_gtk_widget(builder, dialog, vol_meter_pos_spin); assign_gtk_adjustment(builder, dialog, vol_meter_pos_adjustment); assign_gtk_widget(builder, dialog, vol_meter_color_label); assign_gtk_widget(builder, dialog, vol_meter_color_button); assign_gtk_widget(builder, dialog, system_theme); // Device panel assign_gtk_widget(builder, dialog, card_combo); assign_gtk_widget(builder, dialog, chan_combo); assign_gtk_widget(builder, dialog, normalize_vol_check); // Behavior panel assign_gtk_widget(builder, dialog, vol_control_entry); assign_gtk_widget(builder, dialog, scroll_step_spin); assign_gtk_widget(builder, dialog, fine_scroll_step_spin); assign_gtk_widget(builder, dialog, middle_click_combo); assign_gtk_widget(builder, dialog, custom_label); assign_gtk_widget(builder, dialog, custom_entry); // Hotkeys panel assign_gtk_widget(builder, dialog, hotkeys_enable_check); assign_gtk_widget(builder, dialog, hotkeys_grid); assign_gtk_widget(builder, dialog, hotkeys_mute_eventbox); assign_gtk_widget(builder, dialog, hotkeys_mute_label); assign_gtk_widget(builder, dialog, hotkeys_up_eventbox); assign_gtk_widget(builder, dialog, hotkeys_up_label); assign_gtk_widget(builder, dialog, hotkeys_down_eventbox); assign_gtk_widget(builder, dialog, hotkeys_down_label); // Notifications panel #ifdef WITH_LIBNOTIFY assign_gtk_widget(builder, dialog, noti_vbox_enabled); assign_gtk_widget(builder, dialog, noti_enable_check); assign_gtk_widget(builder, dialog, noti_timeout_spin); assign_gtk_widget(builder, dialog, noti_timeout_label); assign_gtk_widget(builder, dialog, noti_hotkey_check); assign_gtk_widget(builder, dialog, noti_mouse_check); assign_gtk_widget(builder, dialog, noti_popup_check); assign_gtk_widget(builder, dialog, noti_ext_check); #else assign_gtk_widget(builder, dialog, noti_vbox_disabled); #endif /* Set transient parent */ gtk_window_set_transient_for(GTK_WINDOW(dialog->prefs_dialog), parent); /* Connect ui signal handlers */ gtk_builder_connect_signals(builder, dialog); /* Save some references */ dialog->hotkeys = hotkeys; dialog->audio = audio; /* Connect audio signal handlers */ audio_signals_connect(audio, on_audio_changed, dialog); /* Setup user callback */ dialog->response_user_cb = cb; dialog->response_handler = g_signal_connect (GTK_WINDOW(dialog->prefs_dialog), "response", G_CALLBACK(on_prefs_dialog_response), dialog); /* Cleanup */ g_object_unref(G_OBJECT(builder)); g_free(uifile); return dialog; } pnmixer-0.7.2/src/ui-prefs-dialog.h000066400000000000000000000021051311427610600171300ustar00rootroot00000000000000/* ui-prefs-dialog.h * PNmixer is written by Nick Lanham, a fork of OBmixer * which was programmed by Lee Ferrett, derived * from the program "AbsVolume" by Paul Sherman * This program is free software; you can redistribute * it and/or modify it under the terms of the GNU General * Public License v3. source code is available at * */ /** * @file ui-prefs-dialog.h * Header for ui-prefs-dialog.c. * @brief Header for ui-prefs-dialog.c. */ #ifndef _UI_PREFS_DIALOG_H_ #define _UI_PREFS_DIALOG_H_ #include "audio.h" #include "hotkeys.h" typedef struct prefs_dialog PrefsDialog; typedef void (*PrefsDialogResponseCallback) (PrefsDialog *dialog, gint response_id); PrefsDialog *prefs_dialog_create(GtkWindow *parent, Audio *audio, Hotkeys *hotkeys, PrefsDialogResponseCallback cb); void prefs_dialog_destroy(PrefsDialog *dialog); void prefs_dialog_present(PrefsDialog *dialog); void prefs_dialog_populate(PrefsDialog *dialog); void prefs_dialog_retrieve(PrefsDialog *dialog); #endif // _UI_PREFS_DIALOG_H_ pnmixer-0.7.2/src/ui-tray-icon.c000066400000000000000000000405621311427610600164650ustar00rootroot00000000000000/* ui-tray-icon.c * PNmixer is written by Nick Lanham, a fork of OBmixer * which was programmed by Lee Ferrett, derived * from the program "AbsVolume" by Paul Sherman * This program is free software; you can redistribute * it and/or modify it under the terms of the GNU General * Public License v3. source code is available at * */ /** * @file ui-tray-icon.c * This file holds the ui-related code for the system tray icon. * @brief Tray icon subsystem. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include "audio.h" #include "prefs.h" #include "support-intl.h" #include "support-log.h" #include "support-ui.h" #include "ui-tray-icon.h" #include "main.h" #define ICON_MIN_SIZE 16 enum { VOLUME_MUTED, VOLUME_OFF, VOLUME_LOW, VOLUME_MEDIUM, VOLUME_HIGH, N_VOLUME_PIXBUFS }; /* * Pixbuf handling */ /** * This is an internally used function to create GdkPixbufs. * * @param filename filename to create the GtkPixbuf from * @return the new GdkPixbuf, NULL on failure */ static GdkPixbuf * pixbuf_new_from_file(const gchar *filename) { GError *error = NULL; GdkPixbuf *pixbuf; gchar *pathname = NULL; if (!filename || !filename[0]) return NULL; pathname = get_pixmap_file(filename); if (!pathname) { WARN("Couldn't find pixmap file '%s'", filename); return NULL; } DEBUG("Loading PNMixer icon '%s' from '%s'", filename, pathname); pixbuf = gdk_pixbuf_new_from_file(pathname, &error); if (!pixbuf) { WARN("Could not create pixbuf from file '%s': %s", pathname, error->message); g_error_free(error); } g_free(pathname); return pixbuf; } /** * Looks up icons based on the currently selected theme. * * @param icon_name icon name to look up * @param size size of the icon * @return the corresponding theme icon, NULL on failure, * use g_object_unref() to release the reference to the icon */ static GdkPixbuf * pixbuf_new_from_stock(const gchar *icon_name, gint size) { static GtkIconTheme *icon_theme = NULL; GError *err = NULL; GtkIconInfo *info = NULL; GdkPixbuf *pixbuf = NULL; if (icon_theme == NULL) icon_theme = gtk_icon_theme_get_default(); info = gtk_icon_theme_lookup_icon(icon_theme, icon_name, size, 0); if (info == NULL) { WARN("Unable to lookup icon '%s'", icon_name); return NULL; } DEBUG("Loading stock icon '%s' from '%s'", icon_name, gtk_icon_info_get_filename(info)); pixbuf = gtk_icon_info_load_icon(info, &err); if (pixbuf == NULL) { WARN("Unable to load icon '%s': %s", icon_name, err->message); g_error_free(err); } #ifdef WITH_GTK3 g_object_unref(info); #else gtk_icon_info_free(info); #endif return pixbuf; } /* Frees a pixbuf array. */ static void pixbuf_array_free(GdkPixbuf **pixbufs) { gsize i; if (!pixbufs) return; for (i = 0; i < N_VOLUME_PIXBUFS; i++) g_object_unref(pixbufs[i]); g_free(pixbufs); } /* Creates a new pixbuf array, containing the icon set that must be used. */ static GdkPixbuf ** pixbuf_array_new(int size) { GdkPixbuf *pixbufs[N_VOLUME_PIXBUFS]; gboolean system_theme; DEBUG("Building pixbuf array (requesting size %d)", size); system_theme = prefs_get_boolean("SystemTheme", FALSE); if (system_theme) { pixbufs[VOLUME_MUTED] = pixbuf_new_from_stock("audio-volume-muted", size); pixbufs[VOLUME_OFF] = pixbuf_new_from_stock("audio-volume-off", size); pixbufs[VOLUME_LOW] = pixbuf_new_from_stock("audio-volume-low", size); pixbufs[VOLUME_MEDIUM] = pixbuf_new_from_stock("audio-volume-medium", size); pixbufs[VOLUME_HIGH] = pixbuf_new_from_stock("audio-volume-high", size); /* 'audio-volume-off' is not available in every icon set. * Check freedesktop standard for more info: * http://standards.freedesktop.org/icon-naming-spec/ * icon-naming-spec-latest.html */ if (pixbufs[VOLUME_OFF] == NULL) pixbufs[VOLUME_OFF] = pixbuf_new_from_stock("audio-volume-low", size); } else { pixbufs[VOLUME_MUTED] = pixbuf_new_from_file("pnmixer-muted.png"); pixbufs[VOLUME_OFF] = pixbuf_new_from_file("pnmixer-off.png"); pixbufs[VOLUME_LOW] = pixbuf_new_from_file("pnmixer-low.png"); pixbufs[VOLUME_MEDIUM] = pixbuf_new_from_file("pnmixer-medium.png"); pixbufs[VOLUME_HIGH] = pixbuf_new_from_file("pnmixer-high.png"); } return g_memdup(pixbufs, sizeof pixbufs); } /* Tray icon volume meter */ struct vol_meter { /* Configuration */ guchar red; guchar green; guchar blue; gint x_offset_pct; gint y_offset_pct; /* Dynamic stuff */ GdkPixbuf *pixbuf; gint width; guchar *row; }; typedef struct vol_meter VolMeter; /* Frees a VolMeter instance. */ static void vol_meter_free(VolMeter *vol_meter) { if (!vol_meter) return; if (vol_meter->pixbuf) g_object_unref(vol_meter->pixbuf); g_free(vol_meter->row); g_free(vol_meter); } /* Returns a new VolMeter instance. Returns NULL if VolMeter is disabled. */ static VolMeter * vol_meter_new(void) { VolMeter *vol_meter; gboolean vol_meter_enabled; gdouble *vol_meter_clrs; vol_meter_enabled = prefs_get_boolean("DrawVolMeter", FALSE); if (vol_meter_enabled == FALSE) return NULL; vol_meter = g_new0(VolMeter, 1); vol_meter->x_offset_pct = prefs_get_integer("VolMeterPos", 0); vol_meter->y_offset_pct = 10; vol_meter_clrs = prefs_get_double_list("VolMeterColor", NULL); vol_meter->red = vol_meter_clrs[0] * 255; vol_meter->green = vol_meter_clrs[1] * 255; vol_meter->blue = vol_meter_clrs[2] * 255; g_free(vol_meter_clrs); return vol_meter; } /* Draws the volume meter on top of the icon. It doesn't modify the pixbuf passed * in parameter. Instead, it makes a copy internally, and return a pointer toward * the modified copy. There's no need to unref it. */ static GdkPixbuf * vol_meter_draw(VolMeter *vol_meter, GdkPixbuf *pixbuf, int volume) { int icon_width, icon_height; int vm_width, vm_height; int x, y; int rowstride, i; guchar *pixels; /* Ensure the pixbuf is as expected */ g_assert(gdk_pixbuf_get_colorspace(pixbuf) == GDK_COLORSPACE_RGB); g_assert(gdk_pixbuf_get_bits_per_sample(pixbuf) == 8); g_assert(gdk_pixbuf_get_has_alpha(pixbuf)); g_assert(gdk_pixbuf_get_n_channels(pixbuf) == 4); icon_width = gdk_pixbuf_get_width(pixbuf); icon_height = gdk_pixbuf_get_height(pixbuf); /* Cache the pixbuf passed in parameter */ if (vol_meter->pixbuf) g_object_unref(vol_meter->pixbuf); vol_meter->pixbuf = pixbuf = gdk_pixbuf_copy(pixbuf); /* Volume meter coordinates */ vm_width = icon_width / 6; x = vol_meter->x_offset_pct * (icon_width - vm_width) / 100; g_assert(x >= 0 && x + vm_width <= icon_width); y = vol_meter->y_offset_pct * icon_height / 100; vm_height = (icon_height - (y * 2)) * (volume / 100.0); g_assert(y >= 0 && y + vm_height <= icon_height); /* Let's check if the icon width changed, in which case we * must reinit our internal row of pixels. */ if (vm_width != vol_meter->width) { vol_meter->width = vm_width; g_free(vol_meter->row); vol_meter->row = NULL; } if (vol_meter->row == NULL) { DEBUG("Allocating vol meter row (width %d)", vm_width); vol_meter->row = g_malloc(vm_width * sizeof(guchar) * 4); for (i = 0; i < vm_width; i++) { vol_meter->row[i * 4 + 0] = vol_meter->red; vol_meter->row[i * 4 + 1] = vol_meter->green; vol_meter->row[i * 4 + 2] = vol_meter->blue; vol_meter->row[i * 4 + 3] = 255; } } /* Draw the volume meter. * Rows in the image are stored top to bottom. */ y = icon_height - y; rowstride = gdk_pixbuf_get_rowstride(pixbuf); pixels = gdk_pixbuf_get_pixels(pixbuf); for (i = 0; i < vm_height; i++) { guchar *p; guint row_offset, col_offset; row_offset = y - i; col_offset = x * 4; p = pixels + (row_offset * rowstride) + col_offset; memcpy(p, vol_meter->row, vm_width * 4); } return pixbuf; } /* Helpers */ /* Update the tray icon pixbuf according to the current audio state. */ static void update_status_icon_pixbuf(GtkStatusIcon *status_icon, GdkPixbuf **pixbufs, VolMeter *vol_meter, gdouble volume, gboolean muted) { GdkPixbuf *pixbuf; if (!muted) { if (volume == 0) pixbuf = pixbufs[VOLUME_OFF]; else if (volume < 33) pixbuf = pixbufs[VOLUME_LOW]; else if (volume < 66) pixbuf = pixbufs[VOLUME_MEDIUM]; else pixbuf = pixbufs[VOLUME_HIGH]; } else { pixbuf = pixbufs[VOLUME_MUTED]; } if (vol_meter && muted == FALSE) pixbuf = vol_meter_draw(vol_meter, pixbuf, volume); gtk_status_icon_set_from_pixbuf(status_icon, pixbuf); } /* Update the tray icon tooltip according to the current audio state. */ static void update_status_icon_tooltip(GtkStatusIcon *status_icon, const gchar *card, const gchar *channel, gdouble volume, gboolean has_mute, gboolean muted) { gchar *card_info; gchar *volume_info; gchar *mute_info; gchar *info; card_info = g_strdup_printf("%s (%s)", card, channel); volume_info = g_strdup_printf("%s: %ld %%", _("Volume"), lround(volume)); if (has_mute == FALSE) mute_info = g_strdup_printf(_("No mute switch")); else if (muted) mute_info = g_strdup_printf(_("Muted")); else mute_info = NULL; info = g_strjoin("\n", card_info, volume_info, mute_info, NULL); gtk_status_icon_set_tooltip_text(status_icon, info); g_free(info); g_free(mute_info); g_free(volume_info); g_free(card_info); } /* Public functions & signal handlers */ struct tray_icon { Audio *audio; VolMeter *vol_meter; GdkPixbuf **pixbufs; GtkStatusIcon *status_icon; gint status_icon_size; }; /** * Handles the 'activate' signal on the GtkStatusIcon, bringing up or hiding * the volume popup window. Usually triggered by left-click. * * @param status_icon the object which received the signal. * @param icon TrayIcon instance set when the signal handler was connected. */ static void on_activate(G_GNUC_UNUSED GtkStatusIcon *status_icon, G_GNUC_UNUSED TrayIcon *icon) { do_toggle_popup_window(); } /** * Handles the 'popup-menu' signal on the GtkStatusIcon, bringing up * the context popup menu. Usually triggered by right-click. * * @param status_icon the object which received the signal. * @param button the button that was pressed, or 0 if the signal * is not emitted in response to a button press event. * @param activate_time the timestamp of the event that triggered * the signal emission. * @param icon TrayIcon instance set when the signal handler was connected. */ static void on_popup_menu(GtkStatusIcon *status_icon, guint button, guint activate_time, G_GNUC_UNUSED TrayIcon *icon) { do_show_popup_menu(gtk_status_icon_position_menu, status_icon, button, activate_time); } /** * Handles 'button-release-event' signal on the GtkStatusIcon. * Only used for middle-click, which runs the middle click action. * * @param status_icon the object which received the signal. * @param event the GdkEventButton which triggered this signal. * @param icon TrayIcon instance set when the signal handler was connected. * @return TRUE to stop other handlers from being invoked for the event. * FALSE to propagate the event further. */ static gboolean on_button_release_event(G_GNUC_UNUSED GtkStatusIcon *status_icon, GdkEventButton *event, G_GNUC_UNUSED TrayIcon *icon) { int middle_click_action; if (event->button != 2) return FALSE; middle_click_action = prefs_get_integer("MiddleClickAction", 0); switch (middle_click_action) { case 0: audio_toggle_mute(icon->audio, AUDIO_USER_TRAY_ICON); break; case 1: run_prefs_dialog(); break; case 2: run_mixer_command(); break; case 3: run_custom_command(); break; default: { } // nothing } return FALSE; } /** * Handles 'scroll-event' signal on the GtkStatusIcon, changing the volume * accordingly. * * @param status_icon the object which received the signal. * @param event the GdkEventScroll which triggered this signal. * @param icon TrayIcon instance set when the signal handler was connected. * @return TRUE to stop other handlers from being invoked for the event. * FALSE to propagate the event further */ static gboolean on_scroll_event(G_GNUC_UNUSED GtkStatusIcon *status_icon, GdkEventScroll *event, TrayIcon *icon) { if (event->direction == GDK_SCROLL_UP) audio_raise_volume(icon->audio, AUDIO_USER_TRAY_ICON); else if (event->direction == GDK_SCROLL_DOWN) audio_lower_volume(icon->audio, AUDIO_USER_TRAY_ICON); return FALSE; } /** * Handles the 'size-changed' signal on the GtkStatusIcon. * Happens when the panel holding the tray icon is resized. * Also happens at startup during the tray icon creation. * * @param status_icon the object which received the signal. * @param size the new size. * @param icon TrayIcon instance set when the signal handler was connected. * @return FALSE, so that Gtk+ scales the icon as necessary. */ static gboolean on_size_changed(G_GNUC_UNUSED GtkStatusIcon *status_icon, gint size, TrayIcon *icon) { DEBUG("Tray icon size is now %d", size); /* Ensure a minimum size. This is needed for Gtk2. * With Gtk2, this handler is invoked with a zero size at startup, * which screws up things here and there. */ if (size < ICON_MIN_SIZE) { size = ICON_MIN_SIZE; DEBUG("Forcing size to the minimum value %d", size); } /* Save new size */ icon->status_icon_size = size; /* Rebuild everything */ tray_icon_reload(icon); return FALSE; } /** * Handle signals from the audio subsystem. * * @param audio the Audio instance that emitted the signal. * @param event the AudioEvent containing useful information. * @param data user supplied data. */ static void on_audio_changed(G_GNUC_UNUSED Audio *audio, AudioEvent *event, gpointer data) { TrayIcon *icon = (TrayIcon *) data; update_status_icon_pixbuf(icon->status_icon, icon->pixbufs, icon->vol_meter, event->volume, event->muted); update_status_icon_tooltip(icon->status_icon, event->card, event->channel, event->volume, event->has_mute, event->muted); } /** * Update the tray icon according to the current preferences * and the current audio status. Both can't be separated. * This has to be called each time the preferences are modified. * * @param icon a TrayIcon instance. */ void tray_icon_reload(TrayIcon *icon) { const gchar *card, *channel; gdouble volume; gboolean has_mute; gboolean muted; pixbuf_array_free(icon->pixbufs); icon->pixbufs = pixbuf_array_new(icon->status_icon_size); vol_meter_free(icon->vol_meter); icon->vol_meter = vol_meter_new(); card = audio_get_card(icon->audio); channel = audio_get_channel(icon->audio); volume = audio_get_volume(icon->audio); has_mute = audio_has_mute(icon->audio); muted = audio_is_muted(icon->audio); update_status_icon_pixbuf(icon->status_icon, icon->pixbufs, icon->vol_meter, volume, muted); update_status_icon_tooltip(icon->status_icon, card, channel, volume, has_mute, muted); } /** * Destroys the tray icon, freeing any resources. * * @param icon a TrayIcon instance. */ void tray_icon_destroy(TrayIcon *icon) { DEBUG("Destroying"); audio_signals_disconnect(icon->audio, on_audio_changed, icon); g_object_unref(icon->status_icon); pixbuf_array_free(icon->pixbufs); vol_meter_free(icon->vol_meter); g_free(icon); } /** * Creates the tray icon and connects all the signals. * * @return the newly created TrayIcon instance. */ TrayIcon * tray_icon_create(Audio *audio) { TrayIcon *icon; DEBUG("Creating tray icon"); icon = g_new0(TrayIcon, 1); /* Create everything */ icon->vol_meter = vol_meter_new(); icon->status_icon = gtk_status_icon_new(); icon->status_icon_size = ICON_MIN_SIZE; /* Connect ui signal handlers */ // Left-click g_signal_connect(icon->status_icon, "activate", G_CALLBACK(on_activate), icon); // Right-click g_signal_connect(icon->status_icon, "popup-menu", G_CALLBACK(on_popup_menu), icon); // Middle-click g_signal_connect(icon->status_icon, "button-release-event", G_CALLBACK(on_button_release_event), icon); // Mouse scrolling on the icon g_signal_connect(icon->status_icon, "scroll_event", G_CALLBACK(on_scroll_event), icon); // Change of size g_signal_connect(icon->status_icon, "size-changed", G_CALLBACK(on_size_changed), icon); /* Connect audio signals handlers */ icon->audio = audio; audio_signals_connect(audio, on_audio_changed, icon); /* Display icon */ gtk_status_icon_set_visible(icon->status_icon, TRUE); /* Load preferences */ tray_icon_reload(icon); return icon; } pnmixer-0.7.2/src/ui-tray-icon.h000066400000000000000000000013521311427610600164640ustar00rootroot00000000000000/* ui-tray-icon.h * PNmixer is written by Nick Lanham, a fork of OBmixer * which was programmed by Lee Ferrett, derived * from the program "AbsVolume" by Paul Sherman * This program is free software; you can redistribute * it and/or modify it under the terms of the GNU General * Public License v3. source code is available at * */ /** * @file ui-tray-icon.h * Header for ui-tray-icon.c. * @brief Header for ui-tray-icon.c. */ #ifndef _UI_TRAY_ICON_H_ #define _UI_TRAY_ICON_H_ #include "audio.h" typedef struct tray_icon TrayIcon; TrayIcon *tray_icon_create(Audio *audio); void tray_icon_destroy(TrayIcon *tray_icon); void tray_icon_reload(TrayIcon *tray_icon); #endif // _UI_TRAY_ICON_H_