pax_global_header00006660000000000000000000000064145657350340014526gustar00rootroot0000000000000052 comment=dd719d56f53cb1e00c658a4095543ef0b9c3d3ac vvmplayer-2.5/000077500000000000000000000000001456573503400134215ustar00rootroot00000000000000vvmplayer-2.5/.gitignore000066400000000000000000000000161456573503400154060ustar00rootroot00000000000000_build/ *.swp vvmplayer-2.5/.gitlab-ci.yml000066400000000000000000000034161456573503400160610ustar00rootroot00000000000000--- .only-default: &only-default only: - main - merge_requests - tags variables: DEB_IMAGE: debian:trixie ALPINE_IMAGE: alpine:edge stages: - build - test build-debian: image: ${DEB_IMAGE} stage: build <<: *only-default before_script: - apt update - apt install -y debhelper-compat meson libcallaudio-dev libgstreamer1.0-dev libebook1.2-dev libgtk-4-dev libadwaita-1-dev libgstreamer-plugins-base1.0-dev desktop-file-utils 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_IMAGE} stage: build <<: *only-default before_script: - apk -q add build-base glib-dev callaudiod-dev evolution-data-server-dev libadwaita-dev gst-plugins-base-dev desktop-file-utils 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/ check-po: image: ${DEB_IMAGE} stage: test <<: *only-default dependencies: - build-debian before_script: - apt-get -y update - apt-get -y install intltool git script: # barf on untranslated C files. Seems intltool # can't be told to exit with non-zero exit status # in this case - cd po/ - intltool-update -m 2>&1 | grep -qs '/.*\.\(c\|ui\|in\)' && { intltool-update -m; exit 1; } || exit 0 except: variables: - $FP_ONLY == "1" vvmplayer-2.5/AUTHORS000066400000000000000000000005421456573503400144720ustar00rootroot00000000000000vvmplayer 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-2.5/CONTRIBUTING.md000066400000000000000000000044261456573503400156600ustar00rootroot00000000000000# 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-2.5/COPYING000066400000000000000000001045141456573503400144610ustar00rootroot00000000000000 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-2.5/NEWS.org000066400000000000000000000050061456573503400147070ustar00rootroot00000000000000vvmplayer (2.5) [ Chris Talbot ] * Make friendlier to translating * Update to use libadwaita 1.4 APIs vvmplayer (2.4) [ Chris Talbot ] * Make Voicemail Save dialog Mobile friendly * Update to use GTK 4.10 APIs vvmplayer (2.3.1) [ Chris Talbot ] * Add iOS to VVM standards vvmplayer (2.3.0) [ Chris Talbot ] * Make Main UI more intuitive on voicemail status vvmplayer (2.2.0) [ Chris Talbot ] * Small bug fixes vvmplayer (2.1.0) [ Chris Talbot ] * Add ability to save Voicemails vvmplayer (2.0.0) [ Chris Talbot ] * Add seperate delete button * UI fixes vvmplayer (2.0~beta1) [ Chris Talbot ] * Various bug fixes vvmplayer (2.0~beta) [ Chris Talbot ] * Rewrite in GTK-4 and libadwaita vvmplayer (1.5) [ Chris Talbot ] * Fix a couple of crashes * Fix some memory leaks * Make the preferences window more responsive vvmplayer (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-2.5/README.md000066400000000000000000000060701456573503400147030ustar00rootroot00000000000000# Visual Voicemail Player (VVM Player) Copyright (C) 2021-2022, 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 - GTK4 library - libadwaita - 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-2.5/build-aux/000077500000000000000000000000001456573503400153135ustar00rootroot00000000000000vvmplayer-2.5/build-aux/meson_post_install.py000066400000000000000000000012461456573503400216040ustar00rootroot00000000000000#!/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-2.5/data/000077500000000000000000000000001456573503400143325ustar00rootroot00000000000000vvmplayer-2.5/data/icons/000077500000000000000000000000001456573503400154455ustar00rootroot00000000000000vvmplayer-2.5/data/icons/hicolor/000077500000000000000000000000001456573503400171045ustar00rootroot00000000000000vvmplayer-2.5/data/icons/hicolor/16x16/000077500000000000000000000000001456573503400176715ustar00rootroot00000000000000vvmplayer-2.5/data/icons/hicolor/16x16/apps/000077500000000000000000000000001456573503400206345ustar00rootroot00000000000000vvmplayer-2.5/data/icons/hicolor/16x16/apps/org.kop316.vvmplayer.png000066400000000000000000000010671456573503400252030ustar00rootroot00000000000000PNG  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-2.5/data/icons/hicolor/32x32/000077500000000000000000000000001456573503400176655ustar00rootroot00000000000000vvmplayer-2.5/data/icons/hicolor/32x32/apps/000077500000000000000000000000001456573503400206305ustar00rootroot00000000000000vvmplayer-2.5/data/icons/hicolor/32x32/apps/org.kop316.vvmplayer.png000066400000000000000000000021331456573503400251720ustar00rootroot00000000000000PNG  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-2.5/data/icons/hicolor/48x48/000077500000000000000000000000001456573503400177035ustar00rootroot00000000000000vvmplayer-2.5/data/icons/hicolor/48x48/apps/000077500000000000000000000000001456573503400206465ustar00rootroot00000000000000vvmplayer-2.5/data/icons/hicolor/48x48/apps/org.kop316.vvmplayer.png000066400000000000000000000033031456573503400252100ustar00rootroot00000000000000PNG  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-2.5/data/icons/hicolor/512x512/000077500000000000000000000000001456573503400200335ustar00rootroot00000000000000vvmplayer-2.5/data/icons/hicolor/512x512/apps/000077500000000000000000000000001456573503400207765ustar00rootroot00000000000000vvmplayer-2.5/data/icons/hicolor/512x512/apps/org.kop316.vvmplayer.png000066400000000000000000000643411456573503400253510ustar00rootroot00000000000000PNG  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-2.5/data/icons/hicolor/icon.ico000066400000000000000000005304361456573503400205430ustar00rootroot00000000000000 (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-2.5/data/icons/hicolor/meson.build000066400000000000000000000003621456573503400212470ustar00rootroot00000000000000icon_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-2.5/data/icons/hicolor/scalable/000077500000000000000000000000001456573503400206525ustar00rootroot00000000000000vvmplayer-2.5/data/icons/hicolor/scalable/apps/000077500000000000000000000000001456573503400216155ustar00rootroot00000000000000vvmplayer-2.5/data/icons/hicolor/scalable/apps/org.kop316.vvmplayer-symbolic.svg000066400000000000000000000060521456573503400300150ustar00rootroot00000000000000 vvmplayer-2.5/data/icons/hicolor/scalable/apps/org.kop316.vvmplayer.svg000066400000000000000000000155701456573503400262030ustar00rootroot00000000000000 vvmplayer-2.5/data/icons/meson.build000066400000000000000000000000221456573503400176010ustar00rootroot00000000000000subdir('hicolor') vvmplayer-2.5/data/meson.build000066400000000000000000000030541456573503400164760ustar00rootroot00000000000000desktop_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, ) compiled = gnome.compile_schemas(build_by_default: true) 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-2.5/data/metainfo/000077500000000000000000000000001456573503400161345ustar00rootroot00000000000000vvmplayer-2.5/data/metainfo/meson.build000066400000000000000000000007421456573503400203010ustar00rootroot00000000000000appstream_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) appstream_args += '--nonet' appstream_args += ['validate-relax', appstream_file] if appstream_util.found() test('Validate appstream file', appstream_util, args: appstream_args) endif vvmplayer-2.5/data/metainfo/org.kop316.vvmplayer.metainfo.xml.in000066400000000000000000000031141456573503400247200ustar00rootroot00000000000000 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-2.5/data/metainfo/screenshot.png000066400000000000000000001474101456573503400210260ustar00rootroot00000000000000PNG  IHDR IDATxwT0 ( ⪈(A,um+.v]׵+"6, (XT:"MzMywCH={f&737}:BŋׯRM~hܸqAAAĖ_ܼySVUjw 6mddd4os F#hǏ!o֞}Mli*aXeee?%B:t( 9ݏ=jbb"999˖- "b0 ,4iR߾}𫩩y]ppp```mmT~Atttyxlv~~~zzo$UQb 333nj*_X,VHHd`0F!UhXc[?lt9p˥Խ{ 1ޛ:z謬,תO˳2:88GMMMľ *fbbbhhXUUUUU%DDD!Կ##wM6/_$GO:511dC~R=RTF ###ڵkFFpBDDDhii"&L0~xQFE٩ݿ_ `0bbb#۵GyOc8:0:nooihh899988ׇ̛7xuBs8::޻wXҥKttG˫h}fffMjjjNdgg75qK.=zb\.wѢEGKGc2L&СCiK.?~؇nٳլY$U}}}SN:ۛrذX,x{{ )`W~𡸸>''ٳgW\6m=ztnx766xnݺuVDDǏ_x##ѣG 1GUUOPPN=zu/< ъ+ÿ|R]]]XXwԩQFwh99)Sܺu˗/O>E'z5>>~M"=s}<377֭[W8͆nj;f̘`nn۷ܺu}Yp^/_|׮]iÇ7nk]]Qlٲeb|oϟs$˗/Ļ700πO5ߋP(<G1e[.\(+–mذ(M>9D?-qpFEE55ŋbTƆ<]RRGEEoXTU'o\ &&^GuYYYxB|RXXÛ7obݺu#~StFtr8odВP^^ٳgϞ={ܹׯ mmmT 777 Hׯ1Zv/^s\tX|de;v_ihh oٲe ]s~VKT*_%]q8SSS*++ɏVhhI2{} 0/PԣG{ΡBxx3dkB J˓(.uVDN#ܼoaxbt9s8::"bbb>|8SS۷'''q8Ҵׯo޼Y<&!!䗴8˗CSIId}̛7'tll,O>tP֞1coݽ{X!w5Įyp8ǏSB!CLڵkzeĈ"G @[QYYI,k( s"Ν; 򰨨VVV.X%^3gNx|>9wA ;}4y?-'Ãښ3f_ ]]ݻw#X,֢E6mZyyd+۷o߾};''ӧO/JN>8x"}~UsDEE988@Qڶm[nnݻMMMg̘!pd4/%$$yЃw***ˆ@䑧EEEΝahhǏՙ3gbNOO'V8r[B[n 0,I5\Y!}+m yJs+//O~9=zDaĈɓ2!h4WVKK(1dȐ &Պ (1~HG`` q^344~,)'C ϖCۨQ!ŷɓ#""D˭9i$9N>ADv}ժU|߉O>P+++OOSN; .FVҫySLSLAAa˖-ƌ3d|5IHZddd{9@׬Yd2{sNr;8xfx񂼚@^Ĩ/+++oooCCC&,//!_nڴݻw8err2M{sI344$ ooo}Mx?J%njZZZ_94!5… ٌ999W\ΦP(Æ 矉N_x\yȨT*r x,&:$fKpo6waÆ/rrr,D!..X666#$[s!7^M=A:::w!޽~hOJJjsHs pɓ'#<^ҋq{D>.]ܹsG`1]]]yyy3Y3%8@uΝ;ǍGt~ɓO>%f*h4+W I}PUU%BUV RF.]Hrs1"p8k׮577?޽皇ׯ'~%վ]]gϞp8s9ϟ޽d?c޼y3?~H啕UUUX,*J~wSr"}}}xŸ\.KRmF~uܸq8Dr~Ƒ[E;GݗmQ!__ߐzD~$sOK^ Çv;>|ܤ)Ll6{ԩ۷o'g%_?3qIQlllI*CCC⢋ڳggϞ۷oGoW0VBݻw& co{رB!:Y޽,ij1Gݗ-'O|2Q1񆾕\.w߾}^N|!ɶ@@񜷉 ,Ó^~zj''3g=z|rfhhH.v G[0|͛*BP9ǺX[[Ǐ=Y),A됗vիW@ 1bĴiӺu/ʦvvv˖-޻~zgggsN< mDJhhh' 8H>|6lC߾}uttRRR|DyvvvyD[b_p?RQQ!2AK#X/\w͛7D'ۉ(MϖF$5_TT{nǏ[M!RUcɒ%D4w(Ç;vM&X2!˓Çb ݝfbbGa< qqqK§,lݺ(jLlY`.#'ļd6 19s܆e˖ $kB{zꕘ8qD====='&%%c%Y|;@'N')b;(ښ}M>/s9s$2'ŝ&566&&&JĠA%''7k`34mAAA\sobWCzX, .];n8SSS===UUՒ?l֭ׯ_5j!ʺ{cDŽ'vrr"QQQ<qppXbW߾}_~dy 8D-p8wi*T[nȑa߿'gS9[[A)((` 8]ٳ)ܹs!ʕ+vs@p>Pbxqxx8yʻw*Qmwvvv&7llذֱh"'''|KR/]4{7o{{{w,y.v[MZZʕ+---B鲽nJ^^^XX<@˗/޽Hc,##8 $\'##C7X[[:t7)))EFF<iuu510777Wp#ϵݻw4u)DyyٳghSLMM#Ǐ_.l]@/--n۶m)k׮m*z!9lhڵkFAEFFxf8pwrl˗/ӦM !Bb`pf̘3:Lfe7oޤ5}۷oYYY=zU/_H|J'e< IDATq B(((h<|ys̞=ĉkQ [dnjL-C555<bbbRSSqp8miii\\n<Οr##((N<̙3-Ɖph?'Yh5"t:]h}CmH:&99YCmHG\BCm\t up@ ARH6p_~]ֵ>m&///Ja9996r]+H=zرCh{ɒ%5557oNNNv)==]477>d٥ҵk={0LQ -ZNkhhlڴIw A3fHLLLJJ1c"X\\\zzzzz7d]uw7o\tIWW? !dݻW[[[\./wK.gݻw )9ydyBݻw_nڵk [֒גA Ŋ+dkktRYWB6Ν;MLLD ;z*+zF,;::hJ.{=>BT4k*]-Б:Q>@t2AR7lп!e׬YfwSիcǎM gϞm #22rƍrrr!uuugϞSQQ:t(^~e~~>B߿@Xq k Չ"../˶2x iA … Yrƍ/e<<<&DQVVF9R`1GGGb ݻwBEEĉ|}}][i Չ"00pժUΝ[je]ڊ8o0yhe2z߫W/iTt` 2F ,+""؞gϞ';;[l-Бp87o믿n޼pd] &&&Ν1b:uL ר"zXB}T=A']WWcVEEaÆOjZ |V&1}WXXBrrr/_/} /[YYHëyѣ񪋋Ǐ!..!PQQ8qnccsrr?~ƍITT.m۶o700ˡW&^ի^eeevvvZZd=\\\ƍgmmY[[sIN!_LUaaw=zD.&//?c 777:紴 ݾ};Bh޽ǎݻiYYӧO322B?|pi4? cԨQzzz***YYYJǏwww={ut:~y޽AAAN<==mFknnnnn>rӧ/\077W @%Y=)d^"{A,˪bW tZ111***!+++o߾͏?exѣGF]]N# ī'!k硠￿{.))I=(++߸qCOOOnuuuO81uԗ/_JJJ7olj,ydk݃࠮f]NNӧOoك̙3ԩS_Te=zDdrrܱcnj3 5LJSs:XVWWo:!**j„ ! B |8ydNNN^q@Pn:vX%˖-#>p8}}C>|(yfeVUUZÇ\.wРA{AY&**\.7<<1[@P\2}={J5C ͎4Y{y=9qQrߏ9B ?1D_",ZW{q {޽#&< [8Ř8p gbk׮IJ3B숈|.//?|Eso>~SS 6 ?~|ĖVWWյƺL&`}b{ӧWɳ+nݺOJJJ8[+jٯ ӨhR*|lA@F≚D?BIIBFFF@@OouuqƝ?5I c֭1116l򲶶ڵ[P=TW⦟ D"cυa 2O7o}Ro8x;ˋbȳ򬭭eYիWxĢq o#P||mmmɭFZd M#]vSO߿Z^^I e===_UUx2 !%ܶm[SwR:!XZZ6[J|Ҭ:4YÇ~-"''h"b6W  A3k֬V~=1,bIY0:!R9| ٳdD,N'!ݻ%RSS 99w]}ŗLA 7,+++8ܕ+WLrJb>*yx-Ba2sX2`nn.f}8)^ӻ})S/_'"BCCEEGGB޽;vX###ee={Ι3gРAׯ_ߺu /khh\p͍QWW?~x'qqq䬚^r%9Y'1=,,L[=J͠h]t!2 ׬!%%eDXE+V4(Z'''"GYYل ȍ4M__qrrjɄ !\@R(mݻwOdgg_~XUWW6l92VUU-_Č(<^.++;4k:[YY6o ,X0tPgg={jkkkiiUWW̙3>>!\8))͚[$:3gΜ'7ĄF~:00PIIC]_>33sر555&< tQsmIV==d2y -ZT__uVXEFKEB{UPPa!qpCR׭[~} AٷpÃRH:8 up@ ԉpatM"dwCmHGCC:&ziףuM"l6NUiMuuul6[ֵ: QgTWWK}5`ٕRJ 55#GmmmUU:jkke] si^⯚vQYYYSS#Z\sP[[Р( II]]]uu52!f+**tSs8P__ Cͮ P[l@H:8 up@ ARH:8 up@ ARH:8 up@ ARH:8 up@ ARH:8 up@ ARH+h4: ''G`Xz6-C[ 8h4+T*UAAAAAdUWWCP8 kl ЦɾBII=F%%%Yhdp0 &):d0v2hmLEEFɺ@%ˀCYYYGV8^^^cbb""F9)͢(FbC$HfNաGJ[[!SvEf-=RP4۷gΜASz$Hf\H"YRP?%""ӧ5551cHp,h[HzܼO>ȆXHVwHy۷(kkt|xS***xJ޹swAAAK~~~7n-K 333cbbBBB =Pdr]VXX(}2!GGǼ<̙3yyy<fGEES(\.wGyۇ _7n_bbƍ~~~vvv <߻wWXX;uvv)\]]fm֭[7WSRRMǸM8qڵim ׬YQ57R󏗗S]]=hРFSv!["@EEE988O[,h4ѣn߾b.]jjjdɒW^tŋ˚++3g0`t:}ҥb"$$OEEeذa>$` _γsgg爈;whXk׮'OhEEE۷oLӦM7oLޕB߿vZzzСCϟߵk@?6<QPPmeed2!GۧH)Ç7oLP<<<"?nܸA$%%EEEO:poƅƍ#i߿qƩSzxxʼnw/55w<R^^^bb"WZuMb5##۷aaarrrIII'Z2}+.3ym۶X,UB>pח/_FEE]|YUUu˖-SLr9r$BĉxK}}}ee/_!t<0h9r$NI^XXѣyz4<[ b#_Bb;v σ7n_}ƳӧOϟ?G\|!$//ߣGb3ճ{>~C V7 IDATI@QSSC h4%''#ttt(333-=zDfssssNCCQMMmذa\.L"\vv6BK./eee޽{#=z$k#882C@Ξ=;f .6MKK 3ٳg|||S<==_x!>Z[ZZZ^^.-!CCC!ʄ (OOO{hrrrxxt8W__ӽ{;w𰷷r?~ţO-t$CSS~ɍ7O2{zzݽ%ύs7AB{{U"xfGhhhKv+>O?Y644,[l{y}}޽e˖ݟ WX@ttt/]?)O>5o|9x`'&&&:JLLSPPpuuETUUݿ%S(ݻ#3&ѣG̙3'!!BL:u֬Y:vp 4uǏ[YYɪJbff޾}2ա%U=&I& ,!}:"r1?ӓJ޽{qpScȑ:880 .@l#g;bcc'O~嗗/_"@'%%%ׯl*I nިPPPjFqsεyuԩ?xx'qñWWW)<7$իl6[MMmƍ<_ڵkB׮]#(<{8X)999H]6) =88xΜ9q`BE0R_555t:=88xҥ ֶݶmۖ-[BCZې,--?'JOjj B!!!FFF&&&ƍ ѣGIIݻo~z}}=8ˉ'-ZCݻB]]w͙3?]?1<tB| ={gPP[85 <ҟEFF[J3Fk[AAٳwmdd@TWWo߾gϊg~!!! 0Ri۳gJ>}աC/|r}:33ɓ't:(Y[[;|pWW#Fϟ?_tӧko#!.{GHãFz1p -x#ȑUHFVZڵk+{hܼyڵkؿ{V޽/лwwڕF{իWvmڴiׯ_ ,ӫWqƵ7jkk۽{wUUUSRRϟX,L&LEE6+++))H}6< DR=zsꕕ?NLL#OWWK.eeeϞ=ܹsf޽[O=gPii l6;00RȮ,X@/_-}QRRzjYBxL4MOO瓷nUUաCZ[[SݑQ(//>} ***TEpp(Kgg猌r WT<)++SVV600000۷sxg``뫨fKKK555----,,n߾M )q=4Y+@dÇ!C(JEEEyy---~*dP(,L]]]KKO>111IIIDIyyyPmm-`fE}Eq8.]46tP-Ntx>xNd***/^UȔ ҿVPPhdd_lС} 'n}}}___###gg稨(Ga cƌrT>Fs} wᡡv$NƳgtc***OMhN*СCn߾]\\b0z0a±cDŽEEE_AAB7rHGG\_ݳnݺ%z(e]]ݻw diiTNJJj*f0666U Odcc{ճg Caٗ/_&\.ښ`?ʧO   ٳW^×|PfffXXBW^&+**Ǹ4f:?AIIӳ˗ p8[nh!T[[{֭_2LҔGBfz*>>!dnnNDzTYYÇ8c>}ȩl6nhjWvvv bW 'O;wʕ+MWRL99ݻl6I]]]"5,A]WWG444" 7c~IAAYY@OOO:~m t:]CCg:ˍEڊx 2E[ے;2&)e!{+_a8:|N[+W)..v8ip#r8a_毿zƍ ,|rOO .=wܾ}[n%**x׮])kjj,x<GD[Ϟ=kBoΦzqc)ˆ>ٳg_z:|*j.N400Vryrrr|f͢jgቨ˗IR\n6O8q14t GllM?lbiikk /o6;vM7͞=\C pɴw^$IZMgSB!7;jlr :t_B""":;;weYO>1L!!!t#Zn{ffl P(EEEZ~lIΦnH4c #?Ŗ-[&ɾ+:tXoP& naԩtQQQQ111\.%$$Ј`QWWk֭믿m۶Ǐk̛nnH{U233U]]ٙA! W^u}F-h4xyBH$d- [ikkkkk뮻322,%hv)p…3g&'' + F+WΙ3/ hpAرuvXf-zQfy``@&IR:v޽qyLh×--*???))c9)禛n :}KtFq3tY'.9bdɒJHH tMMMzvFh4mmm.\X~}NNNEEe){tǴi"##EIKKNikkKOO/))9996 !ǏeP---6 00PRb.k{{ rrrbbb\B]eU*>>f,g#L333];vlsj\.ѣ^dZt8Ʋ} ̴謬,ta]]HyٔĢ"t…RP0XY[[[E"D" ///wiҥth}VNi}pppxxJ^ʝcuuu9# "$$3 GTC;m+(ΦG۷Ͼ& wD677溺:(:5ƲO'Oxe'd2YJJV|={h4뮻?bA=O:&Q Œ `s'8{,KIIW6lٲ?ǭj̑3gڼ4m4Bȉ'l°Q1~W٥tF*t:$r!MMM.|:$B099d29mWWWGGMKKsqڵp[tkh4zwh4<0shi,.[PP`?Q3//vQKR={vmQQQtcPPкu|ɓ'G 48878\UҥKk֬x&HVZ%;Ο?o4322233ir8n!//?t1ǒ$''/[6kZnSȈ>ٳgC\\\DD %%{ gڟh-JrժUMMMt Yzu^^$ Bq뭷466u57ꜽU!\r?O]o `bsАÅMmmmmmmRRwޮJV_<a ڸxXVUUڿgϞիW<fYTxs h4555ycYrWZe@/n漼`@>S뻚t#A[$([tiPPV2QRRRRRD|>?<<<))l6 i4[{{Ν;i MHHHJJZlZJtPkk_|l7UUU͝;wʔ).Ƶn6hp9mo600Ν;222.]/\к n2 }Q~~~NNBgϞuµ}EGG>ںuYJ%ZYYl4ٳg322F ei fBŋm6cƌϗs#:͝;ҥK[/͍ן>}~͉ _`\.*++mkkk_+ E___sssuuWPDFFt:{zzCCC322nH" zyi|o?J*ͥ XN<+VU:b h4CCC'eD\nXXqnA1CCCBϏ{:&`0t:VQ |2B~~~CCC pWtî >oC!p8q8`0C!p8q8`0C!p8q8;d2=|X, |>L&`jj`0 n}X<}`br~~~~~~jz``apmāa}3F^RQ,!?V IDATOZh;h Y/R-QQQoFppD"ikkknnꫯT* w%:::::z7tӇ~k.V+8}tuukj\. 5k|cǎ]M8|w}g߾Wܹ?\UUV ` Q@"H:ǤPVV !l& ߥ"쾾|7 ֌FcKKKLLy+i·plذ!//Y_6mە:',,v]`2-U*?p]]G}T[[VMnnP($;wd4[8jW6yx@.Xr>=NT>cqop̚5kԩ{ٵkD𥎎N9rURgddXOӽ+:nk@|8pPB[n>ӒvF_tO?}9Tt-߲ؗeիW#S>8￿؇v;vtƌӧO MMMgΜ9x [P@LAČ9p 4lt888#yw/l6KKKwdn `7mʼ8\!l65{TWW[΍_Tz>S B8ApDGG/XՙL&Z1Y B th{RaLA9s 666z(A98ԩS=̑Y HfKhj{ƹV ;wBp`{}8!6mf;Wc9SǿÝ1)fp:TJ c[J !X^pQs#8ԡ ҨſA/om}}}l`l(m8 =)(p`[&Ep vxp oು5DŽF$lp 2ǹs -ؾ}'X+BȻr=r}}}o ە믿>,,lb.\()aǎy$&&B>7Y\\G9tЕ+WZ=44(bccΟ?o]844tBh4dÇ_zp8YYY|>d2 䯾>;bp8뮻.11288pBBBBBB:L:UTswD2gH&-ZH& ~T}Q7OD1L2LP8̔TJJJEEАB033L*>p*oQotvbJbqNNNZZ4 bbb Å ?xBB;sLvv)SB?ȗ~].//UՄ??´fK녟MO6 0==}׿͉&SNuvvL&zsΜ9s&77711qhhhT*/^^TTydddvvQn]npϟr饹6o X2ɓ'66vΜ9IIIÞ$%%iK.eee%$$</77EbVV߰'xz̶{~6. .?}Z"99l6455q\ڷ2.]cǎJ6!:XJ K.<^_ZZzUAL/r޽{mss#G!b Ѹw^-c߾}f999YD{5sssÿa;EJٳ>WҶ,oŔ)Sbq}}}]]!$!!^F1%%% "(##C {RIFԩS_}޽{_owq6N򐐐֡!ڙJ^ti +@r4RTVVڔ a;|kkVx#*fF]]]|>Y;u]'9QEw-8GvZ[[[@@u4t&99RWWbTMM ujNN@ =@ODtL&jkk;y;:q0}w\j\.U*;'rэMill%XBFcxxFt!\.7'''""BPhڮӧOgffFGGG#m) DkS hmmu.FoQ[[qLw:=-\P,=zs[g?!؏cMIIohh?rBoEcccXXR qV衡!$&&:.^8eʔ Tb8--w(p.f͚L.#HRRRV\)HخdX__OMMM'>>~ BCCM&Sll7<2C*B-.GS-L@@H$h4)25 ),,zjMMҤ"isGqoVVzzCIh uC(o>!$11YRm,s6d29sټO:G(8RWWwI%X(GDDL6~QQQի+W$&&b&5sLBQWWWRRBoud#]^(zȏ3gBt{^JJ !d;\TnnWWǏwqXڽw5nNƖ۷XrJ^^^KK P˗/[% 4@S˗- ^: rYKH$ʹlwLKV6G_cB"G*<<<&&ѣxR?;wr;GG{BdLNg?d|lv4lr%Yf=z;pZޱcG}dfӧݻeڸx@HHҥKCCCX,NNN@fG ZBtjCf BxSQ×Fg^ϏXI}nt= 4lشr3'Fbbbrrr]k?| |'Ezp@p ɉ---Ύia6mswZ^QwFd4<y 7lذaݺusmhhb]B߰BGLL ʕ+1C*4770ɱ֥Bub miF39ut Ѹd !!#=&m̙c0}t\~7#TWWg}P(D"Q?M4t BH|||ddvcbbl:ujѢE{3&h1Y@??We2YHHx>>!!8ܼ:O$((hԏ Zl@ 8vAzL&S*6je+g͚ߺnhii OJJM A}}}cL&y 2Fll,q]xiiiɏľH.Z*** rvSN-Yd\.b3pujxE/| 5ڸm34pn^ (ϟS-[& ;Bt:]MMMVVVNN΁_"TUUdٳgvuuݻŘ 7YɉyT*tfg͝:uKޮQl=CG`lcbvvX,pDqdrYoooOOOPPP\\k׮MZhd0Jz mT(t IKKz `7Mب%eƍ.H/^,F>?{akT*/_. ;fboqy;k,hGWLKKtַ+Ԏ={8w=FsEClЍ˖-UUU bx͚5֭#~zx<^rrKRy j?逡k׮9{{\ѣG@]CѸ18L(\v!&&榛n6 AAA@tOaY7fv5АHE!}ŋ#""n^4l4T('E&''ۯyUQQA:|RRRzzzd2﷾Yr4j`679TVV&#""nᆡ!@2\zum!111LrL/"..nܹsQTZV*۾h^֡˗/ٯrk'6L l8444<А7oPNHH˟744TTTDEEM>ݺ͂Z=uuʕĸRVy!===y~~~XX\.xbeeڵk]|d4BBA.]|/"'''22R.Ɗ )VK5F79Dܖ,A[[[MMֵVX<ܹs nǏL際/^bsuB EBBURMהZzz:s5DhmT*Մh:ԝ|O8k֬iiiٳguܹS?1UѸ~ A~3P4j H$XC:ZF(=)#pU*Am#m`"psh4@ x5 >bգ ^z22%%%110o h4>C1 ܹs|F2-44t޼yOrcǎ]5IlY_kJrd2LoV }}}uuuG8 ywpxNɹ67C!p8q8`0C!p8q8`0wPKK `0C!p8q8`0C!p8q8`0g B@\o C&h4zVk4ٮ+ܧF[ǓH$B r\@ HZJyEDRZP( p;$D-RD"aܧAlȌ|r{9:3A(g>Y)('xQ@֩09t/.N('O.\v|&'E C!p8q|+0̜9sʕOpU555~'Xsxb♶>D JvOmܸ?iXX;@ /..6͕LTF T̙3W^N3]0NV\fIs-0Zq6pk… :po0<^7kIII7mtyW3M 6YftiP(֮]a +//GٮLjbib=n;NE /޶m؏Hrŋ>|xǎ]]]˙[o $$… ѣGK"BNhHH2{q}Ph_7ߜsX8;ra?07-_#q%&&OSO9^<#6l7|zE9s͛M&Sqq5!VZqƠ BH}}ϝ;`"}m^GG]w5ݙO[f·pzKTlٲΙ3gƍr^.]䑽y衇nBȡCoaÆ%K {S{Q .ؤ]tC=I1L._:+0 ᯡ۴iRO~'_|{4D"yꩧ~_Oٻw߮\|қođ;::6ođ>|BodRMM;#dggO>~^x [| JtY^^z򬿁:söj{QBf8dpph=G`|YZOOA(e/NOvmM\r4ˡFEpTUU @Ϛ|GQQQ1x\j^n=n/BHiiiii:U5]Pۋr8ckR^yHK{Y+ ge,/YzF:8UCn/B%8< {Y&XX,M&er]OGkhh^TDb4Ϟ=nM8WOOH{JKK#444hڱ }ފX,nEfZ?et{8Zƹ&Y^2k,D"]^.*@l2Bh^I\,F.WXajqq1o߾Pcc !K.D6r\z1r !pxsB|d뗔J壏>J9rHuu***zW{13},jppO>ix &&l6oٲŦ+11100h4VTT8|7ƭ&"ū:m45´Xf6_~wyG";[l9~N:uC=P(^~~~ m{w-/޽{Ŋ7pR|CCC׮]K{dlwqwBMh"^3*z/G70ҥKOq0ҽu];vyU?{]rezz\.>{'|bX#ۧM^`XjNTvttR>k68iŚzi 6,\pt]]]x= ׏gwa4](qoaĉ͛79萻B .H}O[f·p m۶m۶UC\ :d (rAV^ݻ/_<#ٳSa˄R6RPru:hd.x> /$$$bߺ{΃R[~ŤRހ@0.jO>y=;zF Z8< -)18`0CƱ8L&[fO^Y(O.(09t/:5s|&'E8Z-[fO^Y(6T|j>09>YlRagr Fqpp x 7| S:Jrɼ0>)/R&t~Ep)]Bh4z^"B2ZVR'>5v^8!Fq``@R B@\[_L&Ѩ1'`R}j%pPF}}jԼ1A!p8q8`0C!p8q8`0C!pb0AxaˠV B`0A[-8`0C!p8q8`0C!p8q8`0v qL&hZh4][ǓH$B r\@ HZJBWH$Jٮň BP888hخ WcB"LĴa!J% ۵j,HwkD"خb3px ݶaM*xжa.X t,[ggP(D#CKO^ر8[fO^ر٥֩0v\||7H`0C!p8q8`0v[QQѣ>P(5MMMΝ;حt-i"rss_x 6X+vW*//߲ediӦ1SGw_gOX kwqDž ǹJ#T*gΜC/ܹs{mhh`Mʕ+6pHx[oޞ0s_jǿ]Ǣ?B>\]]CBB M߳]S8M,]uww %%%eoFWٮ/BXXwxI7KZvlΜ9oH^nr;BHuug}v]Foul޼?yHHK_Aaa!!믿6L#ڗϙ3gѢE~~~׮]tҶmۮ]L} !r-qqq |֭gnȰk׮:t>svAAAwu׬YfskksIb֭{M&s=w^\-m2kaŋYciiitkeev m|W_}O?dE<3N2eʔ)/~Wvm]?O~c9}իW?6?O?dْ8ŋz?n6_z% VLAM2%==fٳgY3f@uvvvtt={㍍]]]iiiׯ|O:uL"##w7)ʂ{W* ˜\|ÕZ6<<|˖-KJJz'y#ϟ?W^!ر:.,,lԩ\.E Ѝ7OB?}L\5 ko5!8$>~z-r_o{v| }'׭[g}۷z+Ws=+V/FC_ś6m"|oe Ylٳ>px_R5hJKK[`o jr#蠋%&&zjjjl455шT4h#Él_^xoqeX,~g lJxg{{WWWmmmRRҲe~!o~C|k4Mrr2s).[/&~_^lhhrh\l"b3ƅ;vlڴIPx'+&|p6!J?wMiӦ)S3oֈ?ߴi}T믿^SLټyX,޳gϖ-[xY 4XݴiӪU:::|#GXJGcccJJ =o߮T*ٳg?S//Fobp8EFFF>!dΝ Vql>3:;Xb{]b-|)99.a$馛!o־}A'{_CUZ^-Z(((hԩ*㥥X⥗^#|7W^\800`2BCC.\8c ˢmglmmꫯ!&óf 3gNUU74wr-u 9|(|#ya6wܹu֑>?&!$))iӦMSNuVd2 !Z#*~X`ŋZXX'|B{+T*׿nO&߿d2Z/mN577?sgΜޘ4[X;uTxxxddM9bٮT*yJ&h4 BТE !WڵkϜ9c݇P(nV|jgo#Booe&v ! ,,===ʗ_~2_oᠺ벲>???.sՊ>_~ʁd2P(4.\8|3<7߬[ϺchhԩS2LV_tv{|ƍ:N(bX___7oWhoo߻wX, ̙3?oN:պRvd28T*驫۵k/li;ijuIIҥK͛wAM3guVݳg?OF0ibKKKwرvZe8W_y^m۶UUU\2%%E, Zxҥ3gzsR& ߥmХ;]*x `0C!p8q&:(c-pFN(c-pzN(c-phZN(cKnZ]*9KERxv 6hd488 gX^C@ÀJh4l{J>ghzD" leZJBO "pBFJ q췾3LFQcN %pPF[ p8q8`0C!p8q8`0C!p8q|w uuu1]x<ްesCP0]z{{-`0C!p8q8`0C!p8q8`0g B@\o C&h4zVk4ٮ-I$PvEr\@ H$ZVR!v +H$JlbĄBP(h4lm!H&bڰJZx5H$򁻵D"Dl{8x<ބn۰&Jy<۵Rlh۰cA:3A(! '/ `X S3'/ `Raɋ;w\>F>yQc$0C!p8q8` _|yqqq\\H$q4M}}c0iB˗{uCInBXGaݺuw_``eX,dsy'y~NQQQO?tQQȼ[obƍ;}ݟ}Nwq>D 8b=o*@" T *"Z+iuJkjb { UElbEQV+("1B/$x:$3g<3,Fq 7DQG=s}Yvvvzzz;tзoΝ;;桮ASLԩSnn /odee4k֬y=zׯŋ+}n-9眧zMty>d'D48:u[(={ĉ+0k֬j &tiǎƍ[~}ؿ,X&1q3]z=\aaaS+O=L :499hʔ){[>NygF9ŕ.ߵkW˖->*6ѩSU(NGQuּxkժUjjjEy %K/4%%eo3&11go=d'C֭[(jӦM6m=Z믿^իO'vպu3<:v8t3gV|Nqǡkձ򗿜0aΝ;Ĥ /pȐ!:t())Yf{w.Zƍ_z˗_s5]t tұcO>d̙c袋5m4ve?^֮]:[nm۶mժUvv_|/?m crss׭[wG:_ɡ{sο/ƍΝ[cǎMLL={vvvvŧx'V*!!aРA#F8ꨣ5ku؍O*rѣG۷u%%%[l?9%%%U ,33n(..;,Xp jϟGRk܃xk󴴴ӧw--[//\A3x'&$$,^g7h}8N:FoРwϗ]}O?={F׿;Npl'(ڼys۶m=3iҤy]_r̀~_ddd[cǎ!C!X6~ IDATo>{⦅+wy&L())]չCW~~78eʔ;u]w5\jժe˖-Z/?C-[NtСý{; 11N{͛nݺ;+ر_bŊUV]?33믏hҥsO5k֭[K/nݺ>lҥWoݺÇ vGxwyg YxɓǏziviٯ/[oJ'9ƌ /=36seeeU*mv޼y/⧟~ڢE^z3aÆwuWVV֊+Jy&M~'׭[WPPЪUHLLیHEguV2jJ"31 ÇڵkԩSݿꫯK׬Y3zߋ5={v&M|ҿ뮹s}&M<Ӎ77owQ<##c 6ӟ4}Oiڴ3EEE#FQq#fvbErڵkK 6dffV}n~O=TVf͚6l]wݕ~֬YUo쏷VJJJ͛w9rԩ~aX@=O2~?O(6mZ+-wuU=*n⫯*oYhQE]t) /lذƍ+޺{۶m~fE:ut ܛ-[s=C͛cǎ(8K/gyb][?*T'V?.dӦMDرcV /lժ֭[|j$Ajcڴij'Qklذaƌ\rɨQ׿92QuQ)))%%%~'QUgB+/Eeƾڗ-[Ͽk4)ZlYͧT:Ȫ,];6l߾v(6mqU<1vJc?׶m38cϞ=󟫿}XhQ,:wϕ+O>(~_{)s=>9φ W_}u~ K,scwJ"C35E9͚50`@;tвeˆ = ,Xdw=hРm۞r)ڔUz&رc.\8f̘g}fX3ׯѣGřj~ȱlܸkڴĉY ݻwœrY+VXp۶mی۷jjժ巷s)zȋ\#G矯_>''hذa5PPP0yحHuVEpDQOdffvK.93Nڵ+=ׇۡ{幊mOtM͚58q7f>ذaCzn{nEm۶ŖO4_W-nذ{cQ}7tӏ~?J4~jj?8(ڲeK֭+^ZN$UW]E?yzXСCE~i7nx1^hK.9׿ȁGJr'fz_c׋s9eoPZϏyЭYf…!^:wܳgϽiϞ=;(/^K/c__|'bHs)))9#ngz,55:3iii'{O jڴi%%%y S:R;w:uo裏V礇݉U8p`Wޭޚot?X7klܸqC_W˗//j!={qwyg5ku] Կ͸q }e˖Yf˖-[nMIIiݺ~)&M:[h<ӳg޸q={իwO>Yͭ`'VaԨQGuٳK?g:t(,,o[~K,y7=m۶ׯ__XXآE>}ddd~7tSN֭+޺~ѣېر3gnL voٲ夓N݋͛rǃC޽{Z\\\TT{]f͚4rssǏ裏m~GQٳ^xJ?^G4iҤ)SSN9#۴iӪUofӦM7n3gNX~_~۷SN;vܳgϚ5k֮]p²w_WʨQv횚駟1cFaa |Q.=zmv֭֭{饗,XpVZ5f̘6m :n6mZn]^͛7oڴiժUO=TKj+r袋N>䣎:*99yӦM˖-{*?䬬3߿Ν۵k}-[\矯:ijGyI&/?{jlpī6wڼm@SCmCPOPʺRp^pT.ujJԩMNp  8'8t8uM[pk7.nQXXMS'G~~~6N|SpyH}=;U*uw(QTTD9997`o|:01[_Vo[9rrr@3@P@EQ^^^aaazzzZZZDzsssI}:$#;w榥$%%%&⢢Bפ@*STT=,P 8'8@pNp  8'8@pNp  8\C jp4k,8Zo:f8@pNp  8'8@pNp  8'8KIIIiii)))IIIb {8P;*CbbbbbbJJJzzz~~~nn}:$^z 6([ZZZZZZNNN^^^HOOQaÆիՋ(HJJse5l0)))ޣCT<mUDq ziii&9Rq :V1uM[pk7.Tp84\~ Np  8'8\N:i̙3g<=8|7o޼y뮻.cW͛ѢEgu<8CPG|+Vx=J${[zzȑ#O8vڵk׮`֭_}˗.]e˖x*-Z;wnbb/|-TI ^~5\˖-4if͚=HJJ޽ڵksss=jqqKׯ߸q.]ok/_V-++kʕ{۷ow޽5Eт j={>C ӦM{Gk8ݻwNN=}#Fp Q}G=g}޼y:۷sN .ݻwZZ'K/mٳg5Pn(޽{ Z$$$t- uQ׿="}N:zQ͞={ĉW5kVRRRQQѿ}hgɒ%zkjjAN;-7|oن/^S5kmPRR2cƌT8t :499hʔ){[Я(rrr^/---??: 4~(l2f̘x{x`?Jվ}(nZ2~(v<%77W_ qںukEmڴiӦMr^{]vEwܤ!CDQ+ԁ"T]W㗿 vܹϧ$''Nk߾}6mRSS⋵kΘ1/(]/̈#6mTuc=G6mZ]t{ꕑqO>駟~w9%KuYrJjjjAAAG6lاO(ϟ_838K. 4ذaÚ5k^z_j7#rUWX 0w{Gl۶mӦMK.]pmj6o?ܸqȑ#wܹQF7n\p̙3(:F}/##cӦMk֬yG֯__ժnOZ'p7xgnzO޽k׮'pô_$?v577Gyw7oܸqΝ;ׯ`j6?w|e˖6mڌ9r ׯ_rrE^z饵k&$$p W^ye˖-o;Sq'?>S曕ફʕ+ٗ\r333v횘سgϞ={^{ԩS݄㢋.* W^tO<ѤI3<b˟}!CuQ]v-{#ÇV(],o}ɒ%|~o+ϟ_M(*..~333RXX[ިQQeק;}_ѣb 7nG?ѐ!CzqԨQ]vݱcE]Tnݺm[K.)=$++kժU Æ KNN?'x"==3ӟTP@mTN?~|͛7o~m߿ bWRR2o޼/xȑSNc=z>}zFUʊ}%;)]rʍ7FQ4lذ+իe˖|+R /lذG}T5\j̙ 489XR4lذwޥ cS6o\zJLzFEѴiJk#xʔ)j?7vWDQCU*fosǎOt-=]>GEsL#j:nrѿ[n%)))?yfÆ 3f̸KF׿uϞ=Q9'?>W_EQԲe%%%%=\E~zbs@D{U|傂)Fc+{͛W*;ڨNR:umKXs}lmٰaꫯN<9==ϟ5kV飉z:餓vڪUf͚իW/--+7ok:b)0gΜkƾ3333336ҳ,pqƝz{iԨQlbpľڷo߾s֭[EQ۶mիWŴۙƾpf\(U:u*8|o„ QY\\|$bŊ .}zjjVUVSLݖcǎ6mڈ#EEE}я~EQ?Ynӣ(?k֬SO=56زes9geeeeŮ :thTӟN8Yfz&LE?\Q(メ#8'83bQ~?믏Uz~پ+'vw={FQh5P(^{ꪒiӦպDo߾cǎ>/_>q؏EQx_~y}4ILnnnly/ꫯ8SN~5k*]/))7nG=y˦"_jUv… O:( /^նn:~;S]vcǎ;vlCӦM+%yVZu=p M4뮻(ˋLEKپ+gɒ%W^ye~ܿoSN 1ZEћoY:ԤILҧOSN9#lӦMVM6mܸqΜ9~KJJ&L0|s9cǎ֭裏{챜.|Egώ}h93g\`AffGݱc͛oIDATݺ/|7Ԓ%Kn7x{233]tiܸqVVʕ+gΜ_̙37=z1ӹs礤O?tÆ ,XlYY}5we}W^{t钗o>*P Gw=ux}Sg8S"3"eNp  Z|-0'8@p.nQ\\MS'GQQQ6N|Spt8uM[pk7.Ts~~C*Px^ǭtuA(**ɉ7qG^^^ˋ(y:LTrEQWXX\GR`hΝiii)))III}5)P}Jp9<uϡ81Np  8'8@pZQRRz@mTHVpٳMՌjGAA   P7U3{HEsC*QڵAσǞ={vYuΝ;Y~܇#77<EѮ]rss+''<vܙ_OIJe&77w۶miii)))7:+,,/...0--mOVpS\\{䤤P[ٳ\jT_###fIII ~ Np  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8@pNp  8'8BB.--袋ڴi@_Μ9o/((X8%{&Nx77j(QF'|rjjK/pX3A}嗭[(۲eID+1pWRR!@WTT!p̙3=F98[lYjjjN!l޼yԩwqIUH;FsIENDB`vvmplayer-2.5/data/metainfo/screenshot2.png000066400000000000000000001462361456573503400211150ustar00rootroot00000000000000PNG  IHDR IDATxwXS8 CLE[""ளŭuj[mmVV  C)!32~<B !!sɽ'}D@ VBфB'N| MMMl6ŋyyy :/N}v1gŋnpϚ2eRXXr۷o++K_m۶YZZ.YDvAA)BH(O{m etuuܹʈ6ݚڵah4Pwǎvvv<Olݻwdu߾}?ܳ!|333JO{ICC!f g۶mBM"gΜYlYS7 رcGXeeGZCr)"رc/zjS1y ŠMLL䘇fiXTtG!MMMGGGhxyNӥ/Z֭[:uRd6m :wlkk:9&@h4ggg+++yF3g3 j1u.]P7͜9SMMM^LɡٳE\|Y)9i***&&&zzzZZZL&SUU!P___[[[QQQZZZ\\,rvرe˖զ9^ϗc~;@BNZYYꪨ 111?~$[ Gx<^ee޿/sI F;rʕ+*رcݻw߼ySJICCc3f߿-W8qNyk h ]t333ʀ41GS>|NIIWfM>]~]'puuqI.*6رcǏ?B{Æ x ի MII7n\NNs|PDALLL\\\飫+e]N޽bXrI``B|5ضmY~iչsٳg?{ HN@{'͍6BUUUՖb# ccl=$ 444trrB믿:u4"uuu=z$y%ӧl722=z?4kLm8:0&9|p77?KOOŅd$!!!>>>-6u#bQQQ^'>~T}}}3& W^?վ}]qvvrvv>r[uN*󩛲pBj6dЯ_ +?I+fff'O={ٳ'MԸs < gҤI._ʕ+eee'777..|󍎎0007n\׮]E744%$$xA)?aP{ݹsܽ{=}ӧ{{{;88`^^ݻwGܹCmƤ88~8ucqqWZW[[[[[fggg:[ѷ~K>|haaAe@@oK0j(ׯ_8p@uڵ]^~]YYYSS7xС7o|=۰aC㧀F^^ټysK!QF{ϢriiIܹsѢE$WӬY -,,d#477>|H6Ӌ=Т ֥K=z111-~ %ycƌlJCCý{RoFFF... . YfMjjg8pkooOweС7o^v Zs驩 >|ڵܻwouuuSulٲGvrr0aŰVt:}vvvԺ ]]]]]];;$-.>>ܣP(\jՈ#뇷~իWS|r񱱱8ִ믯\ Pу,/[L&yyy˖-#E={ϴiӨ߿+WYɓ"Ylف-[ӧOUVm޼Y$ްa޽{iȑ#G2eʘ1cIדY>eyfw&%YYYb߱d{7779s&yzzP>ahhE=̙3QHK3gΐoz:NZZZQ__U*r4h +-'޽{AAgcsrr2dHUUY9^|)}T%%%ڟ=Gjgw/NONN&?+W4մȑ#$PUZ!*b֬YԏZJr$۷oCCd+IfddD9D?-qpQ/YSpEuE1x`jTJJJHHȧO{` +N|8 "{!ܹs?5`FFFX...cǎC^ ֲ3gμxؘҥKdyȐ!?[fYSTTTYY5ѣGr.]O^6r[oNO۲e wss+//ǫ6m"[+9<}tɓQ[jO>mٲȈNcڴixhNL4 YfmKeiijժښիWw֭qz[[Yf/J,vqѱP(ݻ%300l6,7UNN:%RGѤ3$=?~<5j(j߼yoC21j)E`` uNoWZg|J8{ tcȑŖshkkrq}g5fFFFBCC͛#w8=B ;vhhhhkkQxTW>|$;;;.|ܱQ^:H ǢEF l#G$ֻv튏/--7nel6͎~=uu//=zhjjjiizyy>|8++"2331?.[ +V8q℄4_vqqA8ӧO … _}4]8ЧO%K /!6L򡌌ΝKVWXNmַo_PC7@ 8y$"h45jLKKnj<#,, U+W~+b9jjjȲH;FQ~~~xLŋS#BAuֺ˗'%%]-I^TT<&I={zsCz{{b۷!V^-!H7|SUU%޽{ݻk֬0N3gΛ7opDc7c`fTvܙo>kksmXzzzzz]6zJNN>iDmyZZZz9޼y3--Λ7%9իW322g{]._\l BhǎxEqxP gggԨoUUUN%Aֽ",,ՕzMN>Mv`Ʒ̙3l˭4c 9Ξ=C \XYYr򻢢,gffss7oO[[{gΜ۩o.\h!D[ >\q9o 5ij`im߾qooCk׮;@tuu{!3.Kl2a--޽{޽Z·a3U\-NZ}oҤI%2??#Gyymے"/%矟uL8&MYqqz:N1 oj7!yzz^pڛ177ˑ?~h#Fob2/^R8zTt:] •+W^ >/ǣQˆ#jwwwG"Q&EDFFnݺk͹f )++UHy -WVcc|̙! s+Q}F)^nݺݻ.\ϿrgQSQ꟭q8bcc)H'_# }:&!T]]` {{{jX?Yp8/B(;;իd޽{544Lݻc>|XBG333R{RYYYHI \2V~oƲ6W&|Bc'f\͛$믿/\%2q"s^ Ÿ~i޽xNϞ=+2Bd?o←lذzŋdÇZEش4WӘ@ ,**uu,JLLuޞ<ܹKd444ƍOJ'RQQ1b Bp//oҥZR;ydh!#^Pׯ_1޽{_dyԩMVZ%!KEE};qEvv6͛wڵ޽{g+Yq\RdZ۷o]СC"u?{LN?'AU.]zI>i&A%ڸmEO8Aap˖-$5kֺuDE-X,?}qƵ8ɓ5zR(<^qcc1c$$$MlllH:={Lw/^Ȱ511ڢL )xL0sV^z%sv.hБ#G|ux~GGGjui7OnܸQU~ϟӏ=|_&&&p\\l92fɭ 322LeEd@li[pԵkݻ-Rҹsg (ɼ~:6B $nٲ:+nG5tP{H͛77 ߾6Ba|||S$ZXՉׯ_~z@@@bbbS1:ǛRPP'$;v[jo۶_#`X-<={H 6PR[b<oÆ ]ޅwǏ>|NeeeAAAttt@@ȴ5}t")N왟_r%KuΝ;dP.;| Et:$Xf ne@zٳë}V*Om6c |lSDfff]]СC<&&&DgϞkbj1>>q444#4mҥ~~~<%s+VȜ x7\n]DDĔ)SMMMutt>}S!ڱcǍ7-[iaarrr8ڐ5@xM"?d^zzf̘֢ , xY=… O:%߾@j"s΄ L4IlvJJ ))) r<22RA/ 8ë3go}"x{{Cd%KPGhC,jЗK]O 2?.y;P3gL2b-"|QC9ə1cƻwX,V`` iNgʕ\. <<|ժU{nVTՅ$$$ 㕕LJ-dmGF<2 SRR)`0m8`?CS80r!8_[[r [[[8j gnn$`CxoV.Ú0aj}ڴiSBM 666׮]+/////v획MZ]]}QQQeee999'OnL*;:>8pp@ A (P88pp@Td$p8 |>_ 1OB *d0e6>f9"2 L&SSS@)p׳X,FѴՕ Ӽ6l6F!f ӌ_ٹ l}*=`ph5R,:&Eu/MV(:C~)m*h#PR@@ A (P88pm"7osEQQvЫWvI FSt GJ8o.e秡? 4Hy&ggg366VǤRfJii/R[[+MbwISYYg)?]v{ܸq׮]Sv^ě8q _:9*..^bKJJ{9OttsR(-`X˧OLOTUUrUU˗5a-_w )޽KR^p!{򊊊CV%AI㉉uuuIII~~~mr=''G0Sջw) k#;v,YM  4m̘1"P7 "fTZrdБ.4 .SB@o߾d i/:~z'''qԩ!88oiPuuW6bX x!ԫWΝ;WVV":wܳgV̸:Ƞ#]:i8;;z /2D[(ӧO?}Tr#GTUU!sIɜ1cѣGqٳgC =]]]''S膆L O>}}P8qN:N%AIc޼yiii={7n@[Gqq_RRR]]x̙3?^uss;uAfddCyرcu5NC ;naa|r5:Ƞ#]Ϣ>>>>>>mp,_<&&Fh!K>}Jktԉ԰ RRRO9r$߿IpHY^毵u2p~!>m4o߾xݻw&McnAcSj848q"nBdaaq .u⒒UUU]]]33A#rrrfΜϚ5ZPXX8euV+333(((33XKKzΜ9JDddd@@w***Lٰa|}}WHtP޽+//WWW722ݻ#_Gceeemm=c v!۵kBhٲeOMM~zFFFNNϟߵkWPaa+WbccfϞ=p@ՅGGG2339r7N{vжmۼ^=4 8Hf^MNN&G^H|iƌC}Њ YA\]]9`bbƍ5aX#GGs Eח|K,3g GZrFpܴOÆ 2'9~}rr25HKK۾};0&%%%%%%((Wl̓oܸAjiKJJ}믿ƻkjj2bbbG,Y2}t@ӧT򀔍Wuu{ellLrssoܸ3/vpIakkkffyy:={?^E3w'Ohpܹvvv 0!!aȑ$޽{ԩӯ:bo":ꪡ!r 䤣p-\ځ ;;;///KK˼㾻ܹsdH={~WNNN;wzŅ UzEDDĨQ|nAF Bc-B(**}Z]]!doo`P(\lٵk޿O NǏe> !""X`6Ν;/\)P/&Fc/B͍:HVVVRWɤիi+9!'''RÇϦ MMMzڴ{d:9@6t:whhhx왇Grr2Gq\]]qNN_>|[ے7o斔ד-X:P߾}E:::ώM=T~$':K>#BZD5p8ϟ'$$VUUדz8ҨK87 Rҋ'˩dҲ%y_2Г~zzzvm"~WUUZj$ݻwO<=z]YYY]]KP{ iҥ |j`חRʶtaroBB´i֭[wϟVWW_p|w/_ޤD(UTT޽#˽{C&&&bLL =zǒ!C\vٳgIII'O:uqMR IS777;;;`{AFqqH_SSCܹSSKRV[7 Ғa^hiiM4髯266o>W0ǎ;yd||u+Ԇ#G$8s  36zhVSSs52m Ӣ1cYYٽ{N"5ugTU߬@Vx3gΐڠ>Ϝ9# YrJ+OpO~***p 5n>@^*/vkժUzzz?#p8ׯ_'iƎ %zA^I+^~ѢEΝKII2PR'H"RPWWlٲ;wDDD;vlٲeܥK|ƍDPX[[|%!ͨҬͻs۷o–/_;"Ə߸IQFwyyoPPP~~>~׏LZYYrp8Ç_6(߿F(lݺYRGFFJY@q8tM***Ƚ!C\|Yd[ˢ ;v,y'[uo߾}! $ߒݻwK8!|ZbZCC ;;L@ 5k΁>G͹t:} ,߱[zgOd27mD)))ٶm57dݺuX(??~Ƶ8.#GGGҮ޽{WUU(Ç طo (qQáoQkp?ߺuN4PY_j%$Kd:j1c 2+BhbEf)C1m۶Q$#;Vl a3AeeeTT4ߢYסgϞwS :ܹs"_4y۶mM5/&SWWٳԺ@PTTDFDnI LBd](h@dX6,,,&L@V3)mQ--?cݺuǿdBzΞ=[_ KK^z-@ݻ7>>>222++\SSv֬Y"mw۷ogffjiiիWdbW\9s̻wLLL}||\\\vu=]v?vXJJJmmm.]Fxҥ/:::77^WWW^cǎm5>|]ZZߥKgggXMMMť...frD:t~wl6;44TC㏖=ѣGEEEh JӢ^67nEINpI55M66(#*%ׯ_ 8u(.{{_~@%(h/@(P88pp@ A*Οat/MR=t4ru/MRG_ h 8L:&iT:dB jm8|u6Nڀ`hii)4+FKK 7Ԍ`@SSS]]]ٹ,BSS]shiiu hwh\.l6("C d2555&P Ys8>/- CUU%{ %O (P88pp@ A (P88pp@ A (P88pp@ A (P88pp@ A (P88pp@ A (3|#Ng0L&`(;;@@rB|6pf`2v&z\HKKK]]]ٹ4`7@X,6\mfv)3lb|ehpt V:=rEήGхAAAd944THiG60~O>! :(K >}̚5 !{ŝ#eV(Ԋ/rwwwtt@PPZ6G.o!}tڰaB!!! : _ Ho !KKKSr)ۀXѣG!eذa***</$$gϞ"髪<==>qڵ[[[__~5unݺڎ=| .SSS3~_~I###7mڤxȑwݸq#33Ǐ:u0`{zjDDDnn.N9r3ݦ… %%%:uٳ~-rܹs]bȮ7n߿sCׯo޼]XXРߵkaÆM88ځĒ;ޢj*JHH„B!ޒw-X@$}IIɮ]bccɖoo 6hiiv 555OO7njjj"uCnnnSxbƍQQQdK}}}XXXllݻ Ʈ]ޤǏkjjūuuueeeϞ={-[GT"~w_2eJKO155%]]]⊊޼y#B <~xԨQ^^^ #55ɓ999Nrpp'\+tuu;{{{ k׮~: 2b„ 7n`Xqqq#F.22!4~xGEEyxxxzzZ[[ Ǐ_^ ]o߾n JKK;vƍwޮ]Bnnn'N.**?|YY٦MΟ?occwܹG.^ؘ~)%%VUUU#@G[ptxpu>FEEꫯB^2Ç<!4jԨս? IDATB2!驦VWWGmQ]]KѨ%#*++ﲰ dcff&BElɓt:B(++K 4>^ӭ_^CC.]ן>}JLLܵk޽{B->efjj:x`>YYYνӣGӧ#BCC/^===Z'LV__jժТ 69s)l믿fddTUU K.CUvRtңGϟOjڅDܢBB} q!@"СC۷o'LҥKg͚%ۑ8qϯ\_XB ܸq#55u˖-][nӭ[k8p: N:tgϨqG_. xtu+++ۿ.]ڻwoegG*xn0==϶000ꫯ>}rT"\xo޼̬244tppmOlFS]]`0>N233?|d2njC_?##ʪgϞgڵIefwލ)((())r&&&VVVSNurrj/mMY "BɬYO,h"}}}1CCC#駟]\\߯h _D vDGG3gΔ0IHH@7Ny6Çaaa!WW$p;\Ѩa… CCC (Nhh(ԩ,nDX,ج)kkkkkkqȢt_bׯ#v/xwww(a) `)c`2q0xlh999xi. 횫+i.e!mtWWWR:_z7^lwAYH`cc3zhRDc< Xiii=FmgI8gϞ+;\CC>SlgT"z5fj$6HKK &mqaggzyKUU/@zzB`^^^$M6pÆ SWWWv.1$shA BFyyy}wФ9|~ۏ6K.m# j zEI's رc`h޼ykF7_=z:I9f6/1PWWS"u+X6Зp/^29~k0zꥪdڭ}4ش84ڂp@s hF]]Fh)>4hPtt4Y555]hGEZJhǪU/Ə?ydUUUegJnܸQPPdwsskHPUU6z޽{7N͛2>׻wo{{{ xo޼rwwׯ4yjjjjjjh4UT&$$|b[ZZ:88vfZ"~@b 7n 4qj---++wG~MIIIee%144tpp022&+//x#0+WJ->}t%ޜ9s' c޼yZZZp\_mnn.}o);'dt:Ą]WWuǿ{:P( NKKCikkdffN4IeTTT׮]uttfIIIϟ?ohh麺l6ݻw3g޽{NUTTfddxyy>)SSٳgEEE&$$BmmmW^Nlذ\.!8c0R~N(--i>/9MLLYptT"72uY&9m4eef'$$$''|cccUUҴ&LoEEEϏ5jt.ɓ'+KsRRs.]t:B(777$$*<<ˋp8p8 2d*ˍNNN ;wv)Q}ŋbT! p4P__yI أGccc{."""&& oohh@YZZ7NS T&٧O۷o_z%[6`zz /_N2e֬YbPy<˗/t)S]dҤI4ݻwbLTƹo޼wh:>s)SG>B!{jBrrr}}}޽]\\pڨQ|>yIyfhf  6Add$N7n){PWW7n\.]X,.biJϞ=]\\Hb02dB(;;lGKl;;={"өCGS1 @ԡ^xr544d  @3f̘:ueSi޾}[__occ#3ظk׮<גς=d0QQQɺH9UUUx )D1h4\R.1LF:? L(p\OOO@__F 6 !$͉D(b--8޽{ٳ.j)UntttRRR^6+hGRWWuǏ?ǵ >LwK-Қ> < @^^gO 2MB͛7?{SܹDlLLÇ[\@R5nF`bbҹsg.[ZZڬcʐL?oߞ={6<sLKKԩSWXA'Ytww9r`ժUBqM7]~1==ݺo]]˲ӧOi .nں}1R̍A/^LHHm0G Zrd4ۗ.]Dc >NOD8qW_Y,X`;333.]:l2SM>tFLsssjjcy@0ŋ]ta[o&pPb k{`` e0o1 fY 8]%00P ,ABh"|q7+׮]\z>yfPXYYVFzݽZ Oh4bT:gFڞUz9bn ?/~oݶX~~~5kuz=vXIIIl:vXii)mOr"뽽,˲,\UUe{Ɣ͛7?|ϗJǎs%V;;;#""B222"""jjjZ7tSBBL@hg"hppa! D" Y5 L&]VA*zxlRZRRr7;-CՌ3ZMkjjSN544L&z~zrrl/ȑ#fyɒ%Wam^rjpusoo]4;w'wӧ3gΜ9sn ޲eɿ(j{wb0Μ9R+vq?󦦦ڌ W5kޠLrz߉@`Ç_pŽt˲A?:;G}@ Ůz>upppVuf/pժU?|JJӑ*e5T,gff{Lmmb;eX̙3gھD/ո7昣(61A111YҥK333ju@@@\\\FFX,]*&Ji2e_|qլ,R"##O^RR*p7!vf߉ɓ'GGGΛ7O"TVV&%%ar #9r[|\HHHJrA(pBBCC,Yrĉ~ᮻr,@ hӧIuuu``Ӯz;ĉtP-zQ48ru9bt1IcܹsΝ#̟?A5B恁L6%QQQ镕ׯ_w8!tV&\0v8h#Ƿ~{T Wx t?Ǹоd3VN񔔔sJqYwڶRF&llﬓ&Mnjj2 CCC]]]999FFrԩJ:4ı|ttD"h4vS5MWWWPPVsD<77(<xY+Ź)f6i~r C}}P(tZۈHeܜjX,[D{T]*幤zaYqez믿OnX:N7~Wf9;;{t Br|Yv/io:bhhz[n9uTHT]]]]]=i$ z111wqUhKI}}}~~>%Jk[^^.HlC{xLO="#z.^k׮Q=>l6+Ι3ǶD~ٳg;::l[2T*w}e]b|ZLVTxW駦aWaB6lذi&d09]HפgQQQtG$HW"Sxh*K$MH$ |9m_Ԇ jjjz{{ΝtYb})J,q啕h4͘1#++kL@Hnn.~^x*J&eee :}jHf$emp0$ɓ'o߾---*J.gffΝ;׮ѩG7hمiiiXnիW=b(3f8*ٝH,?C͵jz``/444...++kVVVk4)SdddJtD"q3`EPDGGwwwԌzxwBƯqѼ1"'Nze\=sRK)88!r>h```@@!JKOʈ,-ݏOBH$ HM&0,P(DbNʨDžZ`>h4 ro 8Q{9p8C!p8s9p8C!p8s9p8zOa dbeY/ |P(DRT$ 8}2 ;%SR4((hcāC47Gp !mLpCCC#eC׏z=  àm񰰧m`xQ3`PCF8aH(pLU!.U7Tr98aHs9p8C!p|W_0 c4M&08!D"Q@@D"D|W`|0N3|Wdl6fN'Hd2b|"p Vw-Fh4F\.J O NiJt:kx:`0] g`f\mj>`s mt=?cҤI 744<#n dggެgxk3`:;F#~gi22[Ǿ}B'Q2 8L&_d1pzBT*N٥ש ]*<)o\>F^,o]*<?>'^A[8ZZZ~_ꡡnM.]A8!D*JСC͛y L\cΜ9ӧOOLL h4ΝU IDAT;ydo|r Xd?RRR,Xp]w=So֌3!LX4|IBЩSLD|&qߥh{5klܸO q$⚛7Ÿo~eazzzO?Je;;; !|&q8mo<555|U B̙3 LD>p8#}i4_%^,[XXq]]]:!$))i…7j +̙3/^ܼy֭[6hTZ\\/榦W DF*?^?pɓ'm۶tR@wFsҫ=88hK2}b]Kg8(:wVk6DB"睜~棙c??vڅ56w6$f%/h;DŽ˲'O| sv=)Byql?/ѾBcH-V/_| icefm;o@i͛7/00Z Oc8P(\bwEũZ9)/mrpBKYuH'z>};RRR?{6(Z9OQQQsϸ~7vi8~F1@@Y5dz ">oʼn8Bŋ>Bw]$]$=dt. =)V(p`_&Dp ~yp _ශ5|Ǹ2AS}ξp111wy/}Bȿۿ]'}عs'˲ b6l~mGGǰŲ/^|FQQQmme222^X,W\!l߾c?~bŊɓ'{X,uuu===z>$$$"""'''**ʱPIIIKKVJ999vAxxxRR̙3E"(T*]RQ(ӦMv4˲~mWW󳳳=9Ѩwojj:vX,~=9"aJKKT*@ :ul4_|A koo6mڢEʕ+EEEqqq6m~oB3] ﳻW1 -bbblz V[TTT]]mX_X,W\#{xX$ YU*Fs9,X0sLG5BPPh4TV\icYl6 NY]]uVTy1W,K~~R$Du։|rWWרcjO>a+=vX__X, lkkkkkkiiYljjj!Bi]#]0 ]3kjJ7oJt:]IIIee%˲QQQ._VbqVVVUUW*,|ͥ---] mmmjzSLdxŪ/&$$XhFcvvٳ%O}`Ŋ#*TIIR Zv-kvuu}.\pռ400P׏4Y,zi WdXN:7o޼YfxpI&M6mسDY^^T*e4+LpNh\p"66vÆ ~{tt?V={G:,[222mۖM!D",^8>>eFkɪ*0eʔpxR(,,tww_t)%%eԩ---k[9sFӭXfmqq:EJOOQ6 g϶X,EEEv/0 3w\Oj0aШ_IOO7o 'Nhkk+,,t?w %''[3ҚJ(&jRΝST/:V{Ɏo6|ڔD'Ćٽ8zMXIKKP*1cpp:>>>..L4uOf/qJ D"aůGnuuus1ia #qYz{#%FN]BVO<9++y=,Fr|ppP95+((ůt㏽Wv4FQQQwyg]]J'Oi].AQ*fsSSmc-@0wcǎ]reժUEEE,ˎ 0q8D"m'< Nth~#a5J߳,zj۶w[uWcZ,3g455.[y=,f[AZ8eN$??l6wwww<΅ ̙3{lM~ǒfޣ??^+bqt ͚n0D\}JU $''GEE544444$$$y. o# xy{{{~ӟ:68q^Ta/SծKV>|h4.[ tվ.ytlLflb)((Zfa1[555yA j&"" }N8r 8z30UUUbi]xcQooZZZ WG;wѣGO8aXм0,D"p8j_j5Gf,[*--^ (3fETTK,q|.!D"L:dնԘ>}mVX,ΝvZdd]𰘝iӦ= E[B/_0G744駟~ǎ>aqW\dnVgY611կUn-[f)3sLFWWRRRrrrSSӡC"""bF1~ߘvmdRYWWGExx!`ҥGmkkۿxxH$RT~fT*v\*''e)WXqĉꈈ^f9qLCPP].bN͟?_Ѵ7AAAt4'ikllpON>-R|aaak֬q2D[\\BHZZ˗;::<8,,lC&>H$/r7oPV*//ɳfjmm-,,-FG3 O,T*u:!Hd2xIe{zzCzDXD D`aFd1ڝbNʨi4a)f!55:Pv[71L&L&|Njmm=rX, j bծd 9PWWW__g6###cccsrr˲87>fC!p8s9p8C!p8s9p8{RHs]ch!p8s9p8C!p8s9p8C!p8sb+/1faeBP$bD"POat:h"`YeYɤ$L&8D0 ZZh4r\*]ScN7E+Vp)9p _-N3 |)o3p0 33-V0 ߵo}ʋ ~m}{9:sh4o>]?{)(/?y(lˋ#NjKSs// `bˏإ+Ž_^<^ C!p8s9 L,W\9zhCC\Rizzg͚Kݸp|}W իW^zwnݺFVkRA\&m/+**ύp=zÒ27ظR1_|EAAAoo(vW(/;q`w]ff]^{\__jƽqqntiۛwA ڲe|wEvcڰۨoDnqܹsc?ٳg瞱;?{l{{h4i҂ 6n\9rHEEF IKK[v-^:F3f[zW_}_GDD;UUU}ᇕ<̒%KFq"JKK٣Vݔh4:x衇q8FݶaoNSS+f|g}6;;ۋ{~W T*JuҥK>:F!aH4m4~kbl69r?3N555}G/^gMVsj/Tm۶͚5e˗//Tʾ}hӭ޺iӦI&]~*--=sH$z'Ef[+eϜ9o߾NBH$bƱXWWO:ŲP([۽{J }bccƤNW_}+{9U__B֭[z!1&&&''7i4C=Q#GDDΝ;~çBva TZZڶm>k׮q/WDzlLL̎;l G}O?an/h47&VwuE"@cHD6V\y]wǻ9 YfY{=la|G#:X5~;u!$00+VD"BٳgǾSEEE{ٲڵkcڵkv/5ڸqO?;\8֣=Svկ~`ç]rr뭷:N*}/H\/_NX,cˊL۱@ p祗^~?A]te3/uuue>HYK?U:wc,{Qf8 ฑ5S*Z>tnښ[ 6?xƲX,J`kIZyt{QqY\NJX+a껬@(ln/Dsn޼ٮne=zۋ+pd27&v[___GGǦMh ,jmޞG!dٳgvZ+ң8Ɖ IDATGEp8h~#k.0RR][FqUƺ`t{髶7Ea85B] n}I$Ygan/upX=ۋR__D"QVV5B]aaat}"lWI^  ç-[b6_,K}/222!gΜqQ²,=ٳCBBƸ˲Uq xO={vff&!dvrT>2URR/ٳƼ}vBHoo]' Zf{555 :qkb0/_M <=N{y۷O(~x{LW^y|'?4gΜ'No=!!AVѧqvet{t5:D)//㏱pO'Bp?WWjj?kݻw޽֗bbb~L4i{F^O;c=0̙3g͛x5^tĨ7&Ng48 /°[ɸ$]x?FgѢE^ Gvuu ŋoذq6{_~i&WbO?lٲcǎ+O>UF>pܘlܸ'? 1J֮jJ*qD`4-D]Fl>xsFΡP(/^|wz[lDDW3ѴD|~[֙='CRٳ3==W}*!!a2㾅C,s=s18L~f…QVVO ^0K|tB,bŊ!)))77[˸R5RȲl@@H$.x>V_Q월O{qr_]*^{2Lϟoiiq\БT*MLL\pannw!p < C!p8s9oC(ì01G:ۉrAI(/?y(wM~yQ_~xQDש01G:g/&&ܧ12dz{];gDr x\.G}ʋx#J ?d2Tw-p'dqr-+OyOJbXF2D&'>5v>8!"(88ah6aYJ9! E"X,Ɯ 1AD"_hp Q =p8C!p8s9p8C!p8s9pNI^TBB°eCPp]ch!p8s9p8C!p8s9p8C!p8sb+/1faeBP$bD"+aNg40XeYd2t:D";`0hZk1bFh4rTw]|c8t:xLVZV] s0 ~ptZ.>0mÖVeZ(>m"ٹ`4o0vש0v|vujEo7W.#(/{9p8C!p8s91ъݫh?RiZZچ rrrp-{챦 B`z;vy| S__wkkkVBȔ)S,X0ydBa65MwwwYYYYY7wMC?z*8 /tww+_Wsq,i&aD"э'8O@@Up7寿zttbH&,7"B<&m8Bpr!BȔ)S֮]w]Fouܹs޽j񥸸_7fsyy9!dŊBȢltRAAA{{{WWdKII뮻㹩/!X,~hii퍌ξ6ttt8qSR) ]C],C=a/^)4J՝?nŋ$ +577{倎bcc|ABHkkkIIɰGźo{=̏?o,{}mݺ&\t.˲%6^EQT:',YB< :_+yeBHNNcX/^0w}wUKavWXaCii魷:Y(++S*===`0F/3 UUUF),,ikkrk{{;!$66kf9<<'?+c7Gqq޽{m8OEDDܹ3;;ۺEMmY𔔔ӧO?AAA[YY[oBRicccSSgUvV^&Y={9raP$N>m` q#,,lƍwh4?X5Ǟ={>q^Vݻ:vRT-@^~#YfQ;wp_|Q/_|۶m o%p蓔dݲ{GFFF>ϷL&W__OM6T^|wy|0z{ bq6(:c/c [|Ě5kY_u~~{3+#q:1O>x!z-i4W_yty=#e!vWDEE\tl6_z*l6wޙ3g]"L DGGKR׻?B׭[g=׋'Md6:Z;2_~%!R" k/Bhh(-/H ***CCCYM&!dҥaX]]NG BJ?[mr j:H(.XX\|yʔ)gna0n ߵ]|auۆ-V0 ߵQ|?h۰gE:sh4) // `x fSs// `Rˋ;o\>F~yQc_8s9p8CΉV0Hą n.]z^z饜k8.ttt;%%%;;;;;;+++9?q/rݺuÞ>X,N_›0.X Ksw:vO2eիu:ZnkkrJKKˌ3"rss̙۫V.]pBTcǎmܸ)]5M 4pL---v"[Gu,uVaD" 8k׮?Oe˖`Y\v)Ӯ7&Prq,v nT2aiÎP~)ZZZ Rhjoo'DFFJR2uwwL&BH||(v#F βCBB^›@!pHBHWWWgg'u"""hEEE(vۂO<Ϟ=+JovW&PỦNJxޝGUߋ?YH E"QEbqmEԺZm֥zm]-HV-Z@YVR# [HȄk$I=sf{f9s\sMaaa#J&OOЊ+^}6mڌ36Kܑᄏ枒'?s.lԨQ5l‡\TTtwV/?㢢 &4qM2cVV=h~ӟ׿zO0aРAC 6lX=>e֭]wݚ5k 4vTVV.\\bŭdT*5sc9fȑ)..~ᇗ-[#r!Iƍ$СCO>~} .|'y~gС ڵk^^իO>cƌŋ??j=eWY˰a.|b̙3gܹQG5t?|wc5{,Jvi;N5{׮];o޼|wqG.]=5wC3g7ߜ$ɡ/}o߾駼UUU;#$K/> /Uc5 fsηv'MT\\Jϟ?< /u{l͚5 ]xGxW\q> IDATU~׼jϞ=>~6lxj>Iwy\pAz^{~wq7xcqqN7jÇo߾GqDnݞxiӦ};ߩ;Ųg1dȐ'Μ9s˖-ׯ:uԩS۷oꩧs9 <=cժU3f8 W\9cƌvo؀o}[3Ew6,xڥy֭+y_|qSu;cƌ۷oO?Fndhs5jԨ;{ ޹`뮻.e֭[y$IƎ[Lۧ/]`oѭ[ZK>wqI,Zɓ'o޼W^uSN;oX۷/]tw#ݻwC'?5jTЦMx/wr$>!%OR'xbݱ/a gϞַ$YlY֫yɫWڵkuD6ٳΪc Ip{>sn{_ro駟Nlٲm۶eeeÿ{'I+IZGI?_wz ׮]ȧ;Ȇs1W_}C=p}IO?/YuOWYb+$IIIɴirss>ƿN&8ӧ.Yd+!Iva?w_RԹ[1u9K/2d7߼e˖{.ef_wꙞ;UoR,_\RW͙ÇO8Svߵ}MӧO 39}={6JKKoΝ;Roe-28nC=_|ŒҎ;V_0xS,Dmذ!{TVV7nʔ)T*;;|߾}۵k3cƌy&˻KgϞ$… 39-[ON6-''g7n~M{v%_]_}39iz{ܠA^|$IҿU:uJ/w߈wݻ?ݼ /t[G]۶m$I׮]wzg֫z'DŽ $9餓v4j}M{+V$Iү_%!룏>JH#}K_ZvO>os=Ѵ-rǮ^i!/NM6{W$x`z̙316gΜ;4`۶m/R$7.iӦuӚIZ_b,Z(}q|d?>}$IQ.hȑIL:GiЁϒFo5`C%K̟?Gw17o /$ɰaҗk҃D OڴiZh̤j=>^aٟ~iRپ}{6msѪ_xᅇvgڰ]VTTTᆰC=!{I_~ĉ;COGI'C*y:SW7я>̙3;v8dȐw޽k׮۶m[fMQQٳST߾}\ve?֮]{ 7vizjϞ=sss?7x .؝ 4hI'W^Y|Ygn߾'h۷ׯߒ%K|ʣ:]v˗/z&K.=hР;Gݻwo߾u>)Sw\~ K38#}qc4Kls=tSO=c_|6m|]=#8~'KJJ>}]vܹguVͽkᄏsGyd#?೦EG$:uO>k֬%K4~ 6lȑͧ6$ԩSJKKwto?;NzZo{g޼y&M4iRNNN~~-[+r!vK.IR/rqq-R;͹ꪫ[><@:h{&g6m? {:'|}ߴ&|;ӭ[k.ѣW_]xЮ~W]u՝w9wXsrr4k_N*((~7ͯ~/| ;3G$999Gy / cƌ-e]vϝ;__rի׬YӡC={뤓Nz}_y啷zkٲe˗/0`>3|C9d7GնmC}狋+**{s9EEE;}~,X'tڵo߾w܈#y=>`rKII̙3O{ѳgO;5i_b>믿駟~뭷.]Jz1dȐ:wCҥM74mڴ_}ɒ%%%%;v֭!r'6|qΝokfÆ 7tӭ޺si'b+Y ڥ55RTmZ7ENݩoZVjjV_4C*8ƌ!hU4O'8p'8pn*7 v_~ ՍVQ2 j/c*7 v_&缼;] \pt)z@+fNpNpNpNpNpNpNpNpNp.7_RTEEEeee*pꑝ@\#JUTTdz ;QUUUUUm۶;,|͙.(,,XYX6o\VVQ@(//oeee4_ T*բmԴyT*Q@3h6jje{PƂ#}l=BEEPG+VQ2z8r`eJ:N(} y*7 v_/z'8p'8pzwǍ$_|衇fz8p7nݺu֭Kg<8֭[W{<8@pWk6G+?Ku(++2eʂ JJJVZץKݻvaC޽{ؐu]|UUUsO~Wկ~UTTtAWjۭYfƍo[T*p}٧ chM4iĉ7n^u 6,^7xn;,#lX.]>w}޺uk۶mwfYYo$Û^ͻo>vs=#n nƹs?>???9Ѭo$O:>}tܹlݺu+Vx뭷.]zAez;1bĈw}6l؎V{+**rssXa׿oߞ$… 8֖` ܼyewL`Gt/ISO=n]s1{۶m5kV11s$I8:4퍆 6k֬O?cm 9gy0`@(zW*++srroh_IuQsy7+**ꮳe˖#F4w~뭷6}-YguYgezY*ʕ+$ڵk+8HΈ[[o۶`Ȑ!Chv$'|RRR쮣:]vI̚5S>VPWJk w7xc֬Y+WOm֫W}s?_SO=5~$I={}s;vl-_:o޼Ҟ={>vځӁs1/rGU6o;$I2rz>mڴӧ/Zw6lQGUk7^pI^}sy饗>M6uԩGC>|xN>f?ܹs,Yy={>|̘1I,X`ʔ)WѣG;^}zF~w5]'#o.\8wܫ3=ztǎwu~|5Ϙ1K/= Go۶mƌw^YdIqqqVV։'Xp>mVڒ%K^}O?.jxsF/oٲeܹk۶mرcJXf􎴏>裏>zG}%4Ò$ٸq}ꫯV/Yzի$I4y3|W/Yxŋ.\xWN8K;$ҥK.]:gΜ+N~J;Jp4_yyy?O__Zz'L0hР!C 6GҥK׮]/~gϞ;w޴iӇ~OO:蠃Xw裏9sf1mڴ$I=К;?}x //oرÆ ڵkIIԩS}{n>SޜC9sׯ5kVHg9ḱWX}۶m[\\7߬<;WUU}׮]?P*8}m/#۷;k϶_~5OmfozҥK'I2}ʟg5{РAʦMvW?%jUFǍnݺuu]EEEuW(**뮻Ӥ5jwq^xL_`u]PGútr'IdɒꅇrH^$IE͚5Zpɛ7o8p`p1cƴif˖-NG>W0Ҋm֣G9+iO=T$cǎoݺuKoM+**~$IWF۷;ѵzGHΝk=ԧOt&.Z';ZVժZQTTtVUUejTws~=|_N!x~>7ۼv%YYY}J$}<N1{-mڴIOilLp 80ٳO{KVVV&IR3}5*i/7oޜ$NOS$IѨҺSoݺuy@KԪ\tEwuW35Y]tQ'K/2d7߼e˖{3Ϭ~׬Y~򊊊:nݺKsI?&M4iҎFU=˲aÇGnڴwM vر}T~$))))//odLڴiӻlӦM֌8*8<+n֬/|GiӦ{#(**0`@eeeIo߾S`s)vh$IOّ=MK@Ӫ#n+]uҷD z$Iʕ+oᆭ[9ϯCu)̚5kW\qE^^^xI'TkN:Zj_nw_>ٳgqS꽜y:Anݺf͚zwN,_<=z^-}"J}'ޑ= @ p 2+L_sTI,^8I6mڤ"u^z?ls_lo;w\׼zw7nܸNRTTTZZ:wܬ?j#&Ioust;찆߮zok{v3wI;GhqdɒhWͼy^x$I >>QYYkYӆ }ꩣӧOWRȑ#0׾֦Mnmg><;;{Æ <@*:蠃"kԩS_ZvSL7vz߿$=X4f&|wu-g4738:j#IG}k7g}> ꫷z__QQѷo+"~իWxKKK/_>gΜ믿~G; $=ztNNoΗZE뗾d;^KZfԩSw.] }Wo{%TTT\{? ֯_O>>J$IvvW\iӦjڴiغu|0nܸ=i]-ˈ}KndPkQӐ!CrrrҗjR`VN:tPZZ:uzW8ÿo$ɱ{1̙3wIߚ$ ܹ!C̙tҁwԕ>fĉ/$IڵkWQQU}ԩ˗/߶m[~w߳>]v5oGR)I;SvNvv1cF1y?xٲeׯڵ^{uGֽHhҗ ݶmG^8g?x7v׾ֻwƿI't?S/^dI*ٳg޽G/~1h3]MݺuǍx⼼{UjY˖-oȫ8 ^)ԫ] ۵kKOiԩ,ׯ?o߾u]z'o۶mYYYYYYi69ڶm[QQQYYJ:@󗝝kfUTTa&)@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8@8gBVg]~~/~c+cVhʕ&LLϴLϺoG?Q2=h:t0lذ^z)c32lʕ={([jdVvg3=hRTg &L!@hd9dث׿8 Š+瞟vrЙ+IENDB`vvmplayer-2.5/data/org.kop316.vvmplayer-daemon.desktop.in.in000066400000000000000000000004401456573503400240330ustar00rootroot00000000000000[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; NoDisplay=true X-GNOME-AutoRestart=true vvmplayer-2.5/data/org.kop316.vvmplayer.desktop.in.in000066400000000000000000000010221456573503400225670ustar00rootroot00000000000000[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-2.5/data/org.kop316.vvmplayer.gschema.xml000066400000000000000000000016421456573503400223220ustar00rootroot00000000000000 "" 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 Dark Theme Dark Theme Enabled. vvmplayer-2.5/data/org.kop316.vvmplayer.service.in000066400000000000000000000001311456573503400221510ustar00rootroot00000000000000[D-BUS Service] Name=org.kop316.vvmplayer Exec=@bindir@/vvmplayer --gapplication-service vvmplayer-2.5/meson.build000066400000000000000000000100151456573503400155600ustar00rootroot00000000000000project('vvmplayer', 'c', version: '2.5', meson_version: '>= 0.56.0', default_options: [ 'warning_level=2', 'werror=false', 'c_std=gnu11', ], ) 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.project_source_root() pkg_builddir = meson.project_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') i18n = import('i18n') gnome = import('gnome') cc = meson.get_compiler('c') config_h = configuration_data() config_h.set_quoted('PACKAGE_VERSION', meson.project_version()) config_h.set_quoted('GETTEXT_PACKAGE', 'vvmplayer') config_h.set_quoted('LOCALEDIR', join_paths(get_option('prefix'), get_option('localedir'))) config_h.set('NDEBUG', (not pkg_is_debug)) config_h.set('G_DISABLE_ASSERT', (not pkg_is_debug)) config_h.set('G_DISABLE_CAST_CHECKS', (not pkg_is_debug)) config_h.set_quoted('GETTEXT_PACKAGE', pkg_name) config_h.set_quoted('PACKAGE_NAME', pkg_name) config_h.set_quoted('PACKAGE_ID', pkg_id) config_h.set_quoted('PACKAGE_LOCALE_DIR', pkg_localedir) configure_file(output: 'config.h', configuration: config_h) add_project_arguments([ '-I' + meson.project_build_root(), '-DHAVE_CONFIG_H', ], language: 'c') project_c_args = [] test_c_args = [ '-Wcast-align', '-Wdeclaration-after-statement', '-Werror=address', '-Werror=array-bounds', '-Werror=empty-body', '-Werror=implicit', '-Werror=implicit-function-declaration', '-Werror=incompatible-pointer-types', '-Werror=init-self', '-Werror=int-conversion', '-Werror=int-to-pointer-cast', '-Werror=main', '-Werror=misleading-indentation', '-Werror=missing-braces', '-Werror=missing-include-dirs', '-Werror=nonnull', '-Werror=overflow', '-Werror=parenthesis', '-Werror=pointer-arith', '-Werror=pointer-to-int-cast', '-Werror=redundant-decls', '-Werror=return-type', '-Werror=sequence-point', '-Werror=shadow', '-Werror=strict-prototypes', '-Werror=trigraphs', '-Werror=undef', '-Werror=write-strings', '-Wformat-nonliteral', '-Wignored-qualifiers', '-Wimplicit-function-declaration', '-Wlogical-op', '-Wmissing-declarations', '-Wmissing-format-attribute', '-Wmissing-include-dirs', '-Wmissing-noreturn', '-Wnested-externs', '-Wno-cast-function-type', '-Wno-dangling-pointer', '-Wno-missing-field-initializers', '-Wno-sign-compare', '-Wno-unused-parameter', '-Wold-style-definition', '-Wpointer-arith', '-Wredundant-decls', '-Wstrict-prototypes', '-Wswitch-default', '-Wswitch-enum', '-Wundef', '-Wuninitialized', '-Wunused', '-fno-strict-aliasing', ['-Werror=format-security', '-Werror=format=2'], ] if get_option('buildtype') != 'plain' test_c_args += '-fstack-protector-strong' endif foreach arg: test_c_args if cc.has_multi_arguments(arg) project_c_args += arg endif endforeach add_project_arguments(project_c_args, language: 'c') run_data = configuration_data() run_data.set('ABS_BUILDDIR', meson.current_build_dir()) run_data.set('ABS_SRCDIR', meson.current_source_dir()) configure_file( input: 'run.in', output: 'run', configuration: run_data) subdir('data') subdir('src') subdir('po') # gnome.post_install() is available since meson 0.59.0 # Distributions use their own tooling (e.g. postinst, triggers, etc) # so it is okay if the post_install() is not run on distro builds if meson.version().version_compare('>=0.59.0') gnome.post_install( glib_compile_schemas: true, gtk_update_icon_cache: true, update_desktop_database: true, ) else meson.add_install_script('build-aux/meson_post_install.py') endif vvmplayer-2.5/org.kop316.vvmplayer.json000066400000000000000000000015571456573503400201610ustar00rootroot00000000000000{ "app-id" : "org.kop316.vvmplayer", "runtime" : "org.gnome.Platform", "runtime-version" : "master", "sdk" : "org.gnome.Sdk", "command" : "vvmplayer", "finish-args" : [ "--share=network", "--share=ipc", "--socket=fallback-x11", "--device=dri", "--socket=wayland" ], "cleanup" : [ "/include", "/lib/pkgconfig", "/man", "/share/doc", "/share/gtk-doc", "/share/man", "/share/pkgconfig", "*.la", "*.a" ], "modules" : [ { "name" : "vvmplayer", "builddir" : true, "buildsystem" : "meson", "sources" : [ { "type" : "git", "url" : "https://gitlab.com/kop316/vvmplayer.git" } ] } ] } vvmplayer-2.5/po/000077500000000000000000000000001456573503400140375ustar00rootroot00000000000000vvmplayer-2.5/po/LINGUAS000066400000000000000000000000001456573503400150520ustar00rootroot00000000000000vvmplayer-2.5/po/POTFILES000066400000000000000000000005661456573503400152160ustar00rootroot00000000000000data/org.kop316.vvmplayer.desktop.in data/org.kop316.vvmplayer.appdata.xml.in data/org.kop316.vvmplayer.gschema.xml src/main.c src/vvmplayer-contact.c src/vvmplayer-notification.c src/vvmplayer-preferences-window.c src/vvmplayer-voicemail-window.c src/vvmplayer-window.c src/ui/vvmplayer-preferences-window.ui src/ui/vvmplayer-voicemail-window.ui src/ui/vvmplayer-window.ui vvmplayer-2.5/po/meson.build000066400000000000000000000000521456573503400161760ustar00rootroot00000000000000i18n.gettext('vvmplayer', preset: 'glib') vvmplayer-2.5/run.in000077500000000000000000000006101456573503400145550ustar00rootroot00000000000000#!/bin/bash set -e ABS_BUILDDIR='@ABS_BUILDDIR@' ABS_SRCDIR='@ABS_SRCDIR@' if [ "${PHOSH_ANTISPAM_GDB}" = 1 ]; then echo "Running vvmplayer under gdb" WRAPPER="gdb --directory=${ABS_BUILDDIR}/src --args" fi export GSETTINGS_SCHEMA_DIR="${ABS_BUILDDIR}/data" set -x export MALLOC_PERTURB_="$(($RANDOM % 255 + 1))" MALLOC_CHECK_=2 exec ${WRAPPER} "${ABS_BUILDDIR}/src/vvmplayer" "$@"vvmplayer-2.5/src/000077500000000000000000000000001456573503400142105ustar00rootroot00000000000000vvmplayer-2.5/src/main.c000066400000000000000000000027231456573503400153040ustar00rootroot00000000000000/* main.c * * Copyright 2021-2022 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 . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "config.h" #include #include #include "vvmplayer-application.h" int main (int argc, char *argv[]) { g_autoptr(VvmplayerApplication) app = NULL; int ret; /* Initialize GStreamer */ gst_init (&argc, &argv); bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); textdomain (GETTEXT_PACKAGE); // Use G_APPLICATION_DEFAULT_FLAGS for GLIB 2.74 or higher #if GLIB_CHECK_VERSION (2, 74, 0) app = vvmplayer_application_new (PACKAGE_ID, G_APPLICATION_DEFAULT_FLAGS); #else app = vvmplayer_application_new (PACKAGE_ID, G_APPLICATION_FLAGS_NONE); #endif ret = g_application_run (G_APPLICATION (app), argc, argv); return ret; } vvmplayer-2.5/src/meson.build000066400000000000000000000017561456573503400163630ustar00rootroot00000000000000vvmplayer_sources = [ 'main.c', 'vvmplayer-application.c', 'vvmplayer-contact.c', 'vvmplayer-contact-provider.c', 'vvmplayer-debug-info.c', 'vvmplayer-notification.c', 'vvmplayer-preferences-window.c', 'vvmplayer-settings.c', 'vvmplayer-voicemail-window.c', 'vvmplayer-vvmd.c', 'vvmplayer-window.c', ] vvmplayer_deps = [ dependency('gtk4', version : '>=4.10'), dependency('libadwaita-1', version : '>=1.2.0'), dependency('libebook-contacts-1.2'), dependency('libebook-1.2'), dependency('gstreamer-1.0', version : '>1.16'), dependency('gstreamer-pbutils-1.0', version : '>1.0'), dependency('libcallaudio-0.1'), ] revision_tag = vcs_tag( input: 'version.h.in', output: 'version.h', ) vvmplayer_deps += declare_dependency(sources: revision_tag) vvmplayer_sources += gnome.compile_resources('vvmplayer-resources', 'vvmplayer.gresource.xml', c_name: 'vvmplayer' ) executable('vvmplayer', vvmplayer_sources, dependencies: vvmplayer_deps, install: true, ) vvmplayer-2.5/src/ui/000077500000000000000000000000001456573503400146255ustar00rootroot00000000000000vvmplayer-2.5/src/ui/vvmplayer-preferences-window.ui000066400000000000000000000275221456573503400230250ustar00rootroot00000000000000 vvmplayer-2.5/src/ui/vvmplayer-voicemail-window.ui000066400000000000000000000105731456573503400224720ustar00rootroot00000000000000 vvmplayer-2.5/src/ui/vvmplayer-window.ui000066400000000000000000000061011456573503400205140ustar00rootroot00000000000000
_Preferences app.preferences _About Visual Voicemail app.about
vvmplayer-2.5/src/version.h.in000066400000000000000000000015721456573503400164600ustar00rootroot00000000000000/* version.h.in * * Copyright 2021-2022 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-2.5/src/vvmplayer-application.c000066400000000000000000000210701456573503400207020ustar00rootroot00000000000000/* vvmplayer-application.c * * Copyright 2021-2022 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 . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "config.h" #include "version.h" #include "vvmplayer-application.h" #include "vvmplayer-debug-info.h" #include "vvmplayer-preferences-window.h" #include "vvmplayer-settings.h" #include "vvmplayer-window.h" #include "vvmplayer-vvmd.h" struct _VvmplayerApplication { AdwApplication parent_instance; gboolean daemon; gboolean daemon_running; GtkWindow *main_window; gboolean app_debug; VvmVvmd *backend; VvmSettings *settings; }; G_DEFINE_TYPE (VvmplayerApplication, vvmplayer_application, ADW_TYPE_APPLICATION) enum { SIGNAL_MAIN_WINDOW_CLOSED, N_SIGNALS }; static guint signals[N_SIGNALS]; VvmplayerApplication * vvmplayer_application_new (const char *application_id, GApplicationFlags flags) { g_return_val_if_fail (application_id != NULL, NULL); return g_object_new (VVMPLAYER_TYPE_APPLICATION, "application-id", application_id, "flags", flags, NULL); } static int vvmplayer_handle_local_options (GApplication *application, GVariantDict *options) { VvmplayerApplication *self = (VvmplayerApplication *)application; if (g_variant_dict_contains (options, "version")) { g_print ("%s, git version: %s\n", PACKAGE_VERSION, PACKAGE_VCS_VERSION); return 0; } if (g_variant_dict_contains (options, "debug")) { g_setenv ("G_MESSAGES_DEBUG", "all", TRUE); self->app_debug = TRUE; } self->daemon = FALSE; self->app_debug = FALSE; if (g_variant_dict_contains (options, "daemon")) { /* Hold application only the first time daemon mode is set */ if (!self->daemon) g_application_hold (application); self->daemon = TRUE; g_debug ("Application marked as daemon"); } return -1; } static void vvmplayer_application_startup (GApplication *application) { VvmplayerApplication *self = (VvmplayerApplication *)application; g_info ("%s %s, git version: %s", PACKAGE_NAME, PACKAGE_VERSION, PACKAGE_VCS_VERSION); G_APPLICATION_CLASS (vvmplayer_application_parent_class)->startup (application); g_set_application_name ("Visual Voicemail"); gtk_window_set_default_icon_name (PACKAGE_ID); self->backend = vvm_vvmd_get_default (); self->settings = vvm_settings_get_default (); } static gboolean on_widget_deleted (GtkWidget *widget, GdkEvent *event, gpointer data) { /* Passing app through g_signal_connect causes a segfault, so just find the default */ VvmplayerApplication *self = (VvmplayerApplication *)g_application_get_default (); g_autoptr(GError) error = NULL; gboolean ret; /* If we are not running in daemon mode, hide the window and reset speaker button */ if (self->daemon) vvmplayer_window_set_speaker_button (VVMPLAYER_WINDOW (self->main_window), FALSE); g_signal_emit (self, signals[SIGNAL_MAIN_WINDOW_CLOSED], 0); /* Set audio profile back to default whether you are quitting or closing the window */ 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 FALSE; } static void vvmplayer_application_activate (GApplication *app) { VvmplayerApplication *self = (VvmplayerApplication *)app; if (!self->main_window) { self->main_window = g_object_new (VVMPLAYER_TYPE_WINDOW, "application", app, NULL); g_object_add_weak_pointer (G_OBJECT (self->main_window), (gpointer *)&self->main_window); g_signal_connect (G_OBJECT (self->main_window), "close_request", G_CALLBACK (on_widget_deleted), NULL); } if ((!self->daemon && !self->daemon_running) || (self->daemon_running)) gtk_window_present (GTK_WINDOW (self->main_window)); else { self->daemon_running = TRUE; gtk_window_set_hide_on_close (GTK_WINDOW (self->main_window), self->daemon_running); } } static void vvmplayer_application_finalize (GObject *object) { VvmplayerApplication *self = (VvmplayerApplication *)object; g_debug ("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 (VvmplayerApplicationClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GApplicationClass *app_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; app_class->handle_local_options = vvmplayer_handle_local_options; app_class->startup = vvmplayer_application_startup; app_class->activate = vvmplayer_application_activate; } static void vvmplayer_application_show_preferences (GSimpleAction *action, GVariant *state, gpointer user_data) { GtkApplication *app = GTK_APPLICATION (user_data); GtkWindow *window = gtk_application_get_active_window (app); VvmplayerPreferencesWindow *preferences = vvm_player_preferences_window_new (); gtk_window_set_transient_for (GTK_WINDOW (preferences), window); gtk_window_present (GTK_WINDOW (preferences)); } static void vvmplayer_application_about_action (GSimpleAction *action, GVariant *parameter, gpointer user_data) { static const char *developers[] = {"Chris Talbot https://www.gitlab.com/kop316/", NULL}; static const char *artists[] = {"Asiya Morris ", NULL}; VvmplayerApplication *self = (VvmplayerApplication *)user_data; GtkWindow *window = NULL; g_autofree char *debug_info = NULL; g_assert (VVMPLAYER_IS_APPLICATION (self)); window = gtk_application_get_active_window (GTK_APPLICATION (self)); debug_info = vvm_generate_debug_info (); adw_show_about_window (window, "application-name", "Visual Voicemail", "application-icon", PACKAGE_ID, "version", PACKAGE_VCS_VERSION, "developers", developers, "artists", artists, "copyright", "© 2021-2022 Chris Talbot", "website", "https://gitlab.com/kop316/vvmplayer", "issue-url", "https://gitlab.com/kop316/vvmplayer/-/issues", "support-url", "https://gitlab.com/kop316/vvmplayer/-/wikis/home", "debug-info", debug_info, "license-type", GTK_LICENSE_GPL_3_0, NULL); } static GOptionEntry cmd_options[] = { { "daemon", 0, G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, NULL, ("Whether to present the main window on startup"), NULL }, { "debug", 'd', 0, G_OPTION_ARG_NONE, G_OPTION_ARG_NONE, "Enable debugging output"}, { "version", 'v', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, NULL, ("Show release version"), NULL }, { NULL } }; static const GActionEntry app_actions[] = { { "about", vvmplayer_application_about_action }, { "preferences", vvmplayer_application_show_preferences, NULL, NULL, NULL }, }; static void vvmplayer_application_init (VvmplayerApplication *self) { g_action_map_add_action_entries (G_ACTION_MAP (self), app_actions, G_N_ELEMENTS (app_actions), self); g_application_add_main_option_entries (G_APPLICATION (self), cmd_options); } vvmplayer-2.5/src/vvmplayer-application.h000066400000000000000000000022221456573503400207050ustar00rootroot00000000000000/* vvmplayer-application.h * * Copyright 2021-2022 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 . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include G_BEGIN_DECLS #define VVMPLAYER_TYPE_APPLICATION (vvmplayer_application_get_type ()) G_DECLARE_FINAL_TYPE (VvmplayerApplication, vvmplayer_application, VVMPLAYER, APPLICATION, AdwApplication) VvmplayerApplication *vvmplayer_application_new (const char *application_id, GApplicationFlags flags); G_END_DECLS vvmplayer-2.5/src/vvmplayer-contact-provider.c000066400000000000000000000317211456573503400216660ustar00rootroot00000000000000/* -*- 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) { GListModel *model; guint n_items; gboolean match; g_return_val_if_fail (VVM_IS_EDS (self), NULL); 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-2.5/src/vvmplayer-contact-provider.h000066400000000000000000000026651456573503400217000ustar00rootroot00000000000000/* -*- 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-2.5/src/vvmplayer-contact.c000066400000000000000000000117511456573503400200370ustar00rootroot00000000000000/* -*- 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-2.5/src/vvmplayer-contact.h000066400000000000000000000042631456573503400200440ustar00rootroot00000000000000/* -*- 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-2.5/src/vvmplayer-debug-info.c000066400000000000000000000146111456573503400204210ustar00rootroot00000000000000/* vvmplayer-debug-info.h * * Copyright 2017–2022 Purism SPC * 2021-2023 Chris Talbot * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * SPDX-License-Identifier: LGPL-2.1-or-later */ #include "config.h" #include "version.h" #include "vvmplayer-debug-info.h" /* Copied and adapted from https://gitlab.gnome.org/GNOME/libadwaita/-/raw/main/demo/adw-demo-debug-info.c */ static void get_gtk_info (const char **backend, const char **renderer) { GdkDisplay *display = gdk_display_get_default (); GdkSurface *surface; GskRenderer *gsk_renderer; if (!g_strcmp0 (G_OBJECT_TYPE_NAME (display), "GdkX11Display")) *backend = "X11"; else if (!g_strcmp0 (G_OBJECT_TYPE_NAME (display), "GdkWaylandDisplay")) *backend = "Wayland"; else if (!g_strcmp0 (G_OBJECT_TYPE_NAME (display), "GdkBroadwayDisplay")) *backend = "Broadway"; else if (!g_strcmp0 (G_OBJECT_TYPE_NAME (display), "GdkWin32Display")) *backend = "Windows"; else if (!g_strcmp0 (G_OBJECT_TYPE_NAME (display), "GdkMacosDisplay")) *backend = "macOS"; else *backend = G_OBJECT_TYPE_NAME (display); surface = gdk_surface_new_toplevel (display); gsk_renderer = gsk_renderer_new_for_surface (surface); if (!g_strcmp0 (G_OBJECT_TYPE_NAME (gsk_renderer), "GskVulkanRenderer")) *renderer = "Vulkan"; else if (!g_strcmp0 (G_OBJECT_TYPE_NAME (gsk_renderer), "GskGLRenderer")) *renderer = "GL"; else if (!g_strcmp0 (G_OBJECT_TYPE_NAME (gsk_renderer), "GskCairoRenderer")) *renderer = "Cairo"; else *renderer = G_OBJECT_TYPE_NAME (gsk_renderer); gsk_renderer_unrealize (gsk_renderer); g_object_unref (gsk_renderer); gdk_surface_destroy (surface); } char * vvm_generate_debug_info (void) { GString *string = g_string_new (NULL); g_string_append_printf (string, "vvmplayer: %s\n", PACKAGE_VCS_VERSION); g_string_append (string, "\n"); g_string_append (string, "Compiled against:\n"); g_string_append_printf (string, "- GLib: %d.%d.%d\n", GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION); g_string_append_printf (string, "- GTK: %d.%d.%d\n", GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION); g_string_append_printf (string, "- LibAdwaita: %d.%d.%d\n", ADW_MAJOR_VERSION, ADW_MINOR_VERSION, ADW_MICRO_VERSION); g_string_append (string, "\n"); g_string_append (string, "Running against:\n"); g_string_append_printf (string, "- GLib: %d.%d.%d\n", glib_major_version, glib_minor_version, glib_micro_version); g_string_append_printf (string, "- GTK: %d.%d.%d\n", gtk_get_major_version (), gtk_get_minor_version (), gtk_get_micro_version ()); g_string_append_printf (string, "- Libadwaita: %d.%d.%d\n", adw_get_major_version (), adw_get_minor_version (), adw_get_micro_version ()); g_string_append (string, "\n"); { char *os_name = g_get_os_info (G_OS_INFO_KEY_NAME); char *os_version = g_get_os_info (G_OS_INFO_KEY_VERSION); g_string_append (string, "System:\n"); g_string_append_printf (string, "- Name: %s\n", os_name); g_string_append_printf (string, "- Version: %s\n", os_version); g_string_append (string, "\n"); g_free (os_name); g_free (os_version); } { const char *backend, *renderer; get_gtk_info (&backend, &renderer); g_string_append (string, "GTK:\n"); g_string_append_printf (string, "- GDK backend: %s\n", backend); g_string_append_printf (string, "- GSK renderer: %s\n", renderer); g_string_append (string, "\n"); } { const char *desktop = g_getenv ("XDG_CURRENT_DESKTOP"); const char *session_desktop = g_getenv ("XDG_SESSION_DESKTOP"); const char *session_type = g_getenv ("XDG_SESSION_TYPE"); const char *lang = g_getenv ("LANG"); const char *builder = g_getenv ("INSIDE_GNOME_BUILDER"); const char *gtk_debug = g_getenv ("GTK_DEBUG"); const char *gtk_theme = g_getenv ("GTK_THEME"); const char *adw_debug_color_scheme = g_getenv ("ADW_DEBUG_COLOR_SCHEME"); const char *adw_debug_high_contrast = g_getenv ("ADW_DEBUG_HIGH_CONTRAST"); const char *adw_disable_portal = g_getenv ("ADW_DISABLE_PORTAL"); g_string_append (string, "Environment:\n"); g_string_append_printf (string, "- Desktop: %s\n", desktop); g_string_append_printf (string, "- Session: %s (%s)\n", session_desktop, session_type); g_string_append_printf (string, "- Language: %s\n", lang); g_string_append_printf (string, "- Running inside Builder: %s\n", builder ? "yes" : "no"); if (gtk_debug) g_string_append_printf (string, "- GTK_DEBUG: %s\n", gtk_debug); if (gtk_theme) g_string_append_printf (string, "- GTK_THEME: %s\n", gtk_theme); if (adw_debug_color_scheme) g_string_append_printf (string, "- ADW_DEBUG_COLOR_SCHEME: %s\n", adw_debug_color_scheme); if (adw_debug_high_contrast) g_string_append_printf (string, "- ADW_DEBUG_HIGH_CONTRAST: %s\n", adw_debug_high_contrast); if (adw_disable_portal) g_string_append_printf (string, "- ADW_DISABLE_PORTAL: %s\n", adw_disable_portal); } return g_string_free (string, FALSE); } vvmplayer-2.5/src/vvmplayer-debug-info.h000066400000000000000000000021271456573503400204250ustar00rootroot00000000000000/* vvmplayer-debug-info.h * * Copyright 2017–2022 Purism SPC * 2021-2023 Chris Talbot * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once #include /* Copied and adapted from https://gitlab.gnome.org/GNOME/libadwaita/-/raw/main/demo/adw-demo-debug-info.c */ G_BEGIN_DECLS char *vvm_generate_debug_info (void); G_END_DECLS vvmplayer-2.5/src/vvmplayer-notification.c000066400000000000000000000045561456573503400210770ustar00rootroot00000000000000/* -*- 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 #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; g_autofree char *title = NULL; g_autofree char *body = NULL; 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"); body = g_strdup_printf (g_dngettext (GETTEXT_PACKAGE, "You have %d new voicemail", "You have %d new voicemails", unread_vvms), 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); } void vvmplayer_notification_withdraw_unread_vvm (void) { GApplication *vvm_player = g_application_get_default (); g_application_withdraw_notification (vvm_player, "unread-message"); } vvmplayer-2.5/src/vvmplayer-notification.h000066400000000000000000000021271456573503400210740ustar00rootroot00000000000000/* -*- 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); void vvmplayer_notification_withdraw_unread_vvm (void); G_END_DECLS vvmplayer-2.5/src/vvmplayer-preferences-window.c000066400000000000000000000544501456573503400222150ustar00rootroot00000000000000/* vvmplayer-preferences-window.h * * Copyright 2021-2022 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 . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include #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 _VvmplayerPreferencesWindow { AdwPreferencesWindow parent_instance; //Refresh GtkButton *refresh_settings_button; //Enable VVM GtkSwitch *enable_vvm_switch; AdwActionRow *enable_vvm_text; //Appearance Settings AdwActionRow *enable_dark_theme_row; GtkSwitch *enable_dark_theme_switch; //Status GtkImage *vvmd_enabled_image; GtkImage *mailbox_active_image; AdwActionRow *provision_status_text; //Activate GtkButton *activate_vvm_button; //Sync GtkButton *sync_vvm_button; //Modem Manager Settings GtkEntry *destination_number_text; GtkEntryBuffer *destination_number_text_buffer; GtkEntry *modem_number_text; GtkEntryBuffer *modem_number_text_buffer; AdwActionRow *carrier_prefix_text_row; GtkEntry *carrier_prefix_text; GtkEntryBuffer *carrier_prefix_text_buffer; AdwComboRow *vvm_type_combo_row; //Spam Contact GtkSwitch *spam_contact_switch; GtkEntry *spam_contact_text; GtkEntryBuffer *spam_contact_text_buffer; //Watch ID gulong vvm_settings_watch_id; }; G_DEFINE_TYPE (VvmplayerPreferencesWindow, vvm_player_preferences_window, ADW_TYPE_PREFERENCES_WINDOW) static void update_settings_cb (VvmplayerPreferencesWindow *self); static void vvm_preferences_display_toast (const char *title, VvmplayerPreferencesWindow *self) { AdwToast *toast = adw_toast_new (title); adw_preferences_window_add_toast (ADW_PREFERENCES_WINDOW (self), toast); adw_toast_set_timeout (toast, 1); } static void spam_contact_text_button_clicked_cb (GtkButton *btn, VvmplayerPreferencesWindow *self) { VvmSettings *settings = vvm_settings_get_default (); const char *new_contact; new_contact = gtk_entry_buffer_get_text (self->spam_contact_text_buffer); vvm_settings_set_spam_contact (settings, new_contact); } static gboolean spam_contact_switch_flipped_cb (GtkSwitch *widget, gboolean contact_switch_bool, VvmplayerPreferencesWindow *self) { VvmSettings *settings = vvm_settings_get_default (); vvmplayer_settings_set_spam_contact_enabled (settings, contact_switch_bool); return FALSE; } static void vvm_type_selected_cb (GObject *sender, GParamSpec *pspec, VvmplayerPreferencesWindow *self) { VvmVvmd *backend = vvm_vvmd_get_default (); VvmSettings *settings = vvm_settings_get_default (); int row_selected; row_selected = adw_combo_row_get_selected (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!"); adw_combo_row_set_selected (self->vvm_type_combo_row, VVM_TYPE_UNKNOWN); } else { if (row_selected == VVM_TYPE_ATTUSA) { adw_preferences_row_set_title (ADW_PREFERENCES_ROW (self->carrier_prefix_text_row), _("AT&T USA Number (No dashes or spaces)")); gtk_entry_set_placeholder_text (self->carrier_prefix_text, _("AT&T USA Number (No dashes or spaces)")); } else { adw_preferences_row_set_title (ADW_PREFERENCES_ROW (self->carrier_prefix_text_row), _("Carrier Prefix")); gtk_entry_set_placeholder_text (self->carrier_prefix_text, _("Carrier Prefix")); } } } else { vvm_preferences_display_toast ("Cannot Find VVMD", self); adw_combo_row_set_selected (self->vvm_type_combo_row, VVM_TYPE_UNKNOWN); } } static gboolean enable_theme_switch_flipped_cb (GtkSwitch *widget, gboolean prefer_dark_theme, VvmplayerPreferencesWindow *self) { VvmSettings *settings = vvm_settings_get_default (); vvmplayer_settings_set_dark_theme (settings, prefer_dark_theme); return FALSE; } static void refresh_settings_button_clicked_cb (GtkButton *btn, VvmplayerPreferencesWindow *self) { vvm_preferences_display_toast (_("Refreshing Settings"), self); update_settings_cb (self); } static void set_destination_number (VvmplayerPreferencesWindow *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_buffer_get_text (self->destination_number_text_buffer); vvm_settings_set_vvm_destination_number (settings, dest_number); if (vvmplayer_vvmd_set_mm_setting (backend, "VVMDestinationNumber", dest_number) == FALSE) vvm_preferences_display_toast ("Changing setting failed", self); } else g_warning ("VVMD Modem Manager settings not available!"); } static void set_default_modem_number (VvmplayerPreferencesWindow *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_buffer_get_text (self->modem_number_text_buffer); 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) vvm_preferences_display_toast (_("Changing setting failed"), self); } else g_warning ("VVMD Modem Manager settings not available!"); } static void set_carrier_prefix (VvmplayerPreferencesWindow *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_buffer_get_text (self->carrier_prefix_text_buffer); vvm_settings_set_vvm_carrier_prefix (settings, carrier_prefix); if (vvmplayer_vvmd_set_mm_setting (backend, "CarrierPrefix", carrier_prefix) == FALSE) { g_warning ("Error changing setting in vvmd!"); vvm_preferences_display_toast (_("Changing setting failed"), self); } } else g_warning ("VVMD Modem Manager settings not available!"); } static gboolean enable_vvm_switch_timeout (gpointer user_data) { VvmplayerPreferencesWindow *self = user_data; VvmSettings *settings = vvm_settings_get_default (); int VVMActive; int EnableVVMSwitch = gtk_switch_get_state (self->enable_vvm_switch); const char *toast_message = NULL; gtk_widget_set_sensitive (GTK_WIDGET (self->enable_vvm_switch), TRUE); update_settings_cb (self); VVMActive = vvm_settings_get_mailbox_active (settings); if (!VVMActive && !EnableVVMSwitch) toast_message = _("VVM Disabled"); else if (!VVMActive && EnableVVMSwitch) toast_message = _("Could not enable VVM"); else if (VVMActive && !EnableVVMSwitch) toast_message = _("Could not disable VVM"); else if (VVMActive && EnableVVMSwitch) toast_message = _("VVM Enabled"); vvm_preferences_display_toast (toast_message, self); return FALSE; } static gboolean enable_vvm_switch_flipped_cb (GtkSwitch *widget, gboolean state, VvmplayerPreferencesWindow *self) { VvmSettings *settings = vvm_settings_get_default (); int VVMEnabled = vvm_settings_get_vvm_enabled (settings); VvmVvmd *backend = vvm_vvmd_get_default (); if (VVMEnabled == state) return FALSE; gtk_widget_set_sensitive (GTK_WIDGET (widget), FALSE); if (vvm_settings_get_mm_available (settings) == FALSE) { g_debug ("Cannot find vvmd!"); vvm_preferences_display_toast (_("Cannot find vvmd"), self); g_timeout_add_seconds (2, enable_vvm_switch_timeout, self); return FALSE; } if (state) { g_debug ("Enabling VVM"); vvm_preferences_display_toast (_("Enabling VVM…"), self); set_destination_number (self); set_default_modem_number (self); set_carrier_prefix (self); } else { g_debug ("Disabling VVM"); vvm_preferences_display_toast (_("Disabling VVM…"), self); } g_timeout_add_seconds (10, enable_vvm_switch_timeout, self); vvmplayer_vvmd_set_mm_vvm_enabled (backend, state); return FALSE; } static gboolean activate_vvm_button_timeout (gpointer user_data) { VvmplayerPreferencesWindow *self = user_data; VvmSettings *settings = vvm_settings_get_default (); int VVMActive = vvm_settings_get_mailbox_active (settings); int EnableVVMSwitch = gtk_switch_get_state (self->enable_vvm_switch); const char *toast_message = NULL; gtk_widget_set_sensitive (GTK_WIDGET (self->activate_vvm_button), TRUE); update_settings_cb (self); if (!VVMActive && !EnableVVMSwitch) toast_message = _("VVM Disabled"); else if (!VVMActive && EnableVVMSwitch) toast_message = _("Could not activate VVM"); else if (VVMActive && !EnableVVMSwitch) toast_message = _("Could not deactivate VVM"); else if (VVMActive && EnableVVMSwitch) toast_message = _("VVM Enabled"); vvm_preferences_display_toast (toast_message, self); return FALSE; } static void activate_vvm_button_clicked_cb (GtkButton *btn, VvmplayerPreferencesWindow *self) { VvmSettings *settings = vvm_settings_get_default (); int VVMEnabled = vvm_settings_get_vvm_enabled (settings); int MailboxActive = vvm_settings_get_mailbox_active (settings); VvmVvmd *backend = vvm_vvmd_get_default (); if (vvm_settings_get_mm_available (settings) == FALSE) { g_debug ("Cannot find VVMD!"); vvm_preferences_display_toast (_("Cannot find VVMD"), self); return; } if (VVMEnabled == FALSE) { g_debug ("VVM not Active!"); vvm_preferences_display_toast (_("VVM not enabled in VVM Player"), self); return; } if (MailboxActive == TRUE) { g_debug ("Mailbox already Active!"); vvm_preferences_display_toast (_("Mailbox already active"), self); return; } g_debug ("Activating VVM....."); vvm_preferences_display_toast (_("Activating VVM"), self); gtk_widget_set_sensitive (GTK_WIDGET (self->activate_vvm_button), FALSE); g_timeout_add_seconds (10, activate_vvm_button_timeout, self); set_destination_number (self); set_default_modem_number (self); set_carrier_prefix (self); vvmplayer_vvmd_check_subscription_status (backend); } static gboolean sync_vvm_button_timeout (gpointer user_data) { VvmplayerPreferencesWindow *self = user_data; gtk_widget_set_sensitive (GTK_WIDGET (self->sync_vvm_button), TRUE); return FALSE; } static void sync_vvm_button_clicked_cb (GtkButton *btn, VvmplayerPreferencesWindow *self) { VvmSettings *settings = vvm_settings_get_default (); int VVMEnabled = vvm_settings_get_vvm_enabled (settings); int MailboxActive = vvm_settings_get_mailbox_active (settings); VvmVvmd *backend = vvm_vvmd_get_default (); if (vvm_settings_get_mm_available (settings) == FALSE) { g_debug ("Cannot find vvmd!"); vvm_preferences_display_toast (_("Cannot find VVMD"), self); return; } if (VVMEnabled == FALSE) { g_debug ("VVM not Active!"); vvm_preferences_display_toast (_("VVM not enabled"), self); return; } if (MailboxActive == FALSE) { g_debug ("Mailbox not Active!"); vvm_preferences_display_toast (_("Mailbox not active"), self); return; } g_debug ("Syncing VVM....."); vvm_preferences_display_toast (_("Syncing…"), self); gtk_widget_set_sensitive (GTK_WIDGET (self->sync_vvm_button), FALSE); g_timeout_add_seconds (10, sync_vvm_button_timeout, self); vvmplayer_vvmd_sync_vvm (backend); } static void vvm_preferences_window_populate (VvmplayerPreferencesWindow *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; //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_buffer_set_text (self->spam_contact_text_buffer, VVMSpamContact, -1); prefer_dark_theme = vvmplayer_settings_get_dark_theme (settings); 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_buffer_set_text (self->destination_number_text_buffer, VVMDestinationNumber, -1); else gtk_entry_buffer_set_text (self->destination_number_text_buffer, "", -1); VVMDefaultModemNumber = vvm_settings_get_vvm_default_number (settings); if (g_strcmp0 (VVMDefaultModemNumber, "NULL") != 0) //Don't populate invalid settings gtk_entry_buffer_set_text (self->modem_number_text_buffer, VVMDefaultModemNumber, -1); else gtk_entry_buffer_set_text (self->modem_number_text_buffer, "", -1); VVMCarrierPrefix = vvm_settings_get_vvm_carrier_prefix (settings); if (strstr (VVMCarrierPrefix, "invalid") == NULL) //Don't populate invalid settings gtk_entry_buffer_set_text (self->carrier_prefix_text_buffer, VVMCarrierPrefix, -1); else gtk_entry_buffer_set_text (self->carrier_prefix_text_buffer, "", -1); 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 = adw_combo_row_get_selected (self->vvm_type_combo_row); if (vvm_type_combo_row_state != VVMType_encoded) adw_combo_row_set_selected (self->vvm_type_combo_row, VVMType_encoded); //Status if (vvm_settings_get_mm_available (settings)) gtk_image_set_from_icon_name (self->vvmd_enabled_image, STATUS_GOOD); else gtk_image_set_from_icon_name (self->vvmd_enabled_image, STATUS_BAD); if (vvm_settings_get_mailbox_active (settings)) gtk_image_set_from_icon_name (self->mailbox_active_image, STATUS_GOOD); else gtk_image_set_from_icon_name (self->mailbox_active_image, STATUS_BAD); VVMProvisionStatus = vvm_settings_get_vvm_provision_status (settings); VVMProvisionStatus = g_strdup_printf (_("Provision Status: %s"), VVMProvisionStatus); adw_preferences_row_set_title (ADW_PREFERENCES_ROW (self->provision_status_text), VVMProvisionStatus); } 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_debug ("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_update_service_settings (backend) == FALSE) { g_debug ("Error getting VVMD Service Settings"); vvm_settings_load_service_defaults (settings); } } else { g_debug ("Loading VVMD service Defaults"); vvm_settings_load_service_defaults (settings); } } VvmplayerPreferencesWindow * vvm_player_preferences_window_new (void) { return g_object_new (ADW_TYPE_DEMO_PREFERENCES_WINDOW, NULL); } static void vvm_player_preferences_window_finalize (GObject *object) { VvmplayerPreferencesWindow *self = (VvmplayerPreferencesWindow *)object; VvmVvmd *backend = vvm_vvmd_get_default (); g_signal_handler_disconnect (backend, self->vvm_settings_watch_id); G_OBJECT_CLASS (vvm_player_preferences_window_parent_class)->finalize (object); } static void vvm_player_preferences_window_class_init (VvmplayerPreferencesWindowClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->finalize = vvm_player_preferences_window_finalize; 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, VvmplayerPreferencesWindow, refresh_settings_button); gtk_widget_class_bind_template_callback (widget_class, refresh_settings_button_clicked_cb); //Appearance Settings gtk_widget_class_bind_template_child (widget_class, VvmplayerPreferencesWindow, enable_dark_theme_switch); gtk_widget_class_bind_template_child (widget_class, VvmplayerPreferencesWindow, enable_dark_theme_row); 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, VvmplayerPreferencesWindow, enable_vvm_text); gtk_widget_class_bind_template_child (widget_class, VvmplayerPreferencesWindow, 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, VvmplayerPreferencesWindow, vvmd_enabled_image); gtk_widget_class_bind_template_child (widget_class, VvmplayerPreferencesWindow, mailbox_active_image); gtk_widget_class_bind_template_child (widget_class, VvmplayerPreferencesWindow, provision_status_text); gtk_widget_class_bind_template_callback (widget_class, vvm_type_selected_cb); //Activate VVM gtk_widget_class_bind_template_child (widget_class, VvmplayerPreferencesWindow, 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, VvmplayerPreferencesWindow, 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, VvmplayerPreferencesWindow, spam_contact_switch); gtk_widget_class_bind_template_child (widget_class, VvmplayerPreferencesWindow, spam_contact_text); gtk_widget_class_bind_template_child (widget_class, VvmplayerPreferencesWindow, spam_contact_text_buffer); 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, VvmplayerPreferencesWindow, destination_number_text); gtk_widget_class_bind_template_child (widget_class, VvmplayerPreferencesWindow, destination_number_text_buffer); gtk_widget_class_bind_template_child (widget_class, VvmplayerPreferencesWindow, modem_number_text); gtk_widget_class_bind_template_child (widget_class, VvmplayerPreferencesWindow, modem_number_text_buffer); gtk_widget_class_bind_template_child (widget_class, VvmplayerPreferencesWindow, carrier_prefix_text_row); gtk_widget_class_bind_template_child (widget_class, VvmplayerPreferencesWindow, carrier_prefix_text); gtk_widget_class_bind_template_child (widget_class, VvmplayerPreferencesWindow, carrier_prefix_text_buffer); gtk_widget_class_bind_template_child (widget_class, VvmplayerPreferencesWindow, vvm_type_combo_row); } static void update_settings_cb (VvmplayerPreferencesWindow *self) { vvm_preferences_refresh_settings (); vvm_preferences_window_populate (self); } static void vvm_player_preferences_window_init (VvmplayerPreferencesWindow *self) { VvmVvmd *backend = vvm_vvmd_get_default (); gtk_widget_init_template (GTK_WIDGET (self)); vvm_preferences_refresh_settings (); vvm_preferences_window_populate (self); self->vvm_settings_watch_id = g_signal_connect_swapped (backend, "settings-updated", G_CALLBACK (update_settings_cb), self); } vvmplayer-2.5/src/vvmplayer-preferences-window.h000066400000000000000000000021561456573503400222160ustar00rootroot00000000000000/* vvmplayer-preferences-window.h * * Copyright 2021-2022 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 . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include G_BEGIN_DECLS #define ADW_TYPE_DEMO_PREFERENCES_WINDOW (vvm_player_preferences_window_get_type ()) G_DECLARE_FINAL_TYPE (VvmplayerPreferencesWindow, vvm_player_preferences_window, ADW, VVMPLAYER_PREFERENCES_WINDOW, AdwPreferencesWindow) VvmplayerPreferencesWindow *vvm_player_preferences_window_new (void); G_END_DECLS vvmplayer-2.5/src/vvmplayer-settings.c000066400000000000000000000275521456573503400202520ustar00rootroot00000000000000/* -*- 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" #include "config.h" #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; GtkSettings *gtk_settings; //App Settings int prefer_dark_theme; //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_dark_theme (VvmSettings *self) { return self->prefer_dark_theme; } static void adw_style_manager_set_dark_theme (int prefer_dark_theme) { AdwStyleManager *adw_style_manager = adw_style_manager_get_default (); if (prefer_dark_theme) adw_style_manager_set_color_scheme (adw_style_manager, ADW_COLOR_SCHEME_PREFER_DARK); else adw_style_manager_set_color_scheme (adw_style_manager, ADW_COLOR_SCHEME_DEFAULT); } 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); adw_style_manager_set_dark_theme (self->prefer_dark_theme); } 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); } 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; g_debug ("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_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"); adw_style_manager_set_dark_theme (self->prefer_dark_theme); 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-2.5/src/vvmplayer-settings.h000066400000000000000000000102011456573503400202360ustar00rootroot00000000000000/* -*- 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 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); 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); void vvmplayer_settings_set_dark_theme (VvmSettings *self, int prefer_dark_theme); int vvmplayer_settings_get_dark_theme (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-2.5/src/vvmplayer-voicemail-window.c000066400000000000000000000571631456573503400216700ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ /* vvmplayer-voicemail-window.c * * Copyright 2021-2022 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 #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 { AdwExpanderRow parent_instance; GstElement *playbin; GstState state; GtkImage *play_button_icon; GtkButton *delete_button; GtkButton *stop_button; AdwActionRow *second_row; AdwActionRow *call_row; AdwActionRow *sms_row; gint64 duration; gint64 minutes; gint64 seconds; char *duration_formatted; char *objectpath; char *contact_name; char *number; char *voicemail_file; int lifetime_status; GDBusProxy *message_proxy; GDateTime *time_local; gulong window_closed_id; }; G_DEFINE_TYPE (VoicemailWindow, voicemail_window, ADW_TYPE_EXPANDER_ROW) static void voicemail_window_set_title (VoicemailWindow *self) { g_autofree char *title = NULL; if (self->lifetime_status == VVM_LIFETIME_STATUS_NOT_READ) { if (self->contact_name) title = g_strdup_printf (_("%s (Unread)"), self->contact_name); else title = g_strdup_printf (_("%s (Unread)"), self->number); } else { if (self->contact_name) title = g_strdup (self->contact_name); else title = g_strdup (self->number); } adw_preferences_row_set_title (ADW_PREFERENCES_ROW (self), title); } void voicemail_window_delete_self (VoicemailWindow *self) { VvmVvmd *vvmd_object = vvm_vvmd_get_default (); GtkWidget *list_box; 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); /* To dispose: You need to get the parent and have the parent remove it. */ list_box = gtk_widget_get_parent (GTK_WIDGET (self)); gtk_list_box_remove (GTK_LIST_BOX (list_box), (GTK_WIDGET (self))); } static void save_dialog_finished (GObject *dialog, GAsyncResult *response, gpointer user_data) { VoicemailWindow *self = VVM_VOICEMAIL_WINDOW (user_data); g_autoptr(GError) error = NULL; g_autoptr(GFile) save_filename = NULL; save_filename = gtk_file_dialog_save_finish (GTK_FILE_DIALOG (dialog), response, &error); g_clear_object (&dialog); if (error != NULL) { g_warning ("Error saving: %s", error->message); return; } if (g_strcmp0 (self->voicemail_file, g_file_peek_path (save_filename)) != 0) { g_autoptr(GFile) vvm_file = NULL; vvm_file = g_file_new_for_path (self->voicemail_file); g_file_copy_async (vvm_file, save_filename, G_FILE_COPY_OVERWRITE, G_PRIORITY_DEFAULT, NULL, NULL, NULL, NULL, NULL); g_debug ("Saving at %s", g_file_peek_path (save_filename)); } } static void save_button_clicked_cb (GtkButton *btn, VoicemailWindow *self) { GtkFileDialog *dialog; g_autoptr(GFile) vvm_file = NULL; GtkWindow *window; g_debug ("Saving Voicemail..."); window = gtk_application_get_active_window (GTK_APPLICATION (g_application_get_default ())); dialog = gtk_file_dialog_new (); vvm_file = g_file_new_for_path (self->voicemail_file); gtk_file_dialog_set_initial_file (dialog, vvm_file); gtk_file_dialog_set_modal (dialog, TRUE); gtk_file_dialog_set_title (dialog, "Save Voicemail as...."); gtk_file_dialog_save (dialog, window, NULL, save_dialog_finished, self); } static void stop_button_clicked_cb (GtkButton *btn, VoicemailWindow *self) { GstStateChangeReturn ret; GstState old_state = self->state; 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 (); if (old_state == GST_STATE_PLAYING) vvm_settings_decriment_stream_count (settings); gtk_image_set_from_icon_name (self->play_button_icon, ICON_PLAYBACK_START); self->state = GST_STATE_READY; self->minutes = 0; self->seconds = 0; duration = g_strdup_printf ("%02" G_GINT64_FORMAT ":%02" G_GINT64_FORMAT "/%s", self->minutes, self->seconds, self->duration_formatted); adw_preferences_row_set_title (ADW_PREFERENCES_ROW (self->second_row), duration); } } 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 stop_button_clicked_cb (btn, self); voicemail_window_delete_self (self); } static void main_window_closed_cb (VoicemailWindow *self) { stop_button_clicked_cb (self->stop_button, self); adw_expander_row_set_expanded (ADW_EXPANDER_ROW (self), FALSE); } static gboolean refresh_ui (VoicemailWindow *self) { g_autofree char *duration = NULL; 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!"); self->seconds = self->seconds + 1; if (self->seconds == 60) { self->seconds = 0; self->minutes = self->minutes + 1; } duration = g_strdup_printf ("%02" G_GINT64_FORMAT ":%02" G_GINT64_FORMAT "/%s", self->minutes, self->seconds, self->duration_formatted); adw_preferences_row_set_title (ADW_PREFERENCES_ROW (self->second_row), duration); return TRUE; } static void play_button_clicked_cb (GtkButton *btn, VoicemailWindow *self) { VvmVvmd *vvmd_object = vvm_vvmd_get_default (); g_debug ("Play button clicked!"); if (!self->playbin) { g_debug ("Playbin is NULL!"); return; } /* The user probably saw the notification, so dismiss it */ vvmplayer_notification_withdraw_unread_vvm (); 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; 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); gtk_image_set_from_icon_name (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; 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); gtk_image_set_from_icon_name (self->play_button_icon, ICON_PLAYBACK_START); self->state = GST_STATE_PAUSED; } } } /* 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); } } /* 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); gtk_image_set_from_icon_name (self->play_button_icon, ICON_PLAYBACK_START); self->minutes = 0; self->seconds = 0; duration = g_strdup_printf ("%02" G_GINT64_FORMAT ":%02" G_GINT64_FORMAT "/%s", self->minutes, self->seconds, self->duration_formatted); adw_preferences_row_set_title (ADW_PREFERENCES_ROW (self->second_row), duration); } static gboolean phone_utils_simple_is_valid (const char *number) { if (strspn (number, "+()- 0123456789") != strlen (number)) return false; return true; } /* 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); gtk_image_set_from_icon_name (self->play_button_icon, ICON_PLAYBACK_START); self->state = GST_STATE_READY; adw_preferences_row_set_title (ADW_PREFERENCES_ROW (self->second_row), "Playback Error!"); } VoicemailWindow * 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; 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); /* TRANSLATORS: Timestamp for minute accuracy, e.g. “2020-08-11 15:27”. * See https://developer.gnome.org/glib/stable/glib-GDateTime.html#g-date-time-format */ 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++) { g_autoptr(GFile) vvm_file = NULL; g_autoptr(GFileInfo) vvm_file_info = NULL; 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; if (!self->voicemail_file) self->voicemail_file = g_strdup (Attachment_list[attachment_counter]); 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 ("%02" G_GINT64_FORMAT ":%02" G_GINT64_FORMAT, self->minutes, self->seconds); } } } self->minutes = 0; self->seconds = 0; duration = g_strdup_printf ("%02" G_GINT64_FORMAT ":%02" G_GINT64_FORMAT "/%s", self->minutes, self->seconds, self->duration_formatted); adw_preferences_row_set_title (ADW_PREFERENCES_ROW (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); } app_info_tel = g_app_info_get_default_for_uri_scheme ("tel"); if (app_info_tel && phone_utils_simple_is_valid (Sender)) gtk_widget_set_visible (GTK_WIDGET (self->call_row), TRUE); app_info_sms = g_app_info_get_default_for_uri_scheme ("sms"); if (app_info_sms && phone_utils_simple_is_valid (Sender)) gtk_widget_set_visible (GTK_WIDGET (self->sms_row), TRUE); voicemail_window_set_title (self); adw_expander_row_set_subtitle (ADW_EXPANDER_ROW (self), Date); return self; } 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); } 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); } static void call_button_clicked_cb (GtkButton *btn, VoicemailWindow *self) { g_autofree char *uri = NULL; GtkUriLauncher *uri_launcher = NULL; GtkWindow *window; g_debug ("Call Button Clicked"); window = gtk_application_get_active_window (GTK_APPLICATION (g_application_get_default ())); uri = g_strconcat ("tel://", self->number, NULL); uri_launcher = gtk_uri_launcher_new (uri); gtk_uri_launcher_launch (uri_launcher, window, NULL, NULL, NULL); g_clear_object (&uri_launcher); } static void sms_button_clicked_cb (GtkButton *btn, VoicemailWindow *self) { g_autofree char *uri = NULL; GtkUriLauncher *uri_launcher = NULL; GtkWindow *window; g_debug ("SMS Button Clicked"); window = gtk_application_get_active_window (GTK_APPLICATION (g_application_get_default ())); uri = g_strconcat ("sms://", self->number, NULL); uri_launcher = gtk_uri_launcher_new (uri); gtk_uri_launcher_launch (uri_launcher, window, NULL, NULL, NULL); g_clear_object (&uri_launcher); } 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_free (self->voicemail_file); 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, play_button_icon); gtk_widget_class_bind_template_child (widget_class, VoicemailWindow, delete_button); gtk_widget_class_bind_template_child (widget_class, VoicemailWindow, stop_button); 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, stop_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); gtk_widget_class_bind_template_callback (widget_class, save_button_clicked_cb); object_class->finalize = voicemail_window_finalize; } static void voicemail_window_init (VoicemailWindow *self) { gtk_widget_init_template (GTK_WIDGET (self)); } vvmplayer-2.5/src/vvmplayer-voicemail-window.h000066400000000000000000000036511456573503400216660ustar00rootroot00000000000000/* -*- 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 "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, AdwExpanderRow) VoicemailWindow *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-2.5/src/vvmplayer-vvmd.c000066400000000000000000001160631456573503400173620ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ /* vvmplayer-vvmd.c * * Copyright 2021-2022 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 . */ #include "config.h" #include "vvmplayer-vvmd.h" struct _VvmVvmd { GObject parent_instance; VvmplayerWindow *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) enum { SETTINGS_UPDATED, N_SIGNALS }; static guint signals[N_SIGNALS]; 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, "FreeMobileProprietary") == 0) return VVM_TYPE_FREEMOBILEFRA; 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 if (g_strcmp0 (vvm_type, "ios") == 0) return VVM_TYPE_IOS; 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_FREEMOBILEFRA: return g_strdup ("FreeMobileProprietary"); case VVM_TYPE_OTMP: return g_strdup ("otmp"); case VVM_TYPE_VVM_THREE: return g_strdup ("vvm3"); case VVM_TYPE_IOS: return g_strdup ("ios"); default: return g_strdup ("Unknown"); } return g_strdup ("Unknown"); } void vvmplayer_vvmd_set_mm_vvm_list_box (VvmVvmd *self, VvmplayerWindow *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_update_service_settings (VvmVvmd *self) { int MailBoxActiveOld, MailBoxActive; VvmSettings *settings = vvm_settings_get_default (); MailBoxActiveOld = vvm_settings_get_mailbox_active (settings); if (vvmplayer_vvmd_get_service_settings (self) == FALSE) { g_debug ("Error getting VVMD Service Settings"); return FALSE; } MailBoxActive = vvm_settings_get_mailbox_active (settings); /* Send a signal out if this is different */ if (MailBoxActiveOld != MailBoxActive) g_signal_emit (self, signals[SETTINGS_UPDATED], 0); 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) { VoicemailWindow *new_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; } new_voicemail = voicemail_window_new (message_t, message_proxy, self->discoverer); if (new_voicemail == NULL) { g_warning ("There was an error with making the VVM!"); return FALSE; } if (vvmplayer_vvmd_add_contact_name (self, VVM_VOICEMAIL_WINDOW (new_voicemail)) == FALSE) return FALSE; g_list_store_insert_sorted (self->vvm_list, VVM_VOICEMAIL_WINDOW (new_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; int previous_unread = self->unread_vvms; g_debug ("%s", __func__); 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_debug ("Emitting update settings signal"); g_signal_emit (self, signals[SETTINGS_UPDATED], 0); 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); } else { g_debug ("No Services, Sending emit to update settings"); g_signal_emit (self, signals[SETTINGS_UPDATED], 0); } } } 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; g_autofree char *Oldprovision = NULL; const char *provision; g_debug ("%s", __func__); g_variant_get (parameters, "(sv)", NULL, &provisionstatus); provision = g_variant_get_string (provisionstatus, NULL); Oldprovision = vvm_settings_get_vvm_provision_status (settings); if (g_strcmp0 (Oldprovision, provision)) { vvm_settings_set_vvm_provision_status (settings, provision); g_debug ("Emitting update settings signal"); g_signal_emit (self, signals[SETTINGS_UPDATED], 0); } } 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; g_autofree char *OldVVMType = NULL; g_autofree char *OldVVMDestinationNumber = NULL; g_autofree char *OldCarrierPrefix = NULL; const char *VVMType = NULL; const char *VVMDestinationNumber = NULL; const char *CarrierPrefix = NULL; gboolean settings_changed = FALSE; g_debug ("%s", __func__); g_variant_get (parameters, "(sss)", &VVMType, &VVMDestinationNumber, &CarrierPrefix); OldVVMType = vvm_settings_get_vvm_type (settings); OldVVMDestinationNumber = vvm_settings_get_vvm_destination_number (settings); OldCarrierPrefix = vvm_settings_get_vvm_carrier_prefix (settings); if (g_strcmp0 (OldVVMType, VVMType)) { vvm_settings_set_vvm_type (settings, VVMType); settings_changed = TRUE; } if (g_strcmp0 (OldVVMDestinationNumber, VVMDestinationNumber)) { vvm_settings_set_vvm_destination_number (settings, VVMDestinationNumber); settings_changed = TRUE; } if (g_strcmp0 (OldCarrierPrefix, CarrierPrefix)) { vvm_settings_set_vvm_carrier_prefix (settings, CarrierPrefix); settings_changed = TRUE; } if (settings_changed) { g_debug ("Emitting update settings signal"); g_signal_emit (self, signals[SETTINGS_UPDATED], 0); } } static int vvmplayer_vvmd_sub_to_mm_settings (VvmVvmd *self) { if (vvmplayer_vvmd_get_mm_settings (self) == FALSE) return FALSE; 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; } 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); } return TRUE; } static gboolean vvmplayer_vvmd_retry_mm_settings (gpointer user_data) { VvmVvmd *self = user_data; g_debug ("Retrying..."); if (vvmplayer_vvmd_sub_to_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_sub_to_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; VvmSettings *settings = vvm_settings_get_default (); g_assert (G_IS_DBUS_CONNECTION (connection)); g_debug ("VVMD vanished"); vvm_settings_set_mailbox_active (settings, FALSE); 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); g_debug ("Sending emit to update settings"); g_signal_emit (self, signals[SETTINGS_UPDATED], 0); } 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); signals [SETTINGS_UPDATED] = g_signal_new ("settings-updated", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0); 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-2.5/src/vvmplayer-vvmd.h000066400000000000000000000064101456573503400173610ustar00rootroot00000000000000/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ /* vvmplayer-vvmd.h * * Copyright 2021-2022 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 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" #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_FREEMOBILEFRA, VVM_TYPE_VVM_THREE, VVM_TYPE_IOS, }; VvmVvmd *vvm_vvmd_get_default (void); void vvmplayer_vvmd_set_mm_vvm_list_box (VvmVvmd *self, VvmplayerWindow *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_update_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-2.5/src/vvmplayer-window.c000066400000000000000000000160171456573503400177130ustar00rootroot00000000000000/* vvmplayer-window.c * * Copyright 2021-2022 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 . * * SPDX-License-Identifier: GPL-3.0-or-later */ #include #include "config.h" #include "vvmplayer-window.h" #include "vvmplayer-voicemail-window.h" #include "vvmplayer-settings.h" struct _VvmplayerWindow { AdwApplicationWindow parent_instance; /* Template widgets */ GtkWidget *header_bar; GtkListBox *visual_voicemail; GtkToggleButton *speaker_output_button; GtkImage *speaker_output_image; AdwToastOverlay *toast_overlay; AdwToast *toast; GtkScrolledWindow *scroll_window; AdwStatusPage *window_status_page; //Watch ID gulong vvm_settings_watch_id; gulong window_closed_id; }; G_DEFINE_TYPE (VvmplayerWindow, vvmplayer_window, ADW_TYPE_APPLICATION_WINDOW) void vvmplayer_window_set_speaker_button (VvmplayerWindow *self, gboolean setting) { gtk_toggle_button_set_active (self->speaker_output_button, setting); } void vvmplayer_window_add_row (VvmplayerWindow *self, GtkWidget *voicemail) { if (gtk_widget_get_parent (voicemail) == NULL) gtk_list_box_prepend (GTK_LIST_BOX (self->visual_voicemail), GTK_WIDGET (voicemail)); else g_warning ("Voicemail already has a parent!"); } 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, VvmplayerWindow *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 ("Button Toggled"); call_audio_select_mode_async (CALL_AUDIO_MODE_DEFAULT, select_mode_complete, NULL); } else { g_debug ("Button Untoggled"); 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."); } } static void update_settings_cb (VvmplayerWindow *self) { VvmSettings *settings = vvm_settings_get_default (); const char *vvm_disabled_text = _("Go to Preferences to " "enable and see " "" "here for " "configuration help."); const char *no_vvmd_text = _("Please install or enable " "" "vvmd"); if (vvm_settings_get_mm_available (settings) == FALSE) { adw_status_page_set_title (self->window_status_page, _("vvmd not active")); adw_status_page_set_description (self->window_status_page, no_vvmd_text); } else if (vvm_settings_get_mailbox_active (settings) == TRUE) { adw_status_page_set_title (self->window_status_page, _("No Voicemails!")); adw_status_page_set_description (self->window_status_page, ""); } else { adw_status_page_set_title (self->window_status_page, _("Visual Voicemail disabled")); adw_status_page_set_description (self->window_status_page, vvm_disabled_text); } } static void main_window_closed_cb (VvmplayerWindow *self) { GtkAdjustment *vadjustment = NULL; gtk_list_box_unselect_all (GTK_LIST_BOX (self->visual_voicemail)); /* Reset scrolling to the top */ vadjustment = gtk_scrolled_window_get_vadjustment (self->scroll_window); gtk_adjustment_set_value (vadjustment, gtk_adjustment_get_lower (vadjustment)); } static void vvmplayer_window_finalize (GObject *object) { VvmplayerWindow *self = (VvmplayerWindow *)object; VvmVvmd *backend = vvm_vvmd_get_default (); g_signal_handler_disconnect (g_application_get_default (), self->window_closed_id); g_signal_handler_disconnect (backend, self->vvm_settings_watch_id); G_OBJECT_CLASS (vvmplayer_window_parent_class)->finalize (object); } static void vvmplayer_window_class_init (VvmplayerWindowClass *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-window.ui"); gtk_widget_class_bind_template_child (widget_class, VvmplayerWindow, header_bar); gtk_widget_class_bind_template_child (widget_class, VvmplayerWindow, visual_voicemail); gtk_widget_class_bind_template_child (widget_class, VvmplayerWindow, speaker_output_image); gtk_widget_class_bind_template_child (widget_class, VvmplayerWindow, speaker_output_button); gtk_widget_class_bind_template_child (widget_class, VvmplayerWindow, toast_overlay); gtk_widget_class_bind_template_child (widget_class, VvmplayerWindow, scroll_window); gtk_widget_class_bind_template_child (widget_class, VvmplayerWindow, window_status_page); gtk_widget_class_bind_template_callback (widget_class, speaker_output_button_clicked_cb); object_class->finalize = vvmplayer_window_finalize; } static void vvmplayer_window_init (VvmplayerWindow *self) { g_autoptr(GError) error = NULL; VvmVvmd *backend = vvm_vvmd_get_default (); gtk_widget_init_template (GTK_WIDGET (self)); gtk_widget_add_css_class (GTK_WIDGET (self->visual_voicemail), "navigation-sidebar"); 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); self->vvm_settings_watch_id = g_signal_connect_swapped (backend, "settings-updated", G_CALLBACK (update_settings_cb), self); } vvmplayer-2.5/src/vvmplayer-window.h000066400000000000000000000023571456573503400177220ustar00rootroot00000000000000/* vvmplayer-window.h * * Copyright 2021-2022 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 . * * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once #include #include G_BEGIN_DECLS #define VVMPLAYER_TYPE_WINDOW (vvmplayer_window_get_type ()) G_DECLARE_FINAL_TYPE (VvmplayerWindow, vvmplayer_window, VVMPLAYER, WINDOW, AdwApplicationWindow) void vvmplayer_window_add_row (VvmplayerWindow *self, GtkWidget *voicemail); void vvmplayer_window_set_speaker_button (VvmplayerWindow *self, gboolean setting); G_END_DECLS vvmplayer-2.5/src/vvmplayer.gresource.xml000066400000000000000000000005431456573503400207560ustar00rootroot00000000000000 ui/vvmplayer-window.ui ui/vvmplayer-preferences-window.ui ui/vvmplayer-voicemail-window.ui vvmplayer-2.5/uncrustify.cfg000066400000000000000000000077361456573503400163320ustar00rootroot00000000000000# # GNOME style (GNU variant) # input_tab_size = 8 output_tab_size = 8 # { # size = 2; // etc. # ^^ indent_columns = 2 indent_with_tabs = 0 # Don't use tabs for indentation # if ()\n{} // level of endentation before '{' # ^ indent_brace = 2 # exit: #^ // indentation before label # 2 = 1 space indent_label = 2 # size = size + 2; // +, -, *, /, &, |, >>, <<, etc # ^ ^ sp_arith = force # int width, height # ^ ^ sp_after_comma = force sp_before_comma = remove # size = 4; // +=, -=, |=, etc. # ^ ^ sp_assign = add # success = start && go; // &&, || # ^ ^ sp_bool = force # if (size > 2) // >, <, ==, >=, etc. # ^ ^ sp_compare = force # perimeter = (width + height) * 2 // remove space around '(' # ^ ^ sp_inside_paren = remove # int main (void) // remove spaces around '(' in functions # ^ ^ sp_inside_fparen = remove # int main () // remove spaces in empty parameters # ^ sp_inside_fparens = remove # int foo (void); # ^ sp_func_proto_paren = add # int foo (void){} # ^ sp_func_def_paren = force # printf (""); # ^ sp_func_call_paren = force # if ( // if/for/while/switch etc. # ^ sp_before_sparen = force set func_call_user _ N_ C_ Q_ NC_ set func_call_user g_autoptr g_auto # space after user defined functions (above) and paren sp_func_call_user_paren = remove # printf ("") ; # ^ // remove the space sp_before_semi = remove sp_inside_braces = ignore # return (3*2); # ^ sp_return_paren = force # long distance; # int name; # // ^ space b/w type and variable name sp_after_type = add # char *name; // add space before '*' (keep spacing if more than 1) # ^ sp_before_ptr_star = add # char *name; // remove space after '*' # ^ sp_after_ptr_star = remove # char **name (){} // remove space b/w 2 '*' # ^ sp_between_ptr_star = remove # maximum consecutive new lines # 3 = 2 blank lines nl_max = 3 # char *names[] = { // remove newline if any # ^ nl_assign_brace = remove # } else // insert newline # ^ nl_brace_else = force # else if // remove newline if any # ^ nl_else_if = remove # do {} // insert newline # ^ nl_do_brace = force nl_union_brace = force nl_enum_brace = ignore # don't care for enums nl_struct_brace = force # while () {} // insert newline. # ^ nl_while_brace = force nl_for_brace = force nl_if_brace = force nl_switch_brace = force # do ()\n while(); # ^ nl_brace_while = force # int main (void){} // newline after type # ^ nl_func_type_name = force # int main () {} // insert newline # ^ nl_fdef_brace = force # int main () {} # ^ # nl_after_func_body = 2 # int main (int argc, char **argv) // force newline at ',' # ^ nl_func_decl_args = force nl_func_def_args = force # remove blank lines after '{' and before '}' eat_blanks_after_open_brace = true eat_blanks_before_close_brace = true # add newline at end of file nl_end_of_file = force # min number of newlines to be added nl_end_of_file_min = 1 # main (int argc, // add enough spaces to align # char *argv[]) # ^^ align_func_params = true # func (int *square, // stick '*' to parameter # double match) align_var_def_star_style = 2 # #define ADD(x,y,x) ((x) \ # + (y) \ # + (z)) # ^ // align '/' align_nl_cont = true # Add a '*' at beginning of multiline comment lines cmt_star_cont = true # Remove braces for single line statements in # while, for, if, and switch case mod_full_brace_while = remove mod_full_brace_for = remove mod_full_brace_if = remove mod_case_brace = remove # if (is_good \n || \n is_okay) # ^ ^ // If newline present, # where to put &&, ||, | etc. pos_conditional = lead # FIXME: Not working pos_bool = trail # Hack to avoid indentation of following line # consider the following tokens as a comment set COMMENT G_BEGIN_DECLS vvmplayer-2.5/uncrustify.sh000077500000000000000000000031001456573503400161650ustar00rootroot00000000000000#!/bin/sh # 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 # . if [ ! "$(which uncrustify)" ]; then echo "'uncrustify' Not found. Exiting..." exit 1 fi if [ ! "$(which diff)" ]; then echo "'diff' Not found. Exiting..." exit 1 fi # Handle only .c files. There are unfixable issues uncrustifying .h header files uncrustify -l c -c uncrustify.cfg --no-backup --mtime $(find . -path './src/*' -name '*.c') # Simple Hack to work around issues with handling .h files HEADER_FILES=$(find . -path './src/*' -name '*.h') for file in $HEADER_FILES do # Work on a copy. Replace the file only if some actual change # happened. Otherwise, every header file will have a new mtime # and that will result in compiling every file on rebuild. MTIME=$(stat -c '%Y' "$file") cp "$file" temp.h sed -i "/^G_DECLARE_/ s/)$/);/" temp.h cp temp.h temp.bak uncrustify -l c -c uncrustify.cfg --no-backup temp.h -q echo "Parsing: $file as language C" DIFF="$(diff temp.h temp.bak)" if [ "$DIFF" ]; then sed -i "/^G_DECLARE_/ s/;$//" temp.h mv temp.h "$file" # Reset modification time touch --date=@${MTIME} "$file" fi done # Remove temp files, if any. rm -rf temp.h temp.bak