pax_global_header00006660000000000000000000000064141522704570014521gustar00rootroot0000000000000052 comment=c8a90f3f85370fc5220417701fb2c0ee12e14335 vvmplayer-1.4/000077500000000000000000000000001415227045700134125ustar00rootroot00000000000000vvmplayer-1.4/.gitignore000066400000000000000000000000161415227045700153770ustar00rootroot00000000000000_build/ *.swp vvmplayer-1.4/.gitlab-ci.yml000066400000000000000000000021651415227045700160520ustar00rootroot00000000000000--- .only-default: &only-default only: - master - merge_requests - tags build-debian: image: debian:bookworm <<: *only-default before_script: - apt update - apt install -y debhelper-compat meson libcallaudio-dev libgstreamer1.0-dev libebook1.2-dev libgtk-3-dev libhandy-1-dev libgstreamer-plugins-base1.0-dev xvfb script: - meson -Dwerror=true _build - meson compile -C _build - xvfb-run meson test -C _build --print-errorlogs artifacts: paths: - _build/ build-alpine: image: alpine:edge <<: *only-default before_script: - apk -q add build-base glib-dev callaudiod-dev evolution-data-server-dev libhandy1-dev gst-plugins-base-dev meson xvfb-run script: # check for uninitialized g_autoptr, which cause segfaults in musl - grep -n -e 'g_autoptr(\w*)\s*\w*;' -R . && exit 1 - meson -Dwerror=true _build - meson compile -C _build - xvfb-run meson test -C _build --print-errorlogs artifacts: paths: - _build/ vvmplayer-1.4/AUTHORS000066400000000000000000000005421415227045700144630ustar00rootroot00000000000000vvmplayer Authors Chris Talbot Parts based on: https://gitlab.com/sadiq/my-gtemplate/ https://source.puri.sm/Librem5/chatty/ https://gitlab.gnome.org/GNOME/calls/ https://github.com/GStreamer/gst-docs/ Contributors: Evangelos Ribeiro Tzaras Debian on Mobile Team Mohammed Sadiq GStreamer developers Clayton Craft Delirious Error vvmplayer-1.4/CONTRIBUTING.md000066400000000000000000000044261415227045700156510ustar00rootroot00000000000000# Contributing to VVM Player This project is primarily written in C. GUI elements are written in XML. You don't have to be an expert in C to contribute. Find a simple bug to work on and send a merge request. ## Filing a bug Please file bugs for issues, enhancements and features at the [bug tracker](https://gitlab.com/kop316/vvmplayer/issues). Create a Merge request and I’d be happy to review your patch and help you get it merged. ## Coding style All contributions to VVM Player should follow its coding style. The style can mostly be inferred from the code. The following is a shorter version: * Code should be indented with spaces only - **No tabs ever** * Use 2 space for each indentation level * Except for functions, structs, unions, and enum definitions, curly braces should have a new indentation level. * Use curly braces only for multi-statement blocks. * For function definitions and declarations, each argument should go to separate line. * When calling a function, never add a newline between the function call paren, or immediatly after (ie, before the first argument). * Almost always put a space before a paren. This project follows GTK coding style. Read it online at https://gitlab.gnome.org/GNOME/gtk/blob/master/docs/CODING-STYLE The following exceptions apply: 1. Maximum line width is 100 characters. 2. Header files should use `#pragma once` as include guard. 3. Use 2 spaces after the end of a sentence. * This helps navigation in GNU Emacs better. ```c /* FIXME: This is a hack. How to get the window width right? */ ``` 4. Include the full URL to the bug report in commit messages so that they can be accessed from local git log (or mirror repositories). ``` settings: Fix a memory leak g_get_current_dir() returns a newly allocated string. It should be freed using g_free() Closes: https://gitlab.com/kop316/vvmplayer/issues/23 ``` ## Be explicit about ownership transfers Since `GLib 2.44`, we've had helpful macros and functions to be explit about ownership transfers. Please use them as it drastically saves time when tracking down memory leaks. These include: * `g_autoptr()`, `g_auto()`, and `g_autofree`. * `g_steal_pointer()` * `g_clear_object()` and `g_clear_pointer()` We prefer that you zero fields in structures when freeing the contents. vvmplayer-1.4/COPYING000066400000000000000000001045141415227045700144520ustar00rootroot00000000000000 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 . vvmplayer-1.4/NEWS.org000066400000000000000000000032231415227045700146770ustar00rootroot00000000000000vvmplayer (1.4) [ Chris Talbot ] * Make main window scrollable * Fix phantom rows appearing * Add option to auto-delete spam voicemail vvmplayer (1.3) [ Chris Talbot ] * Fix various memory errors * Reset main window GUI if it is closed * Stop playback if main window is closed * Only change Call profile if voicemail is playing [ Delirious Error ] * Update Icons vvmplayer (1.2.1) [ Chris Talbot ] * Fix bug where carrier prefix was not set correctly vvmplayer (1.2) [ Chris Talbot ] * Reformat all icons to be similar * Add option to call and SMS back the person who left you a voicemail vvmplayer (1.1) [ Chris Talbot ] * Add option to switch between headset and speaker * Mark application as adaptive in Phosh vvmplayer (1.0.1) [ Chris Talbot ] * Work around vvmd issue without affecting GUI * remove g_error () vvmplayer (1.0) [ Chris Talbot ] * Reformat icons to be square * Do not automatically override global gtk themes * Add option to force voicemail sync * Clean up preferences GUI to be more user friendly * Add workaround for gst_discoverer issue * Remove Shortcuts window vvmplayer (0.4~beta) [ Chris Talbot ] * Rebase vvmplayer on https://gitlab.com/sadiq/my-gtemplate/ * Enable Dark Theme * Emable daemon mode vvmplayer (0.3~beta) [ Chris Talbot ] * Fix Appdata Schema * Fix Desktop Schema * Fix some g_autofree vvmplayer (0.2~beta) [ Chris Talbot ] * Add preliminary support for notifications * Add support for displaying contacts instead of numbers * Sort voicemails as a function of the date received vvmplayer (0.1~beta) [ Chris Talbot ] * Initial Release vvmplayer-1.4/README.md000066400000000000000000000060651415227045700147000ustar00rootroot00000000000000# Visual Voicemail Player (VVM Player) Copyright (C) 2021, Chris Talbot ## About VVM Player is a front end GUI to display, play, and delete visual voicemails (VVMs). VVM Player depends on vvmd for VVM functionality ( https://gitlab.com/kop316/vvmd )
## License Unless otherwise specified, all code is licensed under the GPL Version 3 or later https://www.gnu.org/licenses/gpl-3.0.en.html All other images/data is licensed under Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) https://creativecommons.org/licenses/by-sa/4.0/ ## Notes VVM Player is configured in the "Settings" page. VVM Player has the same limitations as vvmd (e.g. carrier limitations, backend limitations) ## Settings Notes VVM player will give you feedback on whether vvmd is functional. Both "VVMD Running" and "Mailbox Active" must be checked for VVM to work! Please look here for a databse of known good settings: https://gitlab.com/kop316/vvmd/-/wikis/Carrier-Database Note: Default Modem Number can be left blank (whereas in vvmd, it must be set to NULL) if a default modem number is not needed ## Compiling VVM Player In order to compile VVM Player you need following software packages: - GCC compiler - GTK3 library - libhandy - GStreamer - GStreamer-pbutils ## Running VVM Player VVM sound files are the generally of the Adaptive Multi-Rate (amr) audio codec. gstreamer supports this in the "GStreamer Ugly Plug-ins": https://gstreamer.freedesktop.org/modules/gst-plugins-ugly.html This plugin is not needed to build VVM player, but if the Ugly plugins are not installed, you will get a runtime error in attempting to playback your voicemail. Depending on your distribution, you may have to additionally manually check that support for amr is built into your distributions Ugly Plug-ins. ## Installing VVM Player Build tools requirements When building and testing directly from the repository it is important to have at least meson version 0.56 or later installed. In addition, some supported Meson backend is required (e.g. ninja). To prepare/configure the project for compilation: # meson _build However, if you want to install it, run # meson _build -Dprefix=/usr --sysconfdir=/etc `--sysconfdir=/etc` will install the autostart file in the correct place, and `-Dprefix=/usr` installs `vvmplayer` in `/usr/bin/` rather than `/usr/local/bin` To build the project: # meson compile -C _build Install: # meson install -C _build (Install may require sudo or root privileges). Uninstall: # ninja uninstall -C _build/ (Uninstall may require sudo or root privileges). ## Running from within the source code repository Meson will build the binary in builddir (_build, using the examples above), and can be invoked directly. Run with debugging # G_MESSAGES_DEBUG=all ./_build/src/vvmplayer vvmplayer-1.4/build-aux/000077500000000000000000000000001415227045700153045ustar00rootroot00000000000000vvmplayer-1.4/build-aux/common/000077500000000000000000000000001415227045700165745ustar00rootroot00000000000000vvmplayer-1.4/build-aux/common/Adwaita.theme000066400000000000000000000021001415227045700211630ustar00rootroot00000000000000[Icon Theme] Name=Adwaita Comment=Minimal Adwaita theme Hidden=true Directories=16x16/actions,22x22/actions,32x32/actions,48x48/actions,64x64/actions,96x96/actions,512x512/actions,scalable/actions,16x16/status,22x22/status,24x24/status,32x32/status,48x48/status,512x512/status [16x16/actions] Context=Actions Size=16 Type=Fixed [16x16/status] Context=Status Size=16 Type=Fixed [22x22/actions] Context=Actions Size=22 Type=Fixed [22x22/status] Context=Status Size=22 Type=Fixed [24x24/actions] Context=Actions Size=24 Type=Fixed [24x24/status] Context=Status Size=24 Type=Fixed [32x32/actions] Context=Actions Size=32 Type=Fixed [32x32/status] Context=Status Size=32 Type=Fixed [48x48/actions] Context=Actions Size=48 Type=Fixed [48x48/status] Context=Status Size=48 Type=Fixed [64x64/actions] Context=Actions Size=64 Type=Fixed [96x96/actions] Context=Actions Size=96 Type=Fixed [512x512/actions] Context=Actions Size=512 Type=Fixed [512x512/status] Context=Status Size=512 Type=Fixed [scalable/actions] Context=Actions Size=16 MinSize=8 MaxSize=512 Type=Scalable vvmplayer-1.4/build-aux/common/icons000066400000000000000000000003471415227045700176360ustar00rootroot00000000000000actions/edit-find-symbolic.svg actions/open-menu-symbolic.svg actions/window-minimize-symbolic.svg actions/window-maximize-symbolic.svg actions/window-restore-symbolic.svg actions/window-close-symbolic.svg status/image-missing.png vvmplayer-1.4/build-aux/common/minimal-adwaita.sh000077500000000000000000000035501415227045700221740ustar00rootroot00000000000000#!/usr/bin/env bash # Written in 2018 by Mohammed Sadiq # To the extent possible under law, the author(s) have dedicated all # copyright and related and neighboring rights to this software to # the public domain worldwide. This software is distributed without # any warranty. # You should have received a copy of the CC0 Public Domain Dedication # along with this software. If not, see # . # Space separated sub directory names TARGET="actions status" ADWAITA_DIR="$1" INSTALL_DIR="$2" ADWAITA_INST_DIR="$INSTALL_DIR/share/icons/Adwaita" ICON_DIRS="8x8 16x16 22x22 24x24 32x32 48x48 64x64" ICON_DIRS="$ICON_DIRS 96x96 256x256 512x512 scalable" CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" if [ "$ADWAITA_DIR" = "" ] || [ "$INSTALL_DIR" = "" ]; then echo "usage: $0 ADWAITA_DIR INSTALL_DIR" exit 1 fi make_icon_dirs () { for icon_dir in $ICON_DIRS do for target_dir in $TARGET do mkdir -p "$ADWAITA_INST_DIR/$icon_dir/$target_dir" done done } copy_svg_icons () { icon="$1" cp "$ADWAITA_DIR/scalable/$icon" "$ADWAITA_INST_DIR/scalable/$icon" for icon_dir in $ICON_DIRS do FILE="$ADWAITA_DIR/$icon_dir/${icon%.svg}.symbolic.png" if [ -e "$FILE" ]; then cp "$FILE" "$ADWAITA_INST_DIR/$icon_dir/${icon%.svg}.symbolic.png" fi done } copy_png_icons () { icon="$1" for icon_dir in $ICON_DIRS do FILE="$ADWAITA_DIR/$icon_dir/$icon" if [ -e "$FILE" ]; then cp "$FILE" "$ADWAITA_INST_DIR/$icon_dir/$icon" fi done } echo "Creating a minimal Adwaita icon theme..." make_icon_dirs while read -r icon do echo "$icon" if [ "${icon##*.}" = "svg" ]; then copy_svg_icons $icon else copy_png_icons $icon fi done < "$CURRENT_DIR/icons" cp "$CURRENT_DIR/Adwaita.theme" "$ADWAITA_INST_DIR/index.theme" echo "done" vvmplayer-1.4/build-aux/flatpak/000077500000000000000000000000001415227045700167265ustar00rootroot00000000000000vvmplayer-1.4/build-aux/flatpak/org.kop316.vvmplayer.json000066400000000000000000000022651415227045700234630ustar00rootroot00000000000000{ "app-id" : "org.kop316.vvmplayer", "runtime" : "org.gnome.Platform", "command" : "vvmplayer", "sdk" : "org.gnome.Sdk", "runtime-version" : "master", "tags" : [ "nightly" ], "desktop-file-name-prefix" : "(Nightly) ", "finish-args" : [ "--device=dri", "--share=ipc", "--socket=fallback-x11", "--socket=wayland" ], "build-options" : { "cflags": "-O2 -g3", "env" : { "BASH_COMPLETIONSDIR" : "/app/share/bash-completion/completions", "V" : "1" } }, "cleanup" : [ "/include", "/lib/pkgconfig", "/share/pkgconfig", "/man", "/share/man", "/share/gtk-doc", "/share/bash-completion", "*.la", "*.a" ], "modules" : [ { "name" : "vvmplayer", "buildsystem" : "meson", "config-opts" : [ "-Dprofile=development" ], "sources" : [ { "type" : "git", "url" : "https://gitlab.com/kop316/vvmplayer.git" } ] } ] } vvmplayer-1.4/build-aux/make_po.sh000077500000000000000000000047501415227045700172640ustar00rootroot00000000000000#!/usr/bin/env bash # Written in 2017, 2018 by Mohammed Sadiq # To the extent possible under law, the author(s) have dedicated all # copyright and related and neighboring rights to this software to # the public domain worldwide. This software is distributed without # any warranty. # You should have received a copy of the CC0 Public Domain Dedication # along with this software. If not, see # . package_name="$1" build_dir="$2" po_dir="$3" target_prefix="$4" to_subdir="$5" # Install in sub directory? pot_file="${package_name}.pot" old_dir="$(pwd)" cd "$build_dir" ninja "${target_prefix}${package_name}-pot" echo -n "language list (separated by space): " read langs is_locale () { lang="$1" # Be dumb, and assume the language exists # if locale binary isn't present if [ ! "$(which locale)" ]; then return $(true) fi # Get the locale list, ignore dotted ones # because we always assume UTF-8 encoding locale="$(locale -a | grep "^${lang}\(_\|$\)")" if [ -z "$locale" ]; then return $(false) fi return $(true) } create_po () { orig_lang="$1" cd "$po_dir" msginit --no-translator -o temp.po -i $pot_file -l ${orig_lang}.UTF-8 >/dev/null 2>&1 # Set the charset as UTF-8 sed -i '1,18{s/; charset=[0-9a-zA-Z_-]*/; charset=UTF-8/}' temp.po # Extract the language name from create po file lang=$(head -n 18 temp.po | grep "^[ ]*\"Language: ") lang=$(echo "$lang" | grep -o ": [0-9a-zA-Z_@.]*" | tr -d ': ') # Add the language to LINGUAS file sorted if [ -f LINGUAS ]; then # This assumes that first line is a comment (head -n 1 LINGUAS && (echo $lang && tail -n +2 LINGUAS) | sort -u) > temp_file mv temp_file LINGUAS else echo "LINGUAS file missing in $PWD" fi if [ $to_subdir ] && [ -f $lang/$lang.po ] || [ -f $lang.po ]; then echo "“$lang.po” file already present." return fi if [ $to_subdir ]; then mkdir -p $lang cp temp.po $lang/$lang.po else cp temp.po $lang.po fi echo "“$lang.po” created" } set_case () { if [[ $1 != *_* ]]; then echo ${1,,} fi full_lang=${1^^} country="${lang#*_}" full_lang=${full_lang,,} echo "${full_lang%_*}_${country^^}" } for lang in $langs; do lang=$(set_case $lang) if is_locale $lang; then create_po $lang else echo "Language “$lang.po” does not exist." echo "Is it present in 'locales -a'?" fi done # Clean up cd "$po_dir" rm -rf temp.po rm -rf $pot_file vvmplayer-1.4/build-aux/meson_post_install.py000066400000000000000000000012461415227045700215750ustar00rootroot00000000000000#!/usr/bin/env python3 import os import subprocess prefix = os.environ.get('MESON_INSTALL_PREFIX', '/usr/local') data_dir = os.path.join(prefix, 'share') icon_dir = os.path.join(data_dir, 'icons', 'hicolor') app_dir = os.path.join(data_dir, 'applications') schema_dir = os.path.join(data_dir, 'glib-2.0', 'schemas') if not os.environ.get('DESTDIR'): print('Compiling gsettings schemas...') subprocess.call (['glib-compile-schemas', schema_dir]) print('Update icon cache...') subprocess.call(['gtk-update-icon-cache', '-f', '-t', icon_dir]) print('Updating desktop database...') subprocess.call(['update-desktop-database', '-q', app_dir]) vvmplayer-1.4/build-aux/update-authors.sh000077500000000000000000000051131415227045700206100ustar00rootroot00000000000000#!/bin/bash # Written in 2017, 2018 by Mohammed Sadiq # To the extent possible under law, the author(s) have dedicated all # copyright and related and neighboring rights to this software to # the public domain worldwide. This software is distributed without # any warranty. # You should have received a copy of the CC0 Public Domain Dedication # along with this software. If not, see # . # This script requires GNU Bash 4+. # Get the authors list sorted by commit count, shuffle/add more, # Then sort it again numberwise, and remove the preceding numbers. # Then create an AUTHORS files in project root directory. # If you have to correct some names, like fixing typos, you can use # .mailmap files. Please see the manpage of 'git shortlog' for more. typeset -A MORE_AUTHORS declare -a DELETE_AUTHORS # Translation directories. The directories where the .po files # are saved, related to the project root, separated by space. TRANS_DIR="po" # Add list of extra names you wish to credit as Authors. You can add # names that haven't had any commit to the repository, but you wish to give # credits. Escape regex characters, if any. MORE_AUTHORS=( # [Full Name]=Commit count [New Name]=7 ) # Names to be deleted. Escape regex characters, if any DELETE_AUTHORS=("Bad Name" "Another Bad Name") olddir="$(pwd)" # Go up one level if required if [ ! -d ".git" ]; then cd .. fi topdir="$(pwd)" # Add git exclusion rule to every given path TRANS_DIR=":(exclude)${TRANS_DIR// / :(exclude)}" # Get the authors list from git AUTHORS="$(git shortlog --no-merges -sn --pretty=format:"%an" -- . $TRANS_DIR 2>/dev/null)" if [ ! "${AUTHORS}" ]; then echo "Author list empty. Make sure \"$topdir\" is a git repo directory" exit 1 fi # Delete names for name in "${DELETE_AUTHORS[@]}"; do AUTHORS="$(sed "/^[0-9 \t]*$name\$/d" <<< "$AUTHORS")" done # Delete blank lines AUTHORS="$(sed '/^\s*$/d' <<< "$AUTHORS")" # Add further authors and commit count for name in "${!MORE_AUTHORS[@]}"; do count="${MORE_AUTHORS[$name]}" AUTHORS="${AUTHORS}"$'\n'"$count $name" done # Sort numerically and remove the preceding numbers AUTHORS="$(sort -sgbr <<< "$AUTHORS" | sed 's/^[0-9 \t]*//')" if [ ! "${AUTHORS}" ]; then echo "Author list empty. Not updating" exit 1 fi # Actually update AUTHORS file echo "# Autogenerated. Do NOT update manually." > "${topdir}/AUTHORS" echo "# Sorted with descending order of number of commits" >> "${topdir}/AUTHORS" echo "" >> "${topdir}/AUTHORS" echo "$AUTHORS" >> "${topdir}/AUTHORS" echo "AUTHORS file updated" vvmplayer-1.4/completion/000077500000000000000000000000001415227045700155635ustar00rootroot00000000000000vvmplayer-1.4/completion/meson.build000066400000000000000000000007401415227045700177260ustar00rootroot00000000000000bash_comp_dep = dependency('bash-completion', version: '>=2.10', required: false) bash_comp_dir = '' if bash_comp_dep.found() bash_comp_dir = bash_comp_dep.get_pkgconfig_variable('completionsdir', define_variable: ['datadir', pkg_datadir]) endif if bash_comp_dir == '' bash_comp_dir = join_paths(pkg_datadir, 'bash-completion', 'completions') endif install_data( meson.project_name(), install_dir: bash_comp_dir ) vvmplayer-1.4/completion/vvmplayer000066400000000000000000000010401415227045700175260ustar00rootroot00000000000000# Check for bash [ -z "$BASH_VERSION" ] && return __app () { local cur prev options # Array variable storing the possible completions. COMPREPLY=() CURRENT=${COMP_WORDS[COMP_CWORD]} cur="${COMP_WORDS[COMP_CWORD]}" prev="${COMP_WORDS[COMP_CWORD-1]}" options="--help --quit --version" # An example for file competion # case "$prev" in # -f|--file) # _filedir # return 0 # esac case "$cur" in *) COMPREPLY=($(compgen -W "${options}" -- $cur));; esac return 0 } complete -F __app vvmplayer vvmplayer-1.4/data/000077500000000000000000000000001415227045700143235ustar00rootroot00000000000000vvmplayer-1.4/data/icons/000077500000000000000000000000001415227045700154365ustar00rootroot00000000000000vvmplayer-1.4/data/icons/hicolor/000077500000000000000000000000001415227045700170755ustar00rootroot00000000000000vvmplayer-1.4/data/icons/hicolor/16x16/000077500000000000000000000000001415227045700176625ustar00rootroot00000000000000vvmplayer-1.4/data/icons/hicolor/16x16/apps/000077500000000000000000000000001415227045700206255ustar00rootroot00000000000000vvmplayer-1.4/data/icons/hicolor/16x16/apps/org.kop316.vvmplayer.png000066400000000000000000000010671415227045700251740ustar00rootroot00000000000000PNG  IHDRa pHYs\rtEXtSoftwarewww.inkscape.org<IDAT8Ւka^;thTiQb v(.n bQ⢃""uGE M)%iZ4w1}P0g}x~/%n^ͽlp|P!CǺQPV& }= l0/ﲣ݊fh2>,>b9׎ȱ;~N\op{SP2b57>lץ56<^N l 3A:e)!:G]ws| Њg۴/cn7;M9$#_ۅcCiQܺ[K^EY>}4"n%K&!Y`~빸.v6V@q}/zn<\<F*yxQBqL0>m$-r˪@@?Ja~ʦn/{W aƌEyi`icd?#~%E15nȤK#McnݸϣwΜg7B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!BVO'r$mDB! MBw&w}DeSfe  @) Y4]'斖r?yׅ@R3;u?* rߝf(c'oF(BHqhwPsoM.@{*xq~B5fNĺ?`-zGۋ,%!36M).X9Ob%F~BƗqKovlNf ^m(:,6Ǟ#I}3gJF%I;[@9b ,Z,֌. &ͳ= 8f}*NkSYI5D)kP Le5ER3Å^6%N@MJ&! Κkmw8=}(aIk@ {&u&h/%m0F2)42GT><ڛa>kSWW;BK%%ġ@Hx`dt10s4^bމ09|EJϡP8 d1L5xi\1{J=A9S1> T! dT{p8#6_y?{e P [*Y8`N u8Vd i!&v:-/WWF2|DGuz) Cv<+ -B-3_uNCIõN !9F'm+UNl6n#t a/Y@B\M=5ǩ\MUY`jBI0=M\U ,1ki yiۈ۪BDBFlFZjFaYyj?iZ_+./&R;/߫N~_Fܻ t'-ݵNM]six8@"XvuX;+_u?TYi Ц20 ڵ T"8Գط?17O#W =0ʎؓ?B^\CyWcuo_ c~epSuRD(nt\6DV]8o0,Erû1{}/:}AFΌ|hRy z{/ܑ.0ZBw8w:!UqtoWhRlKoCtëzrb]0e;'ܶaZ6,ӄiXenPE9>HVd] dE,+e* >(cpşwfejxg_r>!LӂeY0-e88 8/!$1 ,AQ\peӏ~sy埃e[P\@GDx݅(͐ɔ 5y ʼ]&1l{_{M>ԅGǹi4/r˥Jhˌy[ oaH3''q,: 舚(\I823G{؇qjK$Kx[dtvxci#GJO'09- - .pq䞿Tǟ1M8 栍?a ڒ~E<.YWkwm 36C'/v<W_;Y`@[k3yy!\W_ۡB<@zdҙ@t-<e}gceGAy*T%ϖp~*m^w\8ϧ;MD,V.uyq4% oͺv.>O.ŽPMx=xl_*R8۟9>>>^e;=pW;m62 gB9ݫעח%}%/_D_I};znyx ,W_; {v KVArϱѦ$%tΦsxlICG}tY && FZ^*ޏg~5ǧR*l'"w%χݢLj-9T ^?%t݂qw6 >Tp.vo/uQOf H|q\>_wg)ɩ}(?ǿ~ݔT$7n(NG= eIgfsgeooFGUI c0NͿ'Tr29vg?a!H!GO<~Dn~t-Eӕ*>w(~xꜣ^sӕL?Y55;#`Ko喺|@ 5!F_&I_V!? g{N35ѽO8ömf9x06-́I2/FxՐ\ҵB[_຋$;Fqb ;džcȳNmqj|Oѱ#ɞYejdRƻt=_8%i3W0SNiq5xǧnŲNˍE&x!|ѵ\n,o13t<?bSYܓ?Zm#ʜXw[(8\m4]v3H)JeNvg ίT!Vkغc:Bp6!y}_|\Ne帚;~$ok[a"r >©]lh?GLfOCpӥ ll"+y|\r\m='1DN1=m'jO;22tlv4.^ "PNa(o bZ&|>pG~Rٝ85a'I^ @gVLv!pw?4&~N,_|ـ!Hpo4Ek!OdH "^[UY$Ζ6i€T:賓~POq.9)6BVnр8 5s4'BSHOT!ǯI">qnB׍[ *6R4GiW.*Fv&`9:.p,Xw`]]񗋧k5jSxQY]r#JT0Î{y)&/E|O }O$=F]}4%҂mUHY}Jy|؀ |꾢ǘudB[v4Uw!pw7ylKwԠ*LUϹ OBpe`R}&nmߚF^;|ؖOV}~k\RWgqe .RBM.]^G.q4'SŃ CdE0B"8LS;cMóQ>U@-zeYzc KzWn|T`Vv˸jC]|@bI/<^MMinVTKuhJq'SU5g;Ke5rqDb pEIdsŗ6*,Y|pDvXy\GjC`6rq |+>QsT|)[x!FYW->gF>TGX]DPk{-jDt⍹B@:j:Jb8FXB,Wo1H2HOц@fz;D2۱oxƥ|j=o$H]ߞs=ԎsHUUײ~;6<-ٔiOcfBLM-M[oKmv;;nU!5/j`a阉IplLiZ9t*߹ghe2;(9f=Gb|u vTdT7 WV!E/jt,CA=XS8-g߅f2Z{93lNi`/kQf/ Og>:2.=[I?ܿnX=δ Nx7Xv lJNwRm;<;v/ᥖ1Vՙ8'̶mXLAod׹Adn yr|[OWcP|^][o$W3ܚ4h^uigDc&ovQ&&ͪK/Ozzí-cWX<݂=:{2jFkrM'؄uð)೟ZAs೟]κ9H&Ӑ/{3-N4(^?tl{5 @Nu>|d[n;ڸQ OBIDAT`d8l60Ѽ*xBpyLv4oxlF*鼥WяC77 '>5_|S*mv͝k`/@s7YtF5z"aۇ04x2-3*]+\`3-ҋ6Ctr΃cW!lB|~|\6Mvivjrԉ af&1a6w '?sbN/9 h*ݾ Yq@eod* yPۻ/;=={gݻsx9i6 tLRw"S?yS<6\0K8lrW6h]rQ|19|bq0&кk[w|9P+. BD <glGqf꺇43!w-B"@ S'Uu.u$\Wö,IGCa_n<^AVgIA8̫;>aZwDƫt~1 DڡM@M0yf26v>nD" tCCiRUp#>9|6;gv}}sn{TܞTfD>=@nj.y;Zq5՝iY|S_/L<ӰmE g5q!8~sl,9 y;Kpf^U3>bG?c ܖe#O¶9ܡV,{_,˄[%E 89#Яhoiӛt^/[xZWR|7~Epp.03eYp[y٭pyh]wM[m!yyc; [ρIpU+=x+CaD)dT` {>?Ja"Hs 6DWq $G^߀A%D!˥e> +XڍW\կa/'A<HUx@C&mϱL明%9+،okUMF͇f6ȃI H^oiK^\ 7q/l` yV@9԰{Oa|ɍZ^G2Ǐe75<64+=݂ `jYg0;όMaJ^1BO `XB8(c:f"U5garDlF*aCZ ]GzW -"[zcZjlc_ ^loB˅:;(yd} ^7C4ImLL10rhBd* `3n|7\KVWdς`j*RcF#}ٱϋH$X!e6ɮOoS3( =+!+~QP݀pyvaU#b**SSqz$ (N|wC_.T ҳAt]z0[f)4G`2a"VO>I, EkEMg9U('Է78@OMtLh:‘~귋,i#͞*+E5o;?H粺u. @H*d ?(-SYSyC~^j eeT5M{gyhr 逿 @aisZ&uz-D#&؋8錊`Wr!Y/lؑkO[׺ݗp ܾ&z P3\^?2S%|2#gxa qUCU$ `^" Z^gLJDоF{ [)zB̾hT]^DWASF]P:^D.9R RixzRH%,$ iA7Lq|*;M]hz+7[6X4"سM !5Cς'mlK3 %CQd0&I LL* 7/E8wEŀ1\@p˶a[ec$+oBtՅ~(|v[z0!uq ڳF^Ef0m 5ۑ8uhQԱaAdacoK}ZIqB@YQ1bAܾ Z6"!5v z гZ|ZlE3&+pm ѮS `e+b- l C{5 8r)hlKoK7-KTr)pS7 pۄL„ 70&)` &j)ֳ=AHn7rAr  @Io@an'.<_00U$: / |:n0 ,#9do7oki$.o.Om$1a(u>ש0rif!UmV"m-m:~ꓠ%c u6D Fi9gZ}!`T9uλR+*U 6I J; T}W 2XFdA`*A]3iw`BY=W &pnPӰ'*A]adRY`BTV'U!L- #!sJ}_m Q,RռJPrܚskmMKqŭ*v-% ZF6nKHC_Kڸ`ӎZ}_˕zIB&O8XV@:3)v 7 lj'*&K[z kj| XZz6 q !/wJu@Zzj+ g<T'd~>k@2#^ ;L=O襹p!`S2< z Lfzð|aNNy) 1;4 zOߞe}bz )7Kc'{], ڿc?t'gOO \!B:dhvb cMzhq_3 @O;!e$AIY04;p8oGncϖ뜄, . :oY'zj@0qrEY0ח vo*&޳m_%EÒ,_CN !B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!RYf^IENDB`vvmplayer-1.4/data/icons/hicolor/32x32/000077500000000000000000000000001415227045700176565ustar00rootroot00000000000000vvmplayer-1.4/data/icons/hicolor/32x32/apps/000077500000000000000000000000001415227045700206215ustar00rootroot00000000000000vvmplayer-1.4/data/icons/hicolor/32x32/apps/org.kop316.vvmplayer.png000066400000000000000000000021331415227045700251630ustar00rootroot00000000000000PNG  IHDR szz pHYs'tEXtSoftwarewww.inkscape.org<IDATX]lU;?-݂]ҴVD R#Ic^D$A^p)DQ14o2 b AMv̙sMkHcL\Mssr3xLbNKC NwFxG1>07~;-sݞrY?cHeNvfU gt\`5X<_]m%kSfsa)l`.僔&*5Nݹ/J B`eٳE3^- }=~V>j RFHy, ,u Wuٸz t_E|s#:@sjwB>{0p9}ĦIosW]iB6H)o߉I. &H",w L8Z+>=3H{Q?cJ+9vx1 /5=[dUD,I_DmXʵ+ V/#p : PǢ@iZ t%e3aZKa1DMh@dBkFo6(R 6?D&T듸"t_e~z[OΏ, .K*,Pxp~{16FZCU_E%GJɮݷRjvֆIV<p#s7#-N}>@WNg닭>EOlnj0*ghmIΝe(%9a-ے]K5"kߑj#\pGg+c.SĎ(Dlvoi(*ƌ.CIM5T?+4/l3J%<9 372ciN.j-6  [v؊Ll}fsȊT Ժg/1|' Г]_,s+C˜#4o̵<Ơ(IENDB`vvmplayer-1.4/data/icons/hicolor/48x48/000077500000000000000000000000001415227045700176745ustar00rootroot00000000000000vvmplayer-1.4/data/icons/hicolor/48x48/apps/000077500000000000000000000000001415227045700206375ustar00rootroot00000000000000vvmplayer-1.4/data/icons/hicolor/48x48/apps/org.kop316.vvmplayer.png000066400000000000000000000033031415227045700252010ustar00rootroot00000000000000PNG  IHDR00W pHYsmhtEXtSoftwarewww.inkscape.org<PIDATh]l\Gs_b'!NHp$qBU$8QZ! U% 4Q)`V *U)\J"VR%cԿkspxfmhr}~B *TP!~9ܻm+oZ\W^z͞П]+Bq4o ]Vd@ yMQ^X;Yo:g:7kD@nIܡֺ- x7mojz![k}AAq2IBU5ԯeF/IzfXm+7nfJ g\j|I2tq>ӣj֞[2Xv֎Oe=H)mqΞFb^:FѰy?>MK(\Ӆ3RS ?wdP=\$ t>MnA ; ce!96 BI/Îu4R ߏQJ)n0?kր NwFZ6Sᘯx7tϽH$|§kkD'ϥw-C% 774w2cxqm=QdH]zԵwطmgxy7O? lk/ݻ; 5'^ItC[˚!8rļI#VxJBh>[*dyԷZTͺz.KRl_ ш)!1UAyq[&q%3){_$eB28tۃc3,w/;9< E]O&{‡$sC[ M'M&XhGޢj>Lto@ޯaabRTTY83Zo8.#g^LU398||UkgO& Nst,NSb1ÞqN=?`SgAZ]7䫄v?! ,ᓻhZa3WsmNVH=SHKh{ٺ%BM$6+K8 5c@@ 4~݃`-@&CWd?"wpzW)H`Y`[(r=0*T::gUGB.p BRĚ>,L' 3q 9H pjj=a-vP)WOdN/րa"0&jV-I"N0 ڡI%,^6c94B9E1l\k VLb\1+m+cB& lYBXVfvQTz"ɱϋGㆢu\-B *Tpϧ;IENDB`vvmplayer-1.4/data/icons/hicolor/512x512/000077500000000000000000000000001415227045700200245ustar00rootroot00000000000000vvmplayer-1.4/data/icons/hicolor/512x512/apps/000077500000000000000000000000001415227045700207675ustar00rootroot00000000000000vvmplayer-1.4/data/icons/hicolor/512x512/apps/org.kop316.vvmplayer.png000066400000000000000000000643411415227045700253420ustar00rootroot00000000000000PNG  IHDRx pHYs;;̶tEXtSoftwarewww.inkscape.org< IDATxg]Wy.g&iԻ-[r KH $nHIM RiwSԄ^ {l*#i4}pFF3xK~*Z7`%G^ !{ZRIMÚkkOպM+p }o<M_tպMDDr ,}%qۯԜZ7b4LN{ QaTE&nR}/JXhO4hu{#hG:ά;$pCBDDt?}MZ7d1zuR#|Q\״{?^Y,.G~?'Ծ25smL[6-x ˅IZlu3G>lqӈ.dzbsآM~K5mY*x a@q5]axwHM눈'{(G b{8_7V]5n rhڳ0Y-JH9q,#r<`8f.nF~?&/5< $%ɵqh*5hQ%fMg /NnԛB.nF  EyW-̝.Pۼ?HaHY/uш|jf{/"~-=Յ"""ZrXFvǕhŨXޖC)/W$""XDr)ަIR@JM~~?gP0""yd$Ny]cA4>~0aQ7>5 JLĺLȮUDDDIpƛK5i"hu H^U8!Ǔ#bQks8r0)YG&VkjH)'Ci*caHe\""j92cCRr+ϭySmfiX:'rvG"A 5/ Gs^.maSe. ?.VGxbZЬBWDD\<=FB%KT0<Ѐ;ơYїrLlO+|p_Pjg7TQ}@a,'OxZe?y!ZJ ݓ5yB =mUU|- t݊XHѓC^Wj^OޑDɭt٤L>IX[;UTDDT[' bXFl \u'RԤ0UC j"">!ԱgO劫.L)kZ.r "+ڑfEwA퐐5ּIi10UZsK8>v7dlϾWTA lㆭihuhԦf@ѕn zw>)"Fg8z0v]u[ 8ڡ)QQck &@9n QCiO̔dWlT@CIQt9%@D\_.YW Ѵ*))%""Z* o &AWV0`,iZ|$fG!3>J RUg…\@f@H@3L //E0Gk}ѱz ѶAcQLOB!5 ]*dp"R <]ta|88m=u#_/R"y4ㅋ.zkݖf n`MBZ_Sʥ0Ø9~c(fp" jKd.,8Vo:4 ±N{עsp;6_ĀZk<02>[Vo݋^.ؑZ7!{`p׍xWLԲ]N 'kݜu}vr 6%&`pԓ_typ%h׿[Z7x 3yMiJt_FD/uS0~L_[{EqCy;лyOBu ?;D;jZ#_8uSs~Wѓ?£`h徦 Ài&  #߁պIM)V3/̾󯀨RlXU#!A7:.{jZ<@1uS.lDžm;pA.pWE4τigq_}/{6Ժ)Qk~m`́ԺHHxUQ(Qi4MCA~f݌\v3n]Oލ'y,l۶Q'//'zh7:[ouSS !p k>plbb}W.2pP0p8ߏz~N7a1ZNzn u=%, S(,J|`Џ`(X\z&W8cz 0PHr8w~ѱ] }OdX*| 7}5=Eo;0X`M!@PBTۇ8 '"+4MC&O|Nv }Oh?@K@7=c_sT6)Q(MlxgJ&hzHD\C"!YonE`:E tlDx[ԛ ##@js#*e7C֤ 0_;$Gj̲ E6N/_z"q @1EF Z644+9~o@&GxɇKl†^ , v茹FۄYǧ82pp4O\E-^M7]W||59GJldsy8ů7hgLD#!BA5 Hzջ`kr}Ua *MƉҫb#JgKv'p"v/ҵ%l[UBWH :SCa<1.->>/]0f+ 'U5kǚ׼F#LKU;u=Φ- Am{2fKѶ?M E0Ah4Ё :v .AbTi?x_;X%gihooǭo{9(bdP(!-Z~Pr E?u0}jKplH) m .A8U(d!5Zju XjX?Tz*0@c%-a3a*1)P/~XH\k,s*Ba`a;aaDЃa@v;)d)I$fgfSN y_y _Fˆ"UaGVasyHrJ80mQ Q˥}0; 7w/[j HŪrAx`;^Ќ c89 O`:HP@uRxÍ3.&^{Ysf$'$N@.qa)[Wog܉"7"]^P(хc1O+~RB:[TJ(]0;zkM&98 K!!. Q1 '88BůS(,>o*x ?(`tM Yz.qS'`(-t |$o'mBU\ ׿/*~V=_Zk\hr4 ^{߽ ,8pǖy)/ "Vߎ+^Ϋ~P #"]N-{~X߻<=okQ*$Ɔ ~x/D5\WT/3y~=-b[HɲNe\wQ߿;`DT7fDk@?]C Pš?3 ;pS8]ѽaj:`w_>yFCpVoj٢CqY@^8t'ՋtW70sGPI9<~F>5Yk %3?0;Z)aO@3p?Mb"M}A&@w3U=wM$(GNj/;Bo:!Kcϣ0?~&js;*6>YJJ?Xll׽ ፻D#뚛F'G8_DC*]w_?݈ ξ~Xu"v@N& ,rú/,'J0Ufa딐Oc`߬><ĖHs(Mыe7"2u[ #пuIۅr^Q;53܆`zWHx7>WlC͟>rsEd2Wkƛx/#"M7t)b{nyW@um= n4KO/6 ,,OdY Uf%35v|d=NhŦR#O[J3֎޺egA߳^> Qo-{_ -P#ji>-B|Y`Os Ǩ?='"[8g+ՏЦ]o3kWn.n93) 8PM<öJEk^߅!6kFf鑀_dx* +HZ2}E]Ltk7ڴ M]*#s7:g ! }u3\z^Iatyտűy=ݱW:";;8mT*t퐕`֩0&Ru]U ?hboTvM<=Eʟf "G]'a%[:g%S|Ai\6?Wm篙žD'b{njFiiJ7'wyȓ{Nѡtu&['5ʮGsY~L D懲 Z*pp2c !˕>M?=Bex4D[Bs_{K'ћ(,  f1r cr"Fxeòʿ7C߳mOmò-_ΰzR mܙy?x$B<z ؏RЃr&U~?zљʳ%Nd ?\`mCh%sٌQ8閐=.Am-Qœs/,k8"*:]jы}[eWyGh)](!.:.n]ކG8lO1'W.=3ǟSN\X! jh 4 K6F(iz @jǧ>~ۇ!u[UdUgJrbQ0У?PV&{*mϤa;\b0̊z @iL[ BW_]ŒO njw f {g syeg5$BHؖ3AݱOI|jL{gY܅O*SϚ: W we h˔Ħ޼|f@XKsGӮT)X a5 xɲ \G8-Bhι'%`LFdl]HS'C*_*?T\ z0V.J/Օ&}qƏ)o?MK_IgN8%X3ͳw!M ga4ÇKŦt45El쳔%?иg̞8(es(1E ;bգNJ)!ˮ,<-T < p۞4J'G)S /(c.sF&tZhhICJ4pi\g^5ug/MK`t L泎|;M-i;nJ5ZHy{,t_=Uf:T8Иb -+"0KE_EeRz($ǔĪ&E13$msOۤDo"l[Q=4D)wolPM>,e9 ȷZDpv͗PR&4v$U p]o{kV ߷7_xfO T6(Ytjyv|hQےB3U-̤ql-qA-ط% )i8kF])zӴ 5;$zXicӞEX`Vv:Yfn@I5mvwJRsuc:m8³dM&^1}oZqwkajԼ7B \Us*o!`^ѺS6B3|JR ެ9[TMHGMMh˶{C<.H^= DluͫTq]PX$&5zPhɨ,ףL[TTѲ,XSdt]fRWQB[ sZH kJЃ!{a \׃RN> %ϧ)k\Q)1n Qw ]C;5rXYJ+g.U6:c.MS:j[סÂ,ĕn.8u)1%qv#-fuHjUA!=$ ,'QA%15{\Es)%qMS&~YB l^$*l+A(*FUH7 ʧ<-hf{H֔?C*Ō89E,Ol/!.g 6[n@V^ͮjy%q<|]tCILjv&%Z )U['yCE1l^hTh7[Q[8Z+sKY%qM&jn@.3<}:C nBFC{ămPԜkQo2NQIH#-ދH@ѡ$8Pʪ)\>6%>?ڣj4`1hsn{LE"& VtŝrLݝj>;楲4eඈ #WZM=yx3֥$ހ8 q]LTUH4_UQ[\uf5s5#֮$8Uww=i'fh*CTG*ժZJ$fSI,jMa%q$ơVuj>CR6?izӔ ThZT #)8Z 4"܋є &ZOgHzUhs VHQ,%lnTEUFPTPrVƲs jV^'KI% 7qvIMє<T3toJj޹i5u2j>CBޖSU kUQ2&f L.j> MWdrɤݛFs> 2t5å\s.*J qjJ2ݜ7]ٔ{SMs&B9T=%Eu_$Լ6 TjhΗL5+TEEqqjR錒0ry5/qPs> 2'Ԝ.;ޜ?.)[4ΩF(n)ECzf.ϡPM>y5<ώ/8Cqx7#Cj3yO^$Vi eoTy>$<@q zjܙr \9n p܀-#WxDg Q3gz0ZÊsu(Uo2;j LL7IEqMt+U j3R(l_'Meڟ=1cJ8*>@LJ>36mLgKW !BcSTgѾ`w9 @ wխ-l@:7] Mod&(PV;ncl|c.O{r:`ˎaMuykX,B9khJZ`r=xBa+xR(өucdKFhù-.Ս|k)89׾nVT^Gоy/`.<cv"S:[Iuo|>Il#fpSfo4 Œi5N| 3jvm@7^@¹M>?Lс(Y {~Jy\ 0a躡,v-1c]B*[; 8翨pm!m}@/<8غK>OhuqxQ>_FR?_mP 21{wq};i=ضp\Yz /Gd`3@|Ai"㎀VDeu:)u 4XnIX6w%qԽ{ vi:?B>bu@YiRƕţ'ԥ>- a`C'v%nY_R3^'`Mh@u(ÐTViǟ, zJ=)% l?m <*&M, jAӮ[B}u? #qD7is~/>0t:vO Z@Dv D]a@Jµ-oQ'e %EeP,A #~WK-4{z.ȝ,vŒ#k2-Ofuۮ8 U~p SQo9y^|ZS bb m(*1 өxrfѵE0A"L-h`asM'*ɨ[x{G(5_Y&pjh8 hdr3Y. l@oک7H ԮKn*?zJNim=4 [qxzy;o}Ғzv{iۘ%8,r2 C$$3 8'pC 90 x7mڀvԭWQRI%j^J{+ύxP0^x;PTDRv>k6Biz3?RN B`"c.d>QdyqQ*MMq \|==Z;ǦZxlzβl7ǟ,/4vhi\W?O>՚\eMtwk6hz@(mFbD٧|Qy2nQxbt5bRJdӫ bw#0yտDPF6ՏFytOя |#mq$sG3k]RlylP5ҿtjWW 5T|زߛ{G{`]#ȶR&%BZ[\ZD/́-O s& TMx֤~j%^RTCծ{nZD&j(nV4R,zxGpݲAgvࠉ8 ԚiDz 2^5@gC~JMAQTex%[g*'O ;Ѻמl"puR RlRoC Ze4Pjnߗp[T)q=G[EG=T X-,t]k݄ئ x/کPuDҵ4HbY;δ ws OG9j{}+Pf=ғPD2CX{g[DR& \ne01)}-+{ZJ)111ut^־NCC|sÒbрmOq͵~9hQ9zU5jO7lrsMA(ڭfDnVS(!z׏E3IkV%1z~tE?̎"xǾtOo1kAWq$~l=d'uK0ʳj?]$Ԛ)Ht#Xq cv9"ޡ+"mk7ݐoL<"¶ $a&Kz-ӝ#ۻӵz&Z6pァ?~*7^kp[~_GK#>J#3`Ys _v\U(H y+'05/2m'M!9N#j?s:[8s~蜇*t:@^`@=a\rq^®!m_1_ l¶rŦA \u3?ۈDat8'8̩ 4XpXA_-hw aв]>p谉 U9jat̃ivחlb|b΁BdF UGz.ZG?ϫ( יC>>!ҁ ;mk[uK6Ȥex\8 X8xC*FHm~,q_)`z5ݍpY ?}Lt GTD# "Q@"AMbqO0'@jJۖ-^w盲-jF3B 33: Om.0'Nt}}4U THFC "!EeApX`p@WkV0<:v~6_J MRn _wk V&[tiRT ɡ A@rqx ( Tz2.L qMv>l}:ytj8oHj@{p=lwۥc^.BձnJdtg5 Rk67~Zxc8uz f*V"5MR㹦'-j<{K` "9Zhz_(3-7UF@lBiZ㺵Z>BAl#%z_ _K$ AMa˛Bb%MRqњ%em߱gh ,cm|~ bb[ DW˅ED(*C;P?jal(zvE(3'9g'AM OY"H#V+`0UO#I ]mB ֿxwRq` !ۈX>|5{u11*Hģ\JD]g1!83w]v  #C!֑iìZ{w /}=[/+E*`nx&=0ƎµwB $]+`7@RRx,P8MKKDKy>,ˆiZٽT&s^w I1_0Fo#N_CP ,Mnm:g*]ː4/>~@(U&kpPz@0W@Dg#m-eu#Mg^v^A75tOcABSDS(])4ܯh:zvEkQ</<+j_Z=:T!h=vXuZ7Pj{ضB4II H:@PCa (gOµ͆P~9/Ci? ˵ƀ tM)Bph} <χp'YV$BE|.ϻѡ=X ў!zp .%Gc0Nid!N:n@nO?sfYP0EQ EU:Mg @}(H) K@R>BqKYǓ= } [#Rdv];O!ߌ .#678zH)K{r /2|O=7uڞw7J ȺmލPr6M'z8BZ ]J(*{(S1!{j^4(@g!d.qTO@as "Gۂ{64%4z$!{7 ؘiat9EQZ % #`oX10MmBb)`Ae(I̔@ B[-<ёٴ30X"ilN*gQΝ8SKCvp XaXٓ pJE*#}f6 `KBEj z8vc|υ]*4r$R|$zH"=8# R[)©hWLD+CG"I==zW@ IνڗmM=`9VnN⽛ ǪS5 r EE ُ@}ue Ϯ·Mvu2Аt9wd/( jVA(W49>B= B B~ %N{P ^5 mbZ"K@QybЍ$` \g?#HljaN{w=\њ$4=2z1/%RZ Ȕ@be|υm!r^CN%ZU8fUk9MD `z(--}`J1"US]u`Z00jr|שvmuLxoED+jazj =5TJg3%Mt)%J)P4A-`4ps,xN ܳ{.|φz}RZ}D9b/f5 o !E*Ph:AQuP4= vfpZJ@5ba*"r˟'"Z$$,w/cf`smuZJ,E\ ȭ)"eƔ@0hZ?<h?-&} TDDg@;1h!u`9x.;-TJZ`JkUau~"G2%j +dSXDD)Vb|υ\nJIDATiVBD*0%: XJyHSDDˎ)e`]6 PdJ8e` |υUs8ODRJH_Z`J`ڔd[\""j-bI&9ED9)#˔9`*fBDDL x>Sy ?Q7QÔi@jgXQw ODBRLΊ<|džm{nBDD$8+fRµpJBDDKq`EV `:<|o"Ն)U)V9KXODDkSlPwh-bJ`UU*BJC!"J FnM%@#eߩ&_m""jPO m"Ο:ӎﹰ<` ˅s~ ϶`8ODDOnoKz02%x  7ʢVpem'DDDk\1qNmlRSDDuFQ΍L wmGWf.Dmu`9.;R3+ʍ|Fgz\/ᯓ?18 RUDD$q){;O]Ħ+/SÁO_:=""EY (tt~J`/xDDDMB@@m{:=ٺƻz/}:=""8tz(te `A} ""βyWuX33c_=p _}}c٬`z:~|k ͪ. >iuz`"fnA_zpR >劢[--ulTIENDB`vvmplayer-1.4/data/icons/hicolor/icon.ico000066400000000000000000005304361415227045700205340ustar00rootroot00000000000000 (N  pD)oDenDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDoDoEzoEUkC&mIoDlnDݣnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDףoEzfM nCAnDݣnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDmEԣoCEoDenDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDoDأoDnDnF3oCLnDnDnDnDnDqFyK}MOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO~N|MwJqEmEԣnDnDnDnDժUfDnDnDnDoDzLˉT֏Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֏YʉT|MoEnDnDmDinDnDnDtH̊U֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐YόWyJnDnEmIqGnDnD~Naݖ\֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֑Y``vInDmFMoCjnD{Lbbb_֐Z֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐YאYٓZbbbܖ\oEmCnEpE^bbbb`ْZ֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֑Xޗ\bbbbbOnDnDʊUbbbbbbaܕ\֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐YՐY`bbbbbb^oEۧqEabbbbbbbb^אY֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐YאYؓ[bbbbbbbbb}MObbbbbbbbbb`ؒZ֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֑Xޗ\bbbbbbbbbbɉT֑Ybbbbbbbbbbbaە[֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐YՐY`bbbbbbbbbbbדY_bbbbbbbbbbbbb^֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐YבZؓ[bbbbbbbbbbbbbߙ]bbbbbbbbbbbbbbb`ؑZ֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֑Xޘ]bbbbbbbbbbbbbbabbbbbbbbbbbbbbbbaە[֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐YԏX_bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb]֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐YבZ֑Zbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb_בY֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֑Xޗ]bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbaړ[֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐YԏX_bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbaߘ]֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐YבZ֑Zbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb`ؑY֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Yޗ]bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb`ۓZ֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐YԐX_bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbߗ]֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐YבZ֑Zbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb_בY֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Yݖ]bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb`ٓ[֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐YԐX_bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbޖ]֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐YבZՑYbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb^אZ֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Yݖ]bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb`ؒY֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐YӐY_bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbaؑZ֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐YבZՑYbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbݖ]֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Yݖ]bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb_֑Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐YӏWҌWэVԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXԏXӎWӍXӍXԏY֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐YӐY_bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbaؑZ֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐YԏX̉TÃQ~NyKuIsGpEnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDpEsGwI{KOŅR΋V֏Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐YבZՑYbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbݖ\֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐YэWƅS}MuHoEnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDnDqExJOʇSԏY֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Yݗ]bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb^֑Y֐Y֐Y֐Y֐YΊVzKqFnDnDnDnDnDnDnDnDhB\=X;}S9vN7pK6hD3M2,P4-R5.U7.X:/\=0dB3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3gD3X:/iF4qK6uN7}S9X;^>iBnDnDnDnDnDnDnDnDsGOӎX֐Y֐Y֐Y֐YӏY_bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbaؑZԏY~NrFnDnDnDnDnDmC]=oJ5]>0L1,:&&1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$9$&L1,_?1qL6_>mCnDnDnDnDoDtHĄRבZՑYbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb`ÅRuInDnDnDnDc?sL6U8.9$'1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$8$&W9/uO8d@nDnDnDoDzK΋VbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbaÄQ{M|M|MxKjAvN7L1,1$1$1$1$1$1$1$1$1$1$1$1$1$1$1!&5#'6%(3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&3!&4"'2$1$1$1$1$1$1$1$1$1$1$1$1$1$1$E-*qK6jDzL|M|M|M̊Ubbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb֒Z}M|M|M|M`AZ;04 $1$1$1$1$1$1$1$3!&8(-=-3A26D4:E6;F8=F8=F8=F8=F8=F8=F8=F8=F8/4;+08(,5#(1 %1$1$1$1$1$1$1$4 %[<1cB|M|M|MPޗ]bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb^ÄR|M|M{L]?J0+1$1$1$1$1$1$1!&9).@15D6G.*1$1$1$1$1$3!(>/4E7;F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F7=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F7/2E7((1$1$1$3!&?06F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F7=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=D5::*/1 %1$1$1$<''eC|M}MԐYbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb`ŅS|MzMoJ62$1$1$3$>/4F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=E8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=D6;9(-1$1$1$1 %sL7{L|M̊Ubbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb`Q|MqIQ5.1$1$1$8(+E6;F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=A274$)1$1$1$N3-uJ|MƆSabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb_P|MeC;''1$1$3!&C38F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=<-12 %1$1$:%&iE|MĄRabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb`P|M_@5"&1$1$9(-E7KNSOgkTY[]^abca_\WQovLTYG;@F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=E7<9(-1$1$2 $Z?|MÄRabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbaQ|MxQ:2$1$3!&C5:F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=HBGOej[ikkkkkkkkkkkkkkkkgXM\bG>DF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=B381 $1$4!%~T:nDuGӎX֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐YӏWuHnDuN81 $1$2 %>.3F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F:?M]cWaikkkkkkkkkkkkkkkkjaXN`fG;@F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=>/42 %1$1 %zR:|MLJTbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbņS|MV<1$1$4#(F7F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=A382!&1$1$~U<|M̊Vbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb͋V|M]?2 %1$7&*F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F9=Obhakkkkkkkkkkkkkkkkkkkkkkkkkkkkkk_LV[F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=E7<4#&1$6#%^>nD~N֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐YNnDX;2$1$3!&B38F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=H>DVekkkkkkkkkkkkkkkkkkkkkkkkkkkkkkeWH@FF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=B493!'1$2$_@|MՑYbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbڔ[|MdB5!%1$7(-F7=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=G:>OflgkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkdN`gF8>F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=E8<5#*1$:&&b@oDdžR֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐YȆSnD_=3!%1$4"'C59F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=H@FVgkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkhXIEKF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=D5;5#)1$2 %fC}N^bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb_~NkE8$&1$8(+F8UkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkiPioF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=D7<1!&1$oJ5nDÃQ֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐YĄQnD\=01$2!%A27F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=G=B[kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk\H>DF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=B383!&1$]>2|Mۖ\bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb`~N\>1$3!&E7.31$3!%rHΌVbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbݖ\|MX:01$?/4F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=N`gkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkiLSYF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=:)01$fC2nD̉U֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐YΊVoEM3,1$7&,F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=T~jkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkXF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=9(-1$L2-}M_bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbƒQ^@1$7(-F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=SykkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkN`gF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=E8<5#)3!$`>wJ֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐YxJZ;1$4"'E6;F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=Wkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk[F:?F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=E6<4#(1$]?ɈTbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbؓZxKB+)3"&F8F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=B382 %9%'|L^bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbPrK81$A37F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=RszkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkM[aF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=>.41${S9xJ֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐YyKfC21$:*/F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=XkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkYF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=;+01$fD4ȇSbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbە\uJ7#%8&+F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=PgmkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkJQVF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8<3#(@*(mD͊U֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐YΊVlC3!$3!'E7;F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=S{kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkVF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F7<3"'2 $vJ_bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbŅRrK81$E7;F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=LRXkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkjHBGF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=B491$zR9|M֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y}McB21$?04F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=QkqkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkRtzF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=@061$cB3̋Ubbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb^wK:%'>.4F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=G>CikkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkdG:>F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=9(-D,)oDӎX֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐YԏXpE5"%6%*F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=IJNhkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkiKQVF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=7',3!%{L`bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbόVwO93!&F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F9=`kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkXF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=D7<1$V:Q֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐YÃQiF41$B39F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F:?bkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkcG=BF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=C591 %jF6֒Ybbbbbbbbbbbbbbbbbbbbbbbbbbbbbb~N='(>/4F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=S|kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkM[aF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=:).K1+vI֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐YxI7#&8&+F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=XkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkZF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=8'-5"%ƒRbbbbbbbbbbbbbbbbbbbbbbbbbbbbbݗ\`@1!&E7/2F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=_kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkVF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=8(-jG4Q֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐YƒQK1,6%+F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=`kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkdF:?F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=8&,I1,ҏXbbbbbbbbbbbbbbbbbbbbbbbbbbbbyM5!%E8gkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk_F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=3"(]<ԏY֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐YՐYtL74"'E8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F:?ekkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkhH>DF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=4$)sM8abbbbbbbbbbbbbbbbbbbbbbbbbbԐYU8/B49F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=NafkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkIHNF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=?05cA2ʈT֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐ỶUD-*;+0F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=T{kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkUF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=<,2B+*۔\bbbbbbbbbbbbbbbbbbbbbbbbbbĆS8#&F8ekkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkfG=BF8=F8=F8=F8=F8=F8=F8=F8=F8=D5;2 %͋VbbbbbbbbbbbbbbbbbbbbbbbbbbiE=,2F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=MX]kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkIEIF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=8',rG֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐Yב[ߝmꬂ첊竀ݛjב[֐Y֐Y֐Y֐Y֐Y֐Y֐Y֐YfC5$)F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=QqwkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkT|F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=7&*fDbbbbbbbbbbbbbbbbbbbbbbbbb`tN9D6:F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=]kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkUF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=@17V;֐Y֐Y֐Y֐Y֐Y֐Yؓ]w첋uؒ\֐Y֐Y֐Y֐Y֐Y֐Yc@2=-2F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=`kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkbF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=>.3_>1bbbbbbbbbbbbbbbbbbbbbbbbbݗ]R5.F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=G>CkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkiF8>F8=F8=F8=F8=F8=F8=F8=F8=F8=F7<`@1ӏW֐Y֐Y֐Yג[vtב[֐Y֐Y֐YՏXA))B38F8=F8=F8=F8=F8=F8=F8=F8=F8=IFLjkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkKPUF8=F8=F8=F8=F8=F8=F8=F8=F8=D5:?)(`bbbbbbbbbbbbbbbbbbbbbbbbӏX<*.F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=QnukkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkKQWF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F/,̉T֐Y֐Yޛk첊뱉ݜi֐Y֐YΊU5"'F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=WkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkXF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=5$(ڕ\bbbbbbbbbbbbbbbbbbbbbbbb~P@06F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=dkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkXF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=>-1ÄQؓ^ؓ]Q8'-F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=bkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkeF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=:).RbbbbbbbbbbbbbbbbbbbbbbbbkGD6;F8=F8=F8=F8=F8=F8=F8=F8=F8=G.3F8=F8=F8=F8=F8=F8=F8=F8=F8=G?DkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkIFLF8=F8=F8=F8=F8=F8=F8=F8=F8=?/5bCbbbbbbbbbbbbbbbbbbbbbbbbY>F7=F8=F8=F8=F8=F8=F8=F8=F8=F8=LW]kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkHBGF8=F8=F8=F8=F8=F8=F8=F8=F8=E6;pUwSDB49F8=F8=F8=F8=F8=F8=F8=F8=F8=PkrkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkRx~F8=F8=F8=F8=F8=F8=F8=F8=F8=C5:mH7bbbbbbbbbbbbbbbbbbbbbbbbdF6F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=WkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkOflF8=F8=F8=F8=F8=F8=F8=F8=F8=F7=]GZ=6E8=F8=F8=F8=F8=F8=F8=F8=F8=F8=[kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk\F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=Q6.bbbbbbbbbbbbbbbbbbbbbbbbQ95F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=ekkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkZF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=gHkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkeF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=Y>;C/0F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=ikkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=?/1bbbbbbbbbbbbbbbbbbbbbbbbC6H8;F8=F8=F8=F8=F8=F8=F8=F8=F8=5YlkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkMw~F8=F8=F8=F8=F8=F8=F8=F8=F8=D8GQF8=F8=F8=F8=F8=F8=F8=F8=F8=G9=H9BNF8=F8=F8=F8=F8=F8=F8=F8=F8=H:>I:=F8=F8=F8=F8=F8=F8=F8=F8=F8=/Mbekkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk@erF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=bbbbbbbbbbbbbbbbbbbbbbbbG8=F8=F8=F8=F8=F8=F8=F8=F8=F8=:L[kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkj>;EF8=F8=F8=F8=F8=F8=F8=F8=F8=J;?M<>F8=F8=F8=F8=F8=F8=F8=F8=F8=3DUUkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk;S`F8=F8=F8=F8=F8=F8=F8=F8=F8=G8F8=F8=F8=F8=F8=F8=F8=F8=F8=N=AT@AF8=F8=F8=F8=F8=F8=F8=F8=F8=89C=kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk8@LF8=F8=F8=F8=F8=F8=F8=F8=F8=M;F8=F8=F8=F8=F8=F8=F8=F8=F8==6?Nkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk>B5:F8=F8=F8=F8=F8=F8=F8=F8=F8=TBD`IGF8=F8=F8=F8=F8=F8=F8=F8=F8=;05$kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkg91:F8=F8=F8=F8=F8=F8=F8=F8=F8=VA=bbbbbbbbbbbbbbbbbbbbbbbbL<>F8=F8=F8=F8=F8=F8=F8=F8=F8=A485kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk'E6:F8=F8=F8=F8=F8=F8=F8=F8=F8=^IGpWPF8=F8=F8=F8=F8=F8=F8=F8=F8=?/4hkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkM>-3F8=F8=F8=F8=F8=F8=F8=F8=F8=cI@bbbbbbbbbbbbbbbbbbbbbbbbVB@F8=F8=F8=F8=F8=F8=F8=F8=F8=D5;kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkgwE7=F8=F8=F8=F8=F8=F8=F8=F8=F8=oVQk]F8=F8=F8=F8=F8=F8=F8=F8=F8=A27|Rkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk4@17F8=F8=F8=F8=F8=F8=F8=F8=F8={YGbbbbbbbbbbbbbbbbbbbbbbbblPFF8=F8=F8=F8=F8=F8=F8=F8=F8=E8<iZkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkI"PlF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=namF8=F8=F8=F8=F8=F8=F8=F8=F8=E7<[z0kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkj"fC5:F8=F8=F8=F8=F8=F8=F8=F8=F8=pQbbbbbbbbbbbbbbbbbbbbbbbbdMF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=%G]6kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk%43=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=qĕyF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=-8GgkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkO(>RF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=Wbbbbbbbbbbbbbbbbbbbbbbbb|UF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=6,4ikkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkb=.3F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=ᩆߩF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=7', Ikkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk,5(.F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=ґ]bbbbbbbbbbbbbbbbbbbbbbbbܖ`F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=?05Lkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk=kB49F8=F8=F8=F8=F8=F8=F8=F8=F8=G9>J;>F8=F8=F8=F8=F8=F8=F8=F8=F8=<,2t"kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkc|;+0F8=F8=F8=F8=F8=F8=F8=F8=F8=G9=abbbbbbbbbbbbbbbbbbbbbbbbbH9>F8=F8=F8=F8=F8=F8=F8=F8=F8=D5;"Rmkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkg);LF8/4F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=qĕyF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=8(-f Xkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk<n7&+F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=Wbbbbbbbbbbbbbbbbbbbbbbbbbb̋[F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=B49);L Nkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk= .*5F7F8=F8=F8=F8=F8=F8=F8=F8=F8=@06,.: $kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkb+6F?/5F8=F8=F8=F8=F8=F8=F8=F8=F8=G8=`bbbbbbbbbbbbbbbbbbbbbbbbbbbJ:=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=3!&gkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk`j6%*F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=YEFiRMF8=F8=F8=F8=F8=F8=F8=F8=F8=F7=3!'s Jkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk,y2 %E7F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=:).*7F fkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk_ .*3>/4F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=ZGFnUOF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=8(,-.9 Lkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk/ ,3A7&+F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=cJBbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbvWHF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=D5;1$k .kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkki! "Tp1!&F8/2F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=H9=篊築J;?F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=7'+0"' hkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk[/#*7%+F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=H8=ߙ_bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbYCBF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=E7<1$&E\ PkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkC +5C3!&F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=oVQl^F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=C491 %):K (ikkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkka 'BV1 %B39F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=\Ibbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb}UF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=>.31$g VkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkI #Pk1$B38F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F9=ӠݦH9=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=;+01$ Yw 1kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkd _1$:*/F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=ѐ\bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbTA@F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8<3"(0"' [kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkP r1$8&+F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=jSOfZF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F7<3"'1$z 7kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkg 0!'3!'E7;F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=yXGbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbwTF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=D4:1$-.9 TkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkL /$,3!&E7F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=E8=7&+1$+3A #ckkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkU *7G1$6$)E8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=I9=Ւ]bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbjNEF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8<3"(1$(AU )ekkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk`! +4B1$8&+F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=i]~jF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=D6:4"'1$*7G Qkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk@ (F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=D7<3!(1$1 % Yw HjkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkhH #Lf1$1$7%)F7 ,0=1$1$8&+F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=H:>ӠިN>@F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=C5:4"(1$1$,3A 2[kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkjP$ *7G1$1$3"&C38F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=K:=Ԓ]bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb_KF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=:).1$1$1 &!Ur -QjkkkkkkkkkkkkkkkkkkkkkkkkhK' #Pk1$1$1$=-3F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=lvF9=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=E6;7'+1$1$1$$Ld Ackkkkkkkkkkkkkkkkkkkkkkkkk[6 Yw1 &1$1$7&*D6:F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=VbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbjOEF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=@173$1$1$-,6o ,D\kkkkkkkkkkkkkkkkkjY@' b/&-1$1$3!&B39F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=h\kF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8==-32$1$1$/'0g !9ShkkkkkkkkkkkkkkkkkcJ2 k.)21$1$1 %;+1F70! b/'01$1$1$8(-E8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=z_UscF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=A385#)1$1$1$/&/^~ ,:ISX^be`\XQE6' j-,61$1$1$5#'A27F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=cLbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbWCAF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=@171!&1$1$1$/(1 Wu $Oi/$+1$1$1$3#(B39F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=jSOi\F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F7==-32 %1$1$1$/&-#Ql !Ur/'/1$1$1$1 %;+1E71$1$1$1$1 %9(-C5:F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=pSEabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb`YDAF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=E7=>/41$1$1$1$1$1$/%.&F\f} yb'@T0#)1$1$1$1$1$3!&?06E80!'1$1$1$1$1$1$1$1$8(-B38F8.39(-3#(1$1$1$1$1$1$1$1$1$1$1$1$5#(:*/>/5D6:F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=I:>oĕyP?AF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=D6:?04:).5%*2!&1$1$1$1$1$1$1$1$1$1$1$1$3!%6%*:).?/4D5;F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=M<=XbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbƉYN=?F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8.3<-1<-1>.3?/5@05A27E6;F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=eKBٖ^bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb`gMDF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=}`W첋weG9=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=hNbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbzTM=?F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=QABuԠjRLF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=]FANJZbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb`]JG9=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=H9>j[qN=?F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=K;=rRabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb̋[_HCF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=G9=mUOݩ⬇l]I:=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=H9=aKޘ`bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbz˙}fPKF8>F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=H9=rXRإߩqaK;>F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=I:>m_ިzbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbfӠmTOG:>F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=J;>y^Uߨ䬇wfRAAF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=O?@sb᪆fbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbm뱊kaLJF9=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=G8=[IHzg뱊̚|g[K<>F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=I9>w[St걋kbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcyۦh]\HGH9>F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=J;>bKJra䭈築rbWSBBF8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=O>@z^Tq歉xcbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbeubX[FGL<@G8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=G9=M=@^JIj[˙}ؤn{_U[HFI:>F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=F8=I:=ZFDy]Tm֢ebbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbk쳉뱊ȗyyh~aXrXRjSObKJ\HGWDEXFF]IHcMKjSOt[ScY}iМ~ܧ“xlxfqafZy]ToWOnVNw]SeYpaxekw٥kbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbuwbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbe쮃dbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbjjbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbt쳌rbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbd쮀쭀cbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbigbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbrrbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbc쭀cbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbg찈fbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbppbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb{{bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbefbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbm쳊lbbbbbbbbbbbbbbbbbbbbbbbbbbbbcyzcbbbbbbbbbbbbbabbbbbbbbbbbe쯅ebbbbbbbbbbbbbbbbbbbbbbbk쳋kbbbbbbbbbbccbbbbbbbbcx쳌xbbbbbbbbbb`(bbbbbbbe쯂dbbbbbbba*cbbbbbjjbbbbbc_#bbbbusbbbbe&cbbdcbcbjv찈fuTKrꪕ 쵋7촌m~b뵍&vvmplayer-1.4/data/icons/hicolor/meson.build000066400000000000000000000003621415227045700212400ustar00rootroot00000000000000icon_sizes = [ '16x16', '22x22', '32x32', '48x48', '256x256', '512x512', 'scalable', ] foreach icon_size: icon_sizes install_subdir( icon_size, install_dir: join_paths(pkg_datadir, 'icons', 'hicolor'), ) endforeach vvmplayer-1.4/data/icons/hicolor/scalable/000077500000000000000000000000001415227045700206435ustar00rootroot00000000000000vvmplayer-1.4/data/icons/hicolor/scalable/apps/000077500000000000000000000000001415227045700216065ustar00rootroot00000000000000vvmplayer-1.4/data/icons/hicolor/scalable/apps/org.kop316.vvmplayer.svg000066400000000000000000000155701415227045700261740ustar00rootroot00000000000000 vvmplayer-1.4/data/icons/meson.build000066400000000000000000000000221415227045700175720ustar00rootroot00000000000000subdir('hicolor') vvmplayer-1.4/data/meson.build000066400000000000000000000031131415227045700164630ustar00rootroot00000000000000desktop_conf = configuration_data() desktop_conf.set('bindir', pkg_bindir) desktop_file = i18n.merge_file( input: configure_file( input: pkg_id + '.desktop.in.in', output: pkg_id + 'desktop.in', configuration: desktop_conf, ), output: pkg_id + '.desktop', type: 'desktop', po_dir: pkg_po_dir, install: true, install_dir: join_paths(pkg_datadir, 'applications'), ) desktop_file = i18n.merge_file( input: configure_file( input: pkg_id + '-daemon.desktop.in.in', output: pkg_id + '-daemondesktop.in', configuration: desktop_conf, ), output: pkg_id + '-daemon.desktop', type: 'desktop', po_dir: pkg_po_dir, install: true, install_dir: join_paths(get_option('sysconfdir'), 'xdg/autostart') ) install_data( pkg_id + '.gschema.xml', install_dir: pkg_schemadir, ) if get_option('tests') compiled = gnome.compile_schemas(build_by_default: true) endif desktop_utils = find_program('desktop-file-validate', required: false) if desktop_utils.found() test('Validate desktop file', desktop_utils, args: [desktop_file]) endif compile_schemas = find_program('glib-compile-schemas', required: false) if compile_schemas.found() test('Validate schema file', compile_schemas, args: ['--strict', '--dry-run', meson.current_source_dir()]) endif service_conf = configuration_data() service_conf.set('bindir', pkg_bindir) configure_file( input: pkg_id + '.service.in', output: pkg_id + '.service', install: true, install_dir: join_paths(pkg_datadir, 'dbus-1', 'services'), configuration: service_conf ) subdir('metainfo') subdir('icons') vvmplayer-1.4/data/metainfo/000077500000000000000000000000001415227045700161255ustar00rootroot00000000000000vvmplayer-1.4/data/metainfo/meson.build000066400000000000000000000010151415227045700202640ustar00rootroot00000000000000appstream_args = [] appstream_file = i18n.merge_file( input: pkg_id + '.metainfo.xml.in', output: pkg_id + '.metainfo.xml', po_dir: pkg_po_dir, install: true, install_dir: join_paths(pkg_datadir, 'metainfo'), ) appstream_util = find_program('appstream-util', required: false) if not get_option('network_tests') appstream_args += '--nonet' endif appstream_args += ['validate-relax', appstream_file] if appstream_util.found() test('Validate appstream file', appstream_util, args: appstream_args) endif vvmplayer-1.4/data/metainfo/org.kop316.vvmplayer.metainfo.xml.in000066400000000000000000000031141415227045700247110ustar00rootroot00000000000000 org.kop316.vvmplayer CC0-1.0 GPL-3.0+ VVM Player Visual Voicemail Player Chris Talbot org.kop316.vvmplayer.desktop

Visual Voicemail Player is a GUI app that plays and deletes Visual voicemails retreived by Visual Voicemail Daemon (vvmd).

Main window https://gitlab.com/kop316/vvmplayer/-/raw/main/data/metainfo/screenshot.png?inline=false https://gitlab.com/kop316/vvmplayer https://gitlab.com/kop316/vvmplayer/issues https://liberapay.com/kop316/donate https://gitlab.com/kop316/vvmplayer/wikis/home GNOME ModernToolkit UserDocs chris@talbothome.com vvmplayer workstation mobile
vvmplayer-1.4/data/metainfo/screenshot.png000066400000000000000000002534721415227045700210250ustar00rootroot00000000000000PNG  IHDRTb~ zTXtRaw profile type exifx[rJDcxXNh|7}~ֈ!؞OC~}O?.|OOˍt}|1a}ˍxb}ܨqn+vSy4OaBvc)d7)o*ƉVIȟD~E3g/S Ó/+cow߯I{{ϻQ;)')/e,xiz䵒 ,7մH7}E5,ʏily+,`#kr+) ę9q3G:xFzeA\ً09Yg'_I{GmyhgkI Hk7IbSOQrȣFKRkyetks{VzBlԏTF+zzҝҤТUvՠòȱY7151XtpՃƘyYg}is,gV_4,[c]6<8PJvθ-vZ Oۥ^-k˹RqRZOUʼܩ~|R/W;md$_u±(ۅEY/0yL5`} = (pZj2'+,Ҟh?l1-'qڹvmulL4zdB⠵hYU~[/OA<P#!|]Y;|`޻+s3ˋA(C݅kck:OS;JzỳOVΘ  RׁJI'ܮzKihixѸE4Jzxc !$+4U$ FYYie˱ e:Bjgqo#%ULs%#^)aBQ) rD:;ܓ+Aj,.,- ߅*;>Ș{-,{BcID3bvCiP wJhjZ3B$єrw`}8k fz1E*m=%^/$NuyFv>R$ESψ_"_ZXJG]qB$P B*iPk`p(CHzH-#o0Gt>( P - ӞT)42ޠVݳd!Kbƻė0<W 0Ȟa]p" pJ?Up)FͣiJ}O$EmQ} _@׭x##pl鋱c #c!,u2fP^jS}.u]65Z_/DF{L!  wUé ˃}[R<:Hx (aJSiξN:Eqc"MbJ3gڐ7̐Ղ8ĥRm4f |<)s #D:V6NVV p.v\X#d83 "VC1\DvH>!>.L|Q~N[ Uf=8 8R\ +?CM47$%9KSwE"$V5q{^A0i8;x̜A_T]]Ѭyr濤0n??BYc7s辁a #}CP>CFCϠ6_j@vXs‹lڀM u]*AC8%Q!faaBL7>H#$TV̧-o8c:ϮApώW~ϩ%;~)?ճ? TGrDC${Ƭ#g?X튎^51t}d`Ol(1޲q}-?B`S$VަUP. trߓ#V]gԄIϛ4b/H sp oriCCPICC profilex}=H@_[*;TP,8jP! :\MGbYWWAqssRtZxp܏wwTcP5H%B&*_э#a(&9]gys*9>xEA xRf>Iз \\4ytɐ)@ӟgMY`Ys{kHSW-Pǻ{Li)rؠiTXtXML:com.adobe.xmp D pHYs  tIME ;e IDATxwtG{RO439g s0` 1^{a~m[{:c0`Qd$@e a b=SU[nX_@_0@ }#'\㜪w@ ĠpBȲS?~0矑@ 1pJN68%Dp *@

@ z70N^禞f9""R$N8aP}oEttt``[j99WS8Mx32[?w*jɒ%z뭷oC AAA+Wsf~r!_#) { 7oެEU|>_$9 0-?…>@Yac|yyyi4j\#}D"[v#!bx޼yBW"ه@ h.Ko`` 'a4MnI0R0 ,ˢ*}八HwRSST*^lnn`4JHBj^ҢAQ"KT*HB!/ Ie!Vl6 F`2L&f{8~X,$&&FDoH$[[[jYYYB?{6af)Slٲ1 s:@aLL/ ؾs.2}Ŋwғ!}}}jX,X, Ü%}}}=<<(J!4 a9RD"b1566LG*ɓ'Q!-/Z(bbb?RRRm۶;w uL&KOO R( tuuuttחWWWMTT*R H$R([n:;;;::Ǩ g}n67lؐ<9$$QhǎUCI @ Je@ 3 "p(̙>h4Baω"xPRRcc<== ooo/--~ϟbR!d[ZZn߾SPP;𔀀3gddLQTEEE99W/]T]]+W?h4MW7o)--ˋ Z)^zGE9g%))iys΍dl63 c0EFEEXwqSV{zj(oP|[[[;;;XEwX,6sk֬(jǎnހNHRSRR|D"ꫯv&TȍWx<`hkk/--cȈpssc;ß"222BrhkkuVqqhGfrz/kځGӧEGGs/^#;vDbxt%0l,&k޼yO=6##CpހT* ̜y ZgϞ~g^j͚5))܀;K.GDD̙3ʕ+۷8vx6lxv'u#:::--Ml۶ydDDU* oxHbYYGhjj_6A+YY2pp6zf̘3Oϟ?񆆆˗TUUuuuI$bZ흘U4[`F#\0vin[7q񸾘 wwwBjii<šC-j6m)z\#mo(hjjZhRԘP(H$|!&5k֤zzjj5ummm 7o=(ssN;&>|d`Wr%Kcj?~_yAQԚ5,X ppAa ,ˠS ]]]e<8doIZh48T* EQPӝk, z˗g=܆+V nEVx-Yu.B习@g2=vq!/Ҟ}YWXRR׿m"~UqvPP A#<~2W\޽{ٳq%XV7bfq|0( Z%Jb͛7ǨN>mZ-kVVF^pXyϷ-ZV!QQQO?n\r~XlYDDEQ%WbbbJJAGYYY/ҴiZD" 4))00p˖׮]g͛i )))30P(BCC|}}}݁aHNNILLpRlңG !e!ABjժ{/)66k)}:_6;;{co /l_Fzbx,Nb)--=zإKܔs̙={Nj|ꩵb1118 7o;v,??g3j@ HN|2Wyd//OaQQ{׿NLLpʋ̹sp~::.<9zj773gh:|YJFT^{X B0fuuuWTTb6u+d2e.\ɹDttBD$yzjn{tjXs;wNߵ*ðgDDJ➠_ll &g}fŊ11$IjꚮN BCd2FYdqww具OZzz:7y؈xxxX,vww;wnGG^/))qbbb^}D Xoii Bkɒ---_|yw`lp*911100zSvȋ)S@M:W@0_;s^^^<O.EDci&oo/We^{-))h=YYY6(*yʔtBqNpVT^^󷿽9eb E|>χl6f6_z饮cǎ}G"(((HV2oYfŋ|}} at^*77uO… jϟ߹ӧO8>{UV͚5]RDFFz?'$$~ѝ;w644b~$&& BaQQ'rr ZJ*Je˖r> 駟!acǎ߸qcE˖-J'\vu$11ᜀnii}ܹspdsΫ<,(***_w=`ÆgHD1BT*Uzz3fsPZ\.|} \8tp\\}霼JY:W[gϞ8wwwozz'/R:Z[[V+ǓH$*|(bŋƽ઩gG?qڴݻw;w~֬Y^W={[WWWyyF^+))|6:@ӟEd^[D.Eap8BCC-[8q]&a؍oݺd2X"((Am:gD=}ٗ_~͍Ϝ9{) =yNpD"J*/?~:k,oZl׿1 h4͕H$Co17\^^!,OQJJHHϿ^ZZ ={'v[vwsQZZZryfL$===GHLLL/M>M$Iŋmݺudɢ]v mNIINHw G g01eqWfYՂnڍeYYwzyyݸqp}0 [} ŋtn,ooPsv札lfI&_QPP}Ν;A824͌=9K'fZ9' 8O_>++f>} wpjj\./..d)PF]v+GDDիW) $Z8NR~~QSSD4m>5k֬ ~ordNp-GAIp }}}g4]Pȹ7JRyxgdLU($I,bkll_"~3X믿;rwfϞ%˹B3TSlii0K$A cUUo, +Wdg1c =<]}֭6/?}iSN87^ ?vG} -hBPutFG \pEucȈ'\í:N;|AAA{{;Mwjjjzz:EH$/'544|6ټnݺHǝ,Mӗ/_~ϝ;M:f|__yswvvT^z jjj*++L<))I,C(6y+$I{`&ˢn BXPPP__z ]]]ArgPL4i$$inkk/,IDQQɓpH$-J^:::Z[ۢT*SR]`AttR*))h4!]BOUH';̙6@i FkD"իW ZtII.7c@ϝ;/q&((huRB,**rkjd_tܹ3fxxx8pBweϝ:uj'_|q'A)S33gn<K5\s~EƂȫW~GN=Z~p5Ȳ Q3ghFnq&Dlٻwc0ܔJSАիWp;l6W6Ah?l6?qq\$)M.\}+/\L,{|V 5+8999>>577/ ޶mEQСûwzn%6tg憆$|H$b$$$)/ 7rD|>_,fjðnf̙3Zd2566 \.ɲ2U*A'L/^⋛\ŲeK U.\Xjz#ț%CjjjHqqq%X̣Huܹ`n񈏏Ϗ~_ Yl,ǽ::J,޸qCOVQgAc/mjjܲekSSԩS׭{j9nnnmmy555tzxxB-x< #h6ee 3g!? Zx@@H$Rl6tued2wڵO?  Jptuu};LfZO<w;anڲes_~S(YYY!yqߩ,cٴiŋN˲,wj[[[ppo``@?۷o߾}o/xqD ôq崴^{53s& E"Wzzz{{{ddfڟ})Snnڴ1%%EQϙ3nܹջKJJ|||<==v;p . 'OtͯaX>_08Ųb1C8BvEӴ81/:u ~| ɓM>ct.3ŋoo5k|^wwٳgEEE4]YYS'(01 jX-_{ʔ)6m5k.[~dɒtJ㠳… 6oPTBðǥKW.]2i$Rhjj>}{キ>.bL}ڱcW^^K&OT*\rY'[جWfN@^g^m۶XL& |.X0UAAAwލ\7EQjj͚5 ,qwƆoDEE 6%B3w[!!!s]QW .]=y/v!!!mBh֭M22-_۷_ bÆgWz"))ںJJ]&fdL T*f20 I\$fO\Oa6M\IuD%ѽ 0 d=BBB83[QRq^D9TBb>cǮ(_X1 '\lqan߾[f_zEnR0ZPPh6G7o8BJvR; ''g`dRppD"jllrpRVV^V~  gftYd`ٸrmŲeK7n| Hg/ ,L={vhhw rq^eYT-fq s766:uj%j:%%y͚USN]uwn= P'V,V/^LQ[?y,sff… D"P(<Ɲ˗ ’w|EDDZ2%%%11QPxyy-_Lվ?\O228c<ȍZ@ zwvk4 vjZmmmm->0yyyPBaZZ ˩[D2;ګWk45kVL VQQ;6|*!P M׷nz˗'?NH^`>i+ IDAT䓱ʺuOEFFq2]]KF4q>>,84Q_ZZY 3Z= ødev>inn溰P؟۷IDN "NML\{U:v}_q_yŋ/~wҥKT*3[r޼y6W_lfe޼fΜ"H(8qP˜9s0ee07fiR'88ظa3,FEE)>eҲ3grx{{'$;O\–naF<#c*wLXX37A qa 0BCCA`s]\.?޿ah퉉 AAAR4<}Zpp0(::*88s-\qܷ^z)/(JKKJ%PϿ^[[aXW[C /8兗WLL -p8rr평⦇M&ӕ+9FB {cGLѨؙ3ϝt[Ξ=1u>l6WTT=ʠݹa߱cgnnuO+!2W^y啟8֍dz/ .Y,3222|}}./v=k5fͶW\g?`T///n͛F?ڄTjZsr>|IV+VݻoUALv.Ce&|.}ݺu룏6i2BBBV^}ʕ;wtvvxeJ/nfp >Ȇ-\Y cYl˖3f̜7o.[xwYԼO?K26l0k'Onmmm]_{yyx㍟{x ˲gf_~c9& P!> ]Zڂ'x"00 !!>66)H`ܻwɓ'srN}\!JCCC7m?yhqryai.,[oҏDSSJJJ/[k׮ JNN%ڵˉߴAvv)S4 ..7HIIϿnXRYYSLQ(Š~_;v #ĉ\6q t:ݶmy{{$9wLP(fϞ)=}ם ;wB+Vpss~_VV'f#ŷ#=<<|||fʕ+EE'KKKg̘%fJRkˮ<-Ih)..ꫯڠ)! Bp[`C,^N)?<2( RsD~~rPHk3iV{]v9b >ښ{~ *00pݺ5Z⮒n ΃wGlFd2nҏ»wkEEEN<9::JHRQ^^QXxΝ;55MM|X?ctHd0Μ9NyDžsIHH$w\x֭>rTf|vajZ#"$y,ifLfy`ƹӘX!o~7+˲&i`E9Ebinnvf bbcccyb1-nڶӓ'Oˋu]n:lժU \(xN70׮=M@S*O>zƍνl˛gΜѣ\qeYn2-P]}IIIee},en6֑ /r7hmm=r(J7vEK%2UA?w=fh4O2 4MFWݻw/_lRgfO>1pjx }ĉzgg[,OHH\)DgϞۨ#۷ؾ}'OaXKKK}}}^^'yjP׿9bdOO/Z]]}l3g O>|ҥK<<30ww7ǹmV+WYWXx*NPS---UUU:2s455 1]tiVV0ǘ?bZ,xbHvV_/= cfFp *gŰ%>K6,¸>>w98 ?(_7{===CCC<<<iii)..޺ CCo{AzذB$/Ƌr+ƑzA*(((((xг?Ñ/׿۷ozܹub{!~^T҃&>|NJ}}}-˵k?%/jkkϝ;G<&bl-0n+زlA]]-\N9'O,//[XݑGqд~[۷`0lڴק5'#pYYKJJ⌚h<{6/yu#>)1Qovϝ;jVVV<7YfTYY0{/L,UV'%% ŋ?QeNb\H[<:tj۷_@Ξ=* @k@ w()Fn@ad ]|r?8r@֓|qeaY 1x{1^ p pYSHd  {a,2 q'p =u2>򢟰`hv,B$9 x|$1w 01ڢ,K4ӴaaG8%Ad%H~"ap-&#<>_&>W l2t6a(1/pu @  \[&!_(Ty)1I5uѠ,fN%I܀V˩ ,^> 7>_@$eip8 :mG[lcD @ -0Y![fxJOx (˲4P9ݝmfA$$@ c?ݪ*/evb!I_Dq,2?`ahhn3 H 8h 1 a6jo_J"0eXOA,d M.Q<>qg8 xj%pB#U,chw`8AP˧jH1QBHӌj EOD^|o6cAȔJ[lV A's8_ABBβ,%*<<A;f%\DnR?q^+ npN;JLni^Yv8hC!H!vGC|_:iAraa̽rÂeYv%RPHe)M@ lvDBTJ3=󰌠g"QfYfhBI$M14C|ػrSG4󄔘u..\;aP-f3˲ćNA ba-x|@j@,S×YÈ(1Nw:|0沖``!ˏރqu\ @ Ũ{k/Y`BG)cp??2[az|2܊!!@ &FdN]0ףt}^ Ʋġޯ%(OM ex;!֓@ SrB!c*ga=wHW#! -cxH偮x@  }7nepCe}cdAόD9j@8CG jGPX%1hy/+sբ2dTɨQ:s~U &= ]{9({sI%C wW?Xp9ʼnx$@Ɗ="I1CPT9j ]ZmAA{||Px[[k;<=BC>az"PձQ|>zl{D߿?8 e@{{ǑcǷ 2EMIN*㧳 RSZAǞ;{OR!v[wֲ, 0LȜ1$Ɂ3 |r !AAAɓ&,SWَ/+kɊ% Ο+Gmv[{EfI~!SZVZVfsH$⁕!֭]td22gLxT,˶} @0's'VeM g_8~j}ō~>8f7nKE ]rБ6ﳩ*㥥e{Sa @ MxT1a/.׺eF657?24),>~6b{%g@Ys>i2 MM{?vdiM>u>VQZv}7eA<$o42,URVID7jq$Ȉ00>TyJ$hJ.\.l]Xt;0`WŲL;zGnnI HTkLA3O]|YRbB|Lԝr$.\RP|+jKWz0wkYuwSHb O~t->6 BUxDxXaQqMm=07͟-;!vw54Xm6>*F!qרU?y酢%%Jŏ &S˖, 7Lў{4":\bM9xM0@qzl. B `HqN`Z F#MӐQH$8i`1 x2Lԛeޠ7Pe"k)l4Ͳ=  $IܮQ׃W!8 Oq[7 I^ M3wJʺ=5P })P[VeNH$J$fȲ|{`aP IDATznc[&P((޿j4AD[h4vtL&HLfdbhL(J%.bFxL*\Bfl0 Ͳ, pH$q7i0\9ģۋS.&Luyc[ʲljjԩSGWvq3]G(b 1 @Ì=A#K9aaX`Wuuuy䝒ɓIR|ɳ$ITU2 ?4qCGRn4ݥ9-ÙFp4562yixS7r%\K;--o64v VM$(2oyYɓB78}w87#ca!!>iGεzr0)&Fu--eUŷK[tz,Un1QBBb ot)q117 oiu4*.^<s~Bdw8(01>V .xZ;ͭmfE,xMNOMTNF{nC#Iyg Ao{ҲN!SjG|Li};hNI+9UwzTOJO%(&e?=~3Qwʮ]/hhhRdRBiSCClVۭWrK+tzB& 🙑P9GKNRZQY|[gZeR=1.fRB|HPH$t#qȲaݯ܆m ?6ţ=E=6YYdz#)?ȵG /C%<2Fɓ=5))% 3,4,8(A  u, 㑡!AjSMhnnmim ljͿQ 0/:"|HHx,I4MWݳۋx$ia&E65OILpK)!z.${ʆJ% nס\ ǧ首ƦfXUtSa\*MIJr vtr:v fX LfsEUMyUM^AE zS;xH'I,˶gxieaNMx|L4fWTV=uܕk,2,biuⲊ7oYlRbsy~l5,H '/74LIMjO`0p'q[q֍[O^1ov' fIrQ8Gw2ׯMwPbiXq f8CkG>as.soKVǫuttDE9-%tvi6P$T*  rnQ,"$j? (pRB|}C#ò%ee>ZEE eR??7۰^\ sr^!BMI'Hfwv_jmV:,4#:"S)aj n7 }x{E9S .ڡd/<,VƖVqaiBo4$Q\ rwdy࠸(_seX"?7M'd9xq@-J-KCK\}k[CGro䄌)inJEgWky9y7nUT*CC]IorBlH` @EuMIyϫ+aX&248<$D"ZZ F 8"Jy$dڢ*w1Eں;:ڽz{},{P】ΝQAR*1f} I侜;5ZnQݝf@H@ HMfaF' S'O:}jwi1 nkm`Y;"8B(JfgΘBD$IYrĩ:?_Tm<e@|Lky-4*|BºƦVfdIJkP'0LIysٟIO,[T(FcB|M.9ZmYmwN=O%͚1,΢3,cnJ%XN{F^-@jR%B|nZmwYUu΍´ᡡzR1%~eɓDB\+_8瑐Ϯ~"-5Ya;rr>ڭwju !A \!-Y0oL  XM5C<}˳woC;{ynޯT*rdo*DS:lgb^508z٘ީQ갞(<؛=BC n:h)j2 COHP@?'  /S{3[i4#zMl 6T^]$%YH!f'K @$Y.l7[3F#ydK%#{{yKT&3=-.֬R*erL. 0ĤB@yaquzBdy96+Mӽ^OVJx3:MbBBS Fzz9$ 45 L2YړQ9&--IBPr؉S, vtuNiO0'zx d޺q}||\cjj(t8 I*#=5=-)^h5d5[9wJ;eRK\%.N l豱qN TNb^nvYkձy}>&DrdEͭm= MB!fՓS9Ǜ’RyZ9EoՙH.fzF ayEH0)\) ABASw j"iYEN!Lv!B\` dqe]k)T%lĄx̋$HL PTJZY;uAj5cNVVnv^ p:(⛀ĔdpE%S8|)MP3D.KϹs8 ]3vL#=9}%^AT*nfhBj%)BD43Yd3ު^k)DRj=^ؘrYv( nA%ujժ8;zfla_?MQGצܾ関<HԽ  }74=HT04Dz԰Yiٙq=}h}-ΝEQT(+L]'"MS2l/$S܍,bԣ\n H$SB }~PDXRaMb "jC}ZE(QZ϶qPskHR*24Me9tWEqݰ} 0RS{&5k׮)Ѕxҋw /B(Gb* U$f_xMsOBqA^%ntlt}=CS(&'&voiQ-2"lԈ&uoJ ofCmgkNyA!'$$ĚM``J1p֬Zr?b::<2>Ndb%12b:PIv!N-lJ&JT&0=R*=^q>\LJ XZTzJ߽c(750mw|Rs8? ??91AO>`uą!1o7WBĺi1MS4s$YO d&iq$w/K{ HC *:H@ӵ2?wz$4 rs,qq} -4Eq<o $iyiIՑ W9 BjbBVF:쿃Eӌc2@9>`L^ICݽ)M4`iHl2$'{ڛ<\~]]'4Jeݷ-=- xr\f-*Y|n9.S]_.ha(U}癀'n y0 ‚CQh>=-UV utJhㅜL(CՐ'0n W"aĄ6њZAI2"9~RT* HRKl\VF:ܹs ˣ zAdjm 6[OoCSu By+ah/qrϲöѱq EQ"x0q!bvtYd贚 (c̿JckZz๣kQ3xZqcK*09o(YVV4!Р&'%U𳀡vݟHġTky^HON6%Dӧ$ |ϝ-gbOд(*L&3 R䧟u:1 t]m]CS MCB!+dr_lvOTQA~YKU9;ua6RZTQΟ?RSHK\F*\8\._^VZ??x` 808HrJ1ZRtuw Ow;w~H~_\XbYAllp%b Au:]NtcN5=QC\(}~)-…yƙu%.XT0EG$TO?}t8% "Y< 5V2 pWO?IQ*62o ŷŶ`OἁP<76!0s g?\ t5M? i! >["ZR _vZ Eo'} r)J508I~=zwM1,H 1!+D[!=1KA_T*i3XGrLYqe9V/$2BH*dan7$% T*I:NORTZ-Ɉ TWx$V N'r4CkF`|><҃\P\~NQAW8sD &)PMh1- p E(0D˜La 2 0-}(Hi Z6' NO!Њs.L& [lvQs2 @t4E L&ER 242> T"\&_24p/4χ-+6(QQzd\sDb^\HG[[>CQy6BRpje^ȃ,$- ,}栍#cUG& ~]4eQx"O+@Bq[HTZU^VPW~Χ&f1_Kj9Q\p^W ľfX\)bҙZ.|Q@YB@"5y))za,+W,s,{%'&)@>H^`CܴUȷ&vẽr}]Ts!JFPn{Śzb""\b0"/!Qx(<]g)6,0  tЂkpM05P/.ǖ`PՖmvѼS_X z% [ Wbr,# w(: B˱إ ."򃠉K/^x&fK0 s,5=7'<_HvɴR& Kt712+] IDAT.py iҙV8|=)Jgz|=ǍCs*6_,\B\B4_^!/@-ŵ:s ^nwŷ yfĥM)9nt쀸?gь9Yj7յdnh.`jkF;8y2i(.ߺ(<I YX T L>#$\  I!DZ$I."T<ljV JIL Qx7X^`!IYtBvN8&\;DZPh! '^Z؆c2GR(["-G~sIQSij˙V<5+u˜B, p .12,@ "yݼz=nQ)J:pTDJ$)^m׏q ORŕ$H`0qĐ$E uŵw]~ !gdF).sI4Dz1chw}IQ$IɨRԔ𪌉{+Xȓ,p^|W敜&r I$)㴏 H(ϱQS4 HoYXkKcl..(B(BQX?I]IR{GYa$EDn ؔoa_x.k]D,0 f P(J!FP^]NT"HI$ 9ɠgh){IQ}b*U*UN.W {ZI|^ct}^B)ȖhO\L'ת!uۥzj a`0A*=>@IAFlnKRGie29EW;rM !8q;nc*G)JTX[f nQI$Ir2#Bީ!2 E@* f&C {c0 f^x`91<~BH^xQ@QHLM!?R+Pzk2"tNAP%+$R)ry^Ag 'b3;HiHhFBR49!pR__55KU3'%9\+|y;)`* $ rJ%x9yATPjz/DRDrA9: fN"${uAKA0Y\gbpvU!L}!.[!xa/U^WBi|Ewa֮@-ŵ:5p T*ENx!Dzq( (( H@E3T"eRv1 s 7aCY~HB$#(Tj d[x.)M3R\"REA WEA9?yy%IRR+*[ u`[x\N BTJ@q(*Uj: 00 ͋kq' QQZ\!>i'B `#n,׺(^GRHm 2LEq c `~ciF"u ILHDZ~1 s]qc%r,' \E$IIe2XVPKy!EqppJ_?.~'###77Wk@#G;wNPr-R_  7yQi^ $4Mrcc޽{)"ѣGO8A]wݕ0NصkWOO JPTWy{1peY6::ale;zw^{---m&B'tvvFJebb+ryQWUU7馛*++y`yq BĒ$ <?3A5 fywvv~'?\z;w|W (+++++PhgΜyw)j*B'#U]]O~ :AJOO_jwߝ,L$Z-08/ `Xr`zqqd]ս@cǎY֬, FFFSPPUS67ΎļQ|+_yǵZ-n>|ȑ#JKK?JQYa0l^`ę>|!{_8e,^QwQSSv łZ!i]BB·gϮZ*&&f!vс,_|?_}ݻwtg] fE׿pǝ>}}iiZ :::T*՝w hll?vئM42 ĘX8S&33{$ B_i޶m[`uuuKK˲e$ 1̕KJc³vl}Lcc_|jժ.LDQܻwokkkZZZVVVQQQbbݻY]Pui޸qcQQhmm-q`0{Y@y***,L& >y믿?w9t8$555d!\:ݾqFDBQTQQÇ[ZZ EH󝝝,ƪA˅)Ra Xsݢ("}R~fZ}9!"EQF1$ z<6Jd ?wOHH>$O4Tu%w)))eY1} vA H& aY(; IR&EGG|>fX$2wzl(r> ah4f|qqFyWvܙ>[o]r0RW_}W^~x`0(??O>~Ν~As}WVVR:LEvw}+zbl߾=999dJ6G?ĿۿLGD~~-[xܹ?G/L[zqqq_Egg /TUUY&Dwtt޽kmm-zqsOKK˕hdRH$V!CCC;t|OFٶmC=bŊ`B'&&[ccc[nڴiݺu999pg?BBo~=/{*z-L&u@Ѧ555~C =O?ϛLݻw+gΜwuV o>†;w9s&YU(mmmL&T*JeJJJ]]]K/q_ NgyGMOOGFhb]:u_~wo#X,V]]o|c^rccF)//EСC_|O裇z@VOw4w]w;===.SN=zt۶m111$CB;::ʏ鲲ꎎ*J*|ʄz>[br»\;v<쳏?׾$R ذaömW>V~nMR$ _K/}fY&裎U`,BSS/nt B|k׮Tn1<<>G}o|#dq$ɸ℄V+4MZZ?>44ڊ2&&&y|fJRfsii~G.'&&\ _~z{{멧T*0WT^^e˖;w}`s}@...7oO?1}a"X_>@:qĉSNmݺ511q4Hs`Zv8Ov\r|z)(Tjn"eٮGydݺu!^ wZmؕݎrt+++ B;2337o޼s.f!y'%%]P)`ΝRB(W~駧 $Ly!ɤ( !yٳ}}}(6 ä_@pJ`lqYכlJry~~Ν;^/b(H(l^`>M(,,|'ozcǎ566wuXlٺu?̙3&)**yZUUok?#Gڵj:QGooouu-[", K_8eٳgϺnZf%Dlkk#=O0>3eA{lA ٓk"<EQeee֭+--UՑ($I5d絵\.䞙~d&++8'%3oL_9]Z[[ xuǃEOOo-HVXz`abAt0H$Bd. XZZy_`0?LNNdMnɔ/_<**%77bN竫˗-[6z(((ؿ}.':Fq  <(v r fWHDOӟ]ɲAV+oo~3$6偌$4ɰBf&(a/ bBVXA$NO,"8I6tnذa!?L&-߶ylDE-W^߾}% 222lْv7lꫯ~;߉;}ѣG}C;;; ?*˲?|M:44$#S2 544ݝyNVgff100`L&L 0 l{{{VVtʜ IyQVzzz233CH$\~L&CN+V|_NKK 8ZЂ"HL&0ٳ TVVfdd\W yjXx`?Ƿ--sifcFSRRO|%%%%BESTT$H:500p- !ܷo_CCCbb T*5 Dr-ٳ' %H,ˑ#GvzA~%BhPG}TSSE;v׿;ClF_P6 MgeeƆ?n{˖-+++ #@.[ _|>t"W` bAWVVZ,Tj}Ϟ=MMM>{/0!44<~vmŒ ̑޲o=МwwNw_\\즺hhh~'FcXS#G>>?i||\fe{饗o Ôš`=44$(P*&Ё:;;Iݻw/((XJy1X0]]/WEy߶97'7?/wiR(EEEEEEsbQQQII~_]yQkkkVh뮻fjJǏiii^#> yQTy督?O=z]wGEEuuu;v,ySccc~7nD~˗? PBnn#`yyFAN:U^^~^s@FD"9p@kk+IΝ۷o˲%%%ySBX]]g~홙g4MzqUUծ]y|BzE"I266K_RyyTƊ 'LNN~C&f9233oYwՃy IDAT裏 Oz7gdd[9}ӟ_ m۶uuu/Tڦ7O$(NLL'8uf k.--_z{ FCw}]<ϻ\3G{ 5NSOUTTر_Fo~ 8wIMMeF*ד$9::z_^^>آy޾He0dfýP !T*%E˗-\`cl c|ȟ|W^ /\%DZ斶'O=JdL;v|_jض`0[N"=zeYq߿vZK!;GkNdǼhnnnhh8;w  ::Çx_~0sն01&MBxɽ{z뭩Ŝ`0 .+PeBRZW "7+s-WVFa4lnn7{)- yMMM(8]ׯYt ؼс򂐞rE^b 6TTTa`aYV&馛n*,,\ jX(DG}֊U+3ӗF6HMMMMM!IR*Kؾ=;+S8! qĉ*˅yyyKIe`w@ (FEege޾eU*  a||è֭X,K VWJbb↛֪TҒu7i4`0LLL ۂakך͋+M_ob0 fAp84Md5kƥɾBIzjL&"`0JZnEQz>++kؼv=Ow!fp$[eO<аjժ&p866fۑP*t:V;}<ϏneA(J* =gĄn8NԄ7WTW*r:ccc>L&&&&}>A hZN7}IB#ZLLLH{.khhH#xl.8$r^iaq@& 0:::66jfsxWff{#)6/0/hllT(!:B(½VvaNgΜ88ZUTTphhjZ|> tyyyߔ!ٳlj!(J,_*t_x<}}}mmm)Etf9x:}t[[y^.gggdՅ0d*((()) ޲ ===ͧOH$_#1/ Ϝ9'"999EEEIII!v: CCC,rJJJf7Ng[[ۙ3gΞ=iӦ(CCCuuu~ Y6>44sξ>L!A$''oݺv"ƂҰLrx5͓O>iXB~P 477ٳ`0<ódYرcwNOO'yzxt F]2Y&UTT9. O޿?07o6ǝ={v``;LIIA7PILL\bT*xGoݺuHl[]]}-[ u+"˲â(^߿_"TVVzǙ3g-b2?oZp8***驩#"'''zȑ[jѣGz׭[ Cm6[sss]]p\j96L۷oW^ȑ#6m˖-j^õ _>==}&sj|>Q*{$9>>~̙}]v< k^"*[֪*ł.x֯_Ϭ777f񚚚[ AB5af bccC@h5šSN$yw&''#7bdG=~x\\B $[J@x066B2?\SSzߚSSSy:zmݦVj5 F$ꊊbbbtbb~||; NHHP*8zb <)))>>>**JTKLLj|IMMMyyB@|N:o6?g.B'f]we2(EiӧOoڴ ͛7¸8Zk4 n>|eٛonٳgg|>jmkkCmdA0LBViUH㢣fYIHHؾ};Z8CǕv܉Dy!]]]&iڵ?ZZZ*** 1?AhmmKOO~1˅1!!;f%?V9fZ^|`hooD jr =ZiӦx ??x((P_PPVg2yy^"3 äL&?::q\$y[[,,,X,+D"|ǎq{zz:;;F ^`08vXssƍyoll<4PNȑ*_|A+#$ɀMDQ پN3ϟw\EzѸ2^^ 9E"ÙDJQ"q\KK AYYY2,##)33sU.cRTTTSzGj===f z!n AQݽ{ne~T*U(۟9w\$s\.S(r|=::y,<'O<{lFFFqqLf 0 㣏>0L4M#U1]Xֽ{EVp8V <[a\.H (ݭHE㙘H$Z6Nx<.K&)jLժTn۝NRj#E[ ,"KR 8h6L,ˢh_Jv*z>L&3L(!rh4655 @d7x^eN'NP$G}}SRR(MMM d2FP(f7vP(Ekdd$==dee9rpHҐ}ryAAAOOω'222)9ǵlut:fOC<(斗N\revv6 v좶Bl@^|uuuSSt\$IYf >@^WUUuvvĤL&\a>sBqDvuht 233S"׷NbŊW!+n)WTjgill49ty'nN$IZ-Ba0LrrbZvZjf;}too/H4S\\L4rEZNMM?|(?FFF|>2Ri|||aalieA.qԛo9>>~&AH'DQliiyyy4MT*UbbbcccssիG oPYYѣGO>zjPαcP*P`gtLZ([)+߯a;4.lRhnfkjjizŊqfm```xxСCZd2$z[[[nʕ+SRRw Efffooy!"ʞ <suttF" rnXtRá(jӧO겲+\|>TK#Nb`>hbӦMmmm(TVgff ={+x·$M6?~СCDt\~ъ:G蕔ŢT*e2[[[EQܺuLe6N:%/ jfhD䗢i://eٲe/~$̒ݓͲ3g<M7ݤT*紪`s-1L6lHMM'Լ -4v:^yGq] ʠ$H` 콊MJ5۱kqr&7N6$gSv7g%}M8Ǜ_eǶlj$EJ,;:3,~ Q&Cə{os{8OߠtQQQaaX,}}}+++>hj8+y$._<::zXQLlMt\v;A`X"/,ׇvލT((ݾi{477W]]t:9rt40lk9N$}-.VGFFl6˲EEFF455 BTnD"j=*qqq(ǯ7WF T hkk Yo\bXnYhɋ^ŢfffD 3T EIIɇ~xƍ&''òb{c`~AIfȷȈv@B@ HNNCCCmN8sz#a8E**ɠ ,q X0Z0??Mܺ})((DjJiii_],:Nuѫׯ_oiiݵk E!uqqqmmm׮]?hzzʕ+ȸ' y/rnJHH:11!Zmoqd2jT%ނ;+W~?;;[__?88Tyu&%%b'n_paddbn8h7޸tjξeSyA A2n"wϹnvn < @ɓ<ϣ,GFn@i$Ӊqm9188hT*UC8szP (,,,));bbb:::|8Z uuuKKD"Qvvv}}}{{;J*ŤV"##gw&+P-@?t.--9V299Y__?22rС-F".(--Ct__ؘhMvDGG޸qCA)-6B(v$RNCID _8{"jjj,ݻ;y<.ͦP=(T_fuwwT 2Gxsv'uuu!!!$IJ$Rf0 ˲^;AAAA\ss3a3ŀaZ)--7,臸ʘ M&SeeeHH`Fc]]ѣGQ+, %JTP,W(UcNd2EEET޹FT򡨨kSjkkA^^غAT$::M&Scc؞={|K^h4TfF$d2 ňrT__?==}ȑ͆tޝAU `nzEQԞ={"""BBB6srȋH,va'Iܱ8ve%p.,,tvvT To>az{{Q=˲(a4--ͷPSSH$B àNJuao(?iooGpH$HPnH${IMME#<<… W^ (t$%%ݻ-xƍ '˲%%%".Poy///GٰH?DbmSTHFeA$9"yw\.kuuðwyG( ݻw );vܹ eXHܽ{wBB/ Jh/ZQQ͑aYvaaM"*kjj㸥%;::9Φ( BH"2!UVVv\7o  YYYAק( $3 cv{dddeew;4XSSc4Q4Tf;8WUUmXWUX,žEfЀTH\\܆O |rb{T&c$)Hr獀qNM(Je!`J@ U"hfZT@iv+Wq<::'DoB|||VVV\\lX ;v,77whhhaafY,Di0ݻ7--h4NOOl6&rss}N𞞞ɥ%ǃ ez_ ѱ&t:P +*nУGˌ Wե@H4n<e sss( lzwgm6X,@25P.bZb8!!!%% IDAT`0xWֽ@)GFNOOsVQ/D"`p\6 6#^HYs]!zןa ښg`۽a AITAQZ[q|7!4`{ Syv9m 2%UJ-9t\$x-}_Woq~A}sJ=Yc|=oۭH=o `f2^~#G>|[mc~º ~- poS̆lez[|#a޿]߷~7+ I0PR%@㭣q_Mnx/Hq۬.]bX$HRR0p 7cnv.EbJ&)-* 3mV3wڻ?w+M]y֑w9[a@q3nֳk%ȋ킘]N.D¸t<'B!AN`6m00 vc8FQL. !M6vDbD*$I8m3<鰻ʕJ1%y10 RL* *8A@ vfY-I ; Õ9aw.J"B38 B\!J<ȋah TF ؎ L7 1%/h%ى~ C":v#nf#IR"S,-qvvbDB޻L"V+˲8T!=ZuxP,Ф<\>HJJJOO|͛7/]sƖq$Jq_^^'Lw'O4?Ϟx≰{xqnrȑrm6˗^ַu)J)H0>[׿Q*tƍ~;O΃˗/ƣGO?׍FF)++ۿNx(g `HOOWGQQQ>hiiTKKG<: KKK_uɴ׾,L XeYv@ò㹥8իvR*AAAðׯ\ OGGg/'x<6{?~o57vq<###**f罷DE~|k7,ݻw _hjjt~iFVիW}o/~eeekv{NV(###FQ.=z($oܸo>`|ddS^?|GG qEEE'NPT~,ϟ9spk׮10lzz?)˲'O~իWNgppTVV{t$Rrrr*++zNoo~|;~#v_~ܹIe)wjL&qoyaVWWϞ={%b8X,s566`&+**M_^^O~SJgXp ۷oQ|òd:s 0"HVUUS93y>**W^y%///<˲d2|_NLL$yCCCQQQ\re  7vZ~fsMM/t:}w} _Bee%0aξ替կV*kkkΝ{.OOOr^~㚛O>|ppBp\.\hll7@ӟ5<<<,, Ͽ{'O|5sssh9$`X>sg###X,555?n׿;>St:|g3iiiN>W__} ;v,::z} \n0?|__655!Crr2EQaۻy X"$%%]vgeee[NsqqNHHPՋ|MJo~YwayL3!Ck2ϟ?;&8_vd2UTT<(@Dɓǎ'?a{{{kjjΜ93;;+*++k#]]]}_|O _YYz˗.k׮b*j8???11Q ?ŋr?B@zd2?O>YZZ 0LgΜ~Ʋ /S?~<==]+Wwя~~9TNgSS?Oo(""B$\W_}'?ILLfݻ5:::88k^&aFs!IvjjԩS5@ (**WMĈLJJdַL&hzz:A 0O>>/..0.y{.//o}ˇ~mUUyJ^xb\\\rr~fϞ=?|aa!rtl x7Yu4Mu\6mddwޙ׾p!22299YT~7L(s$I+|Sz7:!!X˿K}}}~~y/kTTTbbH$zFtll,accc/Ҟ={>WUU"##xr,MA 99ѣ]xqrrðK.ٳk{?l6{;00]RRX^x<~0t:4M V;77wd2l~) [\\C+sss.\(..>t_RT*ܬyj 111qʕ'OIcǎ%'' }:>>O'%%%666>>~wh4\x… |wsQAd2+@w^Vj4Q|LkkkJJc=gB#fRH$ PTMNNq:UUU$yȑ[,x/D"~ݻW*occcgQfggWUU7j」᳟lppp4H\.0 ~ot(geee`` BA^^˚w_Νnoo?qDnn UWW F377g2&&&;{:{zzX> xbJJʆbPeYvrruܫ\.y$t( k6ggg1  w>hq'B ;8R̠$NV_q ~_WTI$^6!/?BJUTTT\\R@^x<7zkaaĤĢT; _׿EFF̼zD"QZZ#<[o=SSV \pf|+_ygP/n?sZ[[?o/djX,lkkk!!!.bfdٜNJ4M///O_,J{geer% ~L4 EQNb/ x8wP 4ԩvcyP_AraȲlIII|5Ed߿/'+7j _S銊233~锔~CPmgjx7| uh|[3 snTc[ܭ÷_b8--MVwww_v~&*u`vL Ö/_\\\WODDDb.\0 ~}U  >c~ L'JiZk(춶6 GSSMwB nݛa ys?O~p:wtIA rss/:u<2{[AP$$${/_+((HMM {innIII1 @o>^?11qҥP(-++kjjn7*ɲl]!ro~+WLLL5{{{??sOHHH|||ff]vmaax< ÌȌy"Lwyi.//?~hnB~ĉz mkDzwx j+**k閖ꩩx/vrHLL̝z7 _G-++S-,,DEEݻ6cvʫUVzW^u8,޼yaCSŽ4=>953vkU?z$\M Yؔw}`0۷/pL(q7n܈ s555CCC.]zꩧ<;ͼGhmH$~_:EQ """"77[Ez-nIIɿ뿾7n8<0I^x㉉E G]SV=zT ={7/T*g2_ʦ-m>D՜P(,** (X\D"W_}UPʵݻw!JDEEeffv P,-,,8>00|0?%ݦP˲o]ՏaXVF=>Jpœ·?jkkw%Gq\}}}uuuApl.{GgOoWo߮GϋhvzjmxQ^AQTzzH$3LALLL\|]2G>qÚnϡ7o>~UrbqrrC:,A333խV%Hl}}՚TkkkccNyP( "bqqqbbn ɉǎ=dHHda6:;;eee;S{!{4:*ᱲݣ==H YYYinnnllDԭ={DFF /;"HUرxLՔm9bcccss3*>+ Q>>7$Ib ++*23)z$IP~p777wڵVxH$EEE%%%~b@^+,8ŔmX50x^ގv`P(EEE"2ȋ{,,X'J=2;; ??XaxaYvllqjuYYYnnn୤A^>^`lH[ǑHMM}+Hʗ_;$2yXX IDATh=E511E\\ܾ}FT /pqX*KPEÁ=.++KNN~P'c~y~Cem?::uKEq_ 6PQ BW@#I~oم-#_z Hm|ѻ7;q&<O~! <`Q]quð[~}50Ybk8> W^zq9zhfffUֆxppm3qnX[[0,444###99Y*6a<00099p8RihhhvvNŁYAt:L&h4IIIqqq"#4Muww/,,4-5MNNzr{zz=JJKKKKK q8}}}CCC+++,򨨨07n{||aӧOoqFdzn2l6@ jYYYxVWW;::&&&f3A&+++11Cqlnkk+***++_v߼y>Hym)ؘh\\\l$I*$B+2뗗/Q>!#GlQyb9sfqqQT>}ZT= ô477>n4\=Ns||~bbeY{AJ211qnMrfB}}L&H$4M={6..QQQQu\kkk"(22R$!m b}}}333ggg7n{yybtuunxqm6[}}"2@^ۚЊ;;8^XXXXXx'\걱`3::ZSSىRѴ2Fn{pp&77wC#󫫫gϞe^+xNG-PE"Ѿ} CPPAsS___[[(~3ڶ={DDD`*twwWVVzVF)--E2kuuƍ.\FC_SSCDBBBօl~޽{ % Mh#iZL>+++~!AǎKKK#IiXWW(***6uP!W@\Ѹ`BPBUaX+))B=00  6:dJdf```||^Y6*>燆 ݻCBBpRPf̌yyyQQQWH$JIIy~bbb˲ӫ~$ccc?#G#'rrr233VWW<11144j{gϞ7o.--y#233=&P_"##ÈE222yݻwo}eٞd)JOOt\kPVWW2220lhhhnnn3 EQ?vXVVV?caa!%%%<<<-===99;PADEEFDDLLL8N^{<η y~rrrqq1%%%33388xjjjeee~$Sׯ_Wշ#^ۚ鵵5Nvq88t:d&''u:]ppM5q}}}V5778=88866R,0B>j"E2M6eY@mtDDEQ8XVCBB +E YG}ԯfpTT^@ HT"#r8C%;; an޼)B0!!!<<|~~~rr2%%qdz$ V@ADD`B`rrBR+ z ggg}yeee~~^*j4V=H"!EQw\1㸞333 ^_\\ [ ¤񮮮4/L޼yeٲjx# /-5իWv{__ښJ?E__߅ }٠-NlD W522ݭT*ğ"aHWW`P(͛7{{{,ˆ榧#tD2<jv!11*J(ym&\Y,-7LS*$Izh4ϻ\.ٌQQQ HDK W\y####""Gl:ɄI6ҥK,˖BPffǥR)˲ +++Al SSS* kv; Qp%Z,.t_&&&VWWz}-Nf32l R<fCϏH$E!ۍVRP*M 绻bbb|G C1 D)sssccchI<~xJJca֎䠒H$q˪(jݻE"""çSSSeBa||^7ccc hn7Baaa!d /㷰X,mmm {W.h޿AAJm0fO&$t:J!p:,!k!JJJt:]KK@oo/GDD$'''$$nߟ_RRJY]]JHH@.}ǓqA_wjRٳ qCCCUUUłp8N 5D"A /l6[{{fC.orPf8.xF-$QYYy .*Jef3Iz~~~R/};rOOO8qB)˜xPwƥ% Y]]eY^P((bfmmm``h4\ m6AZF8DSVV(]m522vv9T@xIIIIHH 38eI$o:866f67,ւ999.QT@)-p_?6JnB kkkFWxIQDT*JSSS !eѹ**==nֶJҊ aΞ={%_St:e2YDDVF7" \rERF `j{v4t4V7 7a=11eyB7nǡT {,`0y Ɠ$p8l6EQ~/w-n###~H$DJR$&&TWW߼y322 -G8 //obbmvv6<<|8-ԙ3gweY~ō...޽AڼyA =9U{l="l E1q,z87H.$''tvvoEAJb ?rLM(>oBSL388XSSag"yKP_fn7 '4M455i4"s98+J@`٬V+J!(ﳼq^BR ;z o%xdffƴ T$P) jB{ ,qJUXXX__?::R~ /I8αϱ0r{wd C ]hccc(㖦͛ ""(,, 9sssޡo|ñ8aA_UU~P hYigG[[[CCCdddUU֓oyOҏd.//122:4MOLLLOOgee_AÇߖb3EQngf}u_yg<64 ^Po߾B5UoB!I4x؝]. ;$nl6OMM!'fdeejxl6[kkbzzzhh7Mqyyyaa?ϲP(PDVxp+JZ-I$!! LOO}I~MOOz{rƦbbb*UM߻/_LQԱc7&$$ f=}xx8%%E7tڵGԾ[ 7oNNN^,˦zJ$U+W233+qȟ1>>_ 4onn+***66vfydddffEl55hsKKK~K.d2hb}l6dq<-- "J8"~˓RRRv H$Eni@;MݴP(mTC}}}aaaQQц<###kjjΞ=[RRB&&&ZZZZm~~wxt:g%<l陝---TM:;;"##R@ @222|A^^^HH@ @$))[qhha&''ڒSSS7K(p8]]]uuu6-11i;t^VΟ?K\KK JP _@%_|B˫CЮȸ\.FD"!BJ$ 9I ovqqJBRmmmTTTpp0Qimm{MMM*^{M">|u0l~~h4a~/h#P͆#D"Jn ZBӴxTyz}PzhX,. euz0nXÃeY;:X d4D&_>|ݻQx V2Z2@ F_qbP}ݱX,ލEBXYYA1jk6^e T*zm6@$Q酅CBBR)MKKK_GVuqqQ$bRM`jIT)ίfUX t˲333 DFFRLi8s\REX, oԔ@ `Oljqm0H,(X, 6^yòn7M\n0^* bMxy4 $/9RUU{AL  a>!cu$< E"L!;b6-K\\]@^l_Sb4r1n7a9m`$IP$(H_[[y>%%@^<Ƞ<7$2v LjN;}4oȋEg8WlaAQTNNZ vpg0 /@^ /y  /@^ /y  @^ /y  @^ /y l/0<#ډpM\,xpnbAA"EDb;e~n0 ñg[֧8 E"\!qȋpmyP$(HL %3q˸ݴvq 2 Ixl'p\AIα<t:6 B %ȋn51S(U%)Vv5 Lz<qLAQN8.(BsagY<ȋ 7M #DHLbeݴ c`[p%He2R;NXLiaxg||w -++8]<^.///@Pܳ ˞?~ttwq]wXJ@ @jHJ؎H#{ؖco'X/%bdG騐V;;H(DYm VIf䶮 IDATьw{=sJJ@^|BD>yT^|̙?(..ϏٳgrOKK!ivwCC W|vV駟~no$ŋNl6swxmaaꫯ5MHHHffիM&$_\dɃ>Ȼ$%IoCBrR<{?L&[ZZvsd/~7NMM>.1yWryssvww;8ZpCCCz .jkkm6..Z---3\.WMMfKOOokku\$ꈈ?"1+4MxxW4$wtt y^RlXoj{^\R’m``f:"DFl&111,,LLnnnPOL&x>299)N_+@^Sg?{뭷233.}M6]x1`Wvw?byqĉ˗kZ\jժ~vϞ=ef^ko֣>j6ݻcc_~͛WZۇy<ݻwbDDƍؖ-[FFF/رc۶m2l…>//\.WGG޽{{_|1,,;Xz5kRSS}׻O~>|8 /l6[mm￿}v%K_eqj;uo;vKd2VݸqT{.$$䡇ںukLLL|+466NNN>C#$I/lRTTT????t===۶ml0z}FFo뵴 [n~_%''[Ç7yx≿ۿ!y=z?/}fBBÇ_|žkN$ɓ555_җ^xᅄ;wرz||Gm^z饗^2LP(jjj^y~UUU7s]wjsΝ;w.//{yBCCy睟mmmO?m{ s[^z饯|+_EXH400455m޼9%%3Ek4˵|򤤤|u n׷nZZZ|'99YKT^^~G?ڱcGDDDjjjvv/l63<|%$$D*ŋ/]4**_^bEqqqXXL&p+K/x衇L&Jr%%%/=0G&)'|?}АL&9qĉ'/L5WXXXRR">Ñ&&&.*++ ŒPU,Koo]N}iX"""FF1L?p||ڼ^P^^~=䄅t:N~l{s\lllHHHpppPP=O<իSRRt:`\vO?-Ănvr555>~cǎw}ݢ}kυ\.7YYYQQQ&I/~iiiMMMbl߾=..Pׇ?cvv#G*++`0IIIaaaAeee=裢zzz{gZ*22RөT*N`oΝ^z "d111+Wo~SPP^]]駟NMM_1FIOO;^{ܷhɓ'O>~YgLMM566.YŋSSSr8:nrrjQ_Jo0VАyٹr˗LP*'ܚ8 2\Lt]lYnn̟X,6lxm6AqΎ82p;w,c>|3gp8M6=c37Bm8;00 Iy…E^: UTW~'B /jڸ8L6<<<::*&&&LMM iii;v۹><j:O'ˍ8쿄T~~?|+'O8vئM羑˗ܹJ|w8mmmھ}{3.v;΀ш啮v! 1O9⸏z׸>wo|#""!n=ka$%Wz^WX ͈׌!ji >'t\uuuSSS^7##\Ύ&w{ܶu%''G++Jsss7|S&]V bLD088^7337t: ,+W?~W^Y|>FSRRww?϶m622m6Gɓ'9@Q("##|ɧ~wߍ,--MLL4L ۶msݷv[iiU^ڲe?oT1eZM&W>Qz}nn`8p@CCBx޽{vEE^|CC.W)}}rfzZŪ ^z^_ ꫣcccַ|s?~l6oܸqֳ3|cK.=qDwwwuu>eAxw <ٳg׮][WW?B0fyӦMV?ɓ'-[&IRssov'|ry5##įG.^899Y,^'i4~}yyy}}}P(O=<09}?Ͼo=z.((zb(hŊ>`dd$oATPթjZш/]TYYt:/^<#yY \ӓyҕ+W,L{+*>h4Yf߾}ׯOII$I.))X,sR\n{ظo߾%Kj1h4*ʙG. GEE=#%%%[n=vɓ'#""/^o}blٲERߔ8r "55__{{~͚5$^3Ϥ]he˖OڹsL&X,֭w_y@PDDD\ѼBa0.UEr<44(**ڶm[UUk6===<r\TqBBByGy睓'Onݺuxx8(((99yʕ%%%, ORvZV{)ߡCҥKoV_ݩwRmSQf?_wﯜ]ӥ.^\|wXv1?2==mټ^oppttt /nÆ b59LLLM&E;11!N 'LNN_ ~*z(`Q5==xBj*JpSSS$i4YW,_ϑi})~N xPo37$Ivtf2uNPsϚtc I5Ƃ~D$*~rgzzU #&̫TgIJz@nqvEhZ4$ 9rG-_<&& |Ԯnkl:~Dyy{1]V`0|^30zښdɒWaTP\nrW({Tճ>/GCU*|U\.u fLW8H.#rr_Tw)90T=A)|/GEE\R=zp8ӧO\+W}g.sMJ)?xk].Wccᄏy搐k\nˆ(//_zv{ Vivݟ^___SS#Ώ<,5%%%-ĥ=:<$IxY{o~~^ZZ 'N~i4}sw_VVg?xIIIV '/nx[m޴qҥ A&gm x^ f66688XL&|wիW'%%2 nM**2h6mLO7L7"}◾d2IFGG?~!ɔJeAAUneȋZJV5筩X]Zh4sCh TٷoߩSĵ|[lfyqmu`A~Td^^4((C!Y={Jd0JKKnDT>þ"*j:((hɒ%eeeZŵ y  Eppprr-|crrgll#`ӣn=t\cccvr Ɔμϒ$twwT+:b%9zó>q)I.]400`<Z6[LiL颣g>|s….xƔW$IpOO^ɹ6w**88866v+Y8o0bbb~$IcccSSSC\=222::#z.]tfs\ Bә戈Y_TVpzv{}}j3 ə㳍tR[[[HHHvv6Gl?9"##+**> .\__/ޚrnh4F&or^H_WWq%_ b^]]]sss||:7xEFF~,GF[ZZ{zzN8XV^^wq8UUU===^ri4ą .X$ippŋ$nBSVV{v:bc655EFFl˱luuuYYY3;<<|&ѵn[\QQQRRܷ!^SSSbj4,YV\.R+,,cᆆznZNJJ/((V[[ SSS(/<OggomZ#""bںgϞ9СC\paFFyݪU.]ˈ={dgg/^888X\O&x Zbo: IDATzNT*=Ooo3gZ[[.*^MOODFF\p#""`8ql6o޼9,,LP8q̙3v}T 6Ivȑ;w꼼|v[Nla̙&t:nwwwӧ;::^Oܹ5??TӍ>}رcbreddرcjRՓ'NTiiilᥥ!!!bmcǎڵKtdqlBvڎ=je2sNf3]^V.,HP(O>;kjR[p )jdr<..;TTFqKvE^TWW?~ŊAAAo.=00000p? .k&&&>CFQӉOQQQAAA?z$IڰaCJJ󏌌h4?~xrrx~j'""h4n߾fZV.{򰰰۷gt:+**4Ҳpo]쏣E677'&&Α6l0 z^bBCC ž} SRRCd2F}jvjllLOO\^^ZPh4~:**JPTVVקhnnnll,,,۽{ĕωI˖-iiiY|wL<5mmmaT*FFFAzO===K,m(Vp¶^$")222h4%44###bYRYVVb N7444vV[QQj5Mwwmjjĉ l6յgggFh|/-zQ;III b||\ !yBREDDOR*jF6L.dqj^Ś7tDGGzbttt>}:%%]{{Paaa}}=o /p oolooߴib}r;ϐ$izzexxXТp^tooB𭤫P(>{,IDCCCzzzRR>vXggbݠᨭݳgϊ+}?>>>~ю5knrTWW_ppLC|ݲV・K.Y,cǎ/]tփ<TVVo.Nt:]zzVjhhə**66d2-Z?Vc/^# |"3l6qxK.UVVvvvFGG'''۷_U%I=j={lWWW^^… }}7TpE---Jbh4Zy ',,,m6[UUաCt:]LLVl'Ox>.ɌF̣N&22Yٔdn{hhQlMLLZ L/>OOO{<q\ܹsbBFDDkoow8Onh/^싹k#ZV1WRW8+**jƼgfdd.q?l688J< / u=$Iy;ӧOZ`0SF{ĉ!z'N8wԔJZhQiii8UG EHHHJJŋ;;;.\8-e^ogg|+r\onnb``PVuAU]]===]QQqػ1J%tn2n}El@V{$uuu36tZ,X+Geffz<q^666=zTxrrr.]:W5Q\qPh4Z,+W|ZOiiÇϞ=b ###NX,W:T91S[[[RRRnndG L&xE7&&x…aaa ҷ~u…h&)??ttgO*ŋ8!??:YUU%fTn10O s䠘'xܹ ܄.w(A.P^~ڵkgML622rى˜`2KJJRSS>sXu8SSSbӣ7o5ՙ ~I$?ŋ WtSSS/^_C]t;Y{p\.qìٹo>XQQqgT^Rv}<V 9zYiLLLLL힞<};#,X;F3Z,rl6H[[ۉ'~|b\ bSS)zCCC}}}>"\\^^;9sfڵ/^[`t(9{a/ga|lz>ľmll#cqjjjrr}VjZ6<<<::z||)<<֮z---SSSgΜ9w?y<̋_vm6ϓnojjR(W8CzKL\.IҬGdJ2bnU߷/VT9nӞnnV*U7tFxԩ`1`rr}pp]|||NNЮ]֬YI455e4$s5553gΌ&''Nj;LZUb'!>VD9Ήtm0vHHHX|\ᶶ6$f 8pZ… :{ݻUvrwuWNN8l4==}.QPP:99)֖bA0m26n(dՓNs``vo߾].vuuuڪ.9R8000/j_XJN%B />r`4.}ZT&匵?nmj6hFͽNárss333G) ###*****117 px<ˍ]6??sddD촴ZmPPPRRRFFNh.>Jt ӳNka)Y_ ",,pEOMM)ʔLyYSz}qqqLLLCC덏OOOߵkSg\.d]c2Jdd]wݕ>11!FIJJn2&==cΑkqLh4nl6'&&feeZ+++tb/xT*x~O~j ElllLLLFFFdd)v=11Q4PqqqJJJGGŋYZm4Ⲳ|c!z*7Dgܔ :\ZZZnnGXrdZhPRR\. L_ YWn9bvĸhzI( '$y=5=5eO՚`\j~GBx_'ܯ?##fyގ^ɓ'7oޜH{P&.Gn+ݘkn]ײP7>^|hu:\ntاKjV(*w.d2Ix<.te2`05Z ~$=s\ rd'&&z)sEc9^_v&&&"##.2rvKkk8r׆-@^j4ZRtrNMNzO@BPT:^ju[i~j-..U'rsٲe'G-xpğxG?#ȺJ;lttt``l6(B ]]]fYI400_QQ1@^lkk;y \.Z e+&Vv\b*RV;`^ ; /y  /y y @^y @^ / @^ / @^ /y@^ /y@^ /y  /y y @^y @^ / @^ / @^ /y@^ /y@^ /y  /y y @^y @^ / @^ / @^ /y@^ /y@^ /y  /y y @^y @^ / @^ / @^ /y@^ /y@^ /y  /y y @^y @^ / @^ / @^ /y@^ /y@^ /y  /y y @^y @^ / @^ / @^ /y@^ /y@^ /y  /y y @^y @^ / @^ / @^ /y@^ /y@^ /y  /y y @^y @^ / @^ /.IDAT @^ /y@^ /y@^ /y  /y y @^y @^ / @^ / @^ /y@^ /y@^ /y  /y y @^y @^M @^ / @^ /y@^ /y@^ /y  /y  /y @^-H09ݧo34#$d8e.c&U6TImʱ6l?%8v l*d{@\#S22جdl %43};u%tZQ[w} / /y y @^ @^@^ / /y /y @^ @^@^ / /y /y y @^ @^ /y /y y @^ @^@^ / /y /y @^ @^@^ / /y /y y @^@^ /y /y y @^ @^@^ / /y /y @^ @^@^ / /y /y y @^@^ /y /y y @^ @^@^ / /y  /y y @^ @^@^ / /y /y @^ @^@^ / /y /y y @^ @^m۶yyW*c/ۢ(<\8/2كA 9<cxB0]T/gYvGF|l?B!<ṔƼtL*meٱpZ?ʋLxB cﱙaB[pFlBap:'xzWjp "Q?2] zw^Q)bX,$IyI5hj 8 j$IP(JB0cp#dDȋP^/MneYt:Dg 8:őr\TBFJPabnyEQiZf9!/HhVUjJ?& L#q?DjZVᗳVK^qR$IzR)J{`aOznh4^ZLדp, ,FFFjZs&i&Yi:33jv6g@qOLLBP,X022$|m_=,?I0n8btjE^$X\jz=/HF\.G:$˗xjCEΝ;ui6 oj5MF1yدjf^{g>pUW]yu]O?q cCss|O.z>w=>>}nnn0jZt: `-[O~+?f͚J߿=Y~կ=P6%#̋n7]ı~xrrb|| JiRyڵ~SOtҒ=>T*kמ~zoG\NT*ʆ혞v ߾}]BLNNm۶mff6=QVfRA+_\|k\^}/BlnU~AGaiX _̋k_Fݾ}5kl?󯎏MO}ժUO<_7;+V/&''&''Ų,[h ^x')ZK:cy̛j|ܕW~bbbbONY5eÆ ;v?;^z饏쵣8GFFN??z;G?qPÁ+m]=uw7tʕ+|_|_n:u=a[niώfk882/gkr-gqzRH޼yOk{߹s磏>qƟ7|LE~>roڰi&p!ܓOݵk뮋hfffzh\W:M74/%dsW]{g?{dkxȲlzzzOw>̳Fc76mzm˖oK/]`A^(?~sc=뜹 M_}织7pƍtpd39xPGƾ/\}U+V/,h4x;_w}ϛoh4ׯ_+<7'|d61_?38}O,YX,fYobbaE'|7BN88O=k] weYG+\/|O>y_W=ܭ 6nٲ^qժs-[6jsW/Yrқonv:'%/,[z;x;k֬G? ̥XvڵkG~ C^bt~ S>Z^7v6lظq 7\5|Zq011{uo߾z^' &Ł2Q<_=/~?;|_OMM_? 7x._| O 7-JH^{]UVyIi<ټy|OSni ^ydYg522}~橧t:{G k֬Ypax׭{dm8̋7~W!ULNNyw,vEjթ7:zcoO\llz,wL ?d: 8̓ kn 8;w _̋OShp~ddDžh#yZ,6Ȳ<$˲}c%=c"aŪNw}qI{ aZp<pxͅ T*M^ݲeKa{cor}׶lR(7/n822;;îg^t*J.JZmoVs_Ї>Tk?߱yrzFcыؓ ]X\`AZT*RiNj;}3JbZ-V5;;*/^$hr\~~4MFefj»E( nIBjܙ Mwy 8RiZ*$vBpF-<߹s 8t:$IJR8M/n;77nC[4CyGDf$bq׮]^o;TՊxzzl^8vdY677ywt#Lܺul۝ vk8a0hZ0۬ڵkjjnqft۔p ۓ&I\eqFc۶m;v wpɲ,˲w EQ茷Ngnnnzzz۶mn7xh>kZt!&<ϋhZ-juOCUFhq"=o? aCbX*&rRvK$GO<niiȋ4M]izy yGxp[N0c/!Jͺ6c0/"x'z=C.گ ~IENDB`vvmplayer-1.4/data/metainfo/screenshot2.png000066400000000000000000003300711415227045700210760ustar00rootroot00000000000000PNG  IHDRTb~zTXtRaw profile type exifxYr#9EZa9`;׹NI)-۲I9p w;?w^G<7ݿ~|~=}|; ɗ]P5>ޏ}5LޕOȯؿ O@m_kY>/a_a)w#zVN$sL59_)) F@~4+=+1wߒ`֏_ۀ +q/-}9Zwf-});N\<=_<y Q~aHZn 7us<&Q:S#yz&c.x.C83Sݫ:W( p陳HHuT?( '̝N^CjKuD  ^  D\0Ȁ!Po1c'?zL9.RJ,cNumsn,u"%H D2FܩYRɥZZeYS͵Z[͖ZnZo͞zzw}9HcusrȓoONsŕV^eV_cMˮӢ%'Zn R:SO;3/vͷzw ?'S:}d>D匌xS(訜rNStE̲(912O冏ܗ99E~헬؆>tOԆ O_5,]q˴[lqNm|=dzjY,,j}}ZHX'lvVY1hg8kM=B2>{XtȂFn!DO oohe\l7CA,ЇJ^7HcD[;-H(9wc3S\7CqvC˪,C6,iܼɶN͖zW|""4w5r{OֱH.\qpaKX[d8&ҶcSb䛒*r۲`3O _5➑ wT '=JtnzD9iHDJ;XNd%;EysZ5#~UY*t7=p5;Z|sg}ikw$w 9v!e<ԵNtA'V?PYInZ@ )ҿ88mtx-k[Id*}J:WJ3^pz%sA ^BwoX |Dkn cWֳ 5~|=H\b:6Õ;e@3.qׂYVzR&g1e jBI'yROvw<ʠV]E1-%uZq pAؽ! GZ!l tz\?0B>+Mp# /tpqM1BPq!i*sR Z2 B`%⬧R-mf)guZ_RhAvXwzSZ|P,E繬`s"DؙDjRP}DuaLBҋO, sQ sM (\WL )CJ{9urrV~AmJMTTEB-h 0Gٮ0s^D\P$Xo5yzrFȀ=8CԚ!U4]T*vGX bij 9G $R]7PI(M=R_܈D@mBbY}vӊ& ]6 Mäuo@`fO׷!+O]&Az@IA! l MIA]E!PxM  [Y3h&mΘG&<|J^{ ZCF`o)Vod)'%Om 9 gzm;ՑA7qԎ% X_6ј%>"PlP6Yd 3w5 t6 $hSyX@Yu簃GE @E 0V:WҵXJ^VN0-ًSpF(- E-d  Q'`Ɛò{ E-AHK8Chh-1!(J%$" ëSٜ/xΊyU&]9RuRE빜L2vTߕd9PdtY0*;C~;TTCcE%Iv>g" ZeeȔ؉h%5-?q(E)„=IF.r Z`ڕfҨ '5>Yۃ8a-#ajΠ ^Btob,.^=v=O p@Y0uEAK RBG[gf5g\XtA #=.Ġ:~j _mv:QQIJ"G|^p*A.pٓ?J W2b7xm.*Y =} 6"ruc-wt6$i/a_j~Bx䗘>ߩ+)onuU=jVH'BŰّ/}1>lH/.-l|E7S`WE{ L]():<0@ 3{nIvmd P:r4$Ỳ :=KAv7e:KF(%2T nPر"$3tS5 -MzㄴStr#͸sQnb@Aߤ6Q*EÏ6nѾ7Q!]&􊜕/rlj%W PhwsVVhnƳ mT e&TM8 \172: X?WD3Lxjw4xf]*UQiCs"MT8gJeC,1ml<vDHSAS#묚hX-' %`ɭCVgQys$G%ZFoE7bNn_2^7<}ʜy.:K=hD2IF)}O(I~эDKEZ 7J+ZU'ćhPqF!Z'\nXxzPu@͜r <hXC]Vj1/X,EJ-0wT td6 3gCCy)\lJ,2]{,BۤCL:6DžR]:&uNX#D3E RQB}Q "CD<#&Rκф꯷W6 &+{\FXG4bz46д$Oz B%zas\$#V' "BeI@R(G̯-|9/3ec5Q[( Ȍ*O* 㺃!b^-,($hl,{\J'zHJ 33,;<2;`T/ b 9$ Xفw35 M: %B}p;g @ZF-4#\I6Gã Fn81~ںp!N' 5Ȗ| r+l.˳rYyqr4S\!5ߌW,.e}Qp7%iCCPICC profilex}=H@_[*;TP,8jP! :\MGbYWWAqssRtZxp܏wwTcP5H%B&*_э#a(&9]gys*9>xEA xRf>Iз \\4ytɐ)@ӟgMY`Ys{kHSW-Pǻ{Li)rؠiTXtXML:com.adobe.xmp L*r pHYs  tIME 4H IDATxw\TWov޻ұhb&M}m/w{Kv7n4Xb(A# rqt2DTpMrfn=s>9:A @F:_0*l@ 2"@60 CӴW?C ޟȀ@ 2J 8{T@IgxEEQ j XF@`X@0ca'D <8@Q`vkf@ d\e@ d @ @ @ @ d\.ϥKPA o*'&&d=x<# Ŋ S*\Ja>W$;iiJjppkITJR s8\f>q$_(B@rlA4Ppl6b6Vju:r ǎ(&%%EFFl$T'sss\oyL>EQ@ o[l&I>0rjo;d&66g?)BQTPl!]t͛i:NR|Ev{___kkde/X IZmCo[[lEN*Jm===VmRtI$I2 \[[p8bujj۶m۹sםDaaaQZV"Ro0Z[[kkk[ZZ._.illL&J%JR*z|zI$;ξ>`2L&fl 6L y$۱cG}}Ý$|vv6 APa@ o8q\;|r!ߪj0.֎<kWSSS5 c5W;wChR0tWWWU˗K8}쬘XRi0VTT\x… MC6^lcZx>͛TWWAxg^LL IINN3gY(c(2Q%I288(::j%uu 4Jh$I($$u~~ZE{gv|2##Cׯ\$;v\V{( B RSSl@ O\.7l&P+,l6VWW?`ΎdEUU]/))}&].wOOϵk*++wm?hhJ:uJLL جŋz r8Ew %#FP3y.kk֬V*  !!!99ӯ\R>!{X|ʕ)` ő3g(,,ܾ}ѣdžaիWuRVm222bݺuJ-Xlinn(׿mVS{sssD"}M6'3g6ammm_~Y/U*_RRb\\\CCcggǃ\OjH+,(r\`cbX,hqDPvuu566>t@/[tcǎU^$r効sr8 EQMMM nqb0쾻 3gA.h4Z, åRD"!I2## 8q»̙37nܘaA(r@ p4޽|rҥKu:l.*/88x…]]۷o"OX,zc9? y~z_xƍoqu._aUA=o,,rΜه%xJ TnlVp͑l0^ II$I0 J |>իN:p8vGnnZ7o. hzŗWϟR~u.kx d\я~xH$_ |VXII؏sN . 88hҤ䠠-[ gϞiө Eaaa:믿>: ))II@aH\xё#GG 04 #Җ/_gϞQ3@M^@/~?6|qOo_Fz Ǜ5w v{uu#G/\R&Μ9sƌz}ŊZfXlill,afkG-))7onNtJpRR&/YW^,\P0 SQQo9rdݺz}llLRRW^̚5EJJJ.^d2a:z*<9b LviqN>;;kppp Xj 8!#t:{{{Zt^ D"MFP___PpKD2D4իpm.\p8vm֬Zf֬_UAyEFF*JXBM?t FcccS 2,,,\$ L ??~bFFAEEEyX_P\|6Oys#"q7Ν۹SNb6cƌ˗)rRY]]k!Gv֎ '))2 SQQq/٬s,_\( ŋUVVVWWG8NQTIIѣǮ\"+,x"6-JWZYTT=wؘ f͚aH$5kvceIQ/믿>6OLL$ Q*^1bOd2a@>^2 #ɧN EHHP({ r90t /q)G亻JvƧI(gǽty φÔ)ͻw>{\^^m+г̘'kkkIm ܸqlLiD"m$)qaa/zw?n0D"A].86[nZK.  X۶m9s@ ϫ|ǟi"dkmm=}ɓ'(ĉ aT|<?EU*| VgϞ%5 pmA_t:m6H$^nQVV88aMS=mu:Np# 24NdE֭[t:O::{ 8--M,WVV64y.k][[>GFF>+K$$Z#BQ0  T*z}o9~۶m6ʕ+Lr[\|w>|6'X^?kLLD"oRT(ngggI$b h.)))..z8@Szzڹs窫%I||X,0v_pܛxSSd㜜ǎJ:AvcGY,VeeUJd.0 AAAA?ɏ~ uII(xǣȐ ]}tFo޴i+2""++SPg6-~knnX,^z^Wbf`/.uժJEQh4]]]iy<0f'?Q`` ͶX,gM:wܤ$BVTTڵN두O??x=(ܜ5en,6<=;xm1/TU\.w```: v=-xQQV# øݞsΕz<A9_ZZZFFIq< ੧{zz'6Ͷv( ü/_ͳgtud:n9gJճ> ܵ:::jjjI&''|a@~ApOHHN]zv XLDHH\@D,EGGfaV+lkkq<,,L,{5ĤIɓ&M"_%bI I^(j0{bbJԩSSSS._*vܹ11RƍjZ %TX0cks8mmmt˗K q\VZ]tEMsa:гg>ܳ@[V(3 lGMM7CBBD"Qbb3l:{i a&'$$d޼y 'O\z3lh48(3}۶8v{bTv7PdXAj?񏢢.];xx{@]@ 4=\R8[QQf:;;CmFdNN:xݟ'44DR^6-00 6ql6/ P޺08hnkk-IG@$:::--̌>}h4Zv,E"QnnRqd2?_ ˴ZN{MbE 7,_H1X dMɐ:::~||!!!0P? $NW~~c^|Z( {YNvH$===H"= h]%%%65_0gf 6ѣNJ/r0L>}zXXXDD^4M 455UW7Z)32H$/lz*99~$M4{ŏ?.66fD ֫w wFno+Re`&2R5ܩI9qZYxD"4iҊƏ?.&&www_repppB|u3E[lZvͬY3e2YOOoq妦{: ub!xV[MMu[[@h?RxcF^tt㩯YbrCex_;)}w˧ܴic^^Kxl˗.\T*1 /((_yRak,DyBE 'M$JPEQvmy,(\.7==mV ̙3&ҥ؄Zr t:^{Js񔔔nݺCK,~bbx=OCC{>v효h0/opaL37>ݲ> IDATið@`(YG^dggj7 (ܩxRUUE;'0z}@\\࠹b``&&  Edd=z/Gc?j&_.ZPTz5dٳg;^xtlٳg3gx<.wqB/3g p8ETm HMM__SN !!_7lx"""hT4]]]3}t_bbwX,`aLA,smmmvv&<gwVc-YY\.}ǰ/ Eрuݻ8W8NDLLP(OvE`)HA***R)fjkkt%$$l4+.AP_"CCC.]b4kjjAVVukpQrjM~m_3Xh! `wZÇdggEEEU|[ZZ_xuICoff3l 903xbԇϛ7$ɼ\ }4Mlٲu}ڴgbX {a/_k/aA.]*:qTww:Hq@^O~P(% Mg䗖^| Sb>ڍ||XVVc&&&ł=Ea6[{ĉ/Mu.[T{0BaXXئM?M\-Nya=Oy՗_~gKKKqHzꐐ6C]>E[gffjE򓟤vP)HcΠx'?#200m!!~~~A̚5S$^H$3fSNzwkDp.]*JKh4 l6ۡC++= E``?6ruuuiSAbfX-JF㐺ˁ_+!!*++?Ӈ6h|;,Dk@r:;;R~tD"I8 Bl Xd``_C,s\^'c4ϝ+صk7k~cǎ PAAAk׮jJR۷̡3gDQ8l~{HЯ.n;Ϝq˦E"v5],0 =8h0w 2 qfٷaX,v[,V}@ cBZ[[x́XNo]\Nj5Bjut\~iӧOO4)$$Or-KKKKiiYiiiuֻZdӦMxf3 Iؼ3g&&&7/^xk*#OІ^A8fFh4VTT:t 1f<Zm^AQwA1m;B_W_iZ +zv{gg'XA޶l6lcX<o=AxͷWZrѤnp}ܹkH^byͷVڵkT*%e Cv~ڵm?qĐX7oa˗/H\.bQe,KqzN1#8=;88p;S啕 K,̛7w] mn(jkkq>ԅ( R;v0(̙|96 Rtժ7ne9}GpnjwjoܸQ__w>4tl61r=3tww>|ܹa`U)r;]È{nb O2 gppN ͛_~Yx"ofpN+GL(@].M&_~[C>noTbbbTTڵkg}VYYd۷Xdɓjmm|wP&W_=|ҥKRSS4hll>?M&+8~_0'z1.-M<\_p8nܸw!.9s ,4Դu{56*Fl6{{{7aXKK˞=L&#,I@ @ @ @ @ @ @ @ @ @ @ @ @ V@ d!`)@ Oyt:a)@ @ ȣ @ @@ @ @a`)@ G@ 8Cn4M4 , aC  0<ʽ'aݏ%EQ*G\^88A8"@ ! @JQ#./|;P @:8q'If?6nn\.pX,Tyv\4M! Y,arJQr8Nvs\@Ld $I8(b'L=+4MqHr@y<@ pp8 xvN'a`lsEQ >b@_z<p8"f( @Y,A,d2y;б( \TEy9NEb1IoJDw~b8vn74`@ !@QdXnuu@d`t:)cz-UiG7Q?zoho]@  $,M$I[`_x<C c,((/ 2EQ,f?"w@y<ag,`w=W^M6F`RLh b- #a0E2c!ljIOap@ AawfGU*/|E@m@ Lw@ t&s j @]=@ d@ 8sPot(@ bzw#~4MS X.v @ ȣ#-/P5L$?88d@ Ȁ0 p8#nr/^ Huu8͆ @ (/FF.7WXfeff̙3afxmpSCaiXlqQBif!"y<ޣ04-8  /X i6.EDp /A;w*W,O6-33=zʕo:s& D"_~Yx~X%!n@$Nyx CddO嶶m(t:!V]]}||VE$**rWyIHHXfm 8kdSa{|v!ժD"UUUuyh4111 ^a|RRrEY,FQ(fQ{daA!0LWWVU\J=\L4)$$$IUXxtp8JJT$FT*z(*JFKTr8_ׂ{mZs0/A a_u?.55>(۷׮\=·nwɓ֯_?uNfG"*BrzO?LV1 jj 0c]GSPJ" 32kpNg_d2bV*~X,0lpw-}^n?̋yBxD*JeH$zȳ+/Ngss3rU ```q2 kZϝ+bE'Oyކw4Mߚe-DQAQ4rhcC0߃3_x8t߱(*..ZzH$0Lt:.;r&Mb=OQQ`v{A}bCxc9o ^Kq i|#} f*++oܸa\X/ {^XևtIVr\9O?LaXxѲeKU*UqqqTTTLL4 4)w޼+JqHaaa>'BQTkk[UTY,VJ䚚i:(((..EQ]QQCCCSR&x HDDJgt0`KHHHPPL&eN`0444xpaj)<]ZAhp8!!!z}T*qp6_EQ "22BVs\a0Z[[o6xfvuuԞ9s  :uJHHFH$BXV^YYy9 nr劈ڌFcGG \.P5Udp܇ 0LTL64666))aD}yD" QS!cl444M&t0 h6_~Y8q>A̞=k嶝IT IDAT 82 rbB!l sƝ3EQz֬QQQ>F>dҐL駟z;1d_) _2妤jt:M&D ڴiSBBL&f 訐͛7Th5kVGFFp8R$y/xoyyK,$T* R(o6&bRpr 6!!^"|p.On_V߼ysU\.2..V(ݻ[w] . 8F%taT*{[|>_Rnp@{#+j rzb&(((>>EQ^]]6NQTDDxzz:0 fah`q8UZzW8^__p,FQL$EDK$DGzl/,  (FEE777(* 32l6Muu---a |ڵYl6ryTT$A&'gzkk˾}JQTBBM<0rv EQ=we˖ׯ;N$#"ƒ5[[[?0 #˜NgccSWWHʧjY,JR* TTT8.T(8ɓ[*+(R[[kx<6`&H"""BL&3gvGGǁ_ܩY `Pv/x`ɎQEO8qnx,E h-IT---N$I\up$ɿovXڿrApO?tD"Q@@\.Gf;wS'00A%ngX4M߮8^Na z{ |rnX6u:ݜ9ΝT*r^W(}}}бx.^lR@hRRS~8jnϥKzzriiiAɎ/8xZ ={s@&Ѕ ^T<$:ad2YFFFbb"PrW^;zhEE࠙i4$;:JFF:رСE,^j%z^deeɐb)-rȑ&fbbWZ ^/8X]]mXZ%32E"X,jJ`0tttٳA7o bzysgϞ-JJe``X,6LFtujgwMX> Jrʕ]TT$a ]Ûi{{_hhh 4y}0 ܹap0 x4E;;>|/E(fCBBD"0B@Ruww8~)=8pmjj:tpvvT*AD*d~ek'lmS} ܟR=[{iIa\.*^Oi6[nNAn3mmW8pRSS+**@֥KEf5A55MMMAϜ9p47e݇Z5O,K"EGGjX)<4 ܵzp8 ΃Tǣ)ʓ fFJJJ}5@ )F7ִڵkII@ K@QajuHH0Wn[Ri4jePe2iWWD`Gp4 VB!m(A\0J(^ѨB I7VXl(x/0D 4ݻlinn roh4H@yIyjI=cb;7/qn8_^wWVN|q[Nw[n$YHJ 81U@pܸh((-Dvj>{ B pCN&p)\ #HYY@ ػO?5LZ7n[E0 xVc~PX,H$eeev;w…_{Oxwwo[6xr'brH(ш_@.cN_iwALaY6j ۦւm:pD"b-":(OyW3T*x:݋2 eEQa/GQѣGxułx~W!cd?H(x>@Lɋذ^`0888YQQތnJ -b 79~ .---..m;El}.\EKKKssjU(|>^zr]~Kg(ahȾ&p ݻ~'zL&lxf=#[jH$R* tt:E4$1aJU|br1PBQ$$ HT($In cT2LMӟEtz$ l屡\.woL&Xoxxl`0Zl[ 5Vz6yIM?斗_~eI8gϞr0{VVV<=x:8?~DCCXڵ*)0jooo@w2ek˗MeX$zβ +kkǏFE wt{zz_xH$0 ܾ}L&vGEEAr9?q\YYYcc#3 ̘?L0 4P(I$}]rȽ Y]]]Z$X,~ 0qh1uE7p*:}Tyy9+~OEK*@ :@}}=> qg|8P*˔JW x<33?s V2tݽwNOH$i "&''y<*J@ h(jiiV(kkA2Mj 3evhd ,\e4dҹ\0o 0@a`m-G?O&gμ`4?!0 h. |>߭[?WUU.q<{$ 5LC-q]WWֶh4T#_RwZA"KCő#GD"H$9AqͲ͛u$I`D" e2YQaZVK4 m6d7;l6;8x =,;88S:w}es<OA_122RŒ, *W^ybPe6f3 8x{nn7{D"檫@&yq: (l@xW^q<b1?PV,/ :uR (#G$əU}MA cN.~Mq B|i"xK@ __9w4OLL Ðf۳ga 8+6tnPa.IKKK׮]7ZV&b "H0\YYzj,8477 GnԔñk_W*`8 }VӂݺͶ[oq?BdϞ.^Od,CQT(m(?::R@YXX,ZìPDǏ566 T H,[YYyU0 Gh(޽{fRT*EQ?;;;/^r R0ւvvr8|QF_9עk+W*S]]Ֆ5➚7@fW;hmT߳lGGF)Cꕶc?>}%HP>𵯽499_w36 to}[m`bxllMLL8F>H^oOOo>- l6+ LaXnyj7V$ =H(i|\ BeTG-/SL&SssB@Qt~~?:X^8r!'`0X,Jah4xV9~T*u8`M5 C=V0 D">/eee * jͬg=T_=p7<\nϞ=&d(:>>>;;9AaD"'//>)ڽ_' qX9sPFr_|NߌK %>]_W; T(aЃaõ7֍MW4P6l;u7{W7]?mތiP^<#a"[OfQ^e;AEIa:x|ddO?w-d{#{ƶ~Yp O{{m4=~MK,DӐ4$4f%8%H$qȻO&' @ .JL _b}rd/ m> 'GX@ ȣMɑ 'GJ;P)?j @v 0@ 6C3 uv(E ppC<1Zx.,~h@ P[8U*U?(a(&T*]HӡP(JAQL@ #Ё3 A젳8.JB!a(ˋ{:Pbfqp8L&E"P(xOŴl6ɤRD"Ja@gDQ>{}:4La$J+׀\.Jl6?sr BX0t@ l6H$˲;Łr9 stKf\.ɀLOPtT>_h@ Ya@:5Os? 0Cx[t|%AAm?24U_(& 4l$ (P8Ƚ@ڸs}Tgi+ yx_>߇w} _>sC@ gI<_wq;v @  C60_@ :@@ @ (/ @@ @0 @ dA)v8A522!'(r_"z%}C 6{!!kAG8P dhgUFVݢ+z :Fw24kdq |0@#;=l 's ڲ-MB yxl @ ʋmF8 @ pr@ (/ @nys/ @ fI @ Ş~Iy'G ١@ ύ#@y@ t {@ @ OP9cYeYiW(aw!Gel.)*8apb @ ϥ 86{Dfl8Eqχ8C5xser\eY w0@Bhô}t#2 (Ѕ zw^8B\ Pa@ iEAa;Z[aǏa<O(z D\.W:=g2 Cr_<_3Yvy q B!I[$L(*]:Mx8$%c,˾+o~oέ_YYyҥ .ͶL>0$I$7L[ua;n@ ώx&8{6聱;__9r$\tw7I0G}xm?_P'N(crdG-4 `0nQ\655S/ ~|%3"\]]u8oߎD"fsGGX,H$) @`Qt:jV+axڵkD e8 ʲ죐J̙3VԒ IDATZݞdr h׾o˗/ (ⱕ>0 L&j-,8sξ{w)dB5 Nxq(544+OTB.r~d2mX]P֦VqJshh1C+NՙfJzʶoOOիW( |>|޽MMM]]]&{ޕ+W8@ ,/鉣jw433n۵kL&{|X|q^0K/O?D}r`0J6<6e&t:m(z3^ph JK|= > ʈD&mfJHUFHR l9^rj4$^f\$ ݻw744l6x&''׻Opa\_\V\ ary[[[mmRizuuuaaarr2H+BY5L'OTՃ/^,d2UUU&Eѥчİ, @ (*RюrP3;;;00~o .Ңjq|+++ccc>/gjÇu:O~wUUUz%aT*ݻkjjbq<w:SSS6MY<122R[[ &&=zҥۣi^kll Dhs >, EQsssn 7|… WmI:.NOMMB!A|MH:>>  7JݧND$IVUUrǃWy j{{`,ˮ\.5ɓ' C(Jǎ3LbpRA /r܁Μ9ܬ% 0POLL|w-\ܹs?PT~oqر:ZMQT2zv]Pl@&` P(vzw^ѨP(pÁ@nWt1iZJjjN;w~=r_|E]A:v͛|@y}Y}}}mm#Gz{{i* ҥK/_.&6M466yGGNFNDB(0!"H^zT*eG6DVu޽:.LL^7a0^׳,Iw6BP(\ʋ-y`{az2+N߮^Y`,/^lnnX,|>??MSbqf+0@dG"[nՙL  z{{Ng4U({}:;;Ϝ9///,[QQq@ _~rqg0v}ٮ~Z,T+Wl6 BalԩSuuu333~___0N:zd>!lرcG}}}}(TWW;vܹselQjh4o~|>ݻSSSf8.~׮][\\D"R7Q˗/OLL,[VVvٽ{b{ʕ++++UVV:tӵoL~~l*h4GfgϞ㏓d.kkk;yjO~288$IGG۷ѣCCCCCC7A (/ O8www_v-[,H$W^~MyiۿZnbb?)0vF)L+'L߷y6i]]]1X7ݺukqqQ*8qرcf`^8~pҁ./x<_~bxޏ> *q^>FQEH$+ɌFfck_.\xwJ&wΝ;`_{/~ &MdzѣG8z]v(GիWʴZVmkks@ ?^ʋ{v R&8nnݺe0_z?3jٮ])@_$ׯQ9"l6t:.1T(G _!'$GCCÁ~_xE`=8fJa@ P "\x1?aMKf\.,//-q\yyZ `/uS]]hh03㸊 Zǭ[ x$zǏ?x`M(uo޼It"AQtOR@jr9tЀdݻCCC'0@̟aP(4ZfYVTj@QgY6 ՚d@xF#<0.R3kf"… w޿WWӧ{zzf@\tW^X,**x#GH$>ljjD$ݻw$ _ryccl<dA6%|X,V(,F`0af&ڰԓeYV+iB`NH---BjVY.!h4Dxѓ|< :\.144422v7SQ0<#9 *`0t:I4 \!P.y.(_l//v&I^xxfY\\"hƒ0v'b2~_z {11q_|رc,~gXbtww:t7+$_jnnA^x;]r ͜n6tlZoD"~Ғ@ k-&&&K8 4 .k3c2L&SMMn&l%^ZZpJ8w\SSS<gYD"dK$۫A]][oݝL&H$Z6L~~a(OFK/TSSo}ԩS`D,ZԆ>r[WWrWw " .xж$ -b__G"gt ӵENP\ר [VKHiQm0p0`ţrFQZ,ӧO'v)}IUHh^ry@X,SYYhfgggffh "N>-A醟bP(ܿݻwAXs|í6<}ZPlfB'Gt:q}իW}>_p(;nMMM555syyy```0>}S ksؐ㸹}{gΜimmxPhiiixxŋsss[4Ru5wȑF^_SSJU힙ipaaA&=| Q ˎGL~~gϞw+~?u7o,;Ym=?šآa{i5R03J?]#b;;ȳ/(Ml_RR(<-",F)ޤ~)h\|dD^ɑ#B痿kvaOѢ.]ezi\7111қ8 7pb뇷Ex}nL=d!OWC=Y~\:%k`QC񴰂e+jCfyrOJlPAaZrJOXX6ǫOQhciA8MꃴCBW$U)IoėE2 ;A'F$b\.8ٳ2laaavvP@ B}(MPWW%F"#U"`,#-7c}bo(4\[[[^^~ ֞maZ;;;r˗as,PI*ZB M).ƣSY1q6- B}8ycm|@1w>xy`A D%\ˑe).[P^<vx?c~ƍ. lȬḝ8kʋw@O\._ R:@6uܳ8R 3 X-}0잽+8+++Dpz[9sle#[[lQNᾌSIһE~ӐW!+}۲,[,[WK{_&-A~[ 6;\.Vv@y68OB[HjBEAQ9;;[z?E޽|nnn||zV+HXF.+ 9V-++</NGQӹejV+|>0T*|D"f#T(:NP$It8vpxCŲZrEx660̦I-//ollLy@yy\.tLf EQa)/PH$r\$aXo$c4 Ad2P(dl6S^ |Af+=WP(vڥbqiw֭P(--B( *N:33ްV  òl$.tJEd2 pgY6LA[uf[RtϞ=:N"R@ IDAT 011Pju[[NAN}>3- eeeUUURnW {I(&IY"Vry&񛼵^ (򖖖 Lϲl*CCCn{ð6>nŢ{$IޞL&,VuvvFN&).z}eee4uR6Nz 2߼y'v]WWҲރ,jkkk)(++^0|>liiƍHf}L&S,s\8qh4:33=xh  H|>_wwlߊFQT&)CQ(mF!8Gz$aœ49k?| !h}F$Iy9B@ $A ZZZBB&GFFN+//篥iכJ@|W0aj0;ـXTbVWWS;0" ^g'10&.mdoـ `& PN,655)ՙX,N9LR***|>عᘞ^[[q0 \nvvڵk+++[DFgffl6FZw W*(8EB!\^WW7 :ݻw\244aq2L"d2DeX]XXX\\d2啕@^ σE7|N'X08gY͖7VZ8^UUEQҒ @mm6u:8 ¢$i0ZnOB yኩ'0/D"rUUUa!>ql{VE0 h\9 FR&Q eee,>z8rBf+//h4"(JyȳRfXBP(8nnnduVggF9uT4x<@  N*++[ZZrA?ߵkWkkkGGqis48ꎎ~-ڄ㸺:DxوðL&dK ۬N  @0qP JrX]]Fr333Dq\8l6= KKK[9HE#뭨0"<d2IR@X"x<Lx@((*?CDssYXXLa`@Qђ$YSSa8.JfofYJuuux|bbH ҆nܸ-Y<8{8a'X4EQP٬0SSS.d2⪪T*p8@&D"1Bpxx8_Nm6JRT:-0˫ PZxߞ={lQt6zS^a6r9kkk,t:@ mw,#'Ojn )eM&SWWa###xMM Ikkkq F #%]vBrfgga S?Xt< f "^weeѣjb ^]] 677́NAh4^D{P t* ZYYժyQ\ ZGR|ߋBÚL{D"ЪkC r xkHTx6n;FKRa;eޚ|~<8]8r^B "(?ƲhܷoT*ڰjIEQ:NR(㪪džѠj5L $ɑglE=ȳ[6,J% PV/X`0Xv3[Sv`~~^"T3 MӳKKKEwN6-$-2 S z޽{6At: T*J8D5dڿB+G/d*xE7BP!a(_B PTZar_QQ!].ȴ]) &y͍n=a&I$6{tւ~Çwuux< ꁡ@y kt [eClvvvV&UWWc`T*j^.l7Aņ~[#ˁ|"ARW6{0L"Y(++Jr $(nl~~^V ʉ|݇^Wdruu3jݿT*bub&Pc@ʋh4QXΟCX ÀݼŊRH$L3߿_. F5J@d}}=A6mtt( JrF1@`Øp8(uA#'ǂBgF^c>zhoo/xb"b, ݻpҘ|[ fggL&S{{;qJ:tB}{`aa5W7RWs\MM^?|;w(I`veDEDb2@K z> +ŲjC@H_YQ$+qb/ir|ii)ȒS__u|>X\WW')A`՚}⩩)ФayyRIl(ieFSUUe6b  ʋml/]MfYqrj b4 ,]z{{:^~X,5) Az d2`,uΝF<h4644477t: z9 φ `QDc DQDYMɴ-9ZN2QII&qf2LĉD;CDҔ"H$U(v($zpA#ʂ\f.ιwu.H @-X --,jV裏+vtQ,744TUUuyLVFqݺuúJ peKJJVZEQY¼[]jnRI,"Z㸵kגE_3ZW\Yz5vSYoݺz"YaÆ Aas2zYrr YYYdDC<~z `Y6??(~2y /wCNR%'''$$h4NGNNY- ~5 qmmmnݺXCHAƍGȠ&uL0Vfs\~`$I'ss{A3/Lda7dz1a(""YF:@f&%wqhYaWa{:qC(t:CEEQ$sWp_|EBBY\`0E:sڵƔxѨV=== U۷͛G6yl>_UUU999&I榦Ʊ.Fdp2kqϐuB477733CW__H!,˒I=òd mbb"C/2A"{󓓓z=XSS~ֲ, GC6[ZZz@[[/s$ɤfl---JBMq&%kzERvQ[ZZZtV7>rbF͒^Qπk) oGcJFg#ʊBք&K6-|X+%O3T6va^|UFrrK'Rg Yksh'ЄCRיș ;jBcF~QhnA6nܸf͚ÇDZ{iyɨB(5KV]Ӵ(L>V?~4 FF#h7R^0Ͳ,E3xq=#x/٩2dz?^`#/PP/"ps"psb0).^ ^&= ċ&x^ ^&PxLQ(E섡0wnN\W/EP%E4M3x˲ Ä^bR̾$I(acdOB( <ϲ,>0Vc^()$pDz, D[%˲$I$ɲ 9y`s":AH afeYUd)C f!D(RT͖lViU*I\/&f_QR$9# /2paY-caȴ|bbf'1LR%'1 ^L!OF`FQ)LsbZ{Xx֤Bk?xS ½;K=̝x4w4YmDӡNċG+$9)[o0v߼500HQqd ELL̃`^|N(J媪ۗ.]~h>((XoKEi47~RtM4VM&(x;7^(a5}ue0~˟ :aR{ۿIhVe>(a~e!_Qu<ϛL&ѨVEzCCCg*l6 Z-Iq8>ojVX,:yAnM:bhZr8 AUK/};xWnw,k0L&Vi: 9NI8h24 EQ>ohhrMma z)z=z^߀0+(8l6 d_eYѠ IDATg(ZDQݾtUVIVQQq۷o{>pժU .(ҥKNsRHPa,;;ߑAӧOcVh<.jw5EGӕ$IeZ޽{`#-u Y_}CTa.\xO>/~/_i&a~_566+VxWN:uE߿xݻwl߾_cXy>11nݺu+-zk2*++?裲2ׯ_}={Ȳj>v8ի;wF-[JJJ222^|EI^~{||e׋ ۓORHIS [ZC܃y]VZEs~;e;;;o޼o}+;;{ӦM W_|뭷<y֍7^^x`Æ ?ah}͛7׿'|B+++ܹsڵ彽.<[ZZ~_zkiiiя~yW~g0E,"$I˗/߶mlu~F%477?Xd͛^zu@`˖-j… q\GGǭ[:::^~ym޼͛޽{ G}oXu_}޽/...moo'U5b(li69Z6>߾}Ǐ=5z,KF>eY A_Pȑ?vC;559J(IIIEEEvtpp8j!//oݺuR%==}ҥ111_| =dIJe/^<aj_~yMr|z{{Y}ꩧC凼%K(RZZzR4M,tAVcǎael_UU:)Ѹp¼>~ǎ(JAAAzzz{{ӧ{zzx5ѣG+++@FFSO=;RSS.]wχ7,ljj$EQUXȭQjVf͚57nܸxÆ NQQCh@8ۆ 7n,޸xݺuz!JNMKNjz5ïw7ȄQW^mX@}}ݻwnk׆RSSSSSU*U|> ǭZJպPQk׮@ FPR ]vm`Y[ZZ͍ P ۤ(JFFƼy(p°2,wܹwh!~EQ\hQJJ$I/^ր$Λ7Oׇ!(V  UUU KӴvHKKKKK 5,B 0xA>F ;w .~…rr32ҿW_}6h(z `vvfhjj9TR]vmppiLn(g2Z[[G^4}e|llj%w,XڳgO~qU*UKKKWW޸qC$ZD& <{{{ iôM& w!ϕ$))))==744 ; -z}ff( ddd$&&:Ά9zzzh6餲eӟ{zLL i`0o6[ZZFNaYne٘2 9x vF,՚ Vk0Ay^Bff&˲/}RB2J HJJX,#4Au:fkkk!55`0477 0Htgg'fbcYvk֬jj,r|oocEQ ͦh^N#U))ۂ $$$VMHH|{)))lqqq㭷t $''64d2Y,Rj$?رc˖-w;w0,;^=0::ß=@ cCҧLRiZ2|Rӱ,x\.ר388H3FC"]xDz=f1EQn7y^O:]/u,Q^dAjVFe%&H!n)( IK`p```$Ɇ8NGPQ>dNHz^9 PêjFC 322(bYz={\rȑ[n^b2ʂ_TjuX2~J[ #."(,˒@ I~;e4?۷o (* wM ɫFn>; =_[$FcXF fLP7)˲^+XVr!zIO(dB'˲l&#;uEQ. Qɝ>Y#eYReQt$$$dff;w  59jwID&AT*j-K(K"3'ѐ‰,:d2qB K 5,Gdn{{/vEQϟo@"bd-ׇjpLOx> %<βZ*r$$$v$%%7444'/f2 =*%---11qX#Š+d󵵵Nfi)rJ^z{{{Av=%%edVjEEE, 扸\ZRRRRSSy!]-\(N <'$$vA‹ tvv655jİE177755lJ`0'''lB& MMM MX bV>p<4^F‡̱x1{jS-iD]M2RSSG'jժ;wގrȢUEEEnTkךZ2& Ց(׮] jzŊv=Oi:..nڵUTTtuu\ It:]qqqh+гRRR/_.͛7-bIdf 4555444mZ,)EHy$4$$$ k@Y/_YYY^Eܙ qd92+͹y~ڵV޽{ ;VYBReE/#< p^1###$???_~9??eڋ/"?M 7nX`͛B,322dYy۷Cccc_}տ ~ƍ@`6lYi6ۗ⋞`uօ {YZZZӓlBPeeeuul޲eʕ+C!SO=vZ^O6]#2H)))i˖-K, o_|qɒ%*dM0EQ4?oر#Tzaƍ7oNOO$I?dY=133ԐCX+\v !#&+0* (T1E)$;R>̒u֙3gܾ}[VoٲeƍvԩS =,gff._gIHH(--wl޹su,_|qy2?7oެߐE)xχ s/^̶=??,[SS#?/??4(JԾ*R\\hѢMa_~С7nOi??_{e˖\\:,Kٳg>\[[f3 &...|F,˷oկ~klݺ ݈>8zhoooWׁҞ{g}42Yȑ#'N|ju||j%GäivGٳ'%%/2i%e[ZZ:駟hv8M[n!гn߾}С:Ԁ(Z,NgX,K`Ⱥo$I+VXbEaaaxÞ?w yjD8 =ω'?^__?y]?$7V๨&P{nAfq7Fy]d EQ˦&2# bggWGG'YLIQ-[J@ x)=pCvzڞv8EQVsxn߾>|xΘ7oj?}YVV;?~iXredd'O~Pd4U*7ŋoKKK{zzF/OVe3:::>~3ȳZŹUUUOuO}>_MM YH N:xGOirUVVF@Kg*9-5$텷1@Ѵh:Nё8( z/bX~7u?}I‹/t~?ZZdExX%h,KaƟHEӔe9Q+%:a7jNFr 4M˲Lk$+hE֓,˅?񏳳߾c@5I%aгH$s%ƵZ-Y}G'ްWK4Y4&o1}QbTi^ryzzڤgB(J%E4C&9D002[zsDQ޷z{Ѣ:~j񢻻"4bBt^ʕk/_Z8 Bf" ^^1c;fKgf', *^`QpċhEz0;{\ 0E~n܉9xa^ ^DEzx1~BE/ 7_eYEQh4M40 VbjfeY$IHV(^pSKg%IAeaYvޚiEQ)R%dYyeY|"*l,ìxXUEEQ C zA$I*,Ihi)EQrdvDu=4"ȝY-C<ϓJ ^NbċpNgo% ei&0'QenU/$IRt̳>c4x?g ((O` @I IDATI:ٲh ^DCw"0"P@0T//" ċ2ct(ŴE¢쏞 ~?|+eU*&G徾an[,f^?g[FF _JJR/:+<8h;^<)7GX]vwrBB0ݞ?8Z@. ȧٝ4ꫯnڴwa(Jꫯ_СCc"wާz7|,#bQQ /~…7|SR/O{BnOz/???Ȳ[\w裏EmPjEEEOLL~gj{4(Jx a@` YYY h4ǘ Cjjjfff]]vx zW/t:}FFJi$ ezVtvv޹s7 $Nrݻw/X@Ѱ,0 رȑ#Ӽ#@ZfD*+? cc9G/01(yCas[ZZsŽK۷olCCCeee~_јLvrSc7)M'l^&X]q6zⅢ(Fq;w.]z޽+$I0 "IgYv'kG`ċ'z n`(JR`駟޴ib %I"SmgP%C>\Y$%rFFƺuҪN<1q($I$,Jz T/BHAhy^VZV!(T'("IR AQFX^Ft xEl) M MӒ$9NItf͚TYQQqܹI|˖-KMMlZr_~a_IJؽ{wvvv||(W\u˲_*˲,ˋ/.((HHHZ4Mwww766?G4ҥK9s8 (uT$%&&ڵkōǎkooG W_l6̕$[(9@ 0|XYY9A,˾qqqFQ<].3<駟:u?+MӉoF||j, mڴ $?dɒ~111:vn;+BȲ`={,_f aIpΝ;=ϱcǎ=p8P(7$eyOY?\Pwrs. FŧJQL&XU'2 {t~/L&ӂ ~fggUWWZoƍ[_}qp-qn7:d벲)i^7L|䞅h+1Lgb*9ݻW_߿?++KӅV5 AV<x8lVf/x貪}7?яzꩶwOƐ @@b<Oww4MRRd"(`vo޼W^6=_@wwLHHXp'&,222RRRf3 /Ԫc C.F#ձKKK#[FZm2}d2fY~CDQaϟoXh马 Yɯ^i'..nNW_}M (z^׻k3ַ233GjZbϟ?+n޼9u/h޹s7񍔔`0r}>YAOZbJHA@ @QTjjK/SO|`l|'77wEz}ff(n[޽'N Oti188HӴJ̬H9r͛7 pf$ kr Vm6<-[X,־l!r}};u].ٳgz_}եKz^AdY&NdYvҭʲoX~EEEii)0  95zayAHD7''gݺui%++#Gj-U^tx<χ 3GTAtEEÇ/\q\II+] xezX+M&s_KJJJNNQaW |p&zV9wl&̛ۭ7ׯ_'VkZZZAAAOO;;;i$Iڵƍ$&&nذa֭&r\dx׫j9er)b<Va_?uVWWWrr5ky晴ӧOnFrl/ɓ'M&S~~֭[ (7o,...))(߯x`07n;vQQ7n\2;;m!T*FnƲݻw; y晕+WIT*Z.]5@i& _ ʥ~sQ-hMTSt$oߐch4;vl_bXCV|`0xcǎ_|%Rق0L͗Hijj~sssgg,ffYVe~KK˗jTTqqq6K.9s&//DP'+$%%Z100@~cRRV訩x<#߈e˖eee=z\%$$,|̙Ǐ߸qeL&rӧ[ZZ.\(]]] EL^ONҥK7ox<,/]j޿/8eٮ͖w,YFL"^x{yˋ*4mv5St$;@ FP;^7EEjz>Eq``.|F$Oj 32 Cdj4MAt:Hn[VJ\.WaaJwްmGt:]FFjed/20b:;;G.>ƲlJJJJJݻwnX,F=tbccI!Mfs~~ᨮ9`0$$$L&N'˲u8===Έ(F133d2766`FFFjj*M]]]݋B$ |ǧMb깄Fcw4 e7Q\\8nYAxܗ/_9{=Od{G/b 0b*+Wvzjԃ#EQEIk׮_x2.[`ZS=VSSy󦜜lN/IR w8]]]--d$ x5{}0,++~ȡ0 >[0̚ ٧{Qe^ `Jܐ]#DX ^@0 @0T//" ċ2 aS\P@lQO2X /&f'e HȲBq-0 d dC5ċ krei$i4((,3 3X#1 #N, @493qGQT0Eq% EQAE,uΎ(r/ $ ?AeY%I"#:9y 01gi4MnȲ,,zyu ZszA(ӹQBty<4<0w2w4MGd($"L8- mՋƔ`v \ ^DvL@0T//" ċ¤E1]OsQG71uˋzEpQp ;/" 7G/" 7G/O x xMP=2YQdYhmA3q#G{P4E$E-xC rƋ,)єJhyx'E!(zF@#AfWNكg@x1@?=p6$I^wppt}&aX) ^L}&Q-jm[ҴZd+Wl6$ @xTzz,)xg L5^7m߹sW.ɔ)t:E1j3! z^J5O{ɲNSTx_/oDA%&&?\rV쳫VjmmgUm۶%%%ݸqg =h:"DI!ȑ}>_]ƕ+W%$$XVI{zzjjj***Ng|l-[<ͺ hڵk.\0!!!66VQ򁁁fz^TT488g9sFV?WɟIQQ/\Aݾnݺxv+**eY',j4ŋTWW>x!IRRRի͛9xx1+Ө;"JvNvSNGU8nϞ=[lIKKjZV{֓'O8q⡝#aDaݻwܹ3333ԌE@ z;;;KKKyP3|+VH]r9;EQrrrn:ׯKYfi4F(tݵ<:9 lx1ͯh0bcc#xIJl\\\T]I׮] ]]].\iZ͖GӴf(?^3~~v{__߅ 0Z6..4fT%Kl۶wh4}4=WzjNW]]]SS344$ZtyyyT/U2Eӌ(K?f(-[$%%]zСCnܰ'@kkGA`駟޾}{JJJEEorDQdyNg$IWXq…QK ,]tٲeFqԊ΁VZÇ?n'2xa6z{{;;;1BS_NՋi :]+W444|'W^6ohhmƥK.XԩSW\ /Q~=rWPPcǎ~{B7̈́^8,"☘ϟ={:`---x`z, /)`|&7%I69N/YO $IϝGDPiZ@oo6!!aҥyyy$O$VXXX^^NnLDQLJJɉ8tvvv644\a# -ZtΝ8Ft:;::ݻFVeYȘ7ojepOd/X,{ꪩ!w)b6 bbb>3I233-(MMMc5 M bŊ7n7#^\pl6Y3Fll짟~ZWWra?t:ɭܶ6Y9\an6rv===j&ӆG#2YYYVeY7Nned2-[,##CCCx1+{U0ݻw,Yce/]t]0-[6lذhѢDGGGݻwϞ={PizrJSSSvvvFFfjCCC'OVt۷o_zu^^^ll,0㏍i:55駟HMMZ&yn:}tSSSEIMM}ϟoL&SNNNJJjU}XeٚymٲEQ/VVV\.J5UChx… 7nܸtҥK޼y3t(>}}}eeeB HJJ^z}2nt9iɴo߾d*"|sΑ4M?3)))111&'Oljjv{IIʕ+Xu:|A}}Xh4>s{/!'& IDATŬ^oyvpm~m˲dYhJf @s`"&~yjHt{{=CL-[l龾χ\NL$xQJvGFF(b:XѼwM1 #i֭KKK@`jj qLV[[[RR>CݎFI G?ڻwovvbA-\Fp8k?:tb|>a奥999oֲIW_}it:v;inn.((H$gϞh9εkrssV}m6L_____"[۟L&/\PPPPVVk׮T Tz!Drٛ7o޽;>ydvvvccmt:ݞ={vhooA8kZJem6y犋j~0q֘CC]QQQZZV?LdEEk(fffQH$2 |> ʼn'^~eXo[V /ͨn|vQg]]򴸸vZZZFFF҃ Iljj:rHnnnGGFLyWFZ˒ X,֝;w\288t:|~MM<ۻ{yBkΟ??<< rss___iff/zcccpX =sG… Bp×.]jmm Z_z5A+/|۾}dhMŋ,k5xKKˎ;kkk_bǍFbr8u|rrf+//7MMMDrŎ .|u.E"W?~||<;vٳ_$IrzzgtttB!Xl6>wƦ/߿o߾P(駟^tivv6 dB@0::rHJwwqu{nuoȦǶZ_XXX\\`0JKKmBh~ zzz>NCT*=ZRRRPP0??vϝ;w…TWᒒ|> e2ى'd2YkkI媨X{}d~~-㩅@ `ِj("x<>11_ a655uɬJ32 _r|XXXh2ʶmvƍ~;cIj_榦h4gPxŶ5v0ldddll2??_әL$ʚ?ݹsgeJyaZ?4 cdddrrr~~___xᅑ@C*yFv{,tҥKH^ azd2y̙7h骳w/IG}p8@[ȋGh%#.4H7[Br166622"4^7 uuufL*b{.x<288( -Awwݻrrr$GaT*J|~8VT8߼y3=١I{ V@Vg4NdfMtݨXvv_d2ggg|~~~`0 555&I"0Z AtuuuuuTݻw:u?^}v @^`0ܹP(t:`(,,ܺu`?OHD|myiN|$^xr>z1 Cu2`P"4Mdz̙t? z36f'?y'\. ^$9RQŰt,۔~ p8<:::22"^ /477k47oNMM4рDkرzttt=*m%@`||0H$Hv; 6f4"y5R+J>,HdTd<>sP@@^<ދx<~ɤTf=zt:M`@`?%(UrllcQQQvvvvv`@E" 4!jKG28QA|m+"H_zl bq-sC=bw}Vƾ&8ߺuKRUWWܼy ? j\n0d2r<<"-ڀ6Ca/RVVM`%'QXX?]'g_M(ݱch|yP("lɋG*/^$Ivtyd2P54Efgn=`nnqoz }}}CoK?)Fd0\;$I:9Bp8p8;vd2[ZZ+HT*WY뼡vD"@_Dg}V___SSc0z{{ݻ(E)Z^W"58叠v{4M_pܹsN3'IFC`Q cʕ+L&s˖-GI$_ ( 7)/LLFNulllϞEEF@9..H\NJ$o\|e```S4- r,OD\Rlǃ N8>22v CIIɅ 2*WCEQ6- ;wT)LVQQ!fgg?! *eZ3cV U(^a0|,,,\zUPttt\~}#'c3bq8Fhie+**P՚)Z79Nj- >aZp8P(˹\ovS93]d2;}AV0 r ^x!MaG1ȡmۗ A2l68p`0|~|---*W^awܱX,DL&3 (uo"W ׮]{饗v /^822x$IQQÇY,TjqPX[[{-rsswa0؆1 SSSAuf}JKKݻFP^)۷GGGq7xMMM9Ny<^vvv]]]ssP(Z]]]k5+211 EEEÇO>C gm۶͛hZΝ; òoF(رcHҥKv=|^/PK:,L&+4qPI؋i?XgbQmmmz]M74-8L&m6Aŭ1 FR---|gx,Y,֩SWYYR۷Ő_.|+A #:ȑ# Xdee)ʵ7wVToݻc999+7{(jGbf: Jx999H'h^6 GࡂZf#D$ "hnnzS y饗f3 p8gΜ(ڵ+''7ܻwojsssWb2wyyyo&*F$˕H$pw؞ϣՊ'N0?O.ٶX,|!+--%NQTkkk$˓:N$qD"|>_{{ݻw\,NwMMMZUbhwey#ZOiz~~:qDeeF)--Fnf={|5F;::JeSSN۹s'\X,/;}5jʻj߈'IVP(B!O&KKK^%}S+)GdLY؞@ p̙ ZP(JH$b١Phiij^v=MheYM-D"@WW2EQdr۩/Mmۍ Ԓz %I2EQhd20֮Cr0 F7 }֟K$*/>-K6%) 2v-e7(=3Lde7$@}-JGދ'H$rF+?vŵ6'cYƞaɐk$d8'udYWk C C e$u-mJNzDz-`(`kh, /{hnŋ7g!p6q4BiȋoI!@:`e`s Xo zOs1 x/xvx/[C( c0쇀)z;zx8ahͧ9H- ^S>?Ѡ{{hD"A-`2h@^c4L&ɤi:''4L&8EQA6!xCab0d0@&_X$IQRE,b9yA Vx\B d2`x"HE',ʋGJqy1L ?D.'ؔ<9鎁M+7krFEX>l-  , X x/ yBx^ȋ¦* */6Lb`{ /8$/`qy#ܴ]xJy4 ̯ 1Y;Jy[4c>cuO 4 d[9+` c0>gf0oS3 2 &L {`Pbn_%*/xo~'g'OOof aBV7~ x~ ? ہ l ^0ߞx /@^ /y  /@^ /yS?EQE4M4@? a3q]f$I$LXlZ@ d8x $MAr ل?iI"X,A /6`2L&3}!!؄?d&d2<fsS 3Z-0 c2,d2I$<ȋodѤ-<@ :)FO3(O':uq#xdr---mB ].W<+q @xVQt䓸&YM^llg$|l6[$FpH$,17~\D"rg(ڿ??y~~}221 wFzH$ڹ>/fR=zt۶m6>[\\% /GO@F"UcB?O]vi.)X7lhhH$ϟp:ECr_{;wXsss߀())9xf;wnLON2Eu8k.[[[X AoVnnnJ55iZbXBrW^yȋ槩#+/@qq֭[њ˭[1 Ájjj^`"xB&?~ `0:??H$xeQs=w񼼼k׮\cm1 o"Mh4?'L_9Uqޒ6L0k.^}U^X*Lfyyynnc0Bt>cD***rj͵;4M߻w;cbryeeht/::: c'??֭W\h(jhhd%Bp,$I8p`ǎ/^|:*))QTCCC `C+hh}gffq BF9x/XXXꫯ\1xyld\9E͡ Z^,"łGFOD"T(---$I j ԩjDa0ǎ CCC~?\|j`i4,&ݻwO:BӴ^ %I2\XX\&H4rss1 c3LdnnɓccchHػwoMMNJxtlW'7xC~\.OoہvUQQpj X9GD"##G yT*Y,嚙StBh4J%A.kaaa||멸Q5͉'˳$IQQQ^^ᘘhooϗ +S B7o^|RI@$I^ph48p3H$:tPvvիW/^А~;;;JJJ***ZZZҳU+**t:]"]#K7773aŒH$0 l;vv2yL#=va^wiiX,RwR>Sg@QTyy~-[pܙBӴ@ YX|qD" N@%:tW^(jZ, Ŷm۪Zɓ'S-w!?|aa띚J$,K"9rd5VE*gaa! 1^/T(;v(++c0'OD#o455dّBaQQQUUd---"@" nprrr:d2_~8~$LOO'I&}"P>@ /oin{ZZZvܙ_UU .p8X,kf9;;e˖2ҥKEEE&ڵk=x@ %IrUUUXTU+֦L&`HիW^:>>vjݻ;V\\|7nl6{  :uSSS4MLm۶߿l6X,6L===ߏF8/,,AdIIѣG-ٳg^:??/ lrX,XIG1CCC_~e[[T(߹sgh80"++ĉgdddel,}KNgVV_z_|HFH҃|zbbO>r{}><000<^XXXγSjΝ555ێX,X<::rڵP(g"@҇tnn.l҆ju$9|$I=A,--VTT>a٩ NBkjzhhH*JRveXH$lUUUF1d9'jіAx (..X_6Ld5E"L&(jiip<Ϙ'*,!J`٣n[(Nfsˮh(bH$BQfC*###zF$BjirXbt:'''Z-k75H.&IQZFh4;wnT[od2m۶:<7;; 㕕D"vmqqQ(c״T'&&nݺWVVL ]r%+b0T*d*))*//`plll~~~ yrjʉ)2m۶uttX֯a}l6_h"!2LǙLJ((GYծ#L&AҥKϟGd2a^곂"_OÇ' =1k׮MNNb{gðNzhܺu+X*ݩ{n.{{{GGG+@dWUU-+h󧾸Dx< /R n-B/^o"P*/bzO$BaCCC^^b^-٥%F޽{dGEu 5j=:Xlaa!XCIT~ MAH$qX,#K]vR]4\.y jALLL1TRRbP ^lskjڶukc{{ٳ_a?{,]]]I---eeeGU(ÉDbND{n155L&3քr\h׌˗/{8JpGGǞ={9D^:==U*Ummmuu`2loo/))|饗(jkkl d2۷ ðs8Ռn,~F)))9qź{tP$|D(R[lwRN>5xl6oݺرcxb& z=aSSSu^بmkkD"B766r8X,,x2Ìh4 555wx_W2[,?A"#_E8~wCuWBP(IDuuu^^*eZ34~qTPPnRLJ?sZm4WWW{<|J~Xp.]h$`@+8HrDDKK'||Gz*98.j5kj~ůzEE:.''wq\_,֭[jZ$?ܶmB?>/J-[oTߥwM$UUUiLVWWtyj KJ̅|͛j@ ryVPGbeܖZt333(ob>0655g 8][nE_|l6s`0r&''o߾k.8 ?tbi3==}Ν3gX,،פi׿hjj2 ;v(9ׯ+]v=qB;?S:%/4M?fsnnnYYvܹsOI>sѩh***lv, Bn{ll *^OˆFߏ555 rWWWs85^z /I?F<}f٥%ZΝw}w``0.2\M"b||?r2ktCdU<陟],H~G\.7oݺdX G^O?` "cd[[pcccAA|sssDbvvVR9 X,/^(+qw7Gy%={lVVݻwE"Qu~*ZM(***i*{L4zIzO"999۶mJ7n{e t:]}}}~~>d2955um]sy/v?+⋦Z힜D@ bFcmmmNNb۷o|>|,==_|by1 sΕ+WX,<`%%%J[wYW gYйs熆S8 tmQQQQ]]-QX^0z:JЂx, uuE5`dy<^uuuEEa텢lWWWw{E"&PX[[[VVv0twwq @$I\7oݽ{w``e`RB&544-..vvvg3PX,\qPX$I шMNڴuA^|;\`&qGؠ)Q}͛7m6ۓ^A CQܜXYϸJB! Bh׌/]<+lȘ?TࠃqJryhٰվkX"z h+@ >ZOmga'Zl쎩hG༼T*iA+> eA;vNm۽~rB4MBťq\&bfx(r: L&cX0|hoFXBB!X,V<n{iH$YYYB0)[6Cr\ 8~J$MZ-ASSS8geer.L& d* DP[ cqW*ف@`ff&u aXv[,j@* .KQT$q~ԑ$???}ԇ%պqcXfb%gQɉD"SSSdr s%J C,Y [[(\wbySRx^F?b2z>;;f:3 ###333,aJbEB!>>>nX^ f977W.Nppܽ{7<p8`0(J@d2I +l6FJF"h4jZBr H$>n{a^/**2 4M{<ñJFP(P@ `ۇW{RiIIFŨI@jͭ-bh,**ʲX,LoM&SiiiF/ڮvttfe4d2d2.6b.kjjjrr2h߾};O&˾fZ rrrv񐜝]lT__ N]>_UUUWW "uߡW^ƒ|F"!9;;i`I9EE&$977h*L&nw$(K򬬬D"p8VS"("WA<g\. o $INWUUr$.)) djZBQTeee]]x'f$t:Z\\D~> 1 ܾԨ"p8l62[gE&i2p\bX:0PXYYx2E0 S&i@^H$211144򍼞l[ (zؚr`u^^^ccNx<~۷o{<χޭA[fgg\x>~EP(lRTTd6].`08<J=98er񦧧- **N$Iϳ욚ԓ |  i H-FeǕE+&IV Bށ"H&}}}@FX,;333>>12eV$d2L`*\=GFFG |>b2L$y< 2V^A4 VVKD2I CTj˅>FURi˵j MӹUUUL&޽{v|>TVj$ɢ"JrS'RUVVV\\z{{{^oƄ ВO_-Bm@cnVp1 ZKKKr`0ͭ ^F.X,R Gd2YII Mӣ2 ^J ^2Z>JJJ(D"dS\@ HVNoDp8LdK$EN'VRXl6 njSx>n2߿a 4D"xk /' LwXZZJg`666ڊLJP_rX!#+̡aL&3L2L^ g.,#lV+J Euuu0Dh @$!T*JsssboN9߿rkjjrssJ\OuBQ^^.&&&fffRrHeF\8]<77Ղ֯S{"0 YZݫZ *** ޾4MKҼ<6i :::zzzHbr"&$J%r""H,c2"`0LBQjr@,MMM !HdddDӕMOO\..k0b{|> dkooɘ˗GN nUp8+?b0pxIF׮]kmmEYzR*^~=T$jHgi7nX,P(ɐ٫N\&S5;;h|\._XXx`9KXe˖FEl62p82~Jںu+FU1Ŕ"\@1&xpfTEX,:$SPUGij}_|x___?E)&IJ$&922:b|Vnٳpnnv؄hdv-),߿R>RrmmmJ/Æ<NgH? @VΘiN&KKKKKKsssaϞ=z)bAIfVPX,\lN2>o X<GU T9A.,,zEQ`0֢@EݞNRBa"pݏ^I4Vr'''m6Q06>>o>Ng0QhƳ&''KKK|H$p8i#WPPfsrrryz6-c(^PP`4-Nr]]]/R /!4uh G"'lvzAA|51ИԲ2RI"G3졡!.sNT*wm MDQD]8#Nl'nӝN:NMq3L߶4m&;m#[|H>n04M~~>TmTC~5NKȩ%%%T4{ZYYܽ{w[[Jz9B/>Ntiwf10*Id2999W^^v&B!# F{M8.lnGOi٬V'''^s~ݠiɤ騐F_mmmcyy{rrr!.bXV͒0LDv811ݽyy]+U㞝 pg4u:ʊiǩP@uAk8Ιu]8圖4Ƶdr9q8jBzbqMMX,tRN tO]S֝x7 *|WlpuuѣGF hlkk+**aXݫP(ƖōmmmfSj6Je}}H$v]ݻw[VZH$:O E$l{^:㸜4-B.]F-F]<ƽ{y޳gRm쵅X^^^j---<ϧ邂N733="8}tvvR_9I+lmxd2iZijw!^FTVVVT*:Դ~GGGԦf2?%%%m3mղt:]QQa2VVVy驧z xw8v/0 SYYY[[+J}>2JRVV&HW߿`0x_xnL&/HJJr:CbinnN4cS"Єt:MEm#)xMMMSSS*J$X&[WR599VKKKѨJt`رcd2Z#-bN'H>ڽ\8*eؘkꨈD"/_Fjkkf;//o~~~pp0;8{aZgϞV TL,r{sN׷^Hӳcǎ rRdCCC¨CeV}RT,Ghm x^iX***d8j Oež>ZQrr szs &v]---ϛLZDB RT*b;DfAT&I"˗/_h.qt;֘477Ӕ׍Kn{aa١ċ;yz. T־9_ވ^=ڪ .\y ôeQQQ:^^^흘.Dk]ꂂh4Ʀ^FeVWWf^ `DVۚx<4hgR+Kl6&''""V.F1N"yPT ٜsim9aahi@xNX,4_QP3\XX`Fח$R:hT** +Th446{!^իVUVKD"AF].‚p0naBQ\\l)LXT*t~山1T*z }>D"\ZZ*...,,TTf&*ryn0hh4\BsF6!v;0SSSƤl6SozF7qp5[_螑NNݫ-KI*>X*tX, 207d2f={ҥK: ɨYM$htngd2D"RW<_ڮ,ꚦ5#(t&uGlЋiY _9pݻgff~_d B/dR)þ ^h@= t/ܦM.Td2@wT#x<[6)A[ 4 8UZ7dWJj:NS6X&)p&T*N:}}9m6\||jmr<\.(J*qMrdhcNTIXVBw3BUSޤҝg}eӧO]ns⥗^nt^ {P)3[Lv<-)ow(I3v/h x/Hnw(B@CH$2ܥ^~n&?<  ]:Og+F3bfgg=fDN[ҳ6 ܼM*ܧF@ @@ @@ @@ @ @ @ @ @ @@ @@ @@ @@ @ $?{cF_ċ;1Xd2t:Nl0 q,˲,w\HR,Zhw y(JQHxqy0$'[ɑ(~0,{6̴":`_7dNw˴pF['rόmh0wԶL&Fo2 m6RD"w^]z8B#Y4#Jګ?UUU%kfL&SVVf6yz,kJJJ8D"M]W*g?o|vٟ;s;*Jm΀~TWWWua漼y~uu5 P //+_ʣ>:>>ll J@FC(RQk,..~'> ;ww׌b;::"/~'Jv"-H6z}"xqgYjn߾8z}mmիWCGypnS[F9O[,zkhh(o6%rquє쪪;vttt466򗿜Nu_>|v,j~at[D.wtt(Q竫{ُ8^ܾԒdj$Ph+֓\&9w~ aǾ}v]YY㏇XZZipyWTGyrWg}Jt=nV=xT*=}t<l.~Fv+'N0 SPPpyK0M]3dDD2dfiiiaa?cO}̙3`?KXF*vvvXl6WVVjx!{ܹP(#bWb~tvvvFќ;{2/ͪͱJz衇bqoo힟d2hZ5柘M^LW}} } 0r\TrmNu˯d2) úcroy|nA @n#$\y;,// 'hĮ]d2YooTμǎ{W~3eOŋ/F2X-))ijj.\z<ϟ;wb;Μc0~~o޽?яdZ%t[o8qWZZzD"199-J_JoƟ'n{1 ĉluuFc,윜T*կ~f/B~~~J={:tRT.-- 9sfOj[OxuO|32lffޚ-e lbxfff||ܹswDgγ>[^^}/Nwttl۶bDw}7l q<@SSF ccc.\8u p|gΜZ >O~BAL&z)100Ɯ088(Ɋ뫫M&S{{{IIɉ'7i&e2 u:Hap8jwuŹ_H$Zj>sZVNavݻ~BsV>Ov*dl6۞={rL&#z}qqq{{3zĉ_T*tw V8;=;|}Ǔ}0|ɣGL& c6|?v\(.xw^y啝;wݻwΝqtzǎ;v`ʕ+OS@ٳ]]]D"H\D/GH$.]:~STw訬|g%sa׶LFVnooO&|j쳟~'OxСCOw ^*x󙒒zkݻF~y(:wܾ}4ͶmFFFPy~||iv M <̎;Vk0Lӵ=Fwx~ww|/]>űcDŽvy={H$z^ONXWW\pի~">WWW~_{2yϟ?|tM( sΧ~W_}ʕ+)===Ta~/yv}~~>Nl{h4 }{ߛ17]]]_җ>tuuB Jc _|ytt4H9rdǎfy~~>L9rC$wH9aG'|СCǎy#t':M@&###:%߿)H-[]]X,6222;;R<|T*FjL4 ,ݻ`0]{ ^;3<<~᮸KRi P,;|u2 DNp896JEX,ƲZybo~9)J T*hD;v,N\-Ca'\n4 &%dLv{>?mVVV.\0::T*7,˞;wvFa].WQQQKKX,d8T*=pJbYnݗ;v\r%S"UTZx>><<69JRobjvttkzm0ST"`YVT*ʛ_$ Dv4@&˓H$t:lԮ3 COC$BX㺾gYV&OT*E{ J ]L7$1 #t {<^do<w:* W$ X,ϯŝ@K7E.W466jh4Z__Ow}wuuUTܮQ=bٳg:d6 s沛u㸷~///w843//7޸۷,Ǐ̞t@zs=/}bTVVNNNfEj0\ZZV{y7nr{eggglFٷo߅ 4555L&;>>,NNNRhliiʎԖaR3EQ"˷o>;;-PiW144tYԓt:O861 CsqE;qd2LVUUE .Dbh͢+\^RRw?LS 4*xO>=88{9v^{uu>oxxx%Bq9>>.yŋx\,ٳ g{J7.kll,//OUȉ`bm ###sss ptڞ={ڵ`0kWꫯ ]]XX~㻢P|mH ühjj8.??>hPDr}Y:oooߵkcZP9_{OOǟ{^x_D"c(J;VUU۷O׿NS$544qM{پ} /pرUa4Muuu"xWPV Tjjj{UTTPߛnH$Νg ^$f2%|䑣{?{/,,d;""<ϻm ^:<c4>\0%  ђuӟ4:tƬK.gϞݤя~R͘y~bbbbbp\ؤ-FyD3ϘLߧ(C{yر+0L8~C'?IS)LӋ(w]i&xΝ;J*++b1~o߾{^d_JEEE>/vuuDrdž D ~iJ"X]]]wɓ'@V__5BPooL5hwnnNRp8JBr X1L.]zjSBAJf"KKKt0 r~>}d2e2u{oyyY0 VVVp#aԑ#GgS|SoOo>d2[š4 siiis HP1H$"B xW._|СjFu{{{?>55>d2,--Oò*~B f?N:k׮Zͦh3gp[\\<{l2e߾}Nz*݉7 יH$RL&UOjFO~/fήwyWՐ8pw molM΍~,˿ۿ[,-vB\f;譶[k_}7yoGLV ð._<<<{I6-yznљhtp)dYh4666Mȯ-J,{OMyFC =F_^^%>kQK*jT~<`2ؘFGFFU3F@-Y]]=w3 'qܑ#G \244 [&oii)))Ȉo6wf"r;$ɾ3gΝ>}Z?yٴ⑑!?ȾHjڝ;w}>߅ hubċAOL~Q<}G[ _ s}{J pk .x&''i-w/nYź4;vҥKp@ ٹn1;w,//n]Ξ={oDIŖ~~㙿{GŲbimmu84=Nsy<{c/n6fG ;D"KK]]]ofgwjqgw!,L&].=VVh4ohO<-b2D 0>>~ܹ@ p/5 U0 DO˗3 ;@t:mZoNQ1<<Qċ}]J|RwT*q:- 󅅅-K"Ƚj ^ܔտӼXIRXa+sNŋ7KR3Sc475?c!v]-zu-{||>봼 ­###PP(zj@?]v ?afQN\rُx5evlh4 aF*t:oD"m۶ݻW$-..k<,B&vn0Ri4|㳳gS(eee:a?11t:WWWeU*Ueejj圝eF"l;vDǏl\.///ohhbǎ[wn6qEEES dz1gF,)D"r&&&:V ///i 7O$Jft:ZL&霚D"9+M&S[[B8u[a ѣGe2Y$o~۶m[ZZ:qD4$I}}}[[[ x11ι[XXEܸ#^Hp UjFb~2 N?DŽ,VTT޽[TDX,F nκD")**/++J;X,*yNW\\v?g6L&X,-徾hl6\.=}4xZ˕]N8y8t݉DBxA4=J-**txWWWE{H$ :|>̜_x1we2ٮ]  L&^#D"0L]]]N>pAaYQXXh4VX,LvG(,Bt8LF7<=ok4_wDΪ/^LtZ@L&D˳4fqqqBETjbbj8Nٹ\PԈ0/.砾Y%}[[[#j(Veٺ|TJ8\vh:>.Jt_H$ XD"j驩) vr|q3bX,<F)њ|{0`'h,˪jZ FytvvZkzL&{zzzzz$eb1a![do<4֤VPLMMӻqRVVݝ2 uxjeggg~?}ʺYpt%{H$299p8˩jHqfy޹j\])?{tz~~~eeE,RZu5eeeFQT꼼T*uyCί8N<Dh4f7k}jݹsgQQʊJl63 s]sRhJ 4ŃpJE4m JrrꏑJp}$Hd2&^;Q%EQ(d2BD"`dϗNWRjW*dzzzppP4D&Q 7/))X,j} IDATZR3 3:::<<=&I$AcP"H*zpXјLp86R)mZKKKtUUU, x Vm6e{{{)TVTT|>*s՞jx`())blx<{fynn̙3B@Z7۹ԤRFFF{kZͲl<_Nz#rD"U*USSH$ʼӛoPe2ϑwpGD>塧Nsݮ ajjj|>pN &i۶mbe`0FiDRYYI.ٽ ~X Jk߁lx<%&A|joE4}9 d*L2OPڠe& G"B̒N+VtT>x^o6y|BӒs$V`0b`0B;}>-!kZAoNN7{yy9 WWW+y ekk+˲/^*9CPRT d2Y}}=}x[պ5Zx:{6*Y۫P(Ƕm*AfI__݁l6BSbq:^XXh hJKKxP]#NLLtwwSkTZUUU[[+P^^}FO<\;D"122qKKKTf Jh۩'md$~LqؘD"5f9D"A|vNqZ55.\|Ϟ=|IIIuuuee%I(UK ee2---9J|M'+**멖D"{졢^o]555TxhDp8| Zaٹ}vNN4G(G!p}T:iM&S]]]QQQ2X,F1+s:4"+(((..fY1JCs;S?j੔gii)=Gx|nnrYfAӚC̙3Ns#-\N5*(Z=ɤ]]]U*VlFљzב0#BT*E\>t:Mmm~e^!tE;ǔldXNMM5440 CtBs511AZ+T* ͐TjqyTٳyyy%%%FR'B!Ǔ]ymI]nQXF6 rj'RTj:J---MMM Œ=!NYVNDzl pݻvtC'RFT +2}#GrMT`ptt4δt<^; Ln4 8J~fQvN9ay2<>>NB5-LvՊ6:$Xq:f`0ѳEZL;{LbqOOl:2 r\xD"r][:Lɍ^OG;LqvڣGGGe(1 >S:0BIc%8N"lbgO'l0"X^PNsr$gOboN"o~gOQhKA!VZO~=B!Mھ+< oxၺo{ӍkDvs/+d :257g#?̵)M$=*JHn˭轸}Tb}u>۽[ر5Tv ^Z-˽^ﺫK}|́4?h _Nj&Enaڼ[k\o 1躎Vv_|+rcgdo?h+g5mIƒk k8.z=0'BD(#+ʫW iS^Zր.JQ^^N+\bZF S?%x&[D"zճ+ iѨj嚘p\{ z%rw2^v41exxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxڻ tMόIHBF66Dz م `  6M9fSrCj_8aBOfHDVf AƶXH3ӷ}:_FK =LZV| /y y @^ @^@^ / /y /y @^xy @^ @^@^ / /y /y y @^@^ /y /y y @^ @^@^ / /y y @^ @^@^ / /y /y y @^@^ /y /y y @^ @^ / /y y @^ @^@^ / /y /y y @^@^ / /y /y y @^ @^ / /y y @^ @^@^ / /y /y @^ @^@^ / /y /y y @^ @^ / /y y @^ @^@^ / /y y @^ @^n{Y]Mt\.7 w}e}dħs3Ky ̋'n{c:-OȲ~ 8U-z~)&$I$AytI%hj 8rr$I.+ a2!/BUt:4MveVj!/ԐbT Q(Baы^{mF/BR(M4MF^ȐpxppR**JTM8(+wh4n~999h4J`HZJB0}aq tvVN4N#/t6<<<00Y T*oL駙dYD3Ǜۼy8V\R̞={`` I6y$ah5VHRrCCCf* o -֊bX GI*JEim 8bΜ9r9͚5kpp0Ͽ+UkNT*ɞ. y'$IFFFr>D wᦻn04-QZ-y0\QTpRyw[PB!p 7 #.! #&x&I鱞*/PV$ >=!Wv;1iZ4"/KdhhX,V*jrvzV<1u<p…8$ +3nwEqWհlסeYTj4\5{(b;šqD{LhZ#nәˍZjl6,VsLE^G,Yr5k?xgdW ۈp[tŋv饗V*{衇׭{^Oߗdq\.4j}*/#*˫V]vM7}3g_u<߿e˳3;H gz(]LMվ?ꪫ >" z¨T*zj7p"/#[h'?ĪUJRppp~gҥ?#zxӦM.x;b$B!lWh={dttthhhquѼysT-8ϟ${Lr\KԔY>+\{} rEzWo[' :8u K|g^ _={׮?Vڼ{g_vŊ6<z{~ٲe?7J<88o}sE.'g~E]/}K.^xA_*W^q._#{mJ Uպ( ZLMMU*fjbЛ&vZ>۵kWfY7lGj6o%w|˖}(<]e[cw ?IDATnMtٲe_sܒ%̟?oɒsy䑿oEBart:퉉(ʲNEv{={ a(Jtllخ(EQկ~u y1I0r??z%/Zhz=W}=Soh4^{5\3gΜ*E]p //KR"˅tK.DQEݹsFQt.?~EW_}- s/.\E 7pWK-Zx[8׷nO-85_ʗV*^5:K/裏>#?O(+n˗'I.\x5sK}]vɀ~F/zϋёё,7oKϟwY{u q뀼fL\G>>122r',j?cy{]{/ippyV\y}?j8zO#X8qP|x0o[|3cK;w\nݺ7L{a;Y8 p&s{V^}w.]z^T:Hܱcڵ_^;h}zm۶'?;N?$ϝ;w3˗{ٴi c߳8Z[S{@eznjr-.]v8=i k|>:##s(:쳿r\ә5kVKs]_ ?44nb YCXO~ w}ه|o޼vΝww?/+V\hѢ[..xgNz"`F"˲+W^|ӯgժUGis)V^zꙺa 8S V甆.FC?׿]͛mv뭷x㍿[,8߾rݺ'뉀:Nv@'LO_g4yWn*/gn<Ÿ=gm^_7~zm^zŋ~Z-<ᰃ=fG `=bŊ??I4MlyvÆ۱cLʆ l߾nZ.P(;v<8Et:֭[$B$P}'W_&n~' ]p{ٲM6Z_^|UV͙3Vmݺuݺ' ?/xZXqhmvve8Xܹs+د{7|7o޼zcll̃Giiv;,G_}cFEQSÝ _yyg㞿y/a;~|nky100O(mN8{ T8wp6,˚f6Ȳjŷ<$˲}cԣч%-c"NaŪV%z8@/֣8pGh4ᄑyRĚ oG(J۷snWm0vtگΝ;s#EGF&''Ӵߕ^ tZVTj6BRrn6[ЇJL-"355qw_xG:V6On۝NV?z{Rg.˥RippP(^jfogwFI>/|H?h4&'';1 8:T$qjjz~X,]JӴVeYV1-ɠnq$I, ̝0t߾}Ǻ,EB!IvNTaڢ۷JZV$B!Fݞj6-q\HX"3I|>NZ[3uӭVkllhq<>>^׏ocy'fj,v6a0s׮]v{rr2 `ߵ 8JZh4Twb#lfqvS^I*lO$ISSSYqg*2BXjݻwݻ7,l6^^'˲,Jz=DFE3NXZݻwnĚV]r\,r۟;jZV8EX{ N aC|>_(&bT*H$GOnhv;M4MC^iJӴ`X 8s99& $| {L۬ 8jczsLϋ m= ף5IENDB`vvmplayer-1.4/data/org.kop316.vvmplayer-daemon.desktop.in.in000066400000000000000000000004631415227045700240310ustar00rootroot00000000000000[Desktop Entry] Name=Visual Voicemail (daemon) Exec=@bindir@/vvmplayer --daemon Icon=org.kop316.vvmplayer Comment=Visaul Voicemail Management application (daemon mode) Keywords=Network; Terminal=false Type=Application Categories=GTK;Network;GNOME; StartupNotify=true NoDisplay=true X-GNOME-AutoRestart=true vvmplayer-1.4/data/org.kop316.vvmplayer.desktop.in.in000066400000000000000000000010221415227045700225600ustar00rootroot00000000000000[Desktop Entry] Name=Visual Voicemail Comment=Visaul Voicemail Management application Exec=@bindir@/vvmplayer # Translators: Do NOT translate. This is an icon file name. Icon=org.kop316.vvmplayer Terminal=false Type=Application StartupNotify=true Categories=GTK;Network;GNOME; # Translators: Do NOT translate the semicolon. keywords should # also end with a semicolon Keywords=Network; DBusActivatable=true # Translators: Do NOT translate or transliterate this text (these are enum types)! X-Purism-FormFactor=Workstation;Mobile; vvmplayer-1.4/data/org.kop316.vvmplayer.gschema.xml000066400000000000000000000027651415227045700223220ustar00rootroot00000000000000 ""

Version of the application Version of the application "Spam" Spam Contact The contact to consider as spam false Delete Spam Contact VVM Autodelete Voicemails from the Spam Contact false Window maximized Window maximized state (300, 600) Window size Window size (width, height). false Dark Theme Dark Theme Enabled. false Override Global Appearence Override Global Appearence Settings. vvmplayer-1.4/data/org.kop316.vvmplayer.service.in000066400000000000000000000001311415227045700221420ustar00rootroot00000000000000[D-BUS Service] Name=org.kop316.vvmplayer Exec=@bindir@/vvmplayer --gapplication-service vvmplayer-1.4/docs/000077500000000000000000000000001415227045700143425ustar00rootroot00000000000000vvmplayer-1.4/docs/help/000077500000000000000000000000001415227045700152725ustar00rootroot00000000000000vvmplayer-1.4/docs/help/C/000077500000000000000000000000001415227045700154545ustar00rootroot00000000000000vvmplayer-1.4/docs/help/C/images/000077500000000000000000000000001415227045700167215ustar00rootroot00000000000000vvmplayer-1.4/docs/help/C/images/icon.png000066400000000000000000000020011415227045700203500ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs\rtEXtSoftwarewww.inkscape.org<tEXtTitleGnome Icon Themexύ+\IDATXMh\UVkm;Q3jTDgTt*nj'I-(ZD2JiUAga+ff=4i*q:3z,踪ڏg "(Đj +hV'XߘХem'lfxD) YYj/oOLnVwr cB{BWmH޳qOĽ銮j66!a0ԧYz+a_xtDf.@P. mv llʠSP~e۞S{3:5zl2;% `23Z|3d\t`?37YJi0 @ޡG~&0īowWnn @\O.咇Գgjkp~]FAE}홑MWi 0qxs/ qWf2aa#V఺8[VZၘ!zv٥-('DeAeHWk0xu]l _ĘN)|Ӽ> Yt\$Evr<;\~it߶]+P̥^ô{5}v2[(w0B7~ŁfP&Z ,UDi Wx uL:y@kYxx1m1ك gfv옲^rgꅉIZS1\?؈?N$7!n;5:ʠsX>1%\7MG}K9|ՌlI렾_ 8}֑(}p@(IENDB`vvmplayer-1.4/docs/help/C/index.page000066400000000000000000000024001415227045700174150ustar00rootroot00000000000000 VVM Player Chris Talbot chris@talbothome.com

Creative Commons Share Alike 4.0

A GTK template application
<media type="image" mime="image/png" its:translate="no" src="images/icon.png" /> VVM Player

VVM Player is a simple GTK application template in C which will help you to develop your own application without much hassles.

VVM Player is not useful by itself. It is supposed to be used as a template for building GTK applications.

Features
vvmplayer-1.4/docs/help/C/legal.xml000066400000000000000000000010561415227045700172640ustar00rootroot00000000000000

This work is licensed under Creative Commons Attribution-ShareAlike 4.0 International license.

As a special exception, the copyright holders give you permission to copy, modify, and distribute the example code contained in this documentation under the terms of your choosing, without restriction.

vvmplayer-1.4/docs/help/C/show-about.page000066400000000000000000000017511415227045700204060ustar00rootroot00000000000000 Chris Talbot chris@talbothome.com

Creative Commons Share Alike 4.0

Learn how to show about dialog
Show about dialog

About dialog shows more info about the application. This include website details, License, etc.

To Open About dialog click on button (menu button) and select About.

vvmplayer-1.4/docs/help/LINGUAS000066400000000000000000000000571415227045700163210ustar00rootroot00000000000000# Please keep this list sorted alphabetically. vvmplayer-1.4/docs/help/meson.build000066400000000000000000000002351415227045700174340ustar00rootroot00000000000000gnome.yelp( 'org.kop316.vvmplayer', sources: [ 'index.page', 'show-about.page', 'legal.xml', ], media : [ 'images/icon.png', ], ) vvmplayer-1.4/docs/man/000077500000000000000000000000001415227045700151155ustar00rootroot00000000000000vvmplayer-1.4/docs/man/meson.build000066400000000000000000000020471415227045700172620ustar00rootroot00000000000000xsltproc = find_program('xsltproc', required: false) if not xsltproc.found() message ('xsltproc not found, disabling man') subdir_done() endif # Disable manpages build_man = false subdir_done() xsltproc_args = [ '--nonet', '--stringparam', 'man.output.quietly', '1', '--stringparam', 'funcsynopsis.style', 'ansi', '--stringparam', 'man.th.extra1.suppress', '1', '--stringparam', 'man.authors.section.enabled', '1', '--stringparam', 'man.copyright.section.enabled', '0', ] man_files = [ [ 'vvmplayer', '1', ], ] foreach man: man_files man_name = man.get(0) man_section = man.get(1, '1') custom_target( '@0@.@1@'.format(man_name, man_section), input: '@0@.xml'.format(man_name), output: '@0@.@1@'.format(man_name, man_section), command: [ xsltproc, xsltproc_args, '-o', '@OUTPUT@', 'http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl', '@INPUT@', ], install: true, install_dir: join_paths(get_option('mandir'), 'man@0@'.format(man_section)), ) endforeach vvmplayer-1.4/docs/man/vvmplayer.xml000066400000000000000000000053051415227045700176670ustar00rootroot00000000000000 vvmplayer GTK Template Developer Chris Talbot vvmplayer 1 User Commands vvmplayer GTK Template Application vvmplayer --dummy EXAMPLE --help --quit --verbose --version Description vvmplayer is a simple GTK application that can be used as a template for developing GTK applications in C. The template contains basic GTK application with meson build script, basic tests using glib test, an example man page, help page using mallard, and gtk-doc documentation, etc. are included. Options The following options are understood: This doesn't exist. Just to show how an optional argument can be added. , Show help options Force quit the application. Any unsaved changes will be lost , Show verbose logs when running. Use multiple times to increase log verbosity. Show version information and exit. This won't quit already running instance of the application. vvmplayer-1.4/docs/meson.build000066400000000000000000000002411415227045700165010ustar00rootroot00000000000000if get_option('help') subdir('help') endif build_man = false if get_option('man') subdir('man') endif if get_option('gtk_doc') subdir('reference') endif vvmplayer-1.4/docs/reference/000077500000000000000000000000001415227045700163005ustar00rootroot00000000000000vvmplayer-1.4/docs/reference/meson.build000066400000000000000000000017161415227045700204470ustar00rootroot00000000000000docs_conf = configuration_data() docs_conf.set('PACKAGE_VERSION', pkg_version) private_headers = [ 'config.h', ] docpath = join_paths(get_option('datadir'), 'gtk-doc', 'html') # External dependencies to fix cross referencing. glib_prefix = dependency('glib-2.0').get_pkgconfig_variable('prefix') glib_docpath = join_paths(glib_prefix, 'share', 'gtk-doc', 'html') gtk_prefix = dependency('gtk+-3.0').get_pkgconfig_variable('prefix') gtk_docpath = join_paths(gtk_prefix, 'share', 'gtk-doc', 'html') docs_version = configure_file( input: 'version.xml.in', output: 'version.xml', configuration: docs_conf, ) gnome.gtkdoc( 'vvmplayer', main_xml: 'vvmplayer-docs.xml', src_dir: [ join_paths(pkg_srcdir, 'src'), join_paths(pkg_builddir, 'src'), ], ignore_headers: private_headers, fixxref_args: [ '--html-dir=@0@'.format(docpath), '--extra-dir=@0@'.format(glib_docpath), '--extra-dir=@0@'.format(gtk_docpath), ], install: true, ) vvmplayer-1.4/docs/reference/version.xml.in000066400000000000000000000000221415227045700211060ustar00rootroot00000000000000@PACKAGE_VERSION@ vvmplayer-1.4/docs/reference/vvmplayer-docs.xml000066400000000000000000000022651415227045700220020ustar00rootroot00000000000000 ]> VVM Player Reference Manual for VVM Player &version; Chris Talbot
chris@talbothome.com
2021 Chris Talbot
API Reference API Index
vvmplayer-1.4/docs/reference/vvmplayer-sections.txt000066400000000000000000000010421415227045700227100ustar00rootroot00000000000000
vvmplayer-utils vvmplayer_utils_get_main_thread VVMPLAYER_IS_MAIN_THREAD
vvmplayer-application VvmApplication VvmApplication vvmplayer_application_new
vvmplayer-settings VvmSettings VvmSettings vvmplayer_settings_new vvmplayer_settings_get_is_first_run vvmplayer_settings_get_window_maximized vvmplayer_settings_set_window_maximized vvmplayer_settings_get_window_geometry vvmplayer_settings_set_window_geometry
vvmplayer-1.4/meson.build000066400000000000000000000115531415227045700155610ustar00rootroot00000000000000project( 'vvmplayer', 'c', version: '1.4', meson_version: '>= 0.50.0', license: 'GPL3+', default_options: [ 'c_std=gnu11', 'warning_level=1', 'buildtype=debugoptimized' ]) pkg_name = meson.project_name() pkg_id = 'org.kop316.vvmplayer' pkg_version = meson.project_version() pkg_is_debug = get_option('buildtype').startswith('debug') pkg_prefix = get_option('prefix') pkg_srcdir = meson.source_root() pkg_builddir = meson.build_root() pkg_bindir = join_paths(pkg_prefix, get_option('bindir')) pkg_libdir = join_paths(pkg_prefix, get_option('libdir')) pkg_localedir = join_paths(pkg_prefix, get_option('localedir')) pkg_datadir = join_paths(pkg_prefix, get_option('datadir')) pkg_schemadir = join_paths(pkg_datadir, 'glib-2.0', 'schemas') pkg_po_dir = join_paths(pkg_srcdir, 'po') top_inc = include_directories('.') src_inc = include_directories('src') gnome = import('gnome') i18n = import('i18n') cc = meson.get_compiler('c') conf = configuration_data() conf.set('NDEBUG', (not pkg_is_debug)) conf.set('G_DISABLE_ASSERT', (not pkg_is_debug)) conf.set('G_DISABLE_CAST_CHECKS', (not pkg_is_debug)) conf.set_quoted('GETTEXT_PACKAGE', pkg_name) conf.set_quoted('PACKAGE_NAME', pkg_name) conf.set_quoted('PACKAGE_VERSION', pkg_version) conf.set_quoted('PACKAGE_ID', pkg_id) conf.set_quoted('PACKAGE_LOCALE_DIR', pkg_localedir) if get_option('help') conf.set_quoted('PACKAGE_HELP_URL', 'help:' + pkg_id) else conf.set_quoted('PACKAGE_HELP_URL', 'https://gitlab.com/kop316/vvmd/wikis/home') endif configure_file( output: 'config.h', configuration: conf, ) run_conf = configuration_data() run_conf.set('BUILD_DIR', meson.current_build_dir()) configure_file( input: 'run.in', output: 'run', configuration: run_conf, ) common_flags = [ '-DHAVE_CONFIG_H', '-D_FORTIFY_SOURCE=2', '-DG_LOG_USE_STRUCTURED', ] add_global_arguments(common_flags, language: 'c') c_link_args = cc.get_supported_arguments( ['-fasynchronous-unwind-tables', '-fno-strict-aliasing', '-Wall', '-Wcast-align', '-Wdate-time', '-Werror=format-security', '-Werror=implicit-function-declaration', '-Werror=pointer-to-int-cast', '-Werror=redundant-decls', '-Werror=return-type', '-Werror=vla', '-Werror=write-strings', '-Wfloat-equal', '-Wformat=2', '-Wimplicit-fallthrough', '-Wlogical-op', '-Wmissing-format-attribute', '-Wmissing-include-dirs', '-Wmissing-prototypes', '-Wnested-externs', '-Wold-style-declaration', '-Wold-style-definition', '-Wpointer-arith', '-Wshadow', '-Wswitch-default', '-Wswitch-enum', '-Wtrigraphs', '-Wunused', '-pipe', ]) if cc.get_id() == 'msvc' warning('Your compiler doesn\'t support C99/C11 features.' + ' Please use MinGW or native GNU/Linux') endif pkg_dep = [ dependency('gio-2.0', version: '>= 2.50'), dependency('gtk+-3.0', version: '>= 3.22.0'), dependency('libebook-contacts-1.2'), dependency('libebook-1.2'), dependency('libhandy-1', version: '>= 1.0.0'), dependency('gstreamer-1.0', version : '>1.16'), dependency('gstreamer-pbutils-1.0', version : '>1.0'), dependency('libcallaudio-0.1'), ] subdir('src') subdir('data') subdir('docs') if get_option('tests') subdir('tests') endif if get_option('po') subdir('po') endif if get_option('bash_completion') subdir('completion') endif meson.add_install_script('build-aux/meson_post_install.py') run_target('make-po', command: [ find_program('build-aux/make_po.sh'), pkg_name, meson.current_build_dir(), join_paths(pkg_srcdir, 'po'), ]) run_target('make-help-po', command: [ find_program('build-aux/make_po.sh'), pkg_id, meson.current_build_dir(), join_paths(pkg_srcdir, 'docs/help'), 'help-', 'true', ]) system = host_machine.system() if system == 'linux' system = 'GNU/Linux' endif output = '\n ' + pkg_name + ' ' + pkg_version + '\n' output += ' ==============================\n\n' output += ' prefix: ' + pkg_prefix + '\n' output += ' compiler: ' + cc.get_id() + ' ' + cc.version()+ '\n' output += ' compiler args: ' + ' '.join(c_link_args) + '\n' output += ' build type: ' + get_option('buildtype') + '\n' output += ' host system: ' + system + '\n' output += ' tests: ' + get_option('tests').to_string() + '\n' output += ' manpage: ' + build_man.to_string() + '\n' output += ' documentation: ' + get_option('gtk_doc').to_string() + '\n' output += ' translations: ' + get_option('po').to_string() + '\n' output += ' help: ' + get_option('help').to_string() + '\n' output += ' bash-completion: ' + get_option('bash_completion').to_string() + '\n' message(output) vvmplayer-1.4/meson_options.txt000066400000000000000000000013051415227045700170460ustar00rootroot00000000000000option('man', type: 'boolean', value: true, description: 'Enable generating man pages') option('bash_completion', type: 'boolean', value: true, description: 'Enable bash completion') option('po', type: 'boolean', value: true, description: 'Enable translations') option('help', type: 'boolean', value: false, description: 'Build help documentation') option('gtk_doc', type: 'boolean', value: false, description: 'Build code documentation') option('tests', type: 'boolean', value: true, description: 'Build tests') option('network_tests', type: 'boolean', value: true, description: 'Enable tests that requires network') option('optimize', type: 'boolean', value: false, description: 'Optimize installer files') vvmplayer-1.4/po/000077500000000000000000000000001415227045700140305ustar00rootroot00000000000000vvmplayer-1.4/po/LINGUAS000066400000000000000000000000621415227045700150530ustar00rootroot00000000000000# Please keep this list sorted alphabetically. ar vvmplayer-1.4/po/Makevars000066400000000000000000000055341415227045700155330ustar00rootroot00000000000000# Makefile variables for PO directory in any package using GNU gettext. # Usually the message domain is the same as the package name. DOMAIN = $(GETTEXT_DOMAIN) # These two variables depend on the location of this directory. subdir = po top_builddir = .. # These options get passed to xgettext. XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ \ --keyword=C_:1c,2 --keyword=NC_:1c,2 \ --keyword=g_dngettext:2,3 \ --flag=g_dngettext:2:pass-c-format \ --flag=g_strdup_printf:1:c-format \ --flag=g_string_printf:2:c-format \ --flag=g_string_append_printf:2:c-format \ --flag=g_error_new:3:c-format \ --flag=g_set_error:4:c-format \ --flag=g_markup_printf_escaped:1:c-format \ --flag=g_log:3:c-format \ --flag=g_print:1:c-format \ --flag=g_printerr:1:c-format \ --flag=g_printf:1:c-format \ --flag=g_fprintf:2:c-format \ --flag=g_sprintf:2:c-format \ --flag=g_snprintf:3:c-format # This is the copyright holder that gets inserted into the header of the # $(DOMAIN).pot file. Set this to the copyright holder of the surrounding # package. (Note that the msgstr strings, extracted from the package's # sources, belong to the copyright holder of the package.) Translators are # expected to transfer the copyright for their translations to this person # or entity, or to disclaim their copyright. The empty string stands for # the public domain; in this case the translators are expected to disclaim # their copyright. COPYRIGHT_HOLDER = Translation copyright holder # This is the email address or URL to which the translators shall report # bugs in the untranslated strings: # - Strings which are not entire sentences, see the maintainer guidelines # in the GNU gettext documentation, section 'Preparing Strings'. # - Strings which use unclear terms or require additional context to be # understood. # - Strings which make invalid assumptions about notation of date, time or # money. # - Pluralisation problems. # - Incorrect English spelling. # - Incorrect formatting. # It can be your email address, or a mailing list address where translators # can write to without being subscribed, or the URL of a web page through # which the translators can contact you. MSGID_BUGS_ADDRESS = # This is the list of locale categories, beyond LC_MESSAGES, for which the # message catalogs shall be used. It is usually empty. EXTRA_LOCALE_CATEGORIES = # Ignore the timestamp of the .pot file, as git clones do not have # deterministic timestamps, and .po files are updated by translators # (only) in GNOME projects. PO_DEPENDS_ON_POT = no # This tells whether or not to forcibly update $(DOMAIN).pot and # regenerate PO files on "make dist". Possible values are "yes" and # "no". Set this to no if the POT file and PO files are maintained # externally. DIST_DEPENDS_ON_UPDATE_PO = no vvmplayer-1.4/po/POTFILES.in000066400000000000000000000006401415227045700156050ustar00rootroot00000000000000# List of source files containing translatable strings. # Please keep this file sorted alphabetically. data/metainfo/org.kop316.vvmplayer.metainfo.xml.in data/org.kop316.vvmplayer.desktop.in.in data/org.kop316.vvmplayer.gschema.xml src/vvmplayer-application.c src/vvmplayer-window.c src/resources/ui/vvmplayer-window.ui src/resources/ui/vvmplayer-preferences-window.ui src/resources/ui/vvmplayer-voicemail-window.ui vvmplayer-1.4/po/POTFILES.skip000066400000000000000000000001611415227045700161430ustar00rootroot00000000000000# List of source files that should *NOT* be translated. # Please keep this file sorted alphabetically. src/main.cvvmplayer-1.4/po/ar.po000066400000000000000000000022301415227045700147670ustar00rootroot00000000000000# Arabic translations for vvmplayer package. # Copyright (C) 2018 THE vvmplayer'S COPYRIGHT HOLDER # This file is distributed under the same license as the vvmplayer package. # Automatically generated, 2018. # msgid "" msgstr "" "Project-Id-Version: vvmplayer\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2018-08-19 12:49+0530\n" "PO-Revision-Date: 2018-08-19 12:49+0530\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" "Language: ar\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: data/org.kop316.vvmplayer.desktop.in:3 src/vvmplayer-application.c:74 #: src/vvmplayer-application.c:220 msgid "VVM Player" msgstr "" #: data/org.kop316.vvmplayer.desktop.in:4 msgid "Template for GTK Applications" msgstr "" #. Translators: Do NOT translate. This is icon name. #: data/org.kop316.vvmplayer.desktop.in:7 msgid "org.kop316.vvmplayer" msgstr "" #: src/vvmplayer-application.c:53 msgid "Quit all running instances of the application" msgstr "" #: src/vvmplayer-application.c:57 msgid "Show release version" msgstr "" #: src/vvmplayer-application.c:81 msgid "translator-credits" msgstr "" vvmplayer-1.4/po/meson.build000066400000000000000000000000521415227045700161670ustar00rootroot00000000000000i18n.gettext('vvmplayer', preset: 'glib') vvmplayer-1.4/run.in000077500000000000000000000001661415227045700145540ustar00rootroot00000000000000#!/usr/bin/env sh set -e export GSETTINGS_SCHEMA_DIR="@BUILD_DIR@/data" set -x exec "@BUILD_DIR@/src/vvmplayer" "$@" vvmplayer-1.4/src/000077500000000000000000000000001415227045700142015ustar00rootroot00000000000000vvmplayer-1.4/src/main.c000066400000000000000000000031661415227045700152770ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ /* main.c * * Copyright 2021 Chris Talbot * * This program is free software: you can 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 . * * Author(s): * Chris Talbot * * SPDX-License-Identifier: GPL-3.0-or-later */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include #include #include "vvmplayer-utils.h" #include "vvmplayer-application.h" #include "vvmplayer-log.h" int main (int argc, char *argv[]) { g_autoptr(VvmApplication) application = NULL; g_assert (VVMPLAYER_IS_MAIN_THREAD ()); /* Initialize GStreamer */ gst_init (&argc, &argv); vvmplayer_log_init (); g_set_prgname (PACKAGE_ID); application = vvmplayer_application_new (); setlocale (LC_ALL, ""); bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); textdomain (GETTEXT_PACKAGE); return g_application_run (G_APPLICATION (application), argc, argv); } vvmplayer-1.4/src/meson.build000066400000000000000000000021641415227045700163460ustar00rootroot00000000000000src = [] revision_tag = vcs_tag( input: 'version.h.in', output: 'version.h', ) pkg_dep += declare_dependency(sources: revision_tag) resources = gnome.compile_resources( 'resources', 'resources/vvmplayer.gresource.xml', source_dir: 'resources', c_name: '_vvmplayer', ) libsrc = [ 'vvmplayer-contact.c', 'vvmplayer-contact-provider.c', 'vvmplayer-log.c', 'vvmplayer-notification.c', 'vvmplayer-preferences-window.c', 'vvmplayer-settings.c', 'vvmplayer-utils.c', 'vvmplayer-voicemail-window.c', 'vvmplayer-vvmd.c', 'vvmplayer-window.c', ] libvvmplayer = both_libraries( 'vvmplayer', libsrc, install: false, include_directories: top_inc, dependencies: pkg_dep, ) ui_files = files( 'resources/ui/vvmplayer-window.ui', 'resources/ui/vvmplayer-preferences-window.ui', 'resources/ui/vvmplayer-voicemail-window.ui', ) src += [ 'main.c', 'vvmplayer-application.c', revision_tag, resources, ] executable( 'vvmplayer', src, install: true, gui_app: true, link_args: c_link_args, link_with: libvvmplayer.get_static_lib(), include_directories: top_inc, dependencies: pkg_dep, ) vvmplayer-1.4/src/resources/000077500000000000000000000000001415227045700162135ustar00rootroot00000000000000vvmplayer-1.4/src/resources/css/000077500000000000000000000000001415227045700170035ustar00rootroot00000000000000vvmplayer-1.4/src/resources/css/gtk.css000066400000000000000000000000001415227045700202700ustar00rootroot00000000000000vvmplayer-1.4/src/resources/ui/000077500000000000000000000000001415227045700166305ustar00rootroot00000000000000vvmplayer-1.4/src/resources/ui/vvmplayer-preferences-window.ui000066400000000000000000000415671415227045700250350ustar00rootroot00000000000000 vvmplayer-1.4/src/resources/ui/vvmplayer-voicemail-window.ui000066400000000000000000000074421415227045700244760ustar00rootroot00000000000000 vvmplayer-1.4/src/resources/ui/vvmplayer-window.ui000066400000000000000000000074671415227045700225370ustar00rootroot00000000000000 1 vertical 12 1 _Preferences 1 _Help app.help 1 _About VVM Player vvmplayer-1.4/src/resources/vvmplayer.gresource.xml000066400000000000000000000006011415227045700227540ustar00rootroot00000000000000 ui/vvmplayer-window.ui ui/vvmplayer-preferences-window.ui ui/vvmplayer-voicemail-window.ui css/gtk.css vvmplayer-1.4/src/version.h.in000066400000000000000000000015651415227045700164530ustar00rootroot00000000000000/* version.h.in * * Copyright 2021 Chris Talbot * * This program is free software: you can 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 . * * Authors: * Chris Talbot * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #define PACKAGE_VCS_VERSION "@VCS_TAG@" vvmplayer-1.4/src/vvmplayer-application.c000066400000000000000000000235431415227045700207020ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ /* vvmplayer-application.c * * Copyright 2021 Chris Talbot * * This program is free software: you can 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 . * * Author(s): * Chris Talbot * * SPDX-License-Identifier: GPL-3.0-or-later */ #define G_LOG_DOMAIN "vvmplayer-application" #ifdef HAVE_CONFIG_H # include "config.h" # include "version.h" #endif #include #include #include #include "vvmplayer-window.h" #include "vvmplayer-application.h" #include "vvmplayer-log.h" #include "vvmplayer-vvmd.h" /** * SECTION: vvmplayer-application * @title: VvmApplication * @short_description: Base Application class * @include: "vvmplayer-application.h" */ struct _VvmApplication { GtkApplication parent_instance; int daemon; int daemon_running; VvmSettings *settings; VvmVvmd *backend; GtkWindow *main_window; }; G_DEFINE_TYPE (VvmApplication, vvmplayer_application, GTK_TYPE_APPLICATION) enum { SIGNAL_MAIN_WINDOW_CLOSED, N_SIGNALS }; static guint signals[N_SIGNALS]; static gboolean cmd_verbose_cb (const char *option_name, const char *value, gpointer data, GError **error); static GOptionEntry cmd_options[] = { { "quit", 0, G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, NULL, N_("Quit all running instances of the application"), NULL }, { "daemon", 0, G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, NULL, N_("Whether to present the main window on startup"), NULL }, { "verbose", 'v', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, cmd_verbose_cb, N_("Show verbose logs"), NULL }, { "version", 0, G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, NULL, N_("Show release version"), NULL }, { NULL } }; static gboolean cmd_verbose_cb (const char *option_name, const char *value, gpointer data, GError **error) { vvmplayer_log_increase_verbosity (); return TRUE; } static void vvmplayer_application_show_help (GSimpleAction *action, GVariant *parameter, gpointer user_data) { GtkWindow *window; g_autoptr(GError) error = NULL; window = gtk_application_get_active_window (GTK_APPLICATION (user_data)); if (!gtk_show_uri_on_window (window, PACKAGE_HELP_URL, GDK_CURRENT_TIME, &error)) g_warning ("Failed to launch help: %s", error->message); } static int vvmplayer_application_handle_local_options (GApplication *application, GVariantDict *options) { VvmApplication *self = (VvmApplication *)application; if (g_variant_dict_contains (options, "version")) { g_print ("%s %s\n", PACKAGE_NAME, PACKAGE_VCS_VERSION); return 0; } self->daemon = FALSE; if (g_variant_dict_contains (options, "daemon")) { if (self->main_window) { g_warning ("Cannot set application as a daemon" " because application is already started"); return -1; } /* Hold application only the first time daemon mode is set */ if (!self->daemon_running) { g_application_hold (application); } self->daemon = TRUE; } return -1; } static void vvmplayer_application_add_actions (VvmApplication *self) { static const GActionEntry app_entries[] = { { "help", vvmplayer_application_show_help }, }; struct { const char *action; const char *accel[2]; } accels[] = { { "app.help", { "F1", NULL } }, }; g_assert (VVMPLAYER_IS_APPLICATION (self)); g_action_map_add_action_entries (G_ACTION_MAP (self), app_entries, G_N_ELEMENTS (app_entries), self); for (gsize i = 0; i < G_N_ELEMENTS (accels); i++) gtk_application_set_accels_for_action (GTK_APPLICATION (self), accels[i].action, accels[i].accel); } static void vvmplayer_application_startup (GApplication *application) { VvmApplication *self = (VvmApplication *)application; g_autoptr(GtkCssProvider) css_provider = NULL; g_info ("%s %s, git version: %s", PACKAGE_NAME, PACKAGE_VERSION, PACKAGE_VCS_VERSION); G_APPLICATION_CLASS (vvmplayer_application_parent_class)->startup (application); self->daemon_running = FALSE; hdy_init (); vvmplayer_application_add_actions (self); g_set_application_name (_("VVM Player")); gtk_window_set_default_icon_name (PACKAGE_ID); self->settings = vvm_settings_get_default (); self->backend = vvm_vvmd_get_default (); css_provider = gtk_css_provider_new (); gtk_css_provider_load_from_resource (css_provider, "/org/kop316/vvmplayer/css/gtk.css"); gtk_style_context_add_provider_for_screen (gdk_screen_get_default (), GTK_STYLE_PROVIDER (css_provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); } static int vvmplayer_application_command_line (GApplication *application, GApplicationCommandLine *command_line) { GVariantDict *options; options = g_application_command_line_get_options_dict (command_line); /* * NOTE: g_application_quit() is almost always a bad idea. * This simply kills the application. So active process like * Saving file will get stopped midst the process. If you * find it bad, find your luck with g_application_release() */ if (g_variant_dict_contains (options, "quit")) { g_application_quit (application); return 0; } g_application_activate (application); return 0; } gboolean on_widget_deleted(GtkWidget *widget, GdkEvent *event, gpointer data) { VvmApplication *self = (VvmApplication *)data; g_autoptr (GError) error = NULL; gboolean hide_on_del = FALSE; gboolean ret; /* If we are not running in daemon mode, hide the window and reset speaker button */ if (self->daemon) { hide_on_del = gtk_widget_hide_on_delete (widget); vvmplayer_window_set_speaker_button (VVMPLAYER_WINDOW (self->main_window), FALSE); } g_signal_emit_by_name (self, "main-window-closed", 0); g_debug ("Setting audio profile to back to default"); ret = call_audio_select_mode (CALL_AUDIO_MODE_DEFAULT, &error); if (!ret && error) g_warning ("Failed to switch profile: %s", error->message); return hide_on_del; } static void vvmplayer_application_activate (GApplication *application) { VvmApplication *self = (VvmApplication *)application; if (!self->main_window) { self->main_window = GTK_WINDOW (vvmplayer_window_new (GTK_APPLICATION (self), self->settings)); g_object_add_weak_pointer (G_OBJECT (self->main_window), (gpointer *)&self->main_window); g_signal_connect(G_OBJECT(self->main_window), "delete-event", G_CALLBACK(on_widget_deleted), application); } if ((!self->daemon && !self->daemon_running) || (self->daemon_running)) { GtkSettings *gtk_settings = gtk_settings_get_default (); int prefer_dark_theme; int default_dark_theme_pref; self->main_window = gtk_application_get_active_window (GTK_APPLICATION (self)); g_object_get (gtk_settings, "gtk-application-prefer-dark-theme", &default_dark_theme_pref, NULL); vvmplayer_settings_set_default_dark_theme_pref (self->settings, default_dark_theme_pref); if (vvmplayer_settings_get_override_global_appearence_pref (self->settings)) { prefer_dark_theme = vvmplayer_settings_get_dark_theme (self->settings); g_object_set (gtk_settings, "gtk-application-prefer-dark-theme", prefer_dark_theme, NULL); } gtk_window_present (GTK_WINDOW (self->main_window)); } else { self->daemon_running = TRUE; } } static void vvmplayer_application_finalize (GObject *object) { VvmApplication *self = (VvmApplication *)object; VVMPLAYER_TRACE_MSG ("disposing application"); g_clear_object (&self->settings); g_clear_object (&self->backend); G_OBJECT_CLASS (vvmplayer_application_parent_class)->finalize (object); } static void vvmplayer_application_class_init (VvmApplicationClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GApplicationClass *application_class = G_APPLICATION_CLASS (klass); signals [SIGNAL_MAIN_WINDOW_CLOSED] = g_signal_new ("main-window-closed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0); object_class->finalize = vvmplayer_application_finalize; application_class->handle_local_options = vvmplayer_application_handle_local_options; application_class->startup = vvmplayer_application_startup; application_class->command_line = vvmplayer_application_command_line; application_class->activate = vvmplayer_application_activate; } static void vvmplayer_application_init (VvmApplication *self) { g_application_add_main_option_entries (G_APPLICATION (self), cmd_options); } VvmApplication * vvmplayer_application_new (void) { return g_object_new (VVMPLAYER_TYPE_APPLICATION, "application-id", PACKAGE_ID, "flags", G_APPLICATION_HANDLES_COMMAND_LINE, "register-session", TRUE, NULL); } vvmplayer-1.4/src/vvmplayer-application.h000066400000000000000000000024521415227045700207030ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ /* vvmplayer-application.h * * Copyright 2021 Chris Talbot * * This program is free software: you can 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 . * * Author(s): * Chris Talbot * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include "vvmplayer-settings.h" G_BEGIN_DECLS #define VVMPLAYER_APPLICATION_DEFAULT() ((VvmApplication *)g_application_get_default ()) #define VVMPLAYER_TYPE_APPLICATION (vvmplayer_application_get_type ()) G_DECLARE_FINAL_TYPE (VvmApplication, vvmplayer_application, VVMPLAYER, APPLICATION, GtkApplication) VvmApplication *vvmplayer_application_new (void); G_END_DECLS vvmplayer-1.4/src/vvmplayer-contact-provider.c000066400000000000000000000316401415227045700216570ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ /* vvm-contact-provider.c * * Copyright 2020 Purism SPC * 2021 Chris Talbot * * Author(s): * Mohammed Sadiq * Chris Talbot * * This program is free software: you can 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 . */ /* See https://gitlab.gnome.org/GNOME/evolution-data-server/-/issues/332#note_1107764 */ #define EDS_DISABLE_DEPRECATED #define G_LOG_DOMAIN "vvmplayer-contact-provider" #ifdef HAVE_CONFIG_H # include "config.h" # include "version.h" #endif #include #include "vvmplayer-contact-provider.h" #define PHONE_SEXP "(contains 'phone' '')" struct _VvmEds { GObject parent_instance; ESourceRegistry *source_registry; GCancellable *cancellable; /* contacts to be saved to contacts_list */ GPtrArray *contacts_array; GListStore *eds_view_list; GListStore *contacts_list; guint providers_to_load; gboolean is_ready; }; G_DEFINE_TYPE (VvmEds, vvm_eds, G_TYPE_OBJECT) enum { PROP_0, PROP_IS_READY, N_PROPS }; static GParamSpec *properties[N_PROPS]; static void eds_find_contact_index (VvmEds *self, const char *uid, guint *position, guint *count) { const char *old_uid; guint n_items, i; gboolean match; g_assert (VVM_IS_EDS (self)); g_assert (position && count); g_assert (uid && *uid); n_items = g_list_model_get_n_items (G_LIST_MODEL (self->contacts_list)); *position = *count = 0; for (i = 0; i < n_items; i++) { g_autoptr(VvmContact) contact = NULL; contact = g_list_model_get_item (G_LIST_MODEL (self->contacts_list), i); old_uid = vvm_contact_get_uid (contact); match = g_str_equal (old_uid, uid); /* The list is sorted. Find the first match and total count. */ if (!*count && match) *position = i, *count = 1; else if (match) /* Subsequent matches */ ++*count; else if (*position) /* We moved past the last match */ break; } } static void vvm_eds_load_contact (VvmEds *self, EContact *contact, EContactField field_id) { g_autoptr(GList) attributes = NULL; g_assert (VVM_IS_EDS (self)); g_assert (E_IS_CONTACT (contact)); /* Only container should be freed, attribute is freed in VvmContact */ attributes = e_contact_get_attributes (contact, field_id); for (GSList *l = (GSList *)attributes; l != NULL; l = l->next) { g_autofree char *value = NULL; value = e_vcard_attribute_get_value (l->data); if (value && *value) g_ptr_array_add (self->contacts_array, vvm_contact_new (contact, l->data)); } } static void vvm_eds_remove_contact (VvmEds *self, const char *uid) { guint position, count; g_assert (VVM_IS_EDS (self)); eds_find_contact_index (self, uid, &position, &count); if (count) g_list_store_splice (self->contacts_list, position, count, NULL, 0); } static void vvm_eds_objects_added_cb (VvmEds *self, const GSList *objects, EBookClientView *view) { g_assert (VVM_IS_EDS (self)); g_assert (E_IS_BOOK_CLIENT_VIEW (view)); if (!self->contacts_array) self->contacts_array = g_ptr_array_new_full (100, g_object_unref); for (GSList *l = (GSList *)objects; l != NULL; l = l->next) { vvm_eds_load_contact (self, l->data, E_CONTACT_TEL); } g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_IS_READY]); } static void vvm_eds_objects_modified_cb (VvmEds *self, const GSList *objects, EBookClientView *view) { g_assert (VVM_IS_EDS (self)); g_assert (E_IS_BOOK_CLIENT_VIEW (view)); for (GSList *l = (GSList *)objects; l != NULL; l = l->next) vvm_eds_remove_contact (self, e_contact_get_const (l->data, E_CONTACT_UID)); vvm_eds_objects_added_cb (self, objects, view); g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_IS_READY]); } static void vvm_eds_objects_removed_cb (VvmEds *self, const GSList *objects, EBookClientView *view) { g_assert (VVM_IS_EDS (self)); g_assert (E_IS_BOOK_CLIENT_VIEW (view)); for (GSList *node = (GSList *)objects; node; node = node->next) vvm_eds_remove_contact (self, node->data); g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_IS_READY]); } static void vvm_eds_load_complete_cb (VvmEds *self) { g_autoptr(GPtrArray) array = NULL; if (!self->contacts_array || !self->contacts_array->len) return; array = g_steal_pointer (&self->contacts_array); g_list_store_splice (self->contacts_list, 0, 0, array->pdata, array->len); self->is_ready = TRUE; g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_IS_READY]); } static void vvm_eds_get_view_cb (GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(VvmEds) self = user_data; EBookClient *client = E_BOOK_CLIENT (object); EBookClientView *client_view; g_autoptr(GError) error = NULL; g_assert (VVM_IS_EDS (self)); g_assert (E_IS_BOOK_CLIENT (client)); e_book_client_get_view_finish (E_BOOK_CLIENT (client), result, &client_view, &error); if (error) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) g_warning ("Error: %s", error->message); return; } g_list_store_append (self->eds_view_list, client_view); g_object_unref (client_view); g_signal_connect_object (client_view, "objects-added", G_CALLBACK (vvm_eds_objects_added_cb), self, G_CONNECT_SWAPPED); g_signal_connect_object (client_view, "objects-modified", G_CALLBACK (vvm_eds_objects_modified_cb), self, G_CONNECT_SWAPPED); g_signal_connect_object (client_view, "objects-removed", G_CALLBACK (vvm_eds_objects_removed_cb), self, G_CONNECT_SWAPPED); g_signal_connect_object (client_view, "complete", G_CALLBACK (vvm_eds_load_complete_cb), self, G_CONNECT_SWAPPED); e_book_client_view_start (client_view, &error); if (error) g_warning ("Error: %s", error->message); } static void vvm_eds_client_connected_cb (GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(VvmEds) self = user_data; EClient *client; g_autoptr(GError) error = NULL; g_assert (VVM_IS_EDS (self)); client = e_book_client_connect_finish (result, &error); if (!error) { ESourceOffline *extension; ESource *source; source = e_client_get_source (client); extension = e_source_get_extension (source, E_SOURCE_EXTENSION_OFFLINE); e_source_offline_set_stay_synchronized (extension, TRUE); e_source_registry_commit_source_sync (self->source_registry, source, self->cancellable, &error); } if (error) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) g_warning ("Error: %s", error->message); g_clear_object (&client); return; } e_book_client_get_view (E_BOOK_CLIENT (client), PHONE_SEXP, NULL, vvm_eds_get_view_cb, g_object_ref (self)); g_clear_object (&client); } static void vvm_eds_load_contacts (VvmEds *self) { GList *sources; g_assert (VVM_IS_EDS (self)); g_assert (E_IS_SOURCE_REGISTRY (self->source_registry)); sources = e_source_registry_list_sources (self->source_registry, E_SOURCE_EXTENSION_ADDRESS_BOOK); for (GList *l = sources; l != NULL; l = l->next) { self->providers_to_load++; e_book_client_connect (l->data, -1, /* timeout seconds */ NULL, vvm_eds_client_connected_cb, g_object_ref (self)); } g_list_free_full (sources, g_object_unref); } static void vvm_eds_registry_new_finish_cb (GObject *object, GAsyncResult *result, gpointer user_data) { g_autoptr(VvmEds) self = user_data; g_autoptr(GError) error = NULL; g_assert (VVM_IS_EDS (self)); self->source_registry = e_source_registry_new_finish (result, &error); if (!error) vvm_eds_load_contacts (self); else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) g_warning ("Error: %s", error->message); } static void vvm_eds_load (VvmEds *self) { g_assert (VVM_IS_EDS (self)); g_assert (G_IS_CANCELLABLE (self->cancellable)); e_source_registry_new (self->cancellable, vvm_eds_registry_new_finish_cb, g_object_ref (self)); } static void vvm_eds_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { VvmEds *self = (VvmEds *)object; switch (prop_id) { case PROP_IS_READY: g_value_set_boolean (value, self->is_ready); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } int vvm_eds_get_is_ready (VvmEds *self) { return self->is_ready; } static void vvm_eds_constructed (GObject *object) { VvmEds *self = (VvmEds *)object; G_OBJECT_CLASS (vvm_eds_parent_class)->constructed (object); vvm_eds_load (self); } static void vvm_eds_finalize (GObject *object) { VvmEds *self = (VvmEds *)object; g_cancellable_cancel (self->cancellable); g_clear_object (&self->cancellable); g_clear_object (&self->eds_view_list); g_clear_object (&self->contacts_list); if (self->contacts_array) g_ptr_array_free (self->contacts_array, TRUE); G_OBJECT_CLASS (vvm_eds_parent_class)->finalize (object); } static void vvm_eds_class_init (VvmEdsClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->get_property = vvm_eds_get_property; object_class->constructed = vvm_eds_constructed; object_class->finalize = vvm_eds_finalize; properties[PROP_IS_READY] = g_param_spec_boolean ("is-ready", "Is Ready", "The contact provider is ready and loaded", FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); } static void vvm_eds_init (VvmEds *self) { self->eds_view_list = g_list_store_new (E_TYPE_BOOK_CLIENT_VIEW); self->contacts_list = g_list_store_new (VVM_TYPE_CONTACT); self->cancellable = g_cancellable_new (); } VvmEds * vvm_eds_get_default (void) { static VvmEds *self; if (!self) { self = g_object_new (VVM_TYPE_EDS, NULL); g_object_add_weak_pointer (G_OBJECT (self), (gpointer *)&self); } return self; } gboolean vvm_eds_is_ready (VvmEds *self) { g_return_val_if_fail (VVM_IS_EDS (self), FALSE); return self->is_ready; } /** * vvm_eds_find_by_number: * @self: A #VvmEds * @phone_number: A Valid Phone number to match * * Find the first #VvmContact matching @phone_number. * A match can be either exact or one excluding the * country prefix (Eg: +1987654321 and 987654321 matches) * * Returns: (transfer none) (nullable): A #VvmContact. */ VvmContact * vvm_eds_find_by_number (VvmEds *self, const char *phone_number) { g_return_val_if_fail (VVM_IS_EDS (self), NULL); GListModel *model; guint n_items; gboolean match; model = G_LIST_MODEL (self->contacts_list); n_items = g_list_model_get_n_items (model); for (guint i = 0; i < n_items; i++) { g_autoptr(GObject) item = NULL; item = g_list_model_get_item (model, i); match = vvm_contact_matches (VVM_CONTACT (item), phone_number); if (match) return VVM_CONTACT (item); } return NULL; } /** * vvm_eds_get_model: * @self: A #VvmEds * * Get A #GListModel that contains all the * #VvmContact loaded. * * Returns: (transfer none): A #GListModel. */ GListModel * vvm_eds_get_model (VvmEds *self) { g_return_val_if_fail (VVM_IS_EDS (self), NULL); return G_LIST_MODEL (self->contacts_list); } vvmplayer-1.4/src/vvmplayer-contact-provider.h000066400000000000000000000026631415227045700216670ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ /* vvmplayer-contact-provider.h * * Copyright 2021 Chris Talbot * * This program is free software: you can 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 . * * Author(s): * Chris Talbot * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include #include "vvmplayer-contact.h" G_BEGIN_DECLS #define VVM_TYPE_EDS (vvm_eds_get_type ()) G_DECLARE_FINAL_TYPE (VvmEds, vvm_eds, VVM, EDS, GObject) VvmEds *vvm_eds_get_default (void); gboolean vvm_eds_is_ready (VvmEds *self); VvmContact *vvm_eds_find_by_number (VvmEds *self, const char *phone_number); GListModel *vvm_eds_get_model (VvmEds *self); int vvm_eds_get_is_ready (VvmEds *self); G_END_DECLS vvmplayer-1.4/src/vvmplayer-contact.c000066400000000000000000000117711415227045700200320ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ /* vvm-contact.c * * Copyright 2020 Purism SPC * 2021 Chris Talbot * * Author(s): * Mohammed Sadiq * Chris Talbot * * This program is free software: you can 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 . */ /* See https://gitlab.gnome.org/GNOME/evolution-data-server/-/issues/332#note_1107764 */ #define EDS_DISABLE_DEPRECATED #define G_LOG_DOMAIN "vvmplayer-contact" #ifdef HAVE_CONFIG_H # include "config.h" # include "version.h" #endif #include #include #include #include "vvmplayer-contact.h" #include "vvmplayer-settings.h" struct _VvmContact { GObject parent_instance; EContact *e_contact; EVCardAttribute *attribute; char *name; char *value; }; G_DEFINE_TYPE (VvmContact, vvm_contact, G_TYPE_OBJECT) gboolean vvm_contact_matches (VvmContact *self, const char *needle) { const char *value; VvmSettings *vvm_setting; const char *country; EPhoneNumberMatch match; g_assert (VVM_IS_CONTACT (self)); value = vvm_contact_get_value (self); vvm_setting = vvm_settings_get_default (); country = vvm_settings_get_vvm_country_code (vvm_setting); match = e_phone_number_compare_strings_with_region (value, needle, country, NULL); if (match == E_PHONE_NUMBER_MATCH_EXACT || match == E_PHONE_NUMBER_MATCH_NATIONAL) return TRUE; if (g_str_equal (value, needle)) return TRUE; return FALSE; } const char * vvm_contact_get_name (VvmContact *self) { g_assert (VVM_IS_CONTACT (self)); if (self->name) return self->name; if (self->e_contact) { const char *value; value = e_contact_get_const (self->e_contact, E_CONTACT_FULL_NAME); if (value) return value; } return ""; } static void vvm_contact_class_init (VvmContactClass *klass) { //GObjectClass *object_class = G_OBJECT_CLASS (klass); } static void vvm_contact_init (VvmContact *self) { } VvmContact * vvm_contact_new (EContact *contact, EVCardAttribute *attr) { VvmContact *self; self = g_object_new (VVM_TYPE_CONTACT, NULL); self->e_contact = g_object_ref (contact); self->attribute = attr; return self; } void vvm_contact_set_name (VvmContact *self, const char *name) { g_return_if_fail (VVM_IS_CONTACT (self)); g_free (self->name); self->name = g_strdup (name); } /** * vvm_contact_get_value: * @self: A #VvmContact * * Get the value stored in @self. It can be a phone * number, an XMPP ID, etc. * Also see vvm_contact_get_value_type(). * * Returns: (transfer none): The value of @self. * Or an empty string if no value. */ const char * vvm_contact_get_value (VvmContact *self) { g_return_val_if_fail (VVM_IS_CONTACT (self), NULL); if (!self->value && self->attribute) self->value = e_vcard_attribute_get_value (self->attribute); if (self->value) return self->value; return ""; } void vvm_contact_set_value (VvmContact *self, const char *value) { g_return_if_fail (VVM_IS_CONTACT (self)); g_free (self->value); self->value = g_strdup (value); } /** * vvm_contact_get_value: * @self: A #VvmContact * * Get the type of value stored in @self. * Eg: “Mobile”, “Work”, etc. translated to * the current locale. * * Returns: (transfer none): The value type of @self. */ const char * vvm_contact_get_value_type (VvmContact *self) { g_return_val_if_fail (VVM_IS_CONTACT (self), NULL); if (!self->attribute) return ""; if (e_vcard_attribute_has_type (self->attribute, "cell")) return _("Mobile: "); if (e_vcard_attribute_has_type (self->attribute, "work")) return _("Work: "); if (e_vcard_attribute_has_type (self->attribute, "other")) return _("Other: "); return ""; } /** * vvm_contact_get_uid: * @self: A #VvmContact * * A unique ID reperesenting the contact. This * ID won’t change unless the contact is modified. * * Returns: (transfer none): A unique ID of @self. */ const char * vvm_contact_get_uid (VvmContact *self) { g_return_val_if_fail (VVM_IS_CONTACT (self), ""); if (self->e_contact) return e_contact_get_const (self->e_contact, E_CONTACT_UID); return ""; } gboolean vvm_contact_is_dummy (VvmContact *self) { g_return_val_if_fail (VVM_IS_CONTACT (self), TRUE); return !!g_object_get_data (G_OBJECT (self), "dummy"); } vvmplayer-1.4/src/vvmplayer-contact.h000066400000000000000000000043561415227045700200400ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ /* vvmplayer-contact.h * * Copyright 2021 Chris Talbot * * This program is free software: you can 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 . * * Author(s): * Chris Talbot * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once /* See https://gitlab.gnome.org/GNOME/evolution-data-server/-/issues/332#note_1107764 */ #define EDS_DISABLE_DEPRECATED #include #include G_BEGIN_DECLS #define VVM_TYPE_CONTACT (vvm_contact_get_type ()) G_DECLARE_FINAL_TYPE (VvmContact, vvm_contact, VVM, CONTACT, GObject) VvmContact *vvm_contact_new (EContact *contact, EVCardAttribute *attr); void vvm_contact_set_name (VvmContact *self, const char *name); const char *vvm_contact_get_value (VvmContact *self); void vvm_contact_set_value (VvmContact *self, const char *value); const char *vvm_contact_get_value_type (VvmContact *self); const char *vvm_contact_get_uid (VvmContact *self); gboolean vvm_contact_is_dummy (VvmContact *self); const char *vvm_contact_get_name (VvmContact *self); gboolean vvm_contact_matches (VvmContact *self, const char *needle); G_END_DECLS vvmplayer-1.4/src/vvmplayer-log.c000066400000000000000000000166731415227045700171660ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ /* vvmplayer-log.c * * Copyright 2021 Chris Talbot * * This program is free software: you can 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 . * * Author(s): * Chris Talbot * * SPDX-License-Identifier: GPL-3.0-or-later */ #include #include #include #include #include "vvmplayer-log.h" #define DEFAULT_DOMAIN "vvmplayer" char *domains; static int verbosity; gboolean any_domain; gboolean stderr_is_journal; static void log_str_append_log_domain (GString *log_str, const char *log_domain, gboolean color) { static const char *colors[] = { "\033[1;32m", "\033[1;33m", "\033[1;35m", "\033[1;36m", "\033[1;91m", "\033[1;92m", "\033[1;93m", "\033[1;94m", "\033[1;95m", "\033[1;96m", }; guint i; g_assert (log_domain && *log_domain); i = g_str_hash (log_domain) % G_N_ELEMENTS (colors); if (color) g_string_append (log_str, colors[i]); g_string_append_printf (log_str, "%20s", log_domain); if (color) g_string_append (log_str, "\033[0m"); } static const char * get_log_level_prefix (GLogLevelFlags log_level, gboolean use_color) { if (use_color) switch ((int)log_level) /* Same colors as used in GLib */ { case G_LOG_LEVEL_ERROR: return " \033[1;31mERROR\033[0m"; case G_LOG_LEVEL_CRITICAL: return "\033[1;35mCRITICAL\033[0m"; case G_LOG_LEVEL_WARNING: return " \033[1;33mWARNING\033[0m"; case G_LOG_LEVEL_MESSAGE: return " \033[1;32mMESSAGE\033[0m"; case G_LOG_LEVEL_INFO: return " \033[1;32mINFO\033[0m"; case G_LOG_LEVEL_DEBUG: return " \033[1;32mDEBUG\033[0m"; case VVMPLAYER_LOG_LEVEL_TRACE: return " \033[1;36mTRACE\033[0m"; default: return " UNKNOWN"; } else switch ((int)log_level) { case G_LOG_LEVEL_ERROR: return " ERROR"; case G_LOG_LEVEL_CRITICAL: return "CRITICAL"; case G_LOG_LEVEL_WARNING: return " WARNING"; case G_LOG_LEVEL_MESSAGE: return " MESSAGE"; case G_LOG_LEVEL_INFO: return " INFO"; case G_LOG_LEVEL_DEBUG: return " DEBUG"; case VVMPLAYER_LOG_LEVEL_TRACE: return " TRACE"; default: return " UNKNOWN"; } } static GLogWriterOutput vvmplayer_log_write (GLogLevelFlags log_level, const char *log_domain, const char *log_message, const GLogField *fields, gsize n_fields, gpointer user_data) { g_autoptr(GString) log_str = NULL; FILE *stream = stdout; gboolean can_color; if (stderr_is_journal) if (g_log_writer_journald (log_level, fields, n_fields, user_data) == G_LOG_WRITER_HANDLED) return G_LOG_WRITER_HANDLED; if (log_level & (G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING)) stream = stderr; log_str = g_string_new (NULL); /* Add local time */ { char buffer[32]; struct tm tm_now; time_t sec_now; gint64 now; now = g_get_real_time (); sec_now = now / G_USEC_PER_SEC; tm_now = *localtime (&sec_now); strftime (buffer, sizeof (buffer), "%H:%M:%S", &tm_now); g_string_append_printf (log_str, "%s.%04d ", buffer, (int)((now % G_USEC_PER_SEC) / 100)); } can_color = g_log_writer_supports_color (fileno (stream)); log_str_append_log_domain (log_str, log_domain, can_color); g_string_append_printf (log_str, "[%5d]:", getpid ()); g_string_append_printf (log_str, "%s: ", get_log_level_prefix (log_level, can_color)); g_string_append (log_str, log_message); fprintf (stream, "%s\n", log_str->str); fflush (stream); return G_LOG_WRITER_HANDLED; } static GLogWriterOutput vvmplayer_log_handler (GLogLevelFlags log_level, const GLogField *fields, gsize n_fields, gpointer user_data) { const char *log_domain = NULL; const char *log_message = NULL; /* If domain is “all” show logs upto debug regardless of the verbosity */ switch ((int)log_level) { case G_LOG_LEVEL_MESSAGE: if (any_domain && domains) break; if (verbosity < 1) return G_LOG_WRITER_HANDLED; break; case G_LOG_LEVEL_INFO: if (any_domain && domains) break; if (verbosity < 2) return G_LOG_WRITER_HANDLED; break; case G_LOG_LEVEL_DEBUG: if (any_domain && domains) break; if (verbosity < 3) return G_LOG_WRITER_HANDLED; break; case VVMPLAYER_LOG_LEVEL_TRACE: if (verbosity < 4) return G_LOG_WRITER_HANDLED; break; default: break; } for (guint i = 0; (!log_domain || !log_message) && i < n_fields; i++) { const GLogField *field = &fields[i]; if (g_strcmp0 (field->key, "GLIB_DOMAIN") == 0) log_domain = field->value; else if (g_strcmp0 (field->key, "MESSAGE") == 0) log_message = field->value; } if (!log_domain) log_domain = "**"; /* Skip logs from other domains if verbosity level is low */ if (any_domain && !domains && verbosity < 5 && log_level > G_LOG_LEVEL_MESSAGE && !strstr (log_domain, DEFAULT_DOMAIN)) return G_LOG_WRITER_HANDLED; /* GdkPixbuf logs are too much verbose, skip unless asked not to. */ if (log_level >= G_LOG_LEVEL_MESSAGE && verbosity < 7 && g_strcmp0 (log_domain, "GdkPixbuf") == 0 && (!domains || !strstr (domains, log_domain))) return G_LOG_WRITER_HANDLED; if (!log_message) log_message = "(NULL) message"; if (any_domain) return vvmplayer_log_write (log_level, log_domain, log_message, fields, n_fields, user_data); if (!log_domain || strstr (domains, log_domain)) return vvmplayer_log_write (log_level, log_domain, log_message, fields, n_fields, user_data); return G_LOG_WRITER_HANDLED; } static void vvmplayer_log_finalize (void) { g_clear_pointer (&domains, g_free); } void vvmplayer_log_init (void) { static gsize initialized = 0; if (g_once_init_enter (&initialized)) { domains = g_strdup (g_getenv ("G_MESSAGES_DEBUG")); if (domains && !*domains) g_clear_pointer (&domains, g_free); if (!domains || g_str_equal (domains, "all")) any_domain = TRUE; stderr_is_journal = g_log_writer_is_journald (fileno (stderr)); g_log_set_writer_func (vvmplayer_log_handler, NULL, NULL); g_once_init_leave (&initialized, 1); atexit (vvmplayer_log_finalize); } } void vvmplayer_log_increase_verbosity (void) { verbosity++; } int vvmplayer_log_get_verbosity (void) { return verbosity; } vvmplayer-1.4/src/vvmplayer-log.h000066400000000000000000000041301415227045700171540ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ /* vvmplayer-log.h * * Copyright 2021 Chris Talbot * * This program is free software: you can 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 . * * Author(s): * Chris Talbot * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #ifndef VVMPLAYER_LOG_LEVEL_TRACE # define VVMPLAYER_LOG_LEVEL_TRACE ((GLogLevelFlags)(1 << G_LOG_LEVEL_USER_SHIFT)) #endif /* XXX: Should we use the semi-private g_log_structured_standard() API? */ #define VVMPLAYER_TRACE_MSG(fmt, ...) \ g_log_structured (G_LOG_DOMAIN, VVMPLAYER_LOG_LEVEL_TRACE, \ "MESSAGE", "%s():%d: " fmt, \ G_STRFUNC, __LINE__, ## __VA_ARGS__) #define VVMPLAYER_TRACE(fmt, ...) \ g_log_structured (G_LOG_DOMAIN, VVMPLAYER_LOG_LEVEL_TRACE, \ "MESSAGE", fmt, ## __VA_ARGS__) #define VVMPLAYER_DEBUG_MSG(fmt, ...) \ g_log_structured (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, \ "MESSAGE", "%s():%d: " fmt, \ G_STRFUNC, __LINE__, ## __VA_ARGS__) #define VVMPLAYER_TODO(_msg) \ g_log_structured (G_LOG_DOMAIN, VVMPLAYER_LOG_LEVEL_TRACE, \ "MESSAGE", "TODO: %s():%d: %s", \ G_STRFUNC, __LINE__, _msg) void vvmplayer_log_init (void); void vvmplayer_log_increase_verbosity (void); int vvmplayer_log_get_verbosity (void); vvmplayer-1.4/src/vvmplayer-notification.c000066400000000000000000000040641415227045700210620ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ /* vvmplayer-notification.c * * Copyright 2021 Chris Talbot * * This program is free software: you can 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 . * * Author(s): * Chris Talbot * * SPDX-License-Identifier: GPL-3.0-or-later */ #define G_LOG_DOMAIN "vvmplayer-notification" #ifdef HAVE_CONFIG_H # include "config.h" #endif #include "vvmplayer-notification.h" /** * SECTION: vvmplayer-notification * @title: vvmplayer-notification * @short_description: Generic functions * @include: "vvmplayer-notification.h" * * A grouping of all notifications. */ void vvmplayer_notification_send_unread_vvm (int unread_vvms) { GNotification *notification; gchar *title; gchar *body; GApplication *vvm_player = g_application_get_default (); /* If the notification is already there, withdraw it */ g_application_withdraw_notification (vvm_player, "unread-message"); title = g_strdup("New Voicemail"); if (unread_vvms == 1) { body = g_strdup_printf ("You have %d new voicemail", unread_vvms); } else { body = g_strdup_printf ("You have %d new voicemails", unread_vvms); } notification = g_notification_new (title); g_notification_set_body (notification, body); g_notification_set_priority (notification, G_NOTIFICATION_PRIORITY_HIGH); g_application_send_notification (vvm_player, "unread-message", notification); g_object_unref (notification); g_free (title); g_free (body); } vvmplayer-1.4/src/vvmplayer-notification.h000066400000000000000000000020371415227045700210650ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ /* vvmplayer-notification.h * * Copyright 2021 Chris Talbot * * This program is free software: you can 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 . * * Author(s): * Chris Talbot * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include G_BEGIN_DECLS void vvmplayer_notification_send_unread_vvm (int unread_vvms); G_END_DECLS vvmplayer-1.4/src/vvmplayer-preferences-window.c000066400000000000000000000645631415227045700222140ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ /* vvmplayer-preferences-window.c * * Copyright 2021 Chris Talbot * * This program is free software: you can 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 . * * Author(s): * Chris Talbot * * SPDX-License-Identifier: GPL-3.0-or-later */ #define G_LOG_DOMAIN "vvmplayer-preferences-window" #ifdef HAVE_CONFIG_H # include "config.h" # include "version.h" #endif #include "vvmplayer-preferences-window.h" #include "vvmplayer-settings.h" #include "vvmplayer-vvmd.h" #define STATUS_GOOD "emblem-ok-symbolic" #define STATUS_BAD "window-close-symbolic" struct _VvmPreferencesWindow { HdyPreferencesWindow parent_instance; //Refresh GtkButton *refresh_settings_button; //Enable VVM GtkSwitch *enable_vvm_switch; HdyActionRow *enable_vvm_text; //Appearence Settings HdyActionRow *enable_dark_theme_row; GtkSwitch *enable_dark_theme_switch; GtkSwitch *override_global_pref_switch; //Status GtkImage *vvmd_enabled_image; GtkImage *mailbox_active_image; HdyActionRow *provision_status_text; //Activate GtkButton *activate_vvm_button; //Sync GtkButton *sync_vvm_button; //Modem Manager Settings GtkEntry *destination_number_text; GtkEntry *modem_number_text; HdyActionRow *carrier_prefix_text_row; GtkEntry *carrier_prefix_text; HdyComboRow *vvm_type_combo_row; //Spam Contact GtkSwitch *spam_contact_switch; GtkEntry *spam_contact_text; //Timeouts int refresh_settings_button_timeout; int activate_vvm_button_clicked_timeout; int sync_vvm_button_clicked_timeout; int enable_vvm_switch_clicked_timeout; }; G_DEFINE_TYPE (VvmPreferencesWindow, vvm_preferences_window, HDY_TYPE_PREFERENCES_WINDOW) static void vvm_preferences_set_gtkimage_icon (GtkImage *image_to_set, const char *icon) { GValue a = G_VALUE_INIT; g_value_init (&a, G_TYPE_STRING); g_assert (G_VALUE_HOLDS_STRING (&a)); g_value_set_static_string (&a, icon); g_object_set_property (G_OBJECT (image_to_set), "icon-name", &a); } static void vvm_preferences_set_hdyactionrow_text (HdyActionRow *hdy_row, const char *text) { GValue a = G_VALUE_INIT; g_value_init (&a, G_TYPE_STRING); g_assert (G_VALUE_HOLDS_STRING (&a)); g_value_set_static_string (&a, text); g_object_set_property (G_OBJECT (hdy_row), "title", &a); } static void vvm_preferences_set_button_content (GtkButton *btn, const char *title) { GValue a = G_VALUE_INIT; g_value_init (&a, G_TYPE_STRING); g_assert (G_VALUE_HOLDS_STRING (&a)); g_value_set_static_string (&a, title); g_object_set_property (G_OBJECT (btn), "label", &a); } static void vvm_preferences_set_hdyactionrow_visibility (HdyActionRow *hdy_row, int visible) { GValue a = G_VALUE_INIT; g_value_init (&a, G_TYPE_BOOLEAN); g_value_set_boolean (&a, visible); g_object_set_property (G_OBJECT (hdy_row), "visible", &a); } static void vvm_preferences_refresh_settings (void) { VvmVvmd *backend = vvm_vvmd_get_default (); VvmSettings *settings = vvm_settings_get_default (); if(vvm_settings_get_mm_available (settings)) { if (vvmplayer_vvmd_get_mm_settings(backend) == FALSE) { g_warning ("Error getting VVMD Modem Manager Settings"); vvm_settings_load_mm_defaults (settings); } } else { g_debug ("Loading VVMD MM Defaults"); vvm_settings_load_mm_defaults (settings); } if (vvm_settings_get_service_available (settings)) { if (vvmplayer_vvmd_get_service_settings (backend) == FALSE) { g_warning ("Error getting VVMD Service Settings"); vvm_settings_load_service_defaults (settings); } } else { g_debug ("Loading VVMD service Defaults"); vvm_settings_load_service_defaults (settings); } } static void vvm_preferences_window_populate (VvmPreferencesWindow *self) { g_autofree char *VVMDestinationNumber = NULL; g_autofree char *VVMDefaultModemNumber = NULL; g_autofree char *VVMProvisionStatus = NULL; g_autofree char *VVMCarrierPrefix = NULL; g_autofree char *VVMType = NULL; g_autofree char *VVMSpamContact = NULL; int VVMEnabled; gboolean VVMSpamContactEnabled; int VVMType_encoded, vvm_type_combo_row_state; VvmSettings *settings = vvm_settings_get_default (); int prefer_dark_theme, enable_dark_theme_switch_state; int override_global_appearence_pref; GtkSettings *gtk_settings = gtk_settings_get_default (); //Enable VVM VVMEnabled = vvm_settings_get_vvm_enabled (settings); gtk_switch_set_active (self->enable_vvm_switch, VVMEnabled); //Spam Contact VVMSpamContact = vvm_settings_get_spam_contact (settings); VVMSpamContactEnabled = vvmplayer_settings_get_spam_contact_enabled (settings); gtk_switch_set_active (self->spam_contact_switch, VVMSpamContactEnabled); gtk_entry_set_text (self->spam_contact_text, VVMSpamContact); //Appearence Settings override_global_appearence_pref = vvmplayer_settings_get_override_global_appearence_pref (settings); gtk_switch_set_active (self->override_global_pref_switch, override_global_appearence_pref); g_object_get (gtk_settings, "gtk-application-prefer-dark-theme", &prefer_dark_theme, NULL); enable_dark_theme_switch_state = gtk_switch_get_state (self->enable_dark_theme_switch); if (prefer_dark_theme != enable_dark_theme_switch_state) gtk_switch_set_active (self->enable_dark_theme_switch, prefer_dark_theme); //Modem Manager settings VVMDestinationNumber = vvm_settings_get_vvm_destination_number (settings); if (strstr (VVMDestinationNumber, "invalid") == NULL) { //Don't populate invalid settings gtk_entry_set_text (self->destination_number_text, VVMDestinationNumber); } else { gtk_entry_set_text (self->destination_number_text, ""); } VVMDefaultModemNumber = vvm_settings_get_vvm_default_number (settings); if (g_strcmp0 (VVMDefaultModemNumber, "NULL") != 0) { //Don't populate invalid settings gtk_entry_set_text (self->modem_number_text, VVMDefaultModemNumber); } else { gtk_entry_set_text (self->modem_number_text, ""); } VVMCarrierPrefix = vvm_settings_get_vvm_carrier_prefix (settings); if (strstr (VVMCarrierPrefix, "invalid") == NULL) { //Don't populate invalid settings gtk_entry_set_text (self->carrier_prefix_text, VVMCarrierPrefix); } else { gtk_entry_set_text (self->carrier_prefix_text, ""); } VVMType = vvm_settings_get_vvm_type (settings); VVMType_encoded = vvmplayer_vvmd_encode_vvm_type (VVMType); g_debug("VVMType: %s, VVMType_encoded: %d", VVMType, VVMType_encoded); vvm_type_combo_row_state = hdy_combo_row_get_selected_index (self->vvm_type_combo_row); if (vvm_type_combo_row_state != VVMType_encoded) hdy_combo_row_set_selected_index (self->vvm_type_combo_row, VVMType_encoded); //Status if(vvm_settings_get_mm_available (settings) && vvm_settings_get_service_available (settings)) { vvm_preferences_set_gtkimage_icon (self->vvmd_enabled_image, STATUS_GOOD); } else { vvm_preferences_set_gtkimage_icon (self->vvmd_enabled_image, STATUS_BAD); } if (vvm_settings_get_mailbox_active (settings)) { vvm_preferences_set_gtkimage_icon (self->mailbox_active_image, STATUS_GOOD); } else { vvm_preferences_set_gtkimage_icon (self->mailbox_active_image, STATUS_BAD); } VVMProvisionStatus = vvm_settings_get_vvm_provision_status (settings); VVMProvisionStatus = g_strdup_printf ("Provision Status: %s", VVMProvisionStatus); vvm_preferences_set_hdyactionrow_text (self->provision_status_text, VVMProvisionStatus); } static gboolean refresh_settings_button_timeout (gpointer user_data) { VvmPreferencesWindow *self = user_data; g_debug("Removing timeout to refresh_settings_button_clicked_cb ()"); self->refresh_settings_button_timeout = FALSE; return FALSE; } static void refresh_settings_button_clicked_cb (GtkButton *btn, VvmPreferencesWindow *self) { if (self->refresh_settings_button_timeout == FALSE) { g_debug ("Refreshing Settings....."); g_debug ("Adding timeout to refresh_settings_button_clicked_cb ()"); //Adding one hundred millisecond timeout g_timeout_add (100,refresh_settings_button_timeout, self); vvm_preferences_refresh_settings (); vvm_preferences_window_populate (self); self->refresh_settings_button_timeout = TRUE; } else { g_debug ("refresh_settings_button_clicked_cb() timed out!"); } } static void override_global_pref (VvmPreferencesWindow *self) { VvmSettings *settings = vvm_settings_get_default (); GtkSettings *gtk_settings = gtk_settings_get_default (); //Dark Theme vvm_preferences_set_hdyactionrow_visibility (self->enable_dark_theme_row, TRUE); int prefer_dark_theme = vvmplayer_settings_get_dark_theme (settings); g_object_set (gtk_settings, "gtk-application-prefer-dark-theme", prefer_dark_theme, NULL); //Set swtich to proper position gtk_switch_set_active (self->enable_dark_theme_switch, prefer_dark_theme); } static void reset_global_pref (VvmPreferencesWindow *self) { VvmSettings *settings = vvm_settings_get_default (); GtkSettings *gtk_settings = gtk_settings_get_default (); //Dark Theme int prefer_dark_theme = vvmplayer_settings_get_default_dark_theme_pref (settings); vvm_preferences_set_hdyactionrow_visibility (self->enable_dark_theme_row, FALSE); g_object_set (gtk_settings, "gtk-application-prefer-dark-theme", prefer_dark_theme, NULL); } static gboolean override_global_pref_switch_flipped_cb (GtkSwitch *widget, gboolean override_global_pref_bool, VvmPreferencesWindow *self) { VvmSettings *settings = vvm_settings_get_default (); if (override_global_pref_bool) { override_global_pref (self); } else { reset_global_pref (self); } vvmplayer_settings_set_override_global_appearence_pref (settings, override_global_pref_bool); return FALSE; } static void spam_contact_text_button_clicked_cb (GtkButton *btn, VvmPreferencesWindow *self) { VvmSettings *settings = vvm_settings_get_default (); const char *new_contact; new_contact = gtk_entry_get_text (self->spam_contact_text); vvm_settings_set_spam_contact (settings, new_contact); } static gboolean spam_contact_switch_flipped_cb (GtkSwitch *widget, gboolean contact_switch_bool, VvmPreferencesWindow *self) { VvmSettings *settings = vvm_settings_get_default (); vvmplayer_settings_set_spam_contact_enabled (settings, contact_switch_bool); return FALSE; } static gboolean enable_theme_switch_flipped_cb (GtkSwitch *widget, gboolean prefer_dark_theme_bool, VvmPreferencesWindow *self) { GtkSettings *gtk_settings = gtk_settings_get_default (); VvmSettings *settings = vvm_settings_get_default (); g_object_set (gtk_settings, "gtk-application-prefer-dark-theme", prefer_dark_theme_bool, NULL); vvmplayer_settings_set_dark_theme (settings, prefer_dark_theme_bool); return FALSE; } static void set_destination_number (VvmPreferencesWindow *self) { VvmVvmd *backend = vvm_vvmd_get_default (); VvmSettings *settings = vvm_settings_get_default (); if (vvm_settings_get_mm_available (settings)) { const char *dest_number = NULL; dest_number = gtk_entry_get_text (self->destination_number_text); vvm_settings_set_vvm_destination_number (settings, dest_number); if (vvmplayer_vvmd_set_mm_setting (backend, "VVMDestinationNumber", dest_number) == FALSE) { g_autofree char *result = g_strdup ("Action Failed"); g_warning ("Error changing setting in vvmd!"); gtk_entry_set_text (self->destination_number_text, result); } } else { g_autofree char *result = g_strdup ("Cannot find vvmd"); g_warning("VVMD Modem Manager settings not available!"); gtk_entry_set_text (self->destination_number_text, result); } } static void set_default_modem_number (VvmPreferencesWindow *self) { VvmVvmd *backend = vvm_vvmd_get_default (); VvmSettings *settings = vvm_settings_get_default (); if(vvm_settings_get_mm_available (settings)) { const char *modem_number = NULL; modem_number = gtk_entry_get_text (self->modem_number_text); if (strlen (modem_number) < 1) { modem_number = "NULL"; } vvm_settings_set_vvm_default_number (settings, modem_number); if(vvmplayer_vvmd_set_mm_setting (backend, "DefaultModemNumber", modem_number) == FALSE) { g_autofree char *result = g_strdup("Action Failed"); g_warning ("Error changing setting in vvmd!"); gtk_entry_set_text (self->destination_number_text, result); } } else { g_autofree char *result = g_strdup ("Cannot find vvmd"); g_warning("VVMD Modem Manager settings not available!"); gtk_entry_set_text (self->modem_number_text, result); } } static void set_carrier_prefix (VvmPreferencesWindow *self) { VvmVvmd *backend = vvm_vvmd_get_default (); VvmSettings *settings = vvm_settings_get_default (); if(vvm_settings_get_mm_available (settings)) { const char *carrier_prefix = NULL; carrier_prefix = gtk_entry_get_text (self->carrier_prefix_text); vvm_settings_set_vvm_carrier_prefix (settings, carrier_prefix); if(vvmplayer_vvmd_set_mm_setting (backend, "CarrierPrefix", carrier_prefix) == FALSE) { g_autofree char *result = g_strdup ("Action Failed"); g_warning ("Error changing setting in vvmd!"); gtk_entry_set_text (self->destination_number_text, result); } } else { g_autofree char *result = g_strdup ("Cannot find vvmd"); g_warning("VVMD Modem Manager settings not available!"); gtk_entry_set_text (self->carrier_prefix_text, result); } } static gboolean enable_vvm_switch_timeout(gpointer user_data) { VvmPreferencesWindow *self = user_data; self->enable_vvm_switch_clicked_timeout = FALSE; vvm_preferences_set_hdyactionrow_text (self->enable_vvm_text, "Enable VVM"); refresh_settings_button_clicked_cb (self->refresh_settings_button, self); return FALSE; } static gboolean enable_vvm_switch_flipped_cb (GtkSwitch *widget, gboolean state, VvmPreferencesWindow *self) { VvmSettings *settings = vvm_settings_get_default (); int VVMEnabled = vvm_settings_get_vvm_enabled (settings); if (VVMEnabled == state) { return FALSE; } if (self->enable_vvm_switch_clicked_timeout == FALSE) { VvmVvmd *backend = vvm_vvmd_get_default (); self->enable_vvm_switch_clicked_timeout = TRUE; if(vvm_settings_get_mm_available (settings) == FALSE) { g_warning("Cannot find vvmd!"); vvm_preferences_set_hdyactionrow_text(self->enable_vvm_text, "Cannot find vvmd"); g_timeout_add_seconds (2, enable_vvm_switch_timeout, self); gtk_switch_set_active (self->enable_vvm_switch, FALSE); return FALSE; } g_timeout_add_seconds(10, enable_vvm_switch_timeout, self); if (state) { g_debug ("Enabling VVM"); vvm_preferences_set_hdyactionrow_text(self->enable_vvm_text, "Enabling VVM..."); set_destination_number (self); set_default_modem_number (self); set_carrier_prefix (self); } else { g_debug ("Disabling VVM"); vvm_preferences_set_hdyactionrow_text(self->enable_vvm_text, "Disabling VVM..."); } vvmplayer_vvmd_set_mm_vvm_enabled (backend, state); } else { g_debug ("enable_vvm_switch_clicked_cb() timed out!"); gtk_switch_set_active (self->enable_vvm_switch, VVMEnabled); } return FALSE; } static gboolean activate_vvm_button_timeout(gpointer user_data) { VvmPreferencesWindow *self = user_data; self->activate_vvm_button_clicked_timeout = FALSE; vvm_preferences_set_button_content (self->activate_vvm_button, "Activate"); refresh_settings_button_clicked_cb (self->refresh_settings_button, self); return FALSE; } static void activate_vvm_button_clicked_cb (GtkButton *btn, VvmPreferencesWindow *self) { VvmSettings *settings = vvm_settings_get_default (); int VVMEnabled = vvm_settings_get_vvm_enabled (settings); int MailboxActive = vvm_settings_get_mailbox_active (settings); if (self->activate_vvm_button_clicked_timeout == FALSE) { VvmVvmd *backend = vvm_vvmd_get_default (); self->activate_vvm_button_clicked_timeout = TRUE; if(vvm_settings_get_mm_available (settings) == FALSE) { g_warning ("Cannot find vvmd!"); vvm_preferences_set_button_content (self->activate_vvm_button, "Cannot find vvmd"); g_timeout_add_seconds (2, activate_vvm_button_timeout, self); return; } if (VVMEnabled == FALSE) { g_warning ("VVM not Active!"); vvm_preferences_set_button_content (self->activate_vvm_button, "VVM not enabled in VVM Player"); g_timeout_add_seconds (2, activate_vvm_button_timeout, self); return; } if (MailboxActive == TRUE) { g_warning ("Mailbox already Active!"); vvm_preferences_set_button_content (self->activate_vvm_button, "Mailbox already active"); g_timeout_add_seconds (2, activate_vvm_button_timeout, self); return; } g_debug ("Activating VVM....."); g_timeout_add_seconds (10, activate_vvm_button_timeout, self); set_destination_number (self); set_default_modem_number (self); set_carrier_prefix (self); vvm_preferences_set_button_content (self->activate_vvm_button, "Activating..."); vvmplayer_vvmd_check_subscription_status (backend); } else { g_debug("activate_vvm_button_clicked_cb() timed out!"); } } static gboolean sync_vvm_button_timeout(gpointer user_data) { VvmPreferencesWindow *self = user_data; self->sync_vvm_button_clicked_timeout = FALSE; vvm_preferences_set_button_content (self->sync_vvm_button, "Sync"); return FALSE; } static void sync_vvm_button_clicked_cb (GtkButton *btn, VvmPreferencesWindow *self) { VvmSettings *settings = vvm_settings_get_default (); int VVMEnabled = vvm_settings_get_vvm_enabled (settings); int MailboxActive = vvm_settings_get_mailbox_active (settings); if (self->sync_vvm_button_clicked_timeout == FALSE) { VvmVvmd *backend = vvm_vvmd_get_default (); g_debug ("Syncing VVM....."); self->sync_vvm_button_clicked_timeout = TRUE; if(vvm_settings_get_mm_available (settings) == FALSE) { g_warning ("Cannot find vvmd!"); vvm_preferences_set_button_content (self->sync_vvm_button, "Cannot find vvmd"); g_timeout_add_seconds (2, sync_vvm_button_timeout, self); return; } if (VVMEnabled == FALSE) { g_warning ("VVM not Active!"); vvm_preferences_set_button_content (self->sync_vvm_button, "VVM not enabled in VVM Player"); g_timeout_add_seconds (2, sync_vvm_button_timeout, self); return; } if (MailboxActive == FALSE) { g_warning ("Mailbox not Active!"); vvm_preferences_set_button_content (self->sync_vvm_button, "Mailbox not active"); g_timeout_add_seconds (2, sync_vvm_button_timeout, self); return; } vvm_preferences_set_button_content (self->sync_vvm_button, "Syncing..."); g_debug ("Adding timeout to sync_vvm_button_clicked_cb()"); g_timeout_add_seconds (10, sync_vvm_button_timeout, self); vvmplayer_vvmd_sync_vvm (backend); } else { g_debug ("sync_vvm_button_clicked_cb() timed out!"); } } static void vvm_preferences_set_placeholder_text (GtkEntry *placeholder, const char *text) { GValue a = G_VALUE_INIT; g_value_init (&a, G_TYPE_STRING); g_assert (G_VALUE_HOLDS_STRING (&a)); g_value_set_static_string (&a, text); g_object_set_property (G_OBJECT (placeholder), "placeholder-text", &a); } static void vvm_type_selected_cb (GObject *sender, GParamSpec *pspec, VvmPreferencesWindow *self) { //HdyComboRow *row = HDY_COMBO_ROW (sender); VvmVvmd *backend = vvm_vvmd_get_default (); VvmSettings *settings = vvm_settings_get_default (); int row_selected; row_selected = hdy_combo_row_get_selected_index (self->vvm_type_combo_row); if (row_selected == VVM_TYPE_UNKNOWN) { //This is not a valid vvmd type, so don't set it return; } if(vvm_settings_get_mm_available (settings)) { g_autofree char *vvm_type = NULL; vvm_type = vvmplayer_vvmd_decode_vvm_type (row_selected); if(vvmplayer_vvmd_set_mm_setting (backend, "VVMType", vvm_type) == FALSE) { g_warning ("Error changing setting in vvmd!"); hdy_combo_row_set_selected_index (self->vvm_type_combo_row, VVM_TYPE_UNKNOWN); } else { if (row_selected == VVM_TYPE_ATTUSA) { vvm_preferences_set_hdyactionrow_text(self->carrier_prefix_text_row, "AT&T USA Number (No dashes or spaces)"); vvm_preferences_set_placeholder_text(self->carrier_prefix_text, "AT&T USA Number (No dashes or spaces)"); } else { vvm_preferences_set_hdyactionrow_text(self->carrier_prefix_text_row, "Carrier Prefix"); vvm_preferences_set_placeholder_text(self->carrier_prefix_text, "Carrier Prefix"); } } } else { hdy_combo_row_set_selected_index (self->vvm_type_combo_row, VVM_TYPE_UNKNOWN); } } static void lists_page_init (VvmPreferencesWindow *self) { GListStore *list_store; HdyValueObject *obj; list_store = g_list_store_new (HDY_TYPE_VALUE_OBJECT); obj = hdy_value_object_new_string ("Unknown"); g_list_store_insert (list_store, VVM_TYPE_UNKNOWN, obj); g_clear_object (&obj); obj = hdy_value_object_new_string ("cvvm"); g_list_store_insert (list_store, VVM_TYPE_CVVM, obj); g_clear_object (&obj); obj = hdy_value_object_new_string ("AT&T USA"); g_list_store_insert (list_store, VVM_TYPE_ATTUSA, obj); g_clear_object (&obj); obj = hdy_value_object_new_string ("otmp"); g_list_store_insert (list_store, VVM_TYPE_OTMP, obj); g_clear_object (&obj); obj = hdy_value_object_new_string ("vvm3"); g_list_store_insert (list_store, VVM_TYPE_VVM_THREE, obj); g_clear_object (&obj); hdy_combo_row_bind_name_model (self->vvm_type_combo_row, G_LIST_MODEL (list_store), (HdyComboRowGetNameFunc) hdy_value_object_dup_string, NULL, NULL); } VvmPreferencesWindow * vvm_preferences_window_new (void) { return g_object_new (HDY_TYPE_VVM_PREFERENCES_WINDOW, NULL); } static void vvm_preferences_window_class_init (VvmPreferencesWindowClass *klass) { GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); gtk_widget_class_set_template_from_resource (widget_class, "/org/kop316/vvmplayer/" "ui/vvmplayer-preferences-window.ui"); //Refresh Page gtk_widget_class_bind_template_child (widget_class, VvmPreferencesWindow, refresh_settings_button); gtk_widget_class_bind_template_callback (widget_class, refresh_settings_button_clicked_cb); //Appearence Settings gtk_widget_class_bind_template_child (widget_class, VvmPreferencesWindow, override_global_pref_switch); gtk_widget_class_bind_template_child (widget_class, VvmPreferencesWindow, enable_dark_theme_switch); gtk_widget_class_bind_template_child (widget_class, VvmPreferencesWindow, enable_dark_theme_row); gtk_widget_class_bind_template_callback (widget_class, override_global_pref_switch_flipped_cb); gtk_widget_class_bind_template_callback (widget_class, enable_theme_switch_flipped_cb); //Whether or not VVM is enabled gtk_widget_class_bind_template_child (widget_class, VvmPreferencesWindow, enable_vvm_text); gtk_widget_class_bind_template_child (widget_class, VvmPreferencesWindow, enable_vvm_switch); gtk_widget_class_bind_template_callback (widget_class, enable_vvm_switch_flipped_cb); //Status Settings gtk_widget_class_bind_template_child (widget_class, VvmPreferencesWindow, vvmd_enabled_image); gtk_widget_class_bind_template_child (widget_class, VvmPreferencesWindow, mailbox_active_image); gtk_widget_class_bind_template_child (widget_class, VvmPreferencesWindow, provision_status_text); //Activate VVM gtk_widget_class_bind_template_child (widget_class, VvmPreferencesWindow, activate_vvm_button); gtk_widget_class_bind_template_callback (widget_class, activate_vvm_button_clicked_cb); //Sync VVM gtk_widget_class_bind_template_child (widget_class, VvmPreferencesWindow, sync_vvm_button); gtk_widget_class_bind_template_callback (widget_class, sync_vvm_button_clicked_cb); //Spam Contact gtk_widget_class_bind_template_child (widget_class, VvmPreferencesWindow, spam_contact_switch); gtk_widget_class_bind_template_child (widget_class, VvmPreferencesWindow, spam_contact_text); gtk_widget_class_bind_template_callback (widget_class, spam_contact_switch_flipped_cb); gtk_widget_class_bind_template_callback (widget_class, spam_contact_text_button_clicked_cb); //Modem Manager Settings gtk_widget_class_bind_template_child (widget_class, VvmPreferencesWindow, destination_number_text); gtk_widget_class_bind_template_child (widget_class, VvmPreferencesWindow, modem_number_text); gtk_widget_class_bind_template_child (widget_class, VvmPreferencesWindow, carrier_prefix_text_row); gtk_widget_class_bind_template_child (widget_class, VvmPreferencesWindow, carrier_prefix_text); gtk_widget_class_bind_template_child (widget_class, VvmPreferencesWindow, vvm_type_combo_row); gtk_widget_class_bind_template_callback (widget_class, vvm_type_selected_cb); } static void vvm_preferences_window_init (VvmPreferencesWindow *self) { gtk_widget_init_template (GTK_WIDGET (self)); lists_page_init (self); vvm_preferences_refresh_settings (); vvm_preferences_window_populate (self); } vvmplayer-1.4/src/vvmplayer-preferences-window.h000066400000000000000000000023201415227045700222000ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ /* vvmplayer-preferences-window.h * * Copyright 2021 Chris Talbot * * This program is free software: you can 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 . * * Author(s): * Chris Talbot * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include G_BEGIN_DECLS #define HDY_TYPE_VVM_PREFERENCES_WINDOW (vvm_preferences_window_get_type()) G_DECLARE_FINAL_TYPE (VvmPreferencesWindow, vvm_preferences_window, HDY, VVM_PREFERENCES_WINDOW, HdyPreferencesWindow) VvmPreferencesWindow *vvm_preferences_window_new (void); G_END_DECLS vvmplayer-1.4/src/vvmplayer-settings.c000066400000000000000000000360051415227045700202340ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ /* vvmplayer-settings.c * * Copyright 2021 Chris Talbot * * This program is free software: you can 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 . * * Author(s): * Chris Talbot * * SPDX-License-Identifier: GPL-3.0-or-later */ #define G_LOG_DOMAIN "vvmplayer-settings" #ifdef HAVE_CONFIG_H # include "config.h" #endif #include "vvmplayer-settings.h" /** * SECTION: vvmplayer-settings * @title: VvmSettings * @short_description: The Application settings * @include: "vvmplayer-settings.h" * * A class that handles application specific settings, and * to store them to disk. */ struct _VvmSettings { GObject parent_instance; GSettings *app_settings; gboolean first_run; GtkSettings *gtk_settings; //App Settings int override_global_appearence_pref; int prefer_dark_theme; int default_dark_theme_pref; //Spam Contact char *spam_contact; gboolean spam_contact_enabled; //Modem Manager Settings char *vvm_destination_number; char *vvm_type; char *default_number; char *carrier_prefix; //Whether or not to activate VVM int enable_vvm; unsigned int stream_count; gboolean speaker_active; //Status Settings char *provision_status; int mm_available; //Boolean int service_available; //Boolean int mailbox_active; //Boolean //Don't need to display this char *country_code; }; G_DEFINE_TYPE (VvmSettings, vvmplayer_settings, G_TYPE_OBJECT) void vvm_settings_set_vvm_enabled (VvmSettings *self, int VVMEnabled) { self->enable_vvm = VVMEnabled; if (self->enable_vvm) g_debug ("VVM Enabled is set to TRUE"); else g_debug ("VVM Enabled is set to FALSE"); } int vvm_settings_get_vvm_enabled (VvmSettings *self) { return self->enable_vvm; } void vvm_settings_set_speaker_button_state (VvmSettings *self, gboolean setting) { self->speaker_active = setting; g_debug ("speaker button state is now %d", self->speaker_active); } unsigned int vvm_settings_get_stream_count (VvmSettings *self) { return self->stream_count; } void vvm_settings_incriment_stream_count (VvmSettings *self) { if (self->stream_count == 0 && self->speaker_active == FALSE) { g_autoptr (GError) error = NULL; gboolean ret; g_debug ("Setting audio profile to call"); ret = call_audio_select_mode (CALL_AUDIO_MODE_CALL, &error); if (!ret && error) g_warning ("Failed to switch profile: %s", error->message); } self->stream_count = self->stream_count + 1; g_debug ("Stream count is imcrimented to %d", self->stream_count); } void vvm_settings_decriment_stream_count (VvmSettings *self) { if (self->stream_count == 0) { g_warning ("Stream count is already at 0!"); return; } self->stream_count = self->stream_count - 1; g_debug ("Stream count is decrimented to %d", self->stream_count); if (self->stream_count == 0 && self->speaker_active == FALSE) { g_autoptr (GError) error = NULL; gboolean ret; g_debug ("Setting audio profile to back to default"); ret = call_audio_select_mode (CALL_AUDIO_MODE_DEFAULT, &error); if (!ret && error) g_warning ("Failed to switch profile: %s", error->message); } } void vvm_settings_set_mm_available (VvmSettings *self, int ModemManagerAvailable) { self->mm_available = ModemManagerAvailable; if (self->mm_available) g_debug ("Modem Manager available through VVMD"); else g_debug ("Modem Manager not available through VVMD"); } int vvmplayer_settings_get_override_global_appearence_pref (VvmSettings *self) { return self->override_global_appearence_pref; } void vvmplayer_settings_set_override_global_appearence_pref (VvmSettings *self, int override_global_appearence_pref) { self->override_global_appearence_pref = override_global_appearence_pref; /* Set the setting right away */ g_settings_set_boolean (self->app_settings, "override-global-appearence-pref", self->override_global_appearence_pref); g_settings_apply (self->app_settings); } int vvmplayer_settings_get_dark_theme (VvmSettings *self) { return self->prefer_dark_theme; } void vvmplayer_settings_set_dark_theme (VvmSettings *self, int prefer_dark_theme) { self->prefer_dark_theme = prefer_dark_theme; /* Set the setting right away */ g_settings_set_boolean (self->app_settings, "dark-theme", self->prefer_dark_theme); g_settings_apply (self->app_settings); } char *vvm_settings_get_spam_contact (VvmSettings *self) { return g_strdup(self->spam_contact); } void vvm_settings_set_spam_contact (VvmSettings *self, const char *spam_contact) { g_free(self->spam_contact); self->spam_contact = g_strdup(spam_contact); g_debug ("Spam Contact is set to %s", self->spam_contact); /* Set the setting right away */ g_settings_set_string (self->app_settings, "spam-contact", self->spam_contact); g_settings_apply (self->app_settings); } gboolean vvmplayer_settings_get_spam_contact_enabled (VvmSettings *self) { return self->spam_contact_enabled; } void vvmplayer_settings_set_spam_contact_enabled (VvmSettings *self, gboolean spam_contact_enabled) { self->spam_contact_enabled = spam_contact_enabled; /* Set the setting right away */ g_settings_set_boolean (self->app_settings, "spam-contact-enabled", self->spam_contact_enabled); g_settings_apply (self->app_settings); } void vvmplayer_settings_set_default_dark_theme_pref (VvmSettings *self, int default_dark_theme_pref) { self->default_dark_theme_pref = default_dark_theme_pref; } int vvmplayer_settings_get_default_dark_theme_pref (VvmSettings *self) { return self->default_dark_theme_pref; } int vvm_settings_get_mm_available (VvmSettings *self) { return self->mm_available; } void vvm_settings_set_vvm_type (VvmSettings *self, const char *VVMType) { g_free(self->vvm_type); self->vvm_type = g_strdup(VVMType); g_debug ("VVM Type is set to %s", self->vvm_type); } char *vvm_settings_get_vvm_type (VvmSettings *self) { return g_strdup(self->vvm_type); } void vvm_settings_set_vvm_destination_number (VvmSettings *self, const char *VVMDestinationNumber) { g_free(self->vvm_destination_number); self->vvm_destination_number = g_strdup(VVMDestinationNumber); g_debug ("VVM Destination Number is set to %s", self->vvm_destination_number); } char *vvm_settings_get_vvm_destination_number (VvmSettings *self) { return g_strdup(self->vvm_destination_number); } void vvm_settings_set_vvm_carrier_prefix (VvmSettings *self, const char *CarrierPrefix) { g_free(self->carrier_prefix); self->carrier_prefix = g_strdup(CarrierPrefix); g_debug ("VVM Carrier Prefix is set to %s", self->carrier_prefix); } char *vvm_settings_get_vvm_carrier_prefix (VvmSettings *self) { return g_strdup(self->carrier_prefix); } void vvm_settings_set_vvm_default_number (VvmSettings *self, const char *DefaultModemNumber) { g_free(self->default_number); self->default_number = g_strdup(DefaultModemNumber); g_debug ("VVM Modem Default Number is set to %s", self->default_number); } char *vvm_settings_get_vvm_default_number (VvmSettings *self) { return g_strdup(self->default_number); } void vvm_settings_set_vvm_provision_status (VvmSettings *self, const char *ProvisionStatus) { g_free(self->provision_status); self->provision_status = g_strdup(ProvisionStatus); g_debug ("VVM ProvisionStatus is set to %s", self->provision_status); } char *vvm_settings_get_vvm_provision_status (VvmSettings *self) { return g_strdup(self->provision_status); } void vvm_settings_set_service_available (VvmSettings *self, int ServiceAvailable) { self->service_available = ServiceAvailable; if (self->service_available) g_debug ("VVMD Service available"); else g_debug ("VVMD Service not available"); } int vvm_settings_get_service_available (VvmSettings *self) { return self->service_available; } void vvm_settings_set_vvm_country_code (VvmSettings *self, const char *CountryCode) { g_free(self->country_code); self->country_code = g_strdup(CountryCode); g_debug ("VVM Modem Country Code is set to %s", self->country_code); } const char *vvm_settings_get_vvm_country_code (VvmSettings *self) { return self->country_code; } void vvm_settings_set_mailbox_active (VvmSettings *self, int MailboxActive) { self->mailbox_active = MailboxActive; if (self->mailbox_active) g_debug ("VVM Mailbox active"); else g_debug ("VVM Mailbox not active"); } int vvm_settings_get_mailbox_active (VvmSettings *self) { return self->mailbox_active; } void vvm_settings_load_mm_defaults (VvmSettings *self) { self->mm_available = FALSE; self->enable_vvm = FALSE; g_free (self->vvm_destination_number); self->vvm_destination_number = g_strdup("Destination Number invalid"); g_free (self->vvm_type); self->vvm_type = g_strdup("Unknown"); g_free (self->default_number); self->default_number = g_strdup("NULL"); g_free (self->provision_status); self->provision_status = g_strdup("Unknown"); g_free (self->carrier_prefix); self->carrier_prefix = g_strdup("Carrier Prefix invalid"); } void vvm_settings_load_service_defaults (VvmSettings *self) { self->mailbox_active = FALSE; g_free(self->country_code); self->country_code = g_strdup("Country Code invalid"); } static void vvmplayer_settings_dispose (GObject *object) { VvmSettings *self = (VvmSettings *)object; VVMPLAYER_TRACE_MSG ("disposing settings"); g_settings_set_string (self->app_settings, "version", PACKAGE_VERSION); g_settings_set_string (self->app_settings, "spam-contact", self->spam_contact); g_settings_set_boolean (self->app_settings, "spam-contact-enabled", self->spam_contact_enabled); g_settings_set_boolean (self->app_settings, "dark-theme", self->prefer_dark_theme); g_settings_set_boolean (self->app_settings, "override-global-appearence-pref", self->override_global_appearence_pref); g_settings_apply (self->app_settings); g_free (self->vvm_destination_number); g_free (self->vvm_type); g_free (self->default_number); g_free (self->carrier_prefix); g_free (self->provision_status); g_free (self->spam_contact); G_OBJECT_CLASS (vvmplayer_settings_parent_class)->dispose (object); } static void vvmplayer_settings_class_init (VvmSettingsClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->dispose = vvmplayer_settings_dispose; } static void vvmplayer_settings_init (VvmSettings *self) { g_autofree char *version = NULL; self->app_settings = g_settings_new (PACKAGE_ID); version = g_settings_get_string (self->app_settings, "version"); self->spam_contact = g_settings_get_string (self->app_settings, "spam-contact"); self->spam_contact_enabled = g_settings_get_boolean (self->app_settings, "spam-contact-enabled"); self->prefer_dark_theme = g_settings_get_boolean (self->app_settings, "dark-theme"); self->override_global_appearence_pref = g_settings_get_boolean (self->app_settings, "override-global-appearence-pref"); if (!g_str_equal (version, PACKAGE_VERSION)) self->first_run = TRUE; g_settings_delay (self->app_settings); } /** * vvmplayer_settings_new: * * Create a new #VvmSettings * * Returns: (transfer full): A #VvmSettings. * Free with g_object_unref(). */ VvmSettings * vvm_settings_get_default (void) { static VvmSettings *self; if (!self) { self = g_object_new (VVMPLAYER_TYPE_SETTINGS, NULL); g_object_add_weak_pointer (G_OBJECT (self), (gpointer *)&self); vvm_settings_load_mm_defaults (self); vvm_settings_load_service_defaults (self); self->stream_count = 0; self->speaker_active = FALSE; } return self; } /** * vvmplayer_settings_save: * @self: A #VvmSettings * * Save modified settings to disk. By default, * the modified settings are saved to disk only * when #VvmSettings is disposed. Use this * to force save to disk. */ void vvmplayer_settings_save (VvmSettings *self) { g_return_if_fail (VVMPLAYER_IS_SETTINGS (self)); g_settings_apply (self->app_settings); } /** * vvmplayer_settings_get_is_first_run: * @self: A #VvmSettings * * Get if the application has ever launched after install * or update. * * Returns: %TRUE for the first launch of application after * install or update. %FALSE otherwise. */ gboolean vvmplayer_settings_get_is_first_run (VvmSettings *self) { g_return_val_if_fail (VVMPLAYER_IS_SETTINGS (self), FALSE); return self->first_run; } /** * vvmplayer_settings_get_window_maximized: * @self: A #VvmSettings * * Get the window maximized state as saved in @self. * * Returns: %TRUE if maximized. %FALSE otherwise. */ gboolean vvmplayer_settings_get_window_maximized (VvmSettings *self) { g_return_val_if_fail (VVMPLAYER_IS_SETTINGS (self), FALSE); return g_settings_get_boolean (self->app_settings, "window-maximized"); } /** * vvmplayer_settings_set_window_maximized: * @self: A #VvmSettings * @maximized: The window state to save * * Set the window maximized state in @self. */ void vvmplayer_settings_set_window_maximized (VvmSettings *self, gboolean maximized) { g_return_if_fail (VVMPLAYER_IS_SETTINGS (self)); g_settings_set_boolean (self->app_settings, "window-maximized", !!maximized); } /** * vvmplayer_settings_get_window_geometry: * @self: A #VvmSettings * @geometry: (out): A #GdkRectangle * * Get the window geometry as saved in @self. */ void vvmplayer_settings_get_window_geometry (VvmSettings *self, GdkRectangle *geometry) { g_return_if_fail (VVMPLAYER_IS_SETTINGS (self)); g_return_if_fail (geometry != NULL); g_settings_get (self->app_settings, "window-size", "(ii)", &geometry->width, &geometry->height); geometry->x = geometry->y = -1; } /** * vvmplayer_settings_set_window_geometry: * @self: A #VvmSettings * @geometry: A #GdkRectangle * * Set the window geometry in @self. */ void vvmplayer_settings_set_window_geometry (VvmSettings *self, GdkRectangle *geometry) { g_return_if_fail (VVMPLAYER_IS_SETTINGS (self)); g_return_if_fail (geometry != NULL); g_settings_set (self->app_settings, "window-size", "(ii)", geometry->width, geometry->height); } vvmplayer-1.4/src/vvmplayer-settings.h000066400000000000000000000117771415227045700202520ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ /* vvmplayer-settings.h * * Copyright 2021 Chris Talbot * * This program is free software: you can 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 . * * Author(s): * Chris Talbot * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include #include "vvmplayer-log.h" G_BEGIN_DECLS #define VVMPLAYER_TYPE_SETTINGS (vvmplayer_settings_get_type ()) G_DECLARE_FINAL_TYPE (VvmSettings, vvmplayer_settings, VVMPLAYER, SETTINGS, GObject) VvmSettings *vvm_settings_get_default (void); void vvmplayer_settings_save (VvmSettings *self); gboolean vvmplayer_settings_get_is_first_run (VvmSettings *self); gboolean vvmplayer_settings_get_window_maximized (VvmSettings *self); void vvmplayer_settings_set_window_maximized (VvmSettings *self, gboolean maximized); void vvmplayer_settings_get_window_geometry (VvmSettings *self, GdkRectangle *geometry); void vvmplayer_settings_set_window_geometry (VvmSettings *self, GdkRectangle *geometry); void vvm_settings_load_mm_defaults (VvmSettings *self); void vvm_settings_load_service_defaults (VvmSettings *self); void vvm_settings_set_vvm_enabled (VvmSettings *self, int VVMEnabled); int vvm_settings_get_vvm_enabled (VvmSettings *self); void vvm_settings_incriment_stream_count (VvmSettings *self); void vvm_settings_decriment_stream_count (VvmSettings *self); unsigned int vvm_settings_get_stream_count (VvmSettings *self); void vvm_settings_set_speaker_button_state (VvmSettings *self, gboolean setting); void vvm_settings_set_vvm_type (VvmSettings *self, const char *VVMType); char *vvm_settings_get_vvm_type (VvmSettings *self); void vvm_settings_set_vvm_destination_number (VvmSettings *self, const char *VVMDestinationNumber); char *vvm_settings_get_vvm_destination_number (VvmSettings *self); void vvm_settings_set_vvm_default_number (VvmSettings *self, const char *DefaultModemNumber); char *vvm_settings_get_vvm_default_number (VvmSettings *self); void vvm_settings_set_vvm_provision_status (VvmSettings *self, const char *ProvisionStatus); char *vvm_settings_get_vvm_provision_status (VvmSettings *self); void vvm_settings_set_vvm_carrier_prefix (VvmSettings *self, const char *CarrierPrefix); char *vvm_settings_get_vvm_carrier_prefix (VvmSettings *self); void vvm_settings_set_mm_available (VvmSettings *self, int ModemManagerAvailable); int vvm_settings_get_mm_available (VvmSettings *self); void vvm_settings_set_service_available (VvmSettings *self, int ServiceAvailable); int vvm_settings_get_service_available (VvmSettings *self); void vvm_settings_set_vvm_country_code (VvmSettings *self, const char *CountryCode); const char *vvm_settings_get_vvm_country_code (VvmSettings *self); void vvm_settings_set_mailbox_active (VvmSettings *self, int MailboxActive); int vvm_settings_get_mailbox_active (VvmSettings *self); int vvmplayer_settings_get_override_global_appearence_pref (VvmSettings *self); void vvmplayer_settings_set_override_global_appearence_pref (VvmSettings *self, int override_global_appearence_pref); void vvmplayer_settings_set_dark_theme (VvmSettings *self, int prefer_dark_theme); int vvmplayer_settings_get_dark_theme (VvmSettings *self); void vvmplayer_settings_set_default_dark_theme_pref (VvmSettings *self, int default_dark_theme_pref); int vvmplayer_settings_get_default_dark_theme_pref (VvmSettings *self); gboolean vvmplayer_settings_get_spam_contact_enabled (VvmSettings *self); void vvmplayer_settings_set_spam_contact_enabled (VvmSettings *self, gboolean spam_contact_enabled); char *vvm_settings_get_spam_contact (VvmSettings *self); void vvm_settings_set_spam_contact (VvmSettings *self, const char *spam_contact); G_END_DECLS vvmplayer-1.4/src/vvmplayer-utils.c000066400000000000000000000034111415227045700175270ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ /* vvmplayer-utils.c * * Copyright 2021 Chris Talbot * * This program is free software: you can 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 . * * Author(s): * Chris Talbot * * SPDX-License-Identifier: GPL-3.0-or-later */ #define G_LOG_DOMAIN "vvmplayer-utils" #ifdef HAVE_CONFIG_H # include "config.h" #endif #include "vvmplayer-utils.h" /** * SECTION: vvmplayer-utils * @title: vvmplayer-utils * @short_description: Generic functions * @include: "vvmplayer-utils.h" * * Generic functions that doesn’t fit elsewhere. */ /** * vvmplayer_utils_get_main_thread: * * Returns the thread-id of the main thread. Useful * to check if current thread is the main UI thread * or not. This is used by VVMPLAYER_IS_MAIN_THREAD() macro. * * The first call to this function should be done in the * UI thread. The main() function * is a good place to do so. * * Returns: (transfer none): a #GThread */ GThread * vvmplayer_utils_get_main_thread (void) { static GThread *main_thread; if (G_UNLIKELY (main_thread == NULL)) main_thread = g_thread_self (); return main_thread; } vvmplayer-1.4/src/vvmplayer-utils.h000066400000000000000000000021351415227045700175360ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ /* vvmplayer-utils.h * * Copyright 2021 Chris Talbot * * This program is free software: you can 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 . * * Author(s): * Chris Talbot * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include G_BEGIN_DECLS #define VVMPLAYER_IS_MAIN_THREAD() (g_thread_self () == vvmplayer_utils_get_main_thread ()) GThread *vvmplayer_utils_get_main_thread (void); G_END_DECLS vvmplayer-1.4/src/vvmplayer-voicemail-window.c000066400000000000000000000514451415227045700216560ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ /* vvmplayer-voicemail-window.c * * Copyright 2021 Chris Talbot * 2021 GStreamer developers * * This program is free software: you can 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 . */ #define G_LOG_DOMAIN "vvmplayer-voicemail-window" #ifdef HAVE_CONFIG_H # include "config.h" #endif #include "vvmplayer-voicemail-window.h" #define ICON_PLAYBACK_STOP "media-playback-stop-symbolic" #define ICON_PLAYBACK_START "media-playback-start-symbolic" #define ICON_PLAYBACK_PAUSE "media-playback-pause-symbolic" #define ICON_DELETE "user-trash-symbolic" struct _VoicemailWindow { HdyActionRow parent_instance; GstElement *playbin; GstState state; GtkImage *play_button_icon; GtkImage *delete_button_icon; GtkButton *delete_button; HdyExpanderRow *action_expander_row; HdyActionRow *second_row; HdyActionRow *call_row; HdyActionRow *sms_row; gint64 duration; gint64 minutes; gint64 seconds; char *duration_formatted; char *objectpath; char *contact_name; char *number; int lifetime_status; GDBusProxy *message_proxy; GDateTime *time_local; gulong window_closed_id; }; G_DEFINE_TYPE (VoicemailWindow, voicemail_window, HDY_TYPE_ACTION_ROW) static void vvm_preferences_set_hdyexpanderrow_text (HdyExpanderRow *hdy_row, const char *text) { GValue a = G_VALUE_INIT; g_value_init (&a, G_TYPE_STRING); g_assert (G_VALUE_HOLDS_STRING (&a)); g_value_set_static_string (&a, text); g_object_set_property (G_OBJECT (hdy_row), "title", &a); } static void voicemail_window_set_title (VoicemailWindow *self) { g_autofree char *title = NULL; if (self->contact_name) { title = g_strdup(self->contact_name); } else { title = g_strdup(self->number); } if (self->lifetime_status == VVM_LIFETIME_STATUS_NOT_READ) { title = g_strdup_printf ("%s (Unread)", title); } vvm_preferences_set_hdyexpanderrow_text(self->action_expander_row, title); } char *voicemail_window_get_number (VoicemailWindow *self) { return g_strdup(self->number); } GDateTime *voicemail_window_get_datetime (VoicemailWindow *self) { return self->time_local; } char *voicemail_window_get_objectpath (VoicemailWindow *self) { return g_strdup(self->objectpath); } void voicemail_window_set_contact_name (VoicemailWindow *self, const char *contact_name) { g_free(self->contact_name); self->contact_name = g_strdup(contact_name); voicemail_window_set_title(self); } static void vvm_preferences_set_hdyactionrow_text (HdyActionRow *hdy_row, const char *text) { GValue a = G_VALUE_INIT; g_value_init (&a, G_TYPE_STRING); g_assert (G_VALUE_HOLDS_STRING (&a)); g_value_set_static_string (&a, text); g_object_set_property (G_OBJECT (hdy_row), "title", &a); } static gboolean refresh_ui (VoicemailWindow *self) { if (self->state == GST_STATE_READY || self->state == GST_STATE_PAUSED) { /* For extra responsiveness, we refresh the GUI as soon as we reach the PAUSED state */ return FALSE; } g_debug("Refreshing UI!"); g_autofree char *duration = NULL; self->seconds = self->seconds + 1; if (self->seconds == 60) { self->seconds = 0; self->minutes = self->minutes + 1; } duration = g_strdup_printf("%02lu:%02lu/%s", self->minutes, self->seconds, self->duration_formatted); vvm_preferences_set_hdyactionrow_text(self->second_row, duration); return TRUE; } static void vvm_voicemail_set_gtkimage_icon (GtkImage *image_to_set, const char *icon) { GValue a = G_VALUE_INIT; g_value_init (&a, G_TYPE_STRING); g_assert (G_VALUE_HOLDS_STRING (&a)); g_value_set_static_string (&a, icon); g_object_set_property (G_OBJECT (image_to_set), "icon-name", &a); } static void play_button_clicked_cb (GtkButton *btn, VoicemailWindow *self) { g_debug("Play button clicked!"); if (!self->playbin) { g_debug("Playbin is NULL!"); return; } VvmVvmd *vvmd_object = vvm_vvmd_get_default (); switch(self->lifetime_status) { case VVM_TYPE_UNKNOWN: case VVM_LIFETIME_STATUS_NOT_READ: g_debug("Marking as read...."); vvmplayer_vvmd_decrement_unread (vvmd_object); self->lifetime_status = VVM_LIFETIME_STATUS_READ; voicemail_window_set_title (self); vvmplayer_vvmd_mark_message_read (self->message_proxy, self->objectpath, self); break; case VVM_LIFETIME_STATUS_READ: break; default: g_warning("Something bad happened!"); } // We are not playing anything // Change it to Playing if (self->state != GST_STATE_PLAYING) { GstStateChangeReturn ret; vvm_voicemail_set_gtkimage_icon (self->delete_button_icon, ICON_PLAYBACK_STOP); ret = gst_element_set_state (self->playbin, GST_STATE_PLAYING); if (ret == GST_STATE_CHANGE_FAILURE) { g_printerr ("Unable to set the pipeline to the playing state.\n"); } else { VvmSettings *settings = vvm_settings_get_default (); vvm_settings_incriment_stream_count (settings); vvm_voicemail_set_gtkimage_icon (self->play_button_icon, ICON_PLAYBACK_PAUSE); /* Register a function that GLib will call every second */ g_timeout_add_seconds (1, (GSourceFunc)refresh_ui, self); self->state = GST_STATE_PLAYING; } // We are playing // Change it to paused } else { GstStateChangeReturn ret; vvm_voicemail_set_gtkimage_icon (self->delete_button_icon, ICON_DELETE); ret = gst_element_set_state (self->playbin, GST_STATE_PAUSED); if (ret == GST_STATE_CHANGE_FAILURE) { g_printerr ("Unable to set the pipeline to the playing state.\n"); } else { VvmSettings *settings = vvm_settings_get_default (); vvm_settings_decriment_stream_count (settings); vvm_voicemail_set_gtkimage_icon (self->play_button_icon, ICON_PLAYBACK_START); self->state = GST_STATE_PAUSED; } } } static void call_button_clicked_cb (GtkButton *btn, VoicemailWindow *self) { g_autoptr(GError) error = NULL; g_autofree char *uri = NULL; uri = g_strconcat ("tel://", self->number, NULL); if (!gtk_show_uri_on_window (NULL, uri, GDK_CURRENT_TIME, &error)) g_warning ("Failed to launch call: %s", error->message); } static void sms_button_clicked_cb (GtkButton *btn, VoicemailWindow *self) { g_autoptr(GError) error = NULL; g_autofree char *uri = NULL; uri = g_strconcat ("sms://", self->number, NULL); if (!gtk_show_uri_on_window (NULL, uri, GDK_CURRENT_TIME, &error)) g_warning ("Failed to launch call: %s", error->message); } void voicemail_window_delete_self (VoicemailWindow *self) { VvmVvmd *vvmd_object = vvm_vvmd_get_default (); g_debug("Deleting: %s", self->objectpath); if (self->lifetime_status == VVM_LIFETIME_STATUS_NOT_READ) vvmplayer_vvmd_decrement_unread (vvmd_object); vvmplayer_vvmd_delete_vvm (vvmd_object, self->message_proxy, self->objectpath, self); gtk_widget_destroy (GTK_WIDGET (self)); } static void delete_button_clicked_cb (GtkButton *btn, VoicemailWindow *self) { if (!self->playbin) { g_debug("Playbin is NULL!"); return; } if (self->state != GST_STATE_PLAYING) { //We are stopped voicemail_window_delete_self (self); return; } else { //We are playing or paused GstStateChangeReturn ret; ret = gst_element_set_state (self->playbin, GST_STATE_READY); if (ret == GST_STATE_CHANGE_FAILURE) { g_printerr ("Unable to set the pipeline to the stopped state.\n"); } else { g_autofree char *duration = NULL; VvmSettings *settings = vvm_settings_get_default (); vvm_settings_decriment_stream_count (settings); gst_element_set_state (self->playbin, GST_STATE_READY); vvm_voicemail_set_gtkimage_icon (self->delete_button_icon, ICON_DELETE); vvm_voicemail_set_gtkimage_icon (self->play_button_icon, ICON_PLAYBACK_START); self->state = GST_STATE_PAUSED; self->minutes = 0; self->seconds = 0; duration = g_strdup_printf("%02lu:%02lu/%s", self->minutes, self->seconds, self->duration_formatted); vvm_preferences_set_hdyactionrow_text(self->second_row, duration); } } } /* This function is called when an error message is posted on the bus */ static void error_cb (GstBus *bus, GstMessage *msg, VoicemailWindow *self) { GError *err; gchar *debug_info; /* Print error details on the screen */ gst_message_parse_error (msg, &err, &debug_info); g_printerr ("Error received from element %s: %s\n", GST_OBJECT_NAME (msg->src), err->message); g_printerr ("Debugging information: %s\n", debug_info ? debug_info : "none"); g_clear_error (&err); g_free (debug_info); /* Set the pipeline to READY (which stops playback) */ gst_element_set_state (self->playbin, GST_STATE_READY); vvm_voicemail_set_gtkimage_icon (self->play_button_icon, ICON_PLAYBACK_START); self->state = GST_STATE_READY; vvm_preferences_set_hdyactionrow_text(self->second_row, "Playback Error!"); } /* This function is called when an End-Of-Stream message is posted on the bus. * We just set the pipeline to READY (which stops playback) */ static void eos_cb (GstBus *bus, GstMessage *msg, VoicemailWindow *self) { g_autofree char *duration = NULL; VvmSettings *settings = vvm_settings_get_default (); g_debug ("End-Of-Stream reached."); gst_element_set_state (self->playbin, GST_STATE_READY); self->state = GST_STATE_READY; vvm_settings_decriment_stream_count (settings); vvm_voicemail_set_gtkimage_icon (self->play_button_icon, ICON_PLAYBACK_START); self->minutes = 0; self->seconds = 0; duration = g_strdup_printf("%02lu:%02lu/%s", self->minutes, self->seconds, self->duration_formatted); vvm_preferences_set_hdyactionrow_text(self->second_row, duration); vvm_voicemail_set_gtkimage_icon (self->delete_button_icon, ICON_DELETE); } /* This function is called when the pipeline changes states. We use it to * keep track of the current state. */ static void state_changed_cb (GstBus *bus, GstMessage *msg, VoicemailWindow *self) { GstState old_state, new_state, pending_state; gst_message_parse_state_changed (msg, &old_state, &new_state, &pending_state); if (GST_MESSAGE_SRC (msg) == GST_OBJECT (self->playbin)) { self->state = new_state; g_print ("State set to %s\n", gst_element_state_get_name (new_state)); if (old_state == GST_STATE_READY && new_state == GST_STATE_PAUSED) { /* For extra responsiveness, we refresh the GUI as soon as we reach the PAUSED state */ refresh_ui (self); } } } static void main_window_closed_cb (VoicemailWindow *self) { if (self->state == GST_STATE_PLAYING) { g_debug("Stopping Playback"); delete_button_clicked_cb (self->delete_button, self); } if (self->action_expander_row) hdy_expander_row_set_expanded (self->action_expander_row, FALSE); } GtkWidget * voicemail_window_new (GVariant *message_t, GDBusProxy *message_proxy, GstDiscoverer *discoverer) { VoicemailWindow *self; g_autofree char *objectpath = NULL; g_autofree char *Date = NULL; g_autofree char *Sender = NULL; g_autofree char *To = NULL; g_autofree char *MessageContext = NULL; g_autofree char *Attachments = NULL; g_autofree char **Attachment_list = NULL; g_autoptr (GError) error = NULL; int lifetime_status; int number_of_attachments; GVariant *properties; GVariantDict dict; g_autoptr(GAppInfo) app_info_tel = NULL; g_autoptr(GAppInfo) app_info_sms = NULL; self = g_object_new (GTK_TYPE_VOICEMAIL_WINDOW, NULL); self->window_closed_id = g_signal_connect_swapped (g_application_get_default (), "main-window-closed", G_CALLBACK (main_window_closed_cb), self); self->minutes = 0; self->seconds = 0; self->message_proxy = message_proxy; self->contact_name = NULL; app_info_tel = g_app_info_get_default_for_uri_scheme ("tel"); if (app_info_tel) { gtk_widget_show (GTK_WIDGET (self->call_row)); } app_info_sms = g_app_info_get_default_for_uri_scheme ("sms"); if (app_info_sms) { gtk_widget_show (GTK_WIDGET (self->sms_row)); } if (!discoverer) { self->duration_formatted = g_strdup ("??:??"); } g_variant_get (message_t, "(o@a{?*})", &objectpath, &properties); self->objectpath = g_strdup(objectpath); g_debug ("%s: Making row for voicemail", __func__); g_variant_dict_init (&dict, properties); if (!g_variant_dict_lookup (&dict, "Date", "s", &Date)) { Date = g_strdup("Invalid Date"); } else { GDateTime *time_utc; GTimeZone *here = g_time_zone_new_local (); time_utc = g_date_time_new_from_iso8601(Date, here); self->time_local = g_date_time_to_timezone (time_utc, here); g_date_time_unref (time_utc); Date = g_date_time_format (self->time_local, "%a, %d %b %Y %I:%M:%S %p"); g_time_zone_unref (here); } if (!g_variant_dict_lookup (&dict, "Sender", "s", &Sender)) Sender = g_strdup("Invalid Sender"); if (!g_variant_dict_lookup (&dict, "To", "s", &To)) To = g_strdup("Invalid To"); if (!g_variant_dict_lookup (&dict, "MessageContext", "s", &MessageContext)) MessageContext = g_strdup("Invalid Message Context"); if (!g_variant_dict_lookup (&dict, "Attachments", "s", &Attachments)) Attachments = NULL; if (!g_variant_dict_lookup (&dict, "LifetimeStatus", "i", &lifetime_status)) lifetime_status = VVM_LIFETIME_STATUS_UNKNOWN; self->lifetime_status = lifetime_status; if (Attachments) Attachment_list = g_strsplit(Attachments, ";", -1); number_of_attachments = g_strv_length (Attachment_list); for (int attachment_counter = 0; attachment_counter < (number_of_attachments); attachment_counter++) { GFile *vvm_file; GFileInfo *vvm_file_info; g_autofree char *mime_type = NULL; g_autofree char *attachment_uri = NULL; g_autofree char *attachment_uri_playbin = NULL; g_autofree char *duration = NULL; GstDiscovererInfo *info; GstBus *bus; g_debug("On Attachment: %s", Attachment_list[attachment_counter]); vvm_file = g_file_new_for_path (Attachment_list[attachment_counter]); vvm_file_info = g_file_query_info (vvm_file, "*", G_FILE_QUERY_INFO_NONE, NULL, &error); if (error != NULL) { g_warning ("Error getting file info: %s", error->message); error = NULL; continue; } mime_type = g_content_type_get_mime_type (g_file_info_get_content_type (vvm_file_info)); if (mime_type == NULL) { g_debug ("Could not get MIME type! Trying Content Type instead"); if (g_file_info_get_content_type (vvm_file_info) != NULL) { mime_type = g_strdup (g_file_info_get_content_type (vvm_file_info)); } else { g_debug ("Could not figure out Content Type! Using a Generic one"); continue; } } g_debug("MIME Type: %s", mime_type); if (strstr (mime_type, "audio") == NULL) { g_debug("MIME Type is not audio! skipping...."); /* Will I get anything else here? */ continue; } self->duration = GST_CLOCK_TIME_NONE; attachment_uri = g_strdup_printf("file://%s", Attachment_list[attachment_counter]); // amr files have issues playing on Mobian, so I need to add `audio-sink='capsfilter caps=audio/x-raw,rate=48000 ! pulsesink'` // gst-launch-1.0 playbin uri=file:///path/to/foo audio-sink='capsfilter caps=audio/x-raw,rate=48000 ! pulsesink' attachment_uri_playbin = g_strdup_printf("playbin uri=%s audio-sink='capsfilter caps=audio/x-raw,rate=48000 ! pulsesink'", attachment_uri); if (discoverer) { info = gst_discoverer_discover_uri(discoverer, attachment_uri, &error); if (error != NULL) { g_warning ("Error discovering file: %s", error->message); self->duration_formatted = g_strdup ("??:??"); } else { self->duration = gst_discoverer_info_get_duration (info); if (self->duration == 0) { /* There is a problem in gst-discoverer: * https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/718 * This code works around it. */ int retry_counter = 0; g_warning ("Error in gst_discoverer!"); while (self->duration == 0) { g_debug ("Retrying...."); info = gst_discoverer_discover_uri(discoverer, attachment_uri, &error); self->duration = gst_discoverer_info_get_duration (info); retry_counter = retry_counter + 1; if (retry_counter == 10) { break; } } if (self->duration == 0) { g_warning ("Could not fix!"); } else { g_debug ("Fixed!"); } } if (self->duration == 0) { self->duration_formatted = g_strdup ("??:??"); } else { self->minutes = (self->duration / (GST_SECOND * 60)) % 60; self->seconds = GST_TIME_AS_SECONDS (self->duration) - self->minutes * 60; self->duration_formatted = g_strdup_printf ("%02lu:%02lu", self->minutes, self->seconds); } } } self->minutes = 0; self->seconds = 0; duration = g_strdup_printf("%02lu:%02lu/%s", self->minutes, self->seconds, self->duration_formatted); vvm_preferences_set_hdyactionrow_text(self->second_row, duration); self->state = GST_STATE_READY; self->playbin = gst_parse_launch (attachment_uri_playbin, NULL); /* Instruct the bus to emit signals for each received message, and connect to the interesting signals */ bus = gst_element_get_bus (self->playbin); gst_bus_add_signal_watch (bus); g_signal_connect (G_OBJECT (bus), "message::error", (GCallback)error_cb, self); g_signal_connect (G_OBJECT (bus), "message::eos", (GCallback)eos_cb, self); g_signal_connect (G_OBJECT (bus), "message::state-changed", (GCallback)state_changed_cb, self); gst_object_unref (bus); } self->number = g_strdup(Sender); if (self->lifetime_status == VVM_LIFETIME_STATUS_NOT_READ) { VvmVvmd *vvmd_object = vvm_vvmd_get_default (); vvmplayer_vvmd_increment_unread (vvmd_object); } voicemail_window_set_title (self); hdy_expander_row_set_subtitle(self->action_expander_row, Date); return GTK_WIDGET (self); } static void voicemail_window_finalize (GObject *object) { VoicemailWindow *self = (VoicemailWindow *)object; g_signal_handler_disconnect (g_application_get_default (), self->window_closed_id); g_free (self->duration_formatted); g_free (self->objectpath); g_free (self->number); g_free (self->contact_name); g_date_time_unref (self->time_local); G_OBJECT_CLASS (voicemail_window_parent_class)->finalize (object); } static void voicemail_window_class_init (VoicemailWindowClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); gtk_widget_class_set_template_from_resource (widget_class, "/org/kop316/vvmplayer/" "ui/vvmplayer-voicemail-window.ui"); gtk_widget_class_bind_template_child (widget_class, VoicemailWindow, action_expander_row); gtk_widget_class_bind_template_child (widget_class, VoicemailWindow, play_button_icon); gtk_widget_class_bind_template_child (widget_class, VoicemailWindow, delete_button); gtk_widget_class_bind_template_child (widget_class, VoicemailWindow, delete_button_icon); gtk_widget_class_bind_template_child (widget_class, VoicemailWindow, second_row); gtk_widget_class_bind_template_child (widget_class, VoicemailWindow, call_row); gtk_widget_class_bind_template_child (widget_class, VoicemailWindow, sms_row); gtk_widget_class_bind_template_callback (widget_class, play_button_clicked_cb); gtk_widget_class_bind_template_callback (widget_class, delete_button_clicked_cb); gtk_widget_class_bind_template_callback (widget_class, call_button_clicked_cb); gtk_widget_class_bind_template_callback (widget_class, sms_button_clicked_cb); object_class->finalize = voicemail_window_finalize; } static void voicemail_window_init (VoicemailWindow *self) { gtk_widget_init_template (GTK_WIDGET (self)); } vvmplayer-1.4/src/vvmplayer-voicemail-window.h000066400000000000000000000036361415227045700216620ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ /* vvmplayer-voicemail-window.h * * Copyright 2021 Chris Talbot * * This program is free software: you can 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 . * * Author(s): * Chris Talbot * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include #include #include #include "vvmplayer-vvmd.h" #include "vvmplayer-settings.h" G_BEGIN_DECLS enum vvmd_lifetime_status { VVM_LIFETIME_STATUS_UNKNOWN, VVM_LIFETIME_STATUS_NOT_READ, VVM_LIFETIME_STATUS_READ }; #define GTK_TYPE_VOICEMAIL_WINDOW (voicemail_window_get_type()) G_DECLARE_FINAL_TYPE (VoicemailWindow, voicemail_window, VVM, VOICEMAIL_WINDOW, HdyExpanderRow) GtkWidget *voicemail_window_new (GVariant *message_t, GDBusProxy *message_proxy, GstDiscoverer *discoverer); void voicemail_window_set_contact_name (VoicemailWindow *self, const char *contact_name); char *voicemail_window_get_number (VoicemailWindow *self); char *voicemail_window_get_objectpath (VoicemailWindow *self); GDateTime *voicemail_window_get_datetime (VoicemailWindow *self); void voicemail_window_delete_self (VoicemailWindow *self); G_END_DECLS vvmplayer-1.4/src/vvmplayer-vvmd.c000066400000000000000000001043611415227045700173510ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ /* vvmplayer-vvmd.c * * Copyright 2021 Chris Talbot * * This program is free software: you can 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 . */ #define G_LOG_DOMAIN "vvmplayer-vvmd" #ifdef HAVE_CONFIG_H # include "config.h" #endif #include "vvmplayer-vvmd.h" #define VVMD_SERVICE "org.kop316.vvm" #define VVMD_PATH "/org/kop316/vvm" #define VVMD_MODEMMANAGER_PATH VVMD_PATH "/modemmanager" #define VVMD_MANAGER_INTERFACE VVMD_SERVICE ".Manager" #define VVMD_SERVICE_INTERFACE VVMD_SERVICE ".Service" #define VVMD_MESSAGE_INTERFACE VVMD_SERVICE ".Message" #define VVMD_MODEMMANAGER_INTERFACE VVMD_SERVICE ".ModemManager" struct _VvmVvmd { GObject parent_instance; VvmWindow *visual_voicemail; GDBusConnection *connection; unsigned int vvmd_watch_id; GDBusProxy *modemmanager_proxy; unsigned int vvmd_manager_proxy_remove_watch_id; unsigned int vvmd_manager_proxy_add_watch_id; unsigned int vvmd_service_proxy_watch_id; unsigned int vvmd_mm_settings_watch_id; unsigned int vvmd_mm_provision_watch_id; GDBusProxy *manager_proxy; GDBusProxy *service_proxy; GListStore *vvm_list; VvmEds *contacts; GstDiscoverer *discoverer; unsigned int unread_vvms; }; G_DEFINE_TYPE (VvmVvmd, vvm_vvmd, G_TYPE_OBJECT) int vvmplayer_vvmd_encode_vvm_type (const char *vvm_type) { if (g_strcmp0(vvm_type, "Unknown") == 0) { return VVM_TYPE_UNKNOWN; } else if (g_strcmp0(vvm_type, "cvvm") == 0) { return VVM_TYPE_CVVM; } else if (g_strcmp0(vvm_type, "AT&TUSAProprietary") == 0) { return VVM_TYPE_ATTUSA; } else if (g_strcmp0(vvm_type, "otmp") == 0) { return VVM_TYPE_OTMP; } else if (g_strcmp0(vvm_type, "vvm3") == 0) { return VVM_TYPE_VVM_THREE; } else { return VVM_TYPE_UNKNOWN; } return VVM_TYPE_UNKNOWN; } char *vvmplayer_vvmd_decode_vvm_type (int vvm_type) { switch(vvm_type) { case VVM_TYPE_UNKNOWN: return g_strdup("Unknown"); case VVM_TYPE_CVVM: return g_strdup("cvvm"); case VVM_TYPE_ATTUSA: return g_strdup("AT&TUSAProprietary"); case VVM_TYPE_OTMP: return g_strdup("otmp"); case VVM_TYPE_VVM_THREE: return g_strdup("vvm3"); default: return g_strdup("Unknown"); } return g_strdup("Unknown"); } void vvmplayer_vvmd_set_mm_vvm_list_box (VvmVvmd *self, VvmWindow *visual_voicemail) { self->visual_voicemail = visual_voicemail; } void vvmplayer_vvmd_increment_unread (VvmVvmd *self) { self->unread_vvms = self->unread_vvms + 1; } void vvmplayer_vvmd_decrement_unread (VvmVvmd *self) { self->unread_vvms = self->unread_vvms - 1; } int vvmplayer_vvmd_set_mm_vvm_enabled (VvmVvmd *self, int enabled) { g_autoptr (GError) error = NULL; GVariant *new_setting; new_setting = g_variant_new_parsed("(%s, <%b>)", "VVMEnabled", enabled); g_dbus_proxy_call_sync (self->modemmanager_proxy, "ChangeSettings", new_setting, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if (error != NULL) { g_warning ("Error Enabling or disabling VVM!"); return FALSE; } return TRUE; } int vvmplayer_vvmd_check_subscription_status (VvmVvmd *self) { g_autoptr (GError) error = NULL; g_dbus_proxy_call_sync (self->modemmanager_proxy, "CheckSubscriptonStatus", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if (error != NULL) { g_warning ("Error Checking Subscription Status!"); return FALSE; } return TRUE; } static void vvmplayer_vvmd_sync_vvm_cb (GObject *interface, GAsyncResult *result, gpointer *user_data) { g_autoptr (GError) error = NULL; if (g_dbus_proxy_call_finish (G_DBUS_PROXY (interface), result, &error)) { g_debug ("Sync'd VVMs"); } else { g_debug ("Couldn't synchronize VVMs: %s", error ? error->message : "unknown"); } } int vvmplayer_vvmd_sync_vvm (VvmVvmd *self) { g_dbus_proxy_call (self->modemmanager_proxy, "SyncVVM", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, (GAsyncReadyCallback) vvmplayer_vvmd_sync_vvm_cb, NULL); return TRUE; } int vvmplayer_vvmd_set_mm_setting (VvmVvmd *self, const char *setting_to_change, const char *updated_setting) { g_autoptr (GError) error = NULL; GVariant *new_setting; new_setting = g_variant_new_parsed("(%s, <%s>)", setting_to_change, updated_setting); g_dbus_proxy_call_sync (self->modemmanager_proxy, "ChangeSettings", new_setting, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if (error != NULL) { g_warning ("Error setting %s to %s: Error is %s", setting_to_change, updated_setting, error->message); return FALSE; } return TRUE; } int vvmplayer_vvmd_get_service_settings (VvmVvmd *self) { g_autoptr (GError) error = NULL; GVariant *ret; ret = g_dbus_proxy_call_sync (self->service_proxy, "GetProperties", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if (error != NULL) { g_warning ("Error in Proxy call: %s\n", error->message); return FALSE; } else { GVariantDict dict; GVariant *all_settings; int MailBoxActive; g_autofree char *ModemCountryCode = NULL; VvmSettings *settings = vvm_settings_get_default (); g_variant_get (ret, "(@a{?*})", &all_settings); g_variant_dict_init (&dict, all_settings); if (g_variant_dict_lookup (&dict, "ModemCountryCode", "s", &ModemCountryCode)) { vvm_settings_set_vvm_country_code (settings, ModemCountryCode); } if (g_variant_dict_lookup (&dict, "MailBoxActive", "b", &MailBoxActive)) { vvm_settings_set_mailbox_active (settings, MailBoxActive); } } return TRUE; } static void vvmplayer_vvmd_delete_vvm_cb (GObject *interface, GAsyncResult *result, gpointer *user_data) { g_autoptr (GError) error = NULL; if (g_dbus_proxy_call_finish (G_DBUS_PROXY (interface), result, &error)) { g_debug ("VVM deleted"); } else { g_debug ("Couldn't delete VVM as read- error: %s", error ? error->message : "unknown"); } } static int vvm_list_match_by_obj_path (VoicemailWindow *old_voicemail, gconstpointer voicemail) { g_autofree char *old_objectpath = NULL; g_autofree char *objectpath = NULL; old_objectpath = voicemail_window_get_objectpath (old_voicemail); objectpath = voicemail_window_get_objectpath ((VoicemailWindow *) voicemail); return g_strcmp0 (old_objectpath, objectpath) == 0; } void vvmplayer_vvmd_delete_vvm (VvmVvmd *self, GDBusProxy *message_proxy, char *objectpath, gconstpointer user_data) { guint position; VoicemailWindow *voicemail = (VoicemailWindow *) user_data; if (g_list_store_find_with_equal_func (self->vvm_list, voicemail, (GEqualFunc)vvm_list_match_by_obj_path, &position)) { g_list_store_remove (self->vvm_list, position); g_debug ("Deleted VVM from g_list_store new length: %d", g_list_model_get_n_items(G_LIST_MODEL (self->vvm_list))); } g_debug ("Deleting VVM with Object Path: %s", objectpath); g_dbus_proxy_call (message_proxy, "Delete", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, (GAsyncReadyCallback) vvmplayer_vvmd_delete_vvm_cb, voicemail); return; } static void vvmplayer_vvmd_mark_message_read_cb (GObject *interface, GAsyncResult *result, gpointer *user_data) { g_autoptr (GError) error = NULL; if (g_dbus_proxy_call_finish (G_DBUS_PROXY (interface), result, &error)) { g_debug ("VVM marked as read"); } else { g_debug ("Couldn't mark VVM as read- error: %s", error ? error->message : "unknown"); } } void vvmplayer_vvmd_mark_message_read (GDBusProxy *message_proxy, char *objectpath, gpointer user_data) { g_debug ("Marking VVM read with Object Path: %s", objectpath); g_dbus_proxy_call (message_proxy, "MarkRead", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, (GAsyncReadyCallback) vvmplayer_vvmd_mark_message_read_cb, user_data); } static gboolean vvmplayer_vvmd_add_contact_name (VvmVvmd *self, VoicemailWindow *voicemail) { if (vvm_eds_get_is_ready (self->contacts)) { g_autofree char *contact_name = NULL; g_autofree char *phone_number = NULL; VvmContact *contact; phone_number = voicemail_window_get_number (VVM_VOICEMAIL_WINDOW (voicemail)); contact = vvm_eds_find_by_number (self->contacts, phone_number); if (contact != NULL) { VvmSettings *settings = vvm_settings_get_default (); contact_name = g_strdup (vvm_contact_get_name (contact)); if (vvmplayer_settings_get_spam_contact_enabled (settings) == TRUE) { g_autofree char *spam_contact = NULL; spam_contact = vvm_settings_get_spam_contact (settings); if (g_strcmp0 (spam_contact, contact_name) == 0) { g_debug("Deleting spam Voicemail."); voicemail_window_delete_self (VVM_VOICEMAIL_WINDOW (voicemail)); return FALSE; } } voicemail_window_set_contact_name (VVM_VOICEMAIL_WINDOW (voicemail), contact_name); } } return TRUE; } static int compare_dates (VoicemailWindow *old_voicemail, VoicemailWindow *voicemail, gpointer user_data) { return g_date_time_compare (voicemail_window_get_datetime (old_voicemail), voicemail_window_get_datetime (voicemail)); } static gboolean vvmplayer_vvmd_receive_message (VvmVvmd *self, GVariant *message_t) { GtkWidget *voicemail; GVariant *properties; char *objectpath; GDBusProxy *message_proxy; guint n_items = g_list_model_get_n_items(G_LIST_MODEL (self->vvm_list)); g_variant_get (message_t, "(o@a{?*})", &objectpath, &properties); g_debug ("Processing VVM: %s", objectpath); if (n_items != 0) { unsigned int i = 0; for (i = 0; i < n_items; i = i + 1) { g_autofree char *temp_objectpath = NULL; g_autoptr(VoicemailWindow) voicemail = NULL; voicemail = g_list_model_get_item (G_LIST_MODEL (self->vvm_list), i); temp_objectpath = voicemail_window_get_objectpath (voicemail); if (g_strcmp0 (temp_objectpath, objectpath) == 0) { g_debug("VVM Already exists!"); return FALSE; } } } message_proxy = g_dbus_proxy_new_sync (self->connection, G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, NULL, VVMD_SERVICE, objectpath, VVMD_MESSAGE_INTERFACE, NULL, NULL); if (message_proxy == NULL) { g_warning ("Error connecting to the message Proxy!"); return FALSE; } voicemail = voicemail_window_new (message_t, message_proxy, self->discoverer); if (voicemail == NULL) { g_warning ("There was an error with making the VVM!"); return FALSE; } if (vvmplayer_vvmd_add_contact_name (self, VVM_VOICEMAIL_WINDOW (voicemail)) == FALSE) { return FALSE; } g_list_store_insert_sorted (self->vvm_list, VVM_VOICEMAIL_WINDOW (voicemail), (GCompareDataFunc) compare_dates, NULL); return TRUE; } static void vvmplayer_vvmd_get_new_vvm_cb (GDBusConnection *connection, const char *sender_name, const char *object_path, const char *interface_name, const char *signal_name, GVariant *parameters, gpointer user_data) { VvmVvmd *self = user_data; unsigned int last_position = g_list_model_get_n_items(G_LIST_MODEL (self->vvm_list)); g_autoptr(VoicemailWindow) voicemail = NULL; int previous_unread = self->unread_vvms; g_debug ("%s", __func__); if (vvmplayer_vvmd_receive_message (self, parameters) == TRUE) { voicemail = g_list_model_get_item (G_LIST_MODEL (self->vvm_list), last_position); vvmplayer_window_add_row (self->visual_voicemail, GTK_WIDGET (voicemail)); if (previous_unread < self->unread_vvms) { vvmplayer_notification_send_unread_vvm (self->unread_vvms); } } } static void vvmplayer_vvmd_get_all_vvm_cb (GObject *service, GAsyncResult *res, gpointer user_data) { VvmVvmd *self = user_data; g_autoptr (GError) error = NULL; GVariant *ret; g_debug ("%s", __func__); int previous_unread = self->unread_vvms; ret = g_dbus_proxy_call_finish (self->service_proxy, res, &error); if (error != NULL) { g_warning ("Error in Proxy call: %s\n", error->message); } else { GVariant *msg_pack = g_variant_get_child_value (ret, 0); GVariantIter iter; unsigned long num; if ((num = g_variant_iter_init (&iter, msg_pack))) { GVariant *message_t; guint n_items; unsigned int i = 0; g_debug ("Have %lu VVM (s) to process", num); while ((message_t = g_variant_iter_next_value (&iter))) { vvmplayer_vvmd_receive_message (self, message_t); } n_items = g_list_model_get_n_items (G_LIST_MODEL (self->vvm_list)); for (i = 0; i < n_items; i = i + 1) { g_autoptr(VoicemailWindow) voicemail = NULL; voicemail = g_list_model_get_item (G_LIST_MODEL (self->vvm_list), i); vvmplayer_window_add_row (self->visual_voicemail, GTK_WIDGET (voicemail)); } } } if (previous_unread < self->unread_vvms) { vvmplayer_notification_send_unread_vvm (self->unread_vvms); } } static void vvmplayer_vvmd_get_service_cb (GObject *service, GAsyncResult *res, gpointer user_data) { VvmVvmd *self = user_data; g_autoptr (GError) error = NULL; self->service_proxy = g_dbus_proxy_new_finish (res, &error); if (error != NULL) { g_warning ("Error in VVMD Service Proxy call: %s\n", error->message); } else { g_debug ("Got VVMD Service"); if (vvmplayer_vvmd_get_service_settings (self) == FALSE) { g_warning ("Error getting VVMD Service Settings"); } else { VvmSettings *settings = vvm_settings_get_default (); vvm_settings_set_service_available (settings, TRUE); self->vvmd_service_proxy_watch_id = g_dbus_connection_signal_subscribe (self->connection, VVMD_SERVICE, VVMD_SERVICE_INTERFACE, "MessageAdded", VVMD_MODEMMANAGER_PATH, NULL, G_DBUS_SIGNAL_FLAGS_NONE, (GDBusSignalCallback)vvmplayer_vvmd_get_new_vvm_cb, self, NULL); if (self->vvmd_service_proxy_watch_id) { g_debug ("Listening for new VVMs"); } else { g_warning ("Failed to connect 'MessageAdded' signal"); } g_dbus_proxy_call (self->service_proxy, "GetMessages", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, (GAsyncReadyCallback)vvmplayer_vvmd_get_all_vvm_cb, self); } } } static void vvmplayer_vvmd_connect_to_service (VvmVvmd *self, GVariant *service) { char *servicepath, *serviceidentity; GVariant *properties; GVariantDict dict; g_variant_get (service, "(o@a{?*})", &servicepath, &properties); g_debug ("Service Path: %s", servicepath); g_variant_dict_init (&dict, properties); if (!g_variant_dict_lookup (&dict, "Identity", "s", &serviceidentity)) { g_warning ("Could not get Service Identity!"); serviceidentity = NULL; return; } g_debug ("Identity: %s", serviceidentity); if (g_strcmp0 (servicepath, VVMD_MODEMMANAGER_PATH) == 0) { g_dbus_proxy_new (self->connection, G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, NULL, VVMD_SERVICE, servicepath, VVMD_SERVICE_INTERFACE, NULL, vvmplayer_vvmd_get_service_cb, self); } } static void vvmplayer_vvmd_service_added_cb (GDBusConnection *connection, const char *sender_name, const char *object_path, const char *interface_name, const char *signal_name, GVariant *parameters, gpointer user_data) { VvmVvmd *self = user_data; g_autoptr (GError) error = NULL; g_debug ("%s", __func__); g_debug ("Service Added g_variant: %s", g_variant_print (parameters, TRUE)); vvmplayer_vvmd_connect_to_service (self, parameters); } static void vvmplayer_vvmd_remove_service (VvmVvmd *self) { if (G_IS_OBJECT (self->service_proxy)) { g_debug ("Removing Service!"); g_object_unref (self->service_proxy); g_dbus_connection_signal_unsubscribe (self->connection, self->vvmd_service_proxy_watch_id); } else { g_warning ("No Service to remove!"); } } static void vvmplayer_vvmd_service_removed_cb (GDBusConnection *connection, const char *sender_name, const char *object_path, const char *interface_name, const char *signal_name, GVariant *parameters, gpointer user_data) { VvmVvmd *self = user_data; g_autoptr (GError) error = NULL; g_debug ("%s", __func__); g_debug ("Service Removed g_variant: %s", g_variant_print (parameters, TRUE)); vvmplayer_vvmd_remove_service (self); } static void vvmplayer_vvmd_get_manager_cb (GObject *manager, GAsyncResult *res, gpointer user_data) { VvmVvmd *self = user_data; g_autoptr (GError) error = NULL; self->manager_proxy = g_dbus_proxy_new_finish (res, &error); if (error != NULL) { g_warning ("Error in VVMD Manager Proxy call: %s\n", error->message); } else { GVariant *all_services, *service_pack; GVariantIter iter; unsigned long num; g_debug ("Got VVMD Manager"); self->vvmd_manager_proxy_add_watch_id = g_dbus_connection_signal_subscribe (self->connection, VVMD_SERVICE, VVMD_MANAGER_INTERFACE, "ServiceAdded", VVMD_PATH, NULL, G_DBUS_SIGNAL_FLAGS_NONE, (GDBusSignalCallback)vvmplayer_vvmd_service_added_cb, self, NULL); self->vvmd_manager_proxy_remove_watch_id = g_dbus_connection_signal_subscribe (self->connection, VVMD_SERVICE, VVMD_MANAGER_INTERFACE, "ServiceRemoved", VVMD_PATH, NULL, G_DBUS_SIGNAL_FLAGS_NONE, (GDBusSignalCallback)vvmplayer_vvmd_service_removed_cb, self, NULL); all_services = g_dbus_proxy_call_sync (self->manager_proxy, "GetServices", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL); service_pack = g_variant_get_child_value (all_services, 0); if ((num = g_variant_iter_init (&iter, service_pack))) { GVariant *service; while ((service = g_variant_iter_next_value (&iter))) { vvmplayer_vvmd_connect_to_service (self, service); } } } } static void vvmplayer_vvmd_provision_status_changed_cb (GDBusConnection *connection, const char *sender_name, const char *object_path, const char *interface_name, const char *signal_name, GVariant *parameters, gpointer user_data) { //VvmVvmd *self = user_data; VvmSettings *settings = vvm_settings_get_default (); g_autoptr (GVariant) provisionstatus = NULL; const char *provision; g_debug ("%s", __func__); g_variant_get (parameters, "(sv)", NULL, &provisionstatus); provision = g_variant_get_string (provisionstatus, NULL); vvm_settings_set_vvm_provision_status (settings, provision); } static void vvmplayer_vvmd_provision_settings_changed_cb (GDBusConnection *connection, const char *sender_name, const char *object_path, const char *interface_name, const char *signal_name, GVariant *parameters, gpointer user_data) { //VvmVvmd *self = user_data; VvmSettings *settings = vvm_settings_get_default (); g_autoptr (GError) error = NULL; g_autoptr (GVariant) provisionstatus = NULL; const char *VVMType = NULL; const char *VVMDestinationNumber = NULL; const char *CarrierPrefix = NULL; g_debug ("%s", __func__); g_variant_get (parameters, "(sss)", &VVMType, &VVMDestinationNumber, &CarrierPrefix); vvm_settings_set_vvm_type (settings, VVMType); vvm_settings_set_vvm_destination_number (settings, VVMDestinationNumber); vvm_settings_set_vvm_carrier_prefix (settings, CarrierPrefix); } int vvmplayer_vvmd_get_mm_settings (VvmVvmd *self) { g_autoptr (GError) error = NULL; GVariant *ret; g_debug ("Got VVMD Modem Manager"); ret = g_dbus_proxy_call_sync (self->modemmanager_proxy, "ViewSettings", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if (error != NULL) { g_warning ("Error in Proxy call: %s\n", error->message); return FALSE; } else { VvmSettings *settings = vvm_settings_get_default (); GVariantDict dict; GVariant *all_settings; int VVMEnabled; g_autofree char *VVMType = NULL; g_autofree char *VVMDestinationNumber = NULL; g_autofree char *CarrierPrefix = NULL; g_autofree char *DefaultModemNumber = NULL; g_autofree char *ProvisionStatus = NULL; g_variant_get (ret, "(@a{?*})", &all_settings); g_variant_dict_init (&dict, all_settings); if (g_variant_dict_lookup (&dict, "VVMEnabled", "b", &VVMEnabled)) { vvm_settings_set_vvm_enabled (settings, VVMEnabled); } if (g_variant_dict_lookup (&dict, "VVMType", "s", &VVMType)) { vvm_settings_set_vvm_type (settings, VVMType); } if (g_variant_dict_lookup (&dict, "VVMDestinationNumber", "s", &VVMDestinationNumber)) { vvm_settings_set_vvm_destination_number (settings, VVMDestinationNumber); } if (g_variant_dict_lookup (&dict, "CarrierPrefix", "s", &CarrierPrefix)) { vvm_settings_set_vvm_carrier_prefix (settings, CarrierPrefix); } if (g_variant_dict_lookup (&dict, "DefaultModemNumber", "s", &DefaultModemNumber)) { vvm_settings_set_vvm_default_number (settings, DefaultModemNumber); } if (g_variant_dict_lookup (&dict, "ProvisionStatus", "s", &ProvisionStatus)) { vvm_settings_set_vvm_provision_status (settings, ProvisionStatus); } } self->vvmd_mm_provision_watch_id = g_dbus_connection_signal_subscribe (self->connection, VVMD_SERVICE, VVMD_MODEMMANAGER_INTERFACE, "ProvisionStatusChanged", VVMD_PATH, NULL, G_DBUS_SIGNAL_FLAGS_NONE, (GDBusSignalCallback)vvmplayer_vvmd_provision_status_changed_cb, self, NULL); self->vvmd_mm_settings_watch_id = g_dbus_connection_signal_subscribe (self->connection, VVMD_SERVICE, VVMD_MODEMMANAGER_INTERFACE, "SettingsChanged", VVMD_PATH, NULL, G_DBUS_SIGNAL_FLAGS_NONE, (GDBusSignalCallback)vvmplayer_vvmd_provision_settings_changed_cb, self, NULL); return TRUE; } static gboolean vvmplayer_vvmd_retry_mm_settings(gpointer user_data) { VvmVvmd *self = user_data; g_debug("Retrying..."); if (vvmplayer_vvmd_get_mm_settings(self) == FALSE) { g_warning ("Error getting VVMD Modem Manager Settings"); return TRUE; } else { VvmSettings *settings = vvm_settings_get_default (); vvm_settings_set_mm_available (settings, TRUE); g_dbus_proxy_new (self->connection, G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, NULL, VVMD_SERVICE, VVMD_PATH, VVMD_MANAGER_INTERFACE, NULL, vvmplayer_vvmd_get_manager_cb, self); } return FALSE; } static void vvmplayer_vvmd_get_modemmanager_cb (GObject *simple, GAsyncResult *res, gpointer user_data) { VvmVvmd *self = user_data; g_autoptr (GError) error = NULL; self->modemmanager_proxy = g_dbus_proxy_new_finish (res, &error); if (error != NULL) { g_warning ("Error in VVMD Modem Manager Proxy call: %s\n", error->message); } else { if (vvmplayer_vvmd_get_mm_settings(self) == FALSE) { g_warning ("Error getting VVMD Modem Manager Settings"); g_timeout_add_seconds (1, vvmplayer_vvmd_retry_mm_settings, self); } else { VvmSettings *settings = vvm_settings_get_default (); vvm_settings_set_mm_available (settings, TRUE); g_dbus_proxy_new (self->connection, G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, NULL, VVMD_SERVICE, VVMD_PATH, VVMD_MANAGER_INTERFACE, NULL, vvmplayer_vvmd_get_manager_cb, self); } } } static void vvmd_appeared_cb (GDBusConnection *connection, const char *name, const char *name_owner, gpointer user_data) { VvmVvmd *self = user_data; g_assert (G_IS_DBUS_CONNECTION (connection)); self->connection = connection; g_debug("VVMD Appeared"); g_dbus_proxy_new (self->connection, G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, NULL, VVMD_SERVICE, VVMD_PATH, VVMD_MODEMMANAGER_INTERFACE, NULL, vvmplayer_vvmd_get_modemmanager_cb, self); } static void vvmd_vanished_cb (GDBusConnection *connection, const char *name, gpointer user_data) { VvmVvmd *self = user_data; g_assert (G_IS_DBUS_CONNECTION (connection)); VvmSettings *settings = vvm_settings_get_default (); g_debug ("VVMD vanished"); vvm_settings_set_mm_available (settings, FALSE); vvm_settings_set_service_available (settings, FALSE); if (G_IS_OBJECT (self->service_proxy)) { vvmplayer_vvmd_remove_service (self); } if (G_IS_OBJECT (self->manager_proxy)) { g_object_unref (self->manager_proxy); g_dbus_connection_signal_unsubscribe (self->connection, self->vvmd_manager_proxy_add_watch_id); g_dbus_connection_signal_unsubscribe (self->connection, self->vvmd_manager_proxy_remove_watch_id); } if (G_IS_OBJECT (self->modemmanager_proxy)) { g_dbus_connection_signal_unsubscribe (self->connection, self->vvmd_mm_settings_watch_id); g_dbus_connection_signal_unsubscribe (self->connection, self->vvmd_mm_provision_watch_id); } if (G_IS_DBUS_CONNECTION (self->connection)) { g_dbus_connection_unregister_object (self->connection, self->vvmd_watch_id); } } static void vvm_vmd_eds_is_ready (VvmVvmd *self) { guint n_items = g_list_model_get_n_items(G_LIST_MODEL (self->vvm_list)); if (n_items != 0) { unsigned int i = 0; for (i = 0; i < n_items; i = i + 1) { g_autoptr(VoicemailWindow) voicemail = NULL; voicemail = g_list_model_get_item (G_LIST_MODEL (self->vvm_list), i); vvmplayer_vvmd_add_contact_name (self, voicemail); } } } static void vvm_vvmd_constructed (GObject *object) { //VvmVvmd *self = (VvmVvmd *)object; G_OBJECT_CLASS (vvm_vvmd_parent_class)->constructed (object); } static void vvm_vvmd_finalize (GObject *object) { VvmVvmd *self = (VvmVvmd *)object; g_object_unref (self->discoverer); g_clear_object (&self->vvm_list); G_OBJECT_CLASS (vvm_vvmd_parent_class)->finalize (object); } static void vvm_vvmd_class_init (VvmVvmdClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->constructed = vvm_vvmd_constructed; object_class->finalize = vvm_vvmd_finalize; } static void vvm_vvmd_init (VvmVvmd *self) { self->vvm_list = g_list_store_new (GTK_TYPE_VOICEMAIL_WINDOW); } VvmVvmd * vvm_vvmd_get_default (void) { static VvmVvmd *self; g_autoptr (GError) error = NULL; if (!self) { self = g_object_new (VVM_TYPE_VVMD, NULL); g_object_add_weak_pointer (G_OBJECT (self), (gpointer *)&self); self->unread_vvms = 0; self->discoverer = gst_discoverer_new (GST_SECOND, &error); if (!self->discoverer) { g_print ("Error creating discoverer instance: %s\n", error->message); error = NULL; } self->vvmd_watch_id = g_bus_watch_name (G_BUS_TYPE_SESSION, VVMD_SERVICE, G_BUS_NAME_WATCHER_FLAGS_AUTO_START, (GBusNameAppearedCallback)vvmd_appeared_cb, (GBusNameVanishedCallback)vvmd_vanished_cb, self, NULL); self->contacts = vvm_eds_get_default (); g_signal_connect_object (self->contacts, "notify::is-ready", G_CALLBACK (vvm_vmd_eds_is_ready), self, G_CONNECT_SWAPPED); } return self; } vvmplayer-1.4/src/vvmplayer-vvmd.h000066400000000000000000000053031415227045700173520ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ /* vvmplayer-vvmd.h * * Copyright 2021 Chris Talbot * * This program is free software: you can 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 . * * Author(s): * Chris Talbot * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include #include #include "vvmplayer-window.h" #include "vvmplayer-settings.h" #include "vvmplayer-voicemail-window.h" #include "vvmplayer-contact-provider.h" #include "vvmplayer-notification.h" G_BEGIN_DECLS #define VVM_TYPE_VVMD (vvm_vvmd_get_type ()) G_DECLARE_FINAL_TYPE (VvmVvmd, vvm_vvmd, VVM, VVMD, GObject) enum vvm_type { VVM_TYPE_UNKNOWN, VVM_TYPE_CVVM, VVM_TYPE_ATTUSA, VVM_TYPE_OTMP, VVM_TYPE_VVM_THREE, }; VvmVvmd *vvm_vvmd_get_default (void); void vvmplayer_vvmd_set_mm_vvm_list_box (VvmVvmd *self, VvmWindow *visual_voicemail); int vvmplayer_vvmd_get_mm_settings (VvmVvmd *self); int vvmplayer_vvmd_set_mm_setting (VvmVvmd *self, const char *setting_to_change, const char *updated_setting); int vvmplayer_vvmd_set_mm_vvm_enabled (VvmVvmd *self, int enabled); int vvmplayer_vvmd_get_service_settings (VvmVvmd *self); int vvmplayer_vvmd_check_subscription_status (VvmVvmd *self); int vvmplayer_vvmd_sync_vvm (VvmVvmd *self); int vvmplayer_vvmd_encode_vvm_type (const char *vvm_type); char *vvmplayer_vvmd_decode_vvm_type (int vvm_type); void vvmplayer_vvmd_mark_message_read (GDBusProxy *message_proxy, char *objectpath, gpointer user_data); void vvmplayer_vvmd_delete_vvm (VvmVvmd *self, GDBusProxy *message_proxy, char *objectpath, gconstpointer user_data); void vvmplayer_vvmd_decrement_unread (VvmVvmd *self); void vvmplayer_vvmd_increment_unread (VvmVvmd *self); G_END_DECLS vvmplayer-1.4/src/vvmplayer-window.c000066400000000000000000000216141415227045700177030ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ /* vvmplayer-window.c * * Copyright 2021 Chris Talbot * * This program is free software: you can 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 . * * Author(s): * Chris Talbot * * SPDX-License-Identifier: GPL-3.0-or-later */ #define G_LOG_DOMAIN "vvmplayer-window" #ifdef HAVE_CONFIG_H # include "config.h" # include "version.h" #endif #include #include #include "vvmplayer-window.h" #include "vvmplayer-log.h" #include "vvmplayer-preferences-window.h" #include "vvmplayer-vvmd.h" struct _VvmWindow { GtkApplicationWindow parent_instance; VvmSettings *settings; GtkWidget *menu_button; GtkListBox *visual_voicemail; GtkToggleButton *speaker_output_button; GtkImage *speaker_output_image; gulong window_closed_id; }; G_DEFINE_TYPE (VvmWindow, vvmplayer_window, GTK_TYPE_APPLICATION_WINDOW) enum { PROP_0, PROP_SETTINGS, N_PROPS }; static GParamSpec *properties[N_PROPS]; static void vvmplayer_window_show_settings_dialog (VvmWindow *self) { VvmPreferencesWindow *preferences = vvm_preferences_window_new (); gtk_window_set_transient_for (GTK_WINDOW (preferences), GTK_WINDOW (self)); gtk_widget_show (GTK_WIDGET (preferences)); } static void vvmplayer_window_show_about (VvmWindow *self) { static const gchar *authors[] = { "Chris Talbot ", NULL }; static const gchar *artists[] = { "Asiya Morris ", NULL }; g_assert (VVMPLAYER_IS_WINDOW (self)); /* * If “program-name” is not set, it is retrieved from * g_get_application_name(). */ gtk_show_about_dialog (GTK_WINDOW (self), "website", "https://gitlab.com/kop316/vvmplayer", "version", PACKAGE_VCS_VERSION, "copyright", "Copyright © 2021 Chris Talbot", "license-type", GTK_LICENSE_GPL_3_0, "authors", authors, "artists", artists, "logo-icon-name", PACKAGE_ID, "translator-credits", _("translator-credits"), NULL); } static void select_mode_complete (gboolean success, GError *error, gpointer data) { if (error) { g_warning ("Failed to select audio mode: %s", error->message); g_error_free (error); } } static void speaker_output_button_clicked_cb (GtkToggleButton *btn, VvmWindow *self) { gboolean toggled; VvmSettings *settings = vvm_settings_get_default (); toggled = gtk_toggle_button_get_active (btn); vvm_settings_set_speaker_button_state (settings, toggled); if (toggled) { g_debug ("Setting audio profile to default"); call_audio_select_mode_async (CALL_AUDIO_MODE_DEFAULT, select_mode_complete, NULL); } else { if (vvm_settings_get_stream_count (settings) > 0) { g_debug ("Setting audio profile to call"); call_audio_select_mode_async (CALL_AUDIO_MODE_CALL, select_mode_complete, NULL); } else { g_debug ("No stream is playing, waiting to change profile."); } } } void vvmplayer_window_set_speaker_button (VvmWindow *self, gboolean setting) { gtk_toggle_button_set_active (self->speaker_output_button, setting); } static void vvmplayer_window_unmap (GtkWidget *widget) { VvmWindow *self = (VvmWindow *)widget; GtkWindow *window = (GtkWindow *)widget; GdkRectangle geometry; gboolean is_maximized; is_maximized = gtk_window_is_maximized (window); vvmplayer_settings_set_window_maximized (self->settings, is_maximized); if (!is_maximized) { gtk_window_get_size (window, &geometry.width, &geometry.height); vvmplayer_settings_set_window_geometry (self->settings, &geometry); } GTK_WIDGET_CLASS (vvmplayer_window_parent_class)->unmap (widget); } static void vvmplayer_window_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { VvmWindow *self = (VvmWindow *)object; switch (prop_id) { case PROP_SETTINGS: self->settings = g_value_dup_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } void vvmplayer_window_add_row (VvmWindow *self, GtkWidget *voicemail) { if (gtk_widget_get_parent (voicemail) == NULL) { gtk_list_box_prepend (GTK_LIST_BOX (self->visual_voicemail), GTK_WIDGET (voicemail)); } } static void main_window_closed_cb (VvmWindow *self) { gtk_list_box_unselect_all (GTK_LIST_BOX (self->visual_voicemail)); } static void vvmplayer_window_constructed (GObject *object) { VvmWindow *self = (VvmWindow *)object; GtkWindow *window = (GtkWindow *)object; GdkRectangle geometry; vvmplayer_settings_get_window_geometry (self->settings, &geometry); gtk_window_set_default_size (window, geometry.width, geometry.height); if (vvmplayer_settings_get_window_maximized (self->settings)) gtk_window_maximize (window); G_OBJECT_CLASS (vvmplayer_window_parent_class)->constructed (object); } static void vvmplayer_window_finalize (GObject *object) { VvmWindow *self = (VvmWindow *)object; VVMPLAYER_TRACE_MSG ("finalizing window"); g_object_unref (self->settings); g_signal_handler_disconnect (g_application_get_default (), self->window_closed_id); G_OBJECT_CLASS (vvmplayer_window_parent_class)->finalize (object); } static void vvmplayer_window_class_init (VvmWindowClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->set_property = vvmplayer_window_set_property; object_class->constructed = vvmplayer_window_constructed; object_class->finalize = vvmplayer_window_finalize; widget_class->unmap = vvmplayer_window_unmap; /** * VvmWindow:settings: * * The Application Settings */ properties[PROP_SETTINGS] = g_param_spec_object ("settings", "Settings", "The Application Settings", VVMPLAYER_TYPE_SETTINGS, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, N_PROPS, properties); gtk_widget_class_set_template_from_resource (widget_class, "/org/kop316/vvmplayer/" "ui/vvmplayer-window.ui"); gtk_widget_class_bind_template_child (widget_class, VvmWindow, menu_button); gtk_widget_class_bind_template_child (widget_class, VvmWindow, visual_voicemail); gtk_widget_class_bind_template_child (widget_class, VvmWindow, speaker_output_image); gtk_widget_class_bind_template_child (widget_class, VvmWindow, speaker_output_button); gtk_widget_class_bind_template_callback (widget_class, vvmplayer_window_show_about); gtk_widget_class_bind_template_callback (widget_class, vvmplayer_window_show_settings_dialog); gtk_widget_class_bind_template_callback (widget_class, speaker_output_button_clicked_cb); } static void vvmplayer_window_init (VvmWindow *self) { g_autoptr (GError) error = NULL; VvmVvmd *backend = vvm_vvmd_get_default (); gtk_widget_init_template (GTK_WIDGET (self)); vvmplayer_vvmd_set_mm_vvm_list_box (backend, self); if (!call_audio_init (&error)) { g_warning ("Failed to init libcallaudio: %s", error->message); } self->window_closed_id = g_signal_connect_swapped (g_application_get_default (), "main-window-closed", G_CALLBACK (main_window_closed_cb), self); } GtkWidget * vvmplayer_window_new (GtkApplication *application, VvmSettings *settings) { g_assert (GTK_IS_APPLICATION (application)); g_assert (VVMPLAYER_IS_SETTINGS (settings)); return g_object_new (VVMPLAYER_TYPE_WINDOW, "application", application, "settings", settings, NULL); } vvmplayer-1.4/src/vvmplayer-window.h000066400000000000000000000026251415227045700177110ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ /* vvmplayer-window.h * * Copyright 2021 Chris Talbot * * This program is free software: you can 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 . * * Author(s): * Chris Talbot * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include "vvmplayer-settings.h" G_BEGIN_DECLS #define VVMPLAYER_TYPE_WINDOW (vvmplayer_window_get_type ()) G_DECLARE_FINAL_TYPE (VvmWindow, vvmplayer_window, VVMPLAYER, WINDOW, GtkApplicationWindow) GtkWidget *vvmplayer_window_new (GtkApplication *application, VvmSettings *settings); void vvmplayer_window_add_row (VvmWindow *self, GtkWidget *voicemail); void vvmplayer_window_set_speaker_button (VvmWindow *self, gboolean setting); G_END_DECLS vvmplayer-1.4/tests/000077500000000000000000000000001415227045700145545ustar00rootroot00000000000000vvmplayer-1.4/tests/meson.build000066400000000000000000000010661415227045700167210ustar00rootroot00000000000000tests_inc = [ top_inc, src_inc, ] env = environment() env.set('G_TEST_SRCDIR', meson.current_source_dir()) env.set('G_TEST_BUILDDIR', meson.current_build_dir()) env.set('GSETTINGS_SCHEMA_DIR', join_paths(meson.build_root(), 'data')) env.set('G_DEBUG', 'gc-friendly') env.set('MALLOC_CHECK_', '2') test_items = [ 'settings', 'utils', ] foreach item: test_items t = executable( item, item + '.c', include_directories: tests_inc, link_with: libvvmplayer.get_static_lib(), dependencies: pkg_dep, ) test(item, t, env: env) endforeach vvmplayer-1.4/tests/settings.c000066400000000000000000000103371415227045700165640ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ /* settings.c * * Copyright 2021 Chris Talbot * * This program is free software: you can 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 . * * Author(s): * Chris Talbot * * SPDX-License-Identifier: GPL-3.0-or-later */ #undef NDEBUG #undef G_DISABLE_ASSERT #undef G_DISABLE_CHECKS #undef G_DISABLE_CAST_CHECKS #undef G_LOG_DOMAIN #include #include "vvmplayer-settings.h" #include "vvmplayer-log.h" static void test_settings_geometry (void) { VvmSettings *settings; GdkRectangle geometry = {100, 200, 300, 400}; GdkRectangle reset = {0, 0, 0, 0}; GdkRectangle out; gboolean is_maximized; settings = vvm_settings_get_default (); g_assert_true (VVMPLAYER_IS_SETTINGS (settings)); vvmplayer_settings_set_window_maximized (settings, 0); g_assert_false (vvmplayer_settings_get_window_maximized (settings)); vvmplayer_settings_set_window_maximized (settings, 1); g_assert_true (vvmplayer_settings_get_window_maximized (settings)); /* * gbooleans are typedef to gint. So test if non boolean * values are clamped. */ vvmplayer_settings_set_window_maximized (settings, 100); is_maximized = vvmplayer_settings_get_window_maximized (settings); g_assert_cmpint (is_maximized, ==, 1); vvmplayer_settings_set_window_geometry (settings, &geometry); vvmplayer_settings_get_window_geometry (settings, &out); g_assert_cmpint (out.width, ==, geometry.width); g_assert_cmpint (out.height, ==, geometry.height); out = reset; g_object_unref (settings); /* create a new object, and check again */ settings = vvm_settings_get_default (); g_assert_true (VVMPLAYER_IS_SETTINGS (settings)); is_maximized = vvmplayer_settings_get_window_maximized (settings); g_assert_cmpint (is_maximized, ==, 1); vvmplayer_settings_get_window_geometry (settings, &out); g_assert_cmpint (out.width, ==, geometry.width); g_assert_cmpint (out.height, ==, geometry.height); g_object_unref (settings); } static void test_settings_first_run (void) { VvmSettings *settings; GSettings *gsettings; /* Reset the first-run settings */ gsettings = g_settings_new ("org.kop316.vvmplayer"); g_settings_reset (gsettings, "version"); g_object_unref (gsettings); settings = vvm_settings_get_default (); g_assert_true (VVMPLAYER_IS_SETTINGS (settings)); g_assert_true (vvmplayer_settings_get_is_first_run (settings)); g_object_unref (settings); /* create a new object, and check again */ settings = vvm_settings_get_default (); g_assert_true (VVMPLAYER_IS_SETTINGS (settings)); g_assert_false (vvmplayer_settings_get_is_first_run (settings)); g_object_unref (settings); /* * Set a custom version and check, this test assumes that * version (ie, PACKAGE_VERSION) is never set to 0.0.0.0 */ gsettings = g_settings_new ("org.kop316.vvmplayer"); g_settings_set_string (gsettings, "version", "0.0.0.0"); g_object_unref (gsettings); settings = vvm_settings_get_default (); g_assert_true (VVMPLAYER_IS_SETTINGS (settings)); g_assert_true (vvmplayer_settings_get_is_first_run (settings)); g_object_unref (settings); } int main (int argc, char *argv[]) { g_test_init (&argc, &argv, NULL); vvmplayer_log_init (); /* Set enough verbosity */ vvmplayer_log_increase_verbosity (); vvmplayer_log_increase_verbosity (); vvmplayer_log_increase_verbosity (); vvmplayer_log_increase_verbosity (); vvmplayer_log_increase_verbosity (); g_setenv ("GSETTINGS_BACKEND", "memory", TRUE); g_test_add_func ("/settings/first_run", test_settings_first_run); g_test_add_func ("/settings/geometry", test_settings_geometry); return g_test_run (); } vvmplayer-1.4/tests/utils.c000066400000000000000000000033261415227045700160640ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ /* utils.c * * Copyright 2021 Chris Talbot * * This program is free software: you can 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 . * * Author(s): * Chris Talbot * * SPDX-License-Identifier: GPL-3.0-or-later */ #undef NDEBUG #undef G_DISABLE_ASSERT #undef G_DISABLE_CHECKS #undef G_DISABLE_CAST_CHECKS #undef G_LOG_DOMAIN #include #include "vvmplayer-utils.h" gpointer test_main_thread (gpointer user_data) { /* * This is being run in a different thread. * So this should return false */ g_assert_false (VVMPLAYER_IS_MAIN_THREAD ()); return NULL; } static void test_utils_main_thread (void) { GThread *thread = NULL; /* * This is the first call to VVMPLAYER_IS_MAIN_THREAD(). * So this will always be true */ g_assert_true (VVMPLAYER_IS_MAIN_THREAD ()); thread = g_thread_new ("test-thread", test_main_thread, NULL); g_thread_join (thread); } int main (int argc, char *argv[]) { g_test_init (&argc, &argv, NULL); g_test_add_func ("/utils/main_thread", test_utils_main_thread); return g_test_run (); }